feat: pre-release
This commit is contained in:
@@ -1,8 +1,16 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "smartcore"
|
name = "smartcore"
|
||||||
|
description = "The most advanced machine learning library in rust."
|
||||||
|
homepage = "https://smartcorelib.org"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["SmartCore Developers"]
|
authors = ["SmartCore Developers"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
license = "Apache-2.0"
|
||||||
|
documentation = "https://docs.rs/smartcore"
|
||||||
|
repository = "https://github.com/smartcorelib/smartcore"
|
||||||
|
readme = "README.md"
|
||||||
|
keywords = ["machine learning", "statistical", "modeling", "machine", "learning", "ai", "optimization", "linear algebra"]
|
||||||
|
categories = ["science"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["datasets"]
|
default = ["datasets"]
|
||||||
|
|||||||
@@ -101,7 +101,6 @@ impl<T: RealNumber> BBDTree<T> {
|
|||||||
) -> T {
|
) -> T {
|
||||||
let d = centroids[0].len();
|
let d = centroids[0].len();
|
||||||
|
|
||||||
// Determine which mean the node mean is closest to
|
|
||||||
let mut min_dist =
|
let mut min_dist =
|
||||||
Euclidian::squared_distance(&self.nodes[node].center, ¢roids[candidates[0]]);
|
Euclidian::squared_distance(&self.nodes[node].center, ¢roids[candidates[0]]);
|
||||||
let mut closest = candidates[0];
|
let mut closest = candidates[0];
|
||||||
@@ -114,9 +113,7 @@ impl<T: RealNumber> BBDTree<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is a non-leaf node, recurse if necessary
|
|
||||||
if !self.nodes[node].lower.is_none() {
|
if !self.nodes[node].lower.is_none() {
|
||||||
// Build the new list of candidates
|
|
||||||
let mut new_candidates = vec![0; k];
|
let mut new_candidates = vec![0; k];
|
||||||
let mut newk = 0;
|
let mut newk = 0;
|
||||||
|
|
||||||
@@ -133,7 +130,6 @@ impl<T: RealNumber> BBDTree<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recurse if there's at least two
|
|
||||||
if newk > 1 {
|
if newk > 1 {
|
||||||
return self.filter(
|
return self.filter(
|
||||||
self.nodes[node].lower.unwrap(),
|
self.nodes[node].lower.unwrap(),
|
||||||
@@ -155,7 +151,6 @@ impl<T: RealNumber> BBDTree<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assigns all data within this node to a single mean
|
|
||||||
for i in 0..d {
|
for i in 0..d {
|
||||||
sums[closest][i] = sums[closest][i] + self.nodes[node].sum[i];
|
sums[closest][i] = sums[closest][i] + self.nodes[node].sum[i];
|
||||||
}
|
}
|
||||||
@@ -203,14 +198,11 @@ impl<T: RealNumber> BBDTree<T> {
|
|||||||
fn build_node<M: Matrix<T>>(&mut self, data: &M, begin: usize, end: usize) -> usize {
|
fn build_node<M: Matrix<T>>(&mut self, data: &M, begin: usize, end: usize) -> usize {
|
||||||
let (_, d) = data.shape();
|
let (_, d) = data.shape();
|
||||||
|
|
||||||
// Allocate the node
|
|
||||||
let mut node = BBDTreeNode::new(d);
|
let mut node = BBDTreeNode::new(d);
|
||||||
|
|
||||||
// Fill in basic info
|
|
||||||
node.count = end - begin;
|
node.count = end - begin;
|
||||||
node.index = begin;
|
node.index = begin;
|
||||||
|
|
||||||
// Calculate the bounding box
|
|
||||||
let mut lower_bound = vec![T::zero(); d];
|
let mut lower_bound = vec![T::zero(); d];
|
||||||
let mut upper_bound = vec![T::zero(); d];
|
let mut upper_bound = vec![T::zero(); d];
|
||||||
|
|
||||||
@@ -231,7 +223,6 @@ impl<T: RealNumber> BBDTree<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate bounding box stats
|
|
||||||
let mut max_radius = T::from(-1.).unwrap();
|
let mut max_radius = T::from(-1.).unwrap();
|
||||||
let mut split_index = 0;
|
let mut split_index = 0;
|
||||||
for i in 0..d {
|
for i in 0..d {
|
||||||
@@ -243,7 +234,6 @@ impl<T: RealNumber> BBDTree<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the max spread is 0, make this a leaf node
|
|
||||||
if max_radius < T::from(1E-10).unwrap() {
|
if max_radius < T::from(1E-10).unwrap() {
|
||||||
node.lower = Option::None;
|
node.lower = Option::None;
|
||||||
node.upper = Option::None;
|
node.upper = Option::None;
|
||||||
@@ -262,9 +252,6 @@ impl<T: RealNumber> BBDTree<T> {
|
|||||||
return self.add_node(node);
|
return self.add_node(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Partition the data around the midpoint in this dimension. The
|
|
||||||
// partitioning is done in-place by iterating from left-to-right and
|
|
||||||
// right-to-left in the same way that partioning is done in quicksort.
|
|
||||||
let split_cutoff = node.center[split_index];
|
let split_cutoff = node.center[split_index];
|
||||||
let mut i1 = begin;
|
let mut i1 = begin;
|
||||||
let mut i2 = end - 1;
|
let mut i2 = end - 1;
|
||||||
@@ -291,11 +278,9 @@ impl<T: RealNumber> BBDTree<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the child nodes
|
|
||||||
node.lower = Option::Some(self.build_node(data, begin, begin + size));
|
node.lower = Option::Some(self.build_node(data, begin, begin + size));
|
||||||
node.upper = Option::Some(self.build_node(data, begin + size, end));
|
node.upper = Option::Some(self.build_node(data, begin + size, end));
|
||||||
|
|
||||||
// Calculate the new sum and opt cost
|
|
||||||
for i in 0..d {
|
for i in 0..d {
|
||||||
node.sum[i] =
|
node.sum[i] =
|
||||||
self.nodes[node.lower.unwrap()].sum[i] + self.nodes[node.upper.unwrap()].sum[i];
|
self.nodes[node.lower.unwrap()].sum[i] + self.nodes[node.upper.unwrap()].sum[i];
|
||||||
|
|||||||
@@ -222,12 +222,8 @@ impl<T: RealNumber + Sum> KMeans<T> {
|
|||||||
|
|
||||||
let mut row = vec![T::zero(); m];
|
let mut row = vec![T::zero(); m];
|
||||||
|
|
||||||
// pick the next center
|
|
||||||
for j in 1..k {
|
for j in 1..k {
|
||||||
// Loop over the samples and compare them to the most recent center. Store
|
|
||||||
// the distance from each sample to its closest center in scores.
|
|
||||||
for i in 0..n {
|
for i in 0..n {
|
||||||
// compute the distance between this sample and the current center
|
|
||||||
data.copy_row_as_vec(i, &mut row);
|
data.copy_row_as_vec(i, &mut row);
|
||||||
let dist = Euclidian::squared_distance(&row, ¢roid);
|
let dist = Euclidian::squared_distance(&row, ¢roid);
|
||||||
|
|
||||||
@@ -257,7 +253,6 @@ impl<T: RealNumber + Sum> KMeans<T> {
|
|||||||
|
|
||||||
for i in 0..n {
|
for i in 0..n {
|
||||||
data.copy_row_as_vec(i, &mut row);
|
data.copy_row_as_vec(i, &mut row);
|
||||||
// compute the distance between this sample and the current center
|
|
||||||
let dist = Euclidian::squared_distance(&row, ¢roid);
|
let dist = Euclidian::squared_distance(&row, ¢roid);
|
||||||
|
|
||||||
if dist < d[i] {
|
if dist < d[i] {
|
||||||
|
|||||||
@@ -103,9 +103,7 @@ fn tred2<T: RealNumber, M: BaseMatrix<T>>(V: &mut M, d: &mut Vec<T>, e: &mut Vec
|
|||||||
d[i] = V.get(n - 1, i);
|
d[i] = V.get(n - 1, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Householder reduction to tridiagonal form.
|
|
||||||
for i in (1..n).rev() {
|
for i in (1..n).rev() {
|
||||||
// Scale to avoid under/overflow.
|
|
||||||
let mut scale = T::zero();
|
let mut scale = T::zero();
|
||||||
let mut h = T::zero();
|
let mut h = T::zero();
|
||||||
for k in 0..i {
|
for k in 0..i {
|
||||||
@@ -119,7 +117,6 @@ fn tred2<T: RealNumber, M: BaseMatrix<T>>(V: &mut M, d: &mut Vec<T>, e: &mut Vec
|
|||||||
V.set(j, i, T::zero());
|
V.set(j, i, T::zero());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Generate Householder vector.
|
|
||||||
for k in 0..i {
|
for k in 0..i {
|
||||||
d[k] = d[k] / scale;
|
d[k] = d[k] / scale;
|
||||||
h = h + d[k] * d[k];
|
h = h + d[k] * d[k];
|
||||||
@@ -136,7 +133,6 @@ fn tred2<T: RealNumber, M: BaseMatrix<T>>(V: &mut M, d: &mut Vec<T>, e: &mut Vec
|
|||||||
e[j] = T::zero();
|
e[j] = T::zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply similarity transformation to remaining columns.
|
|
||||||
for j in 0..i {
|
for j in 0..i {
|
||||||
f = d[j];
|
f = d[j];
|
||||||
V.set(j, i, f);
|
V.set(j, i, f);
|
||||||
@@ -169,7 +165,6 @@ fn tred2<T: RealNumber, M: BaseMatrix<T>>(V: &mut M, d: &mut Vec<T>, e: &mut Vec
|
|||||||
d[i] = h;
|
d[i] = h;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accumulate transformations.
|
|
||||||
for i in 0..n - 1 {
|
for i in 0..n - 1 {
|
||||||
V.set(n - 1, i, V.get(i, i));
|
V.set(n - 1, i, V.get(i, i));
|
||||||
V.set(i, i, T::one());
|
V.set(i, i, T::one());
|
||||||
@@ -210,7 +205,6 @@ fn tql2<T: RealNumber, M: BaseMatrix<T>>(V: &mut M, d: &mut Vec<T>, e: &mut Vec<
|
|||||||
let mut f = T::zero();
|
let mut f = T::zero();
|
||||||
let mut tst1 = T::zero();
|
let mut tst1 = T::zero();
|
||||||
for l in 0..n {
|
for l in 0..n {
|
||||||
// Find small subdiagonal element
|
|
||||||
tst1 = T::max(tst1, d[l].abs() + e[l].abs());
|
tst1 = T::max(tst1, d[l].abs() + e[l].abs());
|
||||||
|
|
||||||
let mut m = l;
|
let mut m = l;
|
||||||
@@ -226,8 +220,6 @@ fn tql2<T: RealNumber, M: BaseMatrix<T>>(V: &mut M, d: &mut Vec<T>, e: &mut Vec<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If m == l, d[l] is an eigenvalue,
|
|
||||||
// otherwise, iterate.
|
|
||||||
if m > l {
|
if m > l {
|
||||||
let mut iter = 0;
|
let mut iter = 0;
|
||||||
loop {
|
loop {
|
||||||
@@ -236,7 +228,6 @@ fn tql2<T: RealNumber, M: BaseMatrix<T>>(V: &mut M, d: &mut Vec<T>, e: &mut Vec<
|
|||||||
panic!("Too many iterations");
|
panic!("Too many iterations");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute implicit shift
|
|
||||||
let mut g = d[l];
|
let mut g = d[l];
|
||||||
let mut p = (d[l + 1] - g) / (T::two() * e[l]);
|
let mut p = (d[l + 1] - g) / (T::two() * e[l]);
|
||||||
let mut r = p.hypot(T::one());
|
let mut r = p.hypot(T::one());
|
||||||
@@ -252,7 +243,6 @@ fn tql2<T: RealNumber, M: BaseMatrix<T>>(V: &mut M, d: &mut Vec<T>, e: &mut Vec<
|
|||||||
}
|
}
|
||||||
f = f + h;
|
f = f + h;
|
||||||
|
|
||||||
// Implicit QL transformation.
|
|
||||||
p = d[m];
|
p = d[m];
|
||||||
let mut c = T::one();
|
let mut c = T::one();
|
||||||
let mut c2 = c;
|
let mut c2 = c;
|
||||||
@@ -273,7 +263,6 @@ fn tql2<T: RealNumber, M: BaseMatrix<T>>(V: &mut M, d: &mut Vec<T>, e: &mut Vec<
|
|||||||
p = c * d[i] - s * g;
|
p = c * d[i] - s * g;
|
||||||
d[i + 1] = h + s * (c * g + s * d[i]);
|
d[i + 1] = h + s * (c * g + s * d[i]);
|
||||||
|
|
||||||
// Accumulate transformation.
|
|
||||||
for k in 0..n {
|
for k in 0..n {
|
||||||
h = V.get(k, i + 1);
|
h = V.get(k, i + 1);
|
||||||
V.set(k, i + 1, s * V.get(k, i) + c * h);
|
V.set(k, i + 1, s * V.get(k, i) + c * h);
|
||||||
@@ -284,7 +273,6 @@ fn tql2<T: RealNumber, M: BaseMatrix<T>>(V: &mut M, d: &mut Vec<T>, e: &mut Vec<
|
|||||||
e[l] = s * p;
|
e[l] = s * p;
|
||||||
d[l] = c * p;
|
d[l] = c * p;
|
||||||
|
|
||||||
// Check for convergence.
|
|
||||||
if e[l].abs() <= tst1 * T::epsilon() {
|
if e[l].abs() <= tst1 * T::epsilon() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -294,7 +282,6 @@ fn tql2<T: RealNumber, M: BaseMatrix<T>>(V: &mut M, d: &mut Vec<T>, e: &mut Vec<
|
|||||||
e[l] = T::zero();
|
e[l] = T::zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort eigenvalues and corresponding vectors.
|
|
||||||
for i in 0..n - 1 {
|
for i in 0..n - 1 {
|
||||||
let mut k = i;
|
let mut k = i;
|
||||||
let mut p = d[i];
|
let mut p = d[i];
|
||||||
|
|||||||
Reference in New Issue
Block a user