Merge potential next release v0.4 (#187) Breaking Changes
* First draft of the new n-dimensional arrays + NB use case * Improves default implementation of multiple Array methods * Refactors tree methods * Adds matrix decomposition routines * Adds matrix decomposition methods to ndarray and nalgebra bindings * Refactoring + linear regression now uses array2 * Ridge & Linear regression * LBFGS optimizer & logistic regression * LBFGS optimizer & logistic regression * Changes linear methods, metrics and model selection methods to new n-dimensional arrays * Switches KNN and clustering algorithms to new n-d array layer * Refactors distance metrics * Optimizes knn and clustering methods * Refactors metrics module * Switches decomposition methods to n-dimensional arrays * Linalg refactoring - cleanup rng merge (#172) * Remove legacy DenseMatrix and BaseMatrix implementation. Port the new Number, FloatNumber and Array implementation into module structure. * Exclude AUC metrics. Needs reimplementation * Improve developers walkthrough New traits system in place at `src/numbers` and `src/linalg` Co-authored-by: Lorenzo <tunedconsulting@gmail.com> * Provide SupervisedEstimator with a constructor to avoid explicit dynamical box allocation in 'cross_validate' and 'cross_validate_predict' as required by the use of 'dyn' as per Rust 2021 * Implement getters to use as_ref() in src/neighbors * Implement getters to use as_ref() in src/naive_bayes * Implement getters to use as_ref() in src/linear * Add Clone to src/naive_bayes * Change signature for cross_validate and other model_selection functions to abide to use of dyn in Rust 2021 * Implement ndarray-bindings. Remove FloatNumber from implementations * Drop nalgebra-bindings support (as decided in conf-call to go for ndarray) * Remove benches. Benches will have their own repo at smartcore-benches * Implement SVC * Implement SVC serialization. Move search parameters in dedicated module * Implement SVR. Definitely too slow * Fix compilation issues for wasm (#202) Co-authored-by: Luis Moreno <morenol@users.noreply.github.com> * Fix tests (#203) * Port linalg/traits/stats.rs * Improve methods naming * Improve Display for DenseMatrix Co-authored-by: Montana Low <montanalow@users.noreply.github.com> Co-authored-by: VolodymyrOrlov <volodymyr.orlov@gmail.com>
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
use num_traits::{Bounded, FromPrimitive, Num, NumCast, ToPrimitive};
|
||||
use std::fmt::{Debug, Display};
|
||||
use std::iter::{Product, Sum};
|
||||
use std::ops::{AddAssign, DivAssign, MulAssign, SubAssign};
|
||||
|
||||
/// Define a `Number` set that acquires traits from `num_traits` to make available a base trait
|
||||
/// to be used by other usable sets like `FloatNumber`.
|
||||
pub trait Number:
|
||||
Num
|
||||
+ FromPrimitive
|
||||
+ ToPrimitive
|
||||
+ Debug
|
||||
+ Display
|
||||
+ Copy
|
||||
+ Sum
|
||||
+ Product
|
||||
+ AddAssign
|
||||
+ SubAssign
|
||||
+ MulAssign
|
||||
+ DivAssign
|
||||
+ Bounded
|
||||
+ NumCast
|
||||
{
|
||||
}
|
||||
|
||||
impl Number for f64 {}
|
||||
impl Number for f32 {}
|
||||
impl Number for i8 {}
|
||||
impl Number for i16 {}
|
||||
impl Number for i32 {}
|
||||
impl Number for i64 {}
|
||||
impl Number for u8 {}
|
||||
impl Number for u16 {}
|
||||
impl Number for u32 {}
|
||||
impl Number for u64 {}
|
||||
impl Number for usize {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::str::FromStr;
|
||||
|
||||
#[test]
|
||||
fn i32_from_string() {
|
||||
assert_eq!(i32::from_str("1").unwrap(), 1)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn i8_from_string() {
|
||||
assert_eq!(i8::from_str("1").unwrap(), 1)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
use rand::Rng;
|
||||
|
||||
use num_traits::{Float, Signed};
|
||||
|
||||
use crate::numbers::basenum::Number;
|
||||
|
||||
/// Defines float number
|
||||
/// <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS_CHTML"></script>
|
||||
pub trait FloatNumber: Number + Float + Signed {
|
||||
/// Copy sign from `sign` - another real number
|
||||
fn copysign(self, sign: Self) -> Self;
|
||||
|
||||
/// Calculates natural \\( \ln(1+e^x) \\) without overflow.
|
||||
fn ln_1pe(self) -> Self;
|
||||
|
||||
/// Efficient implementation of Sigmoid function, \\( S(x) = \frac{1}{1 + e^{-x}} \\), see [Sigmoid function](https://en.wikipedia.org/wiki/Sigmoid_function)
|
||||
fn sigmoid(self) -> Self;
|
||||
|
||||
/// Returns pseudorandom number between 0 and 1
|
||||
fn rand() -> Self;
|
||||
|
||||
/// Returns 2
|
||||
fn two() -> Self;
|
||||
|
||||
/// Returns .5
|
||||
fn half() -> Self;
|
||||
|
||||
/// Returns \\( x^2 \\)
|
||||
fn square(self) -> Self {
|
||||
self * self
|
||||
}
|
||||
|
||||
/// Raw transmutation to u64
|
||||
fn to_f32_bits(self) -> u32;
|
||||
}
|
||||
|
||||
impl FloatNumber for f64 {
|
||||
fn copysign(self, sign: Self) -> Self {
|
||||
self.copysign(sign)
|
||||
}
|
||||
|
||||
fn ln_1pe(self) -> f64 {
|
||||
if self > 15. {
|
||||
self
|
||||
} else {
|
||||
self.exp().ln_1p()
|
||||
}
|
||||
}
|
||||
|
||||
fn sigmoid(self) -> f64 {
|
||||
if self < -40. {
|
||||
0.
|
||||
} else if self > 40. {
|
||||
1.
|
||||
} else {
|
||||
1. / (1. + f64::exp(-self))
|
||||
}
|
||||
}
|
||||
|
||||
fn rand() -> f64 {
|
||||
let mut rng = rand::thread_rng();
|
||||
rng.gen()
|
||||
}
|
||||
|
||||
fn two() -> Self {
|
||||
2f64
|
||||
}
|
||||
|
||||
fn half() -> Self {
|
||||
0.5f64
|
||||
}
|
||||
|
||||
fn to_f32_bits(self) -> u32 {
|
||||
self.to_bits() as u32
|
||||
}
|
||||
}
|
||||
|
||||
impl FloatNumber for f32 {
|
||||
fn copysign(self, sign: Self) -> Self {
|
||||
self.copysign(sign)
|
||||
}
|
||||
|
||||
fn ln_1pe(self) -> f32 {
|
||||
if self > 15. {
|
||||
self
|
||||
} else {
|
||||
self.exp().ln_1p()
|
||||
}
|
||||
}
|
||||
|
||||
fn sigmoid(self) -> f32 {
|
||||
if self < -40. {
|
||||
0.
|
||||
} else if self > 40. {
|
||||
1.
|
||||
} else {
|
||||
1. / (1. + f32::exp(-self))
|
||||
}
|
||||
}
|
||||
|
||||
fn rand() -> f32 {
|
||||
let mut rng = rand::thread_rng();
|
||||
rng.gen()
|
||||
}
|
||||
|
||||
fn two() -> Self {
|
||||
2f32
|
||||
}
|
||||
|
||||
fn half() -> Self {
|
||||
0.5f32
|
||||
}
|
||||
|
||||
fn to_f32_bits(self) -> u32 {
|
||||
self.to_bits()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// this module has been ported from https://github.com/smartcorelib/smartcore/pull/108
|
||||
|
||||
/// Base `Number` from `std` and `num-traits`
|
||||
pub mod basenum;
|
||||
|
||||
/// implementation for `RealNumber`
|
||||
pub mod realnum;
|
||||
|
||||
/// implementation for `FloatNumber`
|
||||
pub mod floatnum;
|
||||
@@ -0,0 +1,151 @@
|
||||
//! # Real Number
|
||||
//! Most algorithms in SmartCore rely on basic linear algebra operations like dot product, matrix decomposition and other subroutines that are defined for a set of real numbers, ℝ.
|
||||
//! This module defines real number and some useful functions that are used in [Linear Algebra](../../linalg/index.html) module.
|
||||
|
||||
use num_traits::Float;
|
||||
|
||||
use crate::numbers::basenum::Number;
|
||||
|
||||
/// Defines real number
|
||||
/// <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS_CHTML"></script>
|
||||
pub trait RealNumber: Number + Float {
|
||||
/// Copy sign from `sign` - another real number
|
||||
fn copysign(self, sign: Self) -> Self;
|
||||
|
||||
/// Calculates natural \\( \ln(1+e^x) \\) without overflow.
|
||||
fn ln_1pe(self) -> Self;
|
||||
|
||||
/// Efficient implementation of Sigmoid function, \\( S(x) = \frac{1}{1 + e^{-x}} \\), see [Sigmoid function](https://en.wikipedia.org/wiki/Sigmoid_function)
|
||||
fn sigmoid(self) -> Self;
|
||||
|
||||
/// Returns pseudorandom number between 0 and 1
|
||||
fn rand() -> Self;
|
||||
|
||||
/// Returns 2
|
||||
fn two() -> Self;
|
||||
|
||||
/// Returns .5
|
||||
fn half() -> Self;
|
||||
|
||||
/// Returns \\( x^2 \\)
|
||||
fn square(self) -> Self {
|
||||
self * self
|
||||
}
|
||||
|
||||
/// Raw transmutation to u32
|
||||
fn to_f32_bits(self) -> u32;
|
||||
|
||||
/// Raw transmutation to u64
|
||||
fn to_f64_bits(self) -> u64;
|
||||
}
|
||||
|
||||
impl RealNumber for f64 {
|
||||
fn copysign(self, sign: Self) -> Self {
|
||||
self.copysign(sign)
|
||||
}
|
||||
|
||||
fn ln_1pe(self) -> f64 {
|
||||
if self > 15. {
|
||||
self
|
||||
} else {
|
||||
self.exp().ln_1p()
|
||||
}
|
||||
}
|
||||
|
||||
fn sigmoid(self) -> f64 {
|
||||
if self < -40. {
|
||||
0.
|
||||
} else if self > 40. {
|
||||
1.
|
||||
} else {
|
||||
1. / (1. + f64::exp(-self))
|
||||
}
|
||||
}
|
||||
|
||||
fn rand() -> f64 {
|
||||
1.0
|
||||
}
|
||||
|
||||
fn two() -> Self {
|
||||
2f64
|
||||
}
|
||||
|
||||
fn half() -> Self {
|
||||
0.5f64
|
||||
}
|
||||
|
||||
fn to_f32_bits(self) -> u32 {
|
||||
self.to_bits() as u32
|
||||
}
|
||||
|
||||
fn to_f64_bits(self) -> u64 {
|
||||
self.to_bits()
|
||||
}
|
||||
}
|
||||
|
||||
impl RealNumber for f32 {
|
||||
fn copysign(self, sign: Self) -> Self {
|
||||
self.copysign(sign)
|
||||
}
|
||||
|
||||
fn ln_1pe(self) -> f32 {
|
||||
if self > 15. {
|
||||
self
|
||||
} else {
|
||||
self.exp().ln_1p()
|
||||
}
|
||||
}
|
||||
|
||||
fn sigmoid(self) -> f32 {
|
||||
if self < -40. {
|
||||
0.
|
||||
} else if self > 40. {
|
||||
1.
|
||||
} else {
|
||||
1. / (1. + f32::exp(-self))
|
||||
}
|
||||
}
|
||||
|
||||
fn rand() -> f32 {
|
||||
1.0
|
||||
}
|
||||
|
||||
fn two() -> Self {
|
||||
2f32
|
||||
}
|
||||
|
||||
fn half() -> Self {
|
||||
0.5f32
|
||||
}
|
||||
|
||||
fn to_f32_bits(self) -> u32 {
|
||||
self.to_bits()
|
||||
}
|
||||
|
||||
fn to_f64_bits(self) -> u64 {
|
||||
self.to_bits() as u64
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[test]
|
||||
fn sigmoid() {
|
||||
assert_eq!(1.0.sigmoid(), 0.7310585786300049);
|
||||
assert_eq!(41.0.sigmoid(), 1.);
|
||||
assert_eq!((-41.0).sigmoid(), 0.);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn f32_from_string() {
|
||||
assert_eq!(f32::from_str("1.111111").unwrap(), 1.111111)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn f64_from_string() {
|
||||
assert_eq!(f64::from_str("1.111111111").unwrap(), 1.111111111)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user