Merge branch 'development' into kmeans-with-fastpair
This commit is contained in:
@@ -37,6 +37,8 @@ $ rust-code-analysis-cli -p src/algorithm/neighbour/fastpair.rs --ls 22 --le 213
|
|||||||
```
|
```
|
||||||
* find more information about what happens in your binary with [`twiggy`](https://rustwasm.github.io/twiggy/install.html). This need a compiled binary so create a brief `main {}` function using `smartcore` and then point `twiggy` to that file.
|
* find more information about what happens in your binary with [`twiggy`](https://rustwasm.github.io/twiggy/install.html). This need a compiled binary so create a brief `main {}` function using `smartcore` and then point `twiggy` to that file.
|
||||||
|
|
||||||
|
* Please take a look to the output of a profiler to spot most evident performance problems, see [this guide about using a profiler](http://www.codeofview.com/fix-rs/2017/01/24/how-to-optimize-rust-programs-on-linux/).
|
||||||
|
|
||||||
## Issue Report Process
|
## Issue Report Process
|
||||||
|
|
||||||
1. Go to the project's issues.
|
1. Go to the project's issues.
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
name = "smartcore"
|
name = "smartcore"
|
||||||
description = "Machine Learning in Rust."
|
description = "Machine Learning in Rust."
|
||||||
homepage = "https://smartcorelib.org"
|
homepage = "https://smartcorelib.org"
|
||||||
version = "0.3.1"
|
version = "0.3.2"
|
||||||
authors = ["smartcore Developers"]
|
authors = ["smartcore Developers"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
|
|||||||
@@ -431,9 +431,9 @@ impl<T: Number + RealNumber> SVDDecomposable<T> for DenseMatrix<T> {}
|
|||||||
impl<'a, T: Debug + Display + Copy + Sized> Array<T, (usize, usize)> for DenseMatrixView<'a, T> {
|
impl<'a, T: Debug + Display + Copy + Sized> Array<T, (usize, usize)> for DenseMatrixView<'a, T> {
|
||||||
fn get(&self, pos: (usize, usize)) -> &T {
|
fn get(&self, pos: (usize, usize)) -> &T {
|
||||||
if self.column_major {
|
if self.column_major {
|
||||||
&self.values[(pos.0 + pos.1 * self.stride)]
|
&self.values[pos.0 + pos.1 * self.stride]
|
||||||
} else {
|
} else {
|
||||||
&self.values[(pos.0 * self.stride + pos.1)]
|
&self.values[pos.0 * self.stride + pos.1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -495,9 +495,9 @@ impl<'a, T: Debug + Display + Copy + Sized> ArrayView1<T> for DenseMatrixView<'a
|
|||||||
impl<'a, T: Debug + Display + Copy + Sized> Array<T, (usize, usize)> for DenseMatrixMutView<'a, T> {
|
impl<'a, T: Debug + Display + Copy + Sized> Array<T, (usize, usize)> for DenseMatrixMutView<'a, T> {
|
||||||
fn get(&self, pos: (usize, usize)) -> &T {
|
fn get(&self, pos: (usize, usize)) -> &T {
|
||||||
if self.column_major {
|
if self.column_major {
|
||||||
&self.values[(pos.0 + pos.1 * self.stride)]
|
&self.values[pos.0 + pos.1 * self.stride]
|
||||||
} else {
|
} else {
|
||||||
&self.values[(pos.0 * self.stride + pos.1)]
|
&self.values[pos.0 * self.stride + pos.1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -519,9 +519,9 @@ impl<'a, T: Debug + Display + Copy + Sized> MutArray<T, (usize, usize)>
|
|||||||
{
|
{
|
||||||
fn set(&mut self, pos: (usize, usize), x: T) {
|
fn set(&mut self, pos: (usize, usize), x: T) {
|
||||||
if self.column_major {
|
if self.column_major {
|
||||||
self.values[(pos.0 + pos.1 * self.stride)] = x;
|
self.values[pos.0 + pos.1 * self.stride] = x;
|
||||||
} else {
|
} else {
|
||||||
self.values[(pos.0 * self.stride + pos.1)] = x;
|
self.values[pos.0 * self.stride + pos.1] = x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,25 @@ pub struct VecView<'a, T: Debug + Display + Copy + Sized> {
|
|||||||
ptr: &'a [T],
|
ptr: &'a [T],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: Debug + Display + Copy + Sized> Array<T, usize> for &[T] {
|
||||||
|
fn get(&self, i: usize) -> &T {
|
||||||
|
&self[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn shape(&self) -> usize {
|
||||||
|
self.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_empty(&self) -> bool {
|
||||||
|
self.len() > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn iterator<'b>(&'b self, axis: u8) -> Box<dyn Iterator<Item = &'b T> + 'b> {
|
||||||
|
assert!(axis == 0, "For one dimensional array `axis` should == 0");
|
||||||
|
Box::new(self.iter())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: Debug + Display + Copy + Sized> Array<T, usize> for Vec<T> {
|
impl<T: Debug + Display + Copy + Sized> Array<T, usize> for Vec<T> {
|
||||||
fn get(&self, i: usize) -> &T {
|
fn get(&self, i: usize) -> &T {
|
||||||
&self[i]
|
&self[i]
|
||||||
@@ -46,6 +65,7 @@ impl<T: Debug + Display + Copy + Sized> MutArray<T, usize> for Vec<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Debug + Display + Copy + Sized> ArrayView1<T> for Vec<T> {}
|
impl<T: Debug + Display + Copy + Sized> ArrayView1<T> for Vec<T> {}
|
||||||
|
impl<T: Debug + Display + Copy + Sized> ArrayView1<T> for &[T] {}
|
||||||
|
|
||||||
impl<T: Debug + Display + Copy + Sized> MutArrayView1<T> for Vec<T> {}
|
impl<T: Debug + Display + Copy + Sized> MutArrayView1<T> for Vec<T> {}
|
||||||
|
|
||||||
|
|||||||
@@ -283,9 +283,7 @@ mod tests {
|
|||||||
(vec![0, 1, 2, 3, 7, 8, 9], vec![4, 5, 6]),
|
(vec![0, 1, 2, 3, 7, 8, 9], vec![4, 5, 6]),
|
||||||
(vec![0, 1, 2, 3, 4, 5, 6], vec![7, 8, 9]),
|
(vec![0, 1, 2, 3, 4, 5, 6], vec![7, 8, 9]),
|
||||||
];
|
];
|
||||||
for ((train, test), (expected_train, expected_test)) in
|
for ((train, test), (expected_train, expected_test)) in k.split(&x).zip(expected) {
|
||||||
k.split(&x).into_iter().zip(expected)
|
|
||||||
{
|
|
||||||
assert_eq!(test, expected_test);
|
assert_eq!(test, expected_test);
|
||||||
assert_eq!(train, expected_train);
|
assert_eq!(train, expected_train);
|
||||||
}
|
}
|
||||||
@@ -307,9 +305,7 @@ mod tests {
|
|||||||
(vec![0, 1, 2, 3, 7, 8, 9], vec![4, 5, 6]),
|
(vec![0, 1, 2, 3, 7, 8, 9], vec![4, 5, 6]),
|
||||||
(vec![0, 1, 2, 3, 4, 5, 6], vec![7, 8, 9]),
|
(vec![0, 1, 2, 3, 4, 5, 6], vec![7, 8, 9]),
|
||||||
];
|
];
|
||||||
for ((train, test), (expected_train, expected_test)) in
|
for ((train, test), (expected_train, expected_test)) in k.split(&x).zip(expected) {
|
||||||
k.split(&x).into_iter().zip(expected)
|
|
||||||
{
|
|
||||||
assert_eq!(test.len(), expected_test.len());
|
assert_eq!(test.len(), expected_test.len());
|
||||||
assert_eq!(train.len(), expected_train.len());
|
assert_eq!(train.len(), expected_train.len());
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-9
@@ -83,7 +83,7 @@ where
|
|||||||
Matrix: Array2<T>,
|
Matrix: Array2<T>,
|
||||||
{
|
{
|
||||||
let csv_text = read_string_from_source(source)?;
|
let csv_text = read_string_from_source(source)?;
|
||||||
let rows: Vec<Vec<T>> = extract_row_vectors_from_csv_text::<T, RowVector, Matrix>(
|
let rows: Vec<Vec<T>> = extract_row_vectors_from_csv_text(
|
||||||
&csv_text,
|
&csv_text,
|
||||||
&definition,
|
&definition,
|
||||||
detect_row_format(&csv_text, &definition)?,
|
detect_row_format(&csv_text, &definition)?,
|
||||||
@@ -103,12 +103,7 @@ where
|
|||||||
|
|
||||||
/// Given a string containing the contents of a csv file, extract its value
|
/// Given a string containing the contents of a csv file, extract its value
|
||||||
/// into row-vectors.
|
/// into row-vectors.
|
||||||
fn extract_row_vectors_from_csv_text<
|
fn extract_row_vectors_from_csv_text<'a, T: Number + RealNumber + std::str::FromStr>(
|
||||||
'a,
|
|
||||||
T: Number + RealNumber + std::str::FromStr,
|
|
||||||
RowVector: Array1<T>,
|
|
||||||
Matrix: Array2<T>,
|
|
||||||
>(
|
|
||||||
csv_text: &'a str,
|
csv_text: &'a str,
|
||||||
definition: &'a CSVDefinition<'_>,
|
definition: &'a CSVDefinition<'_>,
|
||||||
row_format: CSVRowFormat<'_>,
|
row_format: CSVRowFormat<'_>,
|
||||||
@@ -305,12 +300,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
mod extract_row_vectors_from_csv_text {
|
mod extract_row_vectors_from_csv_text {
|
||||||
use super::super::{extract_row_vectors_from_csv_text, CSVDefinition, CSVRowFormat};
|
use super::super::{extract_row_vectors_from_csv_text, CSVDefinition, CSVRowFormat};
|
||||||
use crate::linalg::basic::matrix::DenseMatrix;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn read_default_csv() {
|
fn read_default_csv() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
extract_row_vectors_from_csv_text::<f64, Vec<_>, DenseMatrix<_>>(
|
extract_row_vectors_from_csv_text::<f64>(
|
||||||
"column 1, column 2, column3\n1.0,2.0,3.0\n4.0,5.0,6.0",
|
"column 1, column 2, column3\n1.0,2.0,3.0\n4.0,5.0,6.0",
|
||||||
&CSVDefinition::default(),
|
&CSVDefinition::default(),
|
||||||
CSVRowFormat {
|
CSVRowFormat {
|
||||||
|
|||||||
+55
-64
@@ -322,19 +322,26 @@ impl<'a, TX: Number + RealNumber, TY: Number + Ord, X: Array2<TX> + 'a, Y: Array
|
|||||||
let (n, _) = x.shape();
|
let (n, _) = x.shape();
|
||||||
let mut y_hat: Vec<TX> = Array1::zeros(n);
|
let mut y_hat: Vec<TX> = Array1::zeros(n);
|
||||||
|
|
||||||
|
let mut row = Vec::with_capacity(n);
|
||||||
for i in 0..n {
|
for i in 0..n {
|
||||||
let row_pred: TX =
|
row.clear();
|
||||||
self.predict_for_row(Vec::from_iterator(x.get_row(i).iterator(0).copied(), n));
|
row.extend(x.get_row(i).iterator(0).copied());
|
||||||
|
let row_pred: TX = self.predict_for_row(&row);
|
||||||
y_hat.set(i, row_pred);
|
y_hat.set(i, row_pred);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(y_hat)
|
Ok(y_hat)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn predict_for_row(&self, x: Vec<TX>) -> TX {
|
fn predict_for_row(&self, x: &[TX]) -> TX {
|
||||||
let mut f = self.b.unwrap();
|
let mut f = self.b.unwrap();
|
||||||
|
|
||||||
|
let xi: Vec<_> = x.iter().map(|e| e.to_f64().unwrap()).collect();
|
||||||
for i in 0..self.instances.as_ref().unwrap().len() {
|
for i in 0..self.instances.as_ref().unwrap().len() {
|
||||||
|
let xj: Vec<_> = self.instances.as_ref().unwrap()[i]
|
||||||
|
.iter()
|
||||||
|
.map(|e| e.to_f64().unwrap())
|
||||||
|
.collect();
|
||||||
f += self.w.as_ref().unwrap()[i]
|
f += self.w.as_ref().unwrap()[i]
|
||||||
* TX::from(
|
* TX::from(
|
||||||
self.parameters
|
self.parameters
|
||||||
@@ -343,13 +350,7 @@ impl<'a, TX: Number + RealNumber, TY: Number + Ord, X: Array2<TX> + 'a, Y: Array
|
|||||||
.kernel
|
.kernel
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.apply(
|
.apply(&xi, &xj)
|
||||||
&x.iter().map(|e| e.to_f64().unwrap()).collect(),
|
|
||||||
&self.instances.as_ref().unwrap()[i]
|
|
||||||
.iter()
|
|
||||||
.map(|e| e.to_f64().unwrap())
|
|
||||||
.collect(),
|
|
||||||
)
|
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -472,14 +473,12 @@ impl<'a, TX: Number + RealNumber, TY: Number + Ord, X: Array2<TX>, Y: Array1<TY>
|
|||||||
let tol = self.parameters.tol;
|
let tol = self.parameters.tol;
|
||||||
let good_enough = TX::from_i32(1000).unwrap();
|
let good_enough = TX::from_i32(1000).unwrap();
|
||||||
|
|
||||||
|
let mut x = Vec::with_capacity(n);
|
||||||
for _ in 0..self.parameters.epoch {
|
for _ in 0..self.parameters.epoch {
|
||||||
for i in self.permutate(n) {
|
for i in self.permutate(n) {
|
||||||
self.process(
|
x.clear();
|
||||||
i,
|
x.extend(self.x.get_row(i).iterator(0).take(n).copied());
|
||||||
Vec::from_iterator(self.x.get_row(i).iterator(0).copied(), n),
|
self.process(i, &x, *self.y.get(i), &mut cache);
|
||||||
*self.y.get(i),
|
|
||||||
&mut cache,
|
|
||||||
);
|
|
||||||
loop {
|
loop {
|
||||||
self.reprocess(tol, &mut cache);
|
self.reprocess(tol, &mut cache);
|
||||||
self.find_min_max_gradient();
|
self.find_min_max_gradient();
|
||||||
@@ -511,24 +510,17 @@ impl<'a, TX: Number + RealNumber, TY: Number + Ord, X: Array2<TX>, Y: Array1<TY>
|
|||||||
let mut cp = 0;
|
let mut cp = 0;
|
||||||
let mut cn = 0;
|
let mut cn = 0;
|
||||||
|
|
||||||
|
let mut x = Vec::with_capacity(n);
|
||||||
for i in self.permutate(n) {
|
for i in self.permutate(n) {
|
||||||
|
x.clear();
|
||||||
|
x.extend(self.x.get_row(i).iterator(0).take(n).copied());
|
||||||
if *self.y.get(i) == TY::one() && cp < few {
|
if *self.y.get(i) == TY::one() && cp < few {
|
||||||
if self.process(
|
if self.process(i, &x, *self.y.get(i), cache) {
|
||||||
i,
|
|
||||||
Vec::from_iterator(self.x.get_row(i).iterator(0).copied(), n),
|
|
||||||
*self.y.get(i),
|
|
||||||
cache,
|
|
||||||
) {
|
|
||||||
cp += 1;
|
cp += 1;
|
||||||
}
|
}
|
||||||
} else if *self.y.get(i) == TY::from(-1).unwrap()
|
} else if *self.y.get(i) == TY::from(-1).unwrap()
|
||||||
&& cn < few
|
&& cn < few
|
||||||
&& self.process(
|
&& self.process(i, &x, *self.y.get(i), cache)
|
||||||
i,
|
|
||||||
Vec::from_iterator(self.x.get_row(i).iterator(0).copied(), n),
|
|
||||||
*self.y.get(i),
|
|
||||||
cache,
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
cn += 1;
|
cn += 1;
|
||||||
}
|
}
|
||||||
@@ -539,7 +531,7 @@ impl<'a, TX: Number + RealNumber, TY: Number + Ord, X: Array2<TX>, Y: Array1<TY>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process(&mut self, i: usize, x: Vec<TX>, y: TY, cache: &mut Cache<TX, TY, X, Y>) -> bool {
|
fn process(&mut self, i: usize, x: &[TX], y: TY, cache: &mut Cache<TX, TY, X, Y>) -> bool {
|
||||||
for j in 0..self.sv.len() {
|
for j in 0..self.sv.len() {
|
||||||
if self.sv[j].index == i {
|
if self.sv[j].index == i {
|
||||||
return true;
|
return true;
|
||||||
@@ -551,15 +543,14 @@ impl<'a, TX: Number + RealNumber, TY: Number + Ord, X: Array2<TX>, Y: Array1<TY>
|
|||||||
let mut cache_values: Vec<((usize, usize), TX)> = Vec::new();
|
let mut cache_values: Vec<((usize, usize), TX)> = Vec::new();
|
||||||
|
|
||||||
for v in self.sv.iter() {
|
for v in self.sv.iter() {
|
||||||
|
let xi: Vec<_> = v.x.iter().map(|e| e.to_f64().unwrap()).collect();
|
||||||
|
let xj: Vec<_> = x.iter().map(|e| e.to_f64().unwrap()).collect();
|
||||||
let k = self
|
let k = self
|
||||||
.parameters
|
.parameters
|
||||||
.kernel
|
.kernel
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.apply(
|
.apply(&xi, &xj)
|
||||||
&v.x.iter().map(|e| e.to_f64().unwrap()).collect(),
|
|
||||||
&x.iter().map(|e| e.to_f64().unwrap()).collect(),
|
|
||||||
)
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
cache_values.push(((i, v.index), TX::from(k).unwrap()));
|
cache_values.push(((i, v.index), TX::from(k).unwrap()));
|
||||||
g -= v.alpha * k;
|
g -= v.alpha * k;
|
||||||
@@ -578,7 +569,7 @@ impl<'a, TX: Number + RealNumber, TY: Number + Ord, X: Array2<TX>, Y: Array1<TY>
|
|||||||
cache.insert(v.0, v.1.to_f64().unwrap());
|
cache.insert(v.0, v.1.to_f64().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
let x_f64 = x.iter().map(|e| e.to_f64().unwrap()).collect();
|
let x_f64: Vec<_> = x.iter().map(|e| e.to_f64().unwrap()).collect();
|
||||||
let k_v = self
|
let k_v = self
|
||||||
.parameters
|
.parameters
|
||||||
.kernel
|
.kernel
|
||||||
@@ -701,8 +692,10 @@ impl<'a, TX: Number + RealNumber, TY: Number + Ord, X: Array2<TX>, Y: Array1<TY>
|
|||||||
let km = sv1.k;
|
let km = sv1.k;
|
||||||
let gm = sv1.grad;
|
let gm = sv1.grad;
|
||||||
let mut best = 0f64;
|
let mut best = 0f64;
|
||||||
|
let xi: Vec<_> = sv1.x.iter().map(|e| e.to_f64().unwrap()).collect();
|
||||||
for i in 0..self.sv.len() {
|
for i in 0..self.sv.len() {
|
||||||
let v = &self.sv[i];
|
let v = &self.sv[i];
|
||||||
|
let xj: Vec<_> = v.x.iter().map(|e| e.to_f64().unwrap()).collect();
|
||||||
let z = v.grad - gm;
|
let z = v.grad - gm;
|
||||||
let k = cache.get(
|
let k = cache.get(
|
||||||
sv1,
|
sv1,
|
||||||
@@ -711,10 +704,7 @@ impl<'a, TX: Number + RealNumber, TY: Number + Ord, X: Array2<TX>, Y: Array1<TY>
|
|||||||
.kernel
|
.kernel
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.apply(
|
.apply(&xi, &xj)
|
||||||
&sv1.x.iter().map(|e| e.to_f64().unwrap()).collect(),
|
|
||||||
&v.x.iter().map(|e| e.to_f64().unwrap()).collect(),
|
|
||||||
)
|
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
);
|
);
|
||||||
let mut curv = km + v.k - 2f64 * k;
|
let mut curv = km + v.k - 2f64 * k;
|
||||||
@@ -732,6 +722,12 @@ impl<'a, TX: Number + RealNumber, TY: Number + Ord, X: Array2<TX>, Y: Array1<TY>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let xi: Vec<_> = self.sv[idx_1]
|
||||||
|
.x
|
||||||
|
.iter()
|
||||||
|
.map(|e| e.to_f64().unwrap())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
idx_2.map(|idx_2| {
|
idx_2.map(|idx_2| {
|
||||||
(
|
(
|
||||||
idx_1,
|
idx_1,
|
||||||
@@ -742,16 +738,12 @@ impl<'a, TX: Number + RealNumber, TY: Number + Ord, X: Array2<TX>, Y: Array1<TY>
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.apply(
|
.apply(
|
||||||
&self.sv[idx_1]
|
&xi,
|
||||||
.x
|
|
||||||
.iter()
|
|
||||||
.map(|e| e.to_f64().unwrap())
|
|
||||||
.collect(),
|
|
||||||
&self.sv[idx_2]
|
&self.sv[idx_2]
|
||||||
.x
|
.x
|
||||||
.iter()
|
.iter()
|
||||||
.map(|e| e.to_f64().unwrap())
|
.map(|e| e.to_f64().unwrap())
|
||||||
.collect(),
|
.collect::<Vec<_>>(),
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}),
|
}),
|
||||||
@@ -765,8 +757,11 @@ impl<'a, TX: Number + RealNumber, TY: Number + Ord, X: Array2<TX>, Y: Array1<TY>
|
|||||||
let km = sv2.k;
|
let km = sv2.k;
|
||||||
let gm = sv2.grad;
|
let gm = sv2.grad;
|
||||||
let mut best = 0f64;
|
let mut best = 0f64;
|
||||||
|
|
||||||
|
let xi: Vec<_> = sv2.x.iter().map(|e| e.to_f64().unwrap()).collect();
|
||||||
for i in 0..self.sv.len() {
|
for i in 0..self.sv.len() {
|
||||||
let v = &self.sv[i];
|
let v = &self.sv[i];
|
||||||
|
let xj: Vec<_> = v.x.iter().map(|e| e.to_f64().unwrap()).collect();
|
||||||
let z = gm - v.grad;
|
let z = gm - v.grad;
|
||||||
let k = cache.get(
|
let k = cache.get(
|
||||||
sv2,
|
sv2,
|
||||||
@@ -775,10 +770,7 @@ impl<'a, TX: Number + RealNumber, TY: Number + Ord, X: Array2<TX>, Y: Array1<TY>
|
|||||||
.kernel
|
.kernel
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.apply(
|
.apply(&xi, &xj)
|
||||||
&sv2.x.iter().map(|e| e.to_f64().unwrap()).collect(),
|
|
||||||
&v.x.iter().map(|e| e.to_f64().unwrap()).collect(),
|
|
||||||
)
|
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
);
|
);
|
||||||
let mut curv = km + v.k - 2f64 * k;
|
let mut curv = km + v.k - 2f64 * k;
|
||||||
@@ -797,6 +789,12 @@ impl<'a, TX: Number + RealNumber, TY: Number + Ord, X: Array2<TX>, Y: Array1<TY>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let xj: Vec<_> = self.sv[idx_2]
|
||||||
|
.x
|
||||||
|
.iter()
|
||||||
|
.map(|e| e.to_f64().unwrap())
|
||||||
|
.collect();
|
||||||
|
|
||||||
idx_1.map(|idx_1| {
|
idx_1.map(|idx_1| {
|
||||||
(
|
(
|
||||||
idx_1,
|
idx_1,
|
||||||
@@ -811,12 +809,8 @@ impl<'a, TX: Number + RealNumber, TY: Number + Ord, X: Array2<TX>, Y: Array1<TY>
|
|||||||
.x
|
.x
|
||||||
.iter()
|
.iter()
|
||||||
.map(|e| e.to_f64().unwrap())
|
.map(|e| e.to_f64().unwrap())
|
||||||
.collect(),
|
.collect::<Vec<_>>(),
|
||||||
&self.sv[idx_2]
|
&xj,
|
||||||
.x
|
|
||||||
.iter()
|
|
||||||
.map(|e| e.to_f64().unwrap())
|
|
||||||
.collect(),
|
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}),
|
}),
|
||||||
@@ -835,12 +829,12 @@ impl<'a, TX: Number + RealNumber, TY: Number + Ord, X: Array2<TX>, Y: Array1<TY>
|
|||||||
.x
|
.x
|
||||||
.iter()
|
.iter()
|
||||||
.map(|e| e.to_f64().unwrap())
|
.map(|e| e.to_f64().unwrap())
|
||||||
.collect(),
|
.collect::<Vec<_>>(),
|
||||||
&self.sv[idx_2]
|
&self.sv[idx_2]
|
||||||
.x
|
.x
|
||||||
.iter()
|
.iter()
|
||||||
.map(|e| e.to_f64().unwrap())
|
.map(|e| e.to_f64().unwrap())
|
||||||
.collect(),
|
.collect::<Vec<_>>(),
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)),
|
)),
|
||||||
@@ -895,7 +889,10 @@ impl<'a, TX: Number + RealNumber, TY: Number + Ord, X: Array2<TX>, Y: Array1<TY>
|
|||||||
self.sv[v1].alpha -= step.to_f64().unwrap();
|
self.sv[v1].alpha -= step.to_f64().unwrap();
|
||||||
self.sv[v2].alpha += step.to_f64().unwrap();
|
self.sv[v2].alpha += step.to_f64().unwrap();
|
||||||
|
|
||||||
|
let xi_v1: Vec<_> = self.sv[v1].x.iter().map(|e| e.to_f64().unwrap()).collect();
|
||||||
|
let xi_v2: Vec<_> = self.sv[v2].x.iter().map(|e| e.to_f64().unwrap()).collect();
|
||||||
for i in 0..self.sv.len() {
|
for i in 0..self.sv.len() {
|
||||||
|
let xj: Vec<_> = self.sv[i].x.iter().map(|e| e.to_f64().unwrap()).collect();
|
||||||
let k2 = cache.get(
|
let k2 = cache.get(
|
||||||
&self.sv[v2],
|
&self.sv[v2],
|
||||||
&self.sv[i],
|
&self.sv[i],
|
||||||
@@ -903,10 +900,7 @@ impl<'a, TX: Number + RealNumber, TY: Number + Ord, X: Array2<TX>, Y: Array1<TY>
|
|||||||
.kernel
|
.kernel
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.apply(
|
.apply(&xi_v2, &xj)
|
||||||
&self.sv[v2].x.iter().map(|e| e.to_f64().unwrap()).collect(),
|
|
||||||
&self.sv[i].x.iter().map(|e| e.to_f64().unwrap()).collect(),
|
|
||||||
)
|
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
);
|
);
|
||||||
let k1 = cache.get(
|
let k1 = cache.get(
|
||||||
@@ -916,10 +910,7 @@ impl<'a, TX: Number + RealNumber, TY: Number + Ord, X: Array2<TX>, Y: Array1<TY>
|
|||||||
.kernel
|
.kernel
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.apply(
|
.apply(&xi_v1, &xj)
|
||||||
&self.sv[v1].x.iter().map(|e| e.to_f64().unwrap()).collect(),
|
|
||||||
&self.sv[i].x.iter().map(|e| e.to_f64().unwrap()).collect(),
|
|
||||||
)
|
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
);
|
);
|
||||||
self.sv[i].grad -= step.to_f64().unwrap() * (k2 - k1);
|
self.sv[i].grad -= step.to_f64().unwrap() * (k2 - k1);
|
||||||
|
|||||||
+7
-9
@@ -248,19 +248,20 @@ impl<'a, T: Number + FloatNumber + PartialOrd, X: Array2<T>, Y: Array1<T>> SVR<'
|
|||||||
|
|
||||||
let mut y_hat: Vec<T> = Vec::<T>::zeros(n);
|
let mut y_hat: Vec<T> = Vec::<T>::zeros(n);
|
||||||
|
|
||||||
|
let mut x_i = Vec::with_capacity(n);
|
||||||
for i in 0..n {
|
for i in 0..n {
|
||||||
y_hat.set(
|
x_i.clear();
|
||||||
i,
|
x_i.extend(x.get_row(i).iterator(0).copied());
|
||||||
self.predict_for_row(Vec::from_iterator(x.get_row(i).iterator(0).copied(), n)),
|
y_hat.set(i, self.predict_for_row(&x_i));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(y_hat)
|
Ok(y_hat)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn predict_for_row(&self, x: Vec<T>) -> T {
|
pub(crate) fn predict_for_row(&self, x: &[T]) -> T {
|
||||||
let mut f = self.b;
|
let mut f = self.b;
|
||||||
|
|
||||||
|
let xi: Vec<_> = x.iter().map(|e| e.to_f64().unwrap()).collect();
|
||||||
for i in 0..self.instances.as_ref().unwrap().len() {
|
for i in 0..self.instances.as_ref().unwrap().len() {
|
||||||
f += self.w.as_ref().unwrap()[i]
|
f += self.w.as_ref().unwrap()[i]
|
||||||
* T::from(
|
* T::from(
|
||||||
@@ -270,10 +271,7 @@ impl<'a, T: Number + FloatNumber + PartialOrd, X: Array2<T>, Y: Array1<T>> SVR<'
|
|||||||
.kernel
|
.kernel
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.apply(
|
.apply(&xi, &self.instances.as_ref().unwrap()[i])
|
||||||
&x.iter().map(|e| e.to_f64().unwrap()).collect(),
|
|
||||||
&self.instances.as_ref().unwrap()[i],
|
|
||||||
)
|
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|||||||
Reference in New Issue
Block a user