From 750015b861646f16e57cd2129cfd6cf6f87708c6 Mon Sep 17 00:00:00 2001 From: Volodymyr Orlov Date: Tue, 22 Sep 2020 20:23:51 -0700 Subject: [PATCH] feat: + cluster metrics --- src/algorithm/neighbour/bbd_tree.rs | 13 ++- src/cluster/kmeans.rs | 24 ++++-- src/dataset/digits.rs | 67 +++++++++++++++ src/dataset/digits.xy | Bin 0 -> 467236 bytes src/dataset/mod.rs | 1 + src/linalg/mod.rs | 10 +++ src/linalg/naive/dense_matrix.rs | 59 +++++++++++++ src/linalg/nalgebra_bindings.rs | 27 ++++++ src/linalg/ndarray_bindings.rs | 27 ++++++ src/math/distance/euclidian.rs | 4 +- src/math/mod.rs | 1 + src/math/vector.rs | 40 +++++++++ src/metrics/cluster_hcv.rs | 54 ++++++++++++ src/metrics/cluster_helpers.rs | 127 ++++++++++++++++++++++++++++ src/metrics/mod.rs | 39 +++++++++ 15 files changed, 477 insertions(+), 16 deletions(-) create mode 100644 src/dataset/digits.rs create mode 100644 src/dataset/digits.xy create mode 100644 src/math/vector.rs create mode 100644 src/metrics/cluster_hcv.rs create mode 100644 src/metrics/cluster_helpers.rs diff --git a/src/algorithm/neighbour/bbd_tree.rs b/src/algorithm/neighbour/bbd_tree.rs index be3324a..163ebd8 100644 --- a/src/algorithm/neighbour/bbd_tree.rs +++ b/src/algorithm/neighbour/bbd_tree.rs @@ -71,11 +71,11 @@ impl BBDTree { ) -> T { let k = centroids.len(); - counts.iter_mut().for_each(|x| *x = 0); + counts.iter_mut().for_each(|v| *v = 0); let mut candidates = vec![0; k]; for i in 0..k { candidates[i] = i; - sums[i].iter_mut().for_each(|x| *x = T::zero()); + sums[i].iter_mut().for_each(|v| *v = T::zero()); } self.filter( @@ -124,7 +124,7 @@ impl BBDTree { if !BBDTree::prune( &self.nodes[node].center, &self.nodes[node].radius, - ¢roids, + centroids, closest, candidates[i], ) { @@ -135,7 +135,7 @@ impl BBDTree { // Recurse if there's at least two if newk > 1 { - let result = self.filter( + return self.filter( self.nodes[node].lower.unwrap(), centroids, &mut new_candidates, @@ -152,7 +152,6 @@ impl BBDTree { counts, membership, ); - return result; } } @@ -198,7 +197,7 @@ impl BBDTree { } } - return lhs >= T::two() * rhs; + lhs >= T::two() * rhs } fn build_node>(&mut self, data: &M, begin: usize, end: usize) -> usize { @@ -336,7 +335,7 @@ mod tests { use crate::linalg::naive::dense_matrix::DenseMatrix; #[test] - fn fit_predict_iris() { + fn bbdtree_iris() { let data = DenseMatrix::from_2d_array(&[ &[5.1, 3.5, 1.4, 0.2], &[4.9, 3.0, 1.4, 0.2], diff --git a/src/cluster/kmeans.rs b/src/cluster/kmeans.rs index f56ba57..dde450a 100644 --- a/src/cluster/kmeans.rs +++ b/src/cluster/kmeans.rs @@ -189,15 +189,18 @@ impl KMeans { /// Predict clusters for `x` /// * `x` - matrix with new data to transform of size _KxM_ , where _K_ is number of new samples and _M_ is number of features. pub fn predict>(&self, x: &M) -> Result { - let (n, _) = x.shape(); + let (n, m) = x.shape(); let mut result = M::zeros(1, n); + let mut row = vec![T::zero(); m]; + for i in 0..n { let mut min_dist = T::max_value(); let mut best_cluster = 0; for j in 0..self.k { - let dist = Euclidian::squared_distance(&x.get_row_as_vec(i), &self.centroids[j]); + x.copy_row_as_vec(i, &mut row); + let dist = Euclidian::squared_distance(&row, &self.centroids[j]); if dist < min_dist { min_dist = dist; best_cluster = j; @@ -211,19 +214,22 @@ impl KMeans { fn kmeans_plus_plus>(data: &M, k: usize) -> Vec { let mut rng = rand::thread_rng(); - let (n, _) = data.shape(); + let (n, m) = data.shape(); let mut y = vec![0; n]; let mut centroid = data.get_row_as_vec(rng.gen_range(0, n)); let mut d = vec![T::max_value(); n]; + let mut row = vec![T::zero(); m]; + // pick the next center 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 { // compute the distance between this sample and the current center - let dist = Euclidian::squared_distance(&data.get_row_as_vec(i), ¢roid); + data.copy_row_as_vec(i, &mut row); + let dist = Euclidian::squared_distance(&row, ¢roid); if dist < d[i] { d[i] = dist; @@ -237,20 +243,22 @@ impl KMeans { } let cutoff = T::from(rng.gen::()).unwrap() * sum; let mut cost = T::zero(); - let index = 0; - for index in 0..n { + let mut index = 0; + while index < n { cost = cost + d[index]; if cost >= cutoff { break; } + index += 1; } - centroid = data.get_row_as_vec(index); + data.copy_row_as_vec(index, &mut centroid); } for i in 0..n { + data.copy_row_as_vec(i, &mut row); // compute the distance between this sample and the current center - let dist = Euclidian::squared_distance(&data.get_row_as_vec(i), ¢roid); + let dist = Euclidian::squared_distance(&row, ¢roid); if dist < d[i] { d[i] = dist; diff --git a/src/dataset/digits.rs b/src/dataset/digits.rs new file mode 100644 index 0000000..10068ab --- /dev/null +++ b/src/dataset/digits.rs @@ -0,0 +1,67 @@ +//! # Optical Recognition of Handwritten Digits Data Set +//! +//! | Number of Instances | Number of Attributes | Missing Values? | Associated Tasks: | +//! |-|-|-|-| +//! | 1797 | 64 | No | Classification, Clusteing | +//! +//! [Digits dataset](https://archive.ics.uci.edu/ml/datasets/Optical+Recognition+of+Handwritten+Digits) contains normalized bitmaps of handwritten digits (0-9) from a preprinted form. +//! This multivariate dataset is frequently used to demonstrate various machine learning algorithms. +//! +//! All input attributes are integers in the range 0..16. +//! +use crate::dataset::deserialize_data; +use crate::dataset::Dataset; + +/// Get dataset +pub fn load_dataset() -> Dataset { + let (x, y, num_samples, num_features) = match deserialize_data(std::include_bytes!("digits.xy")) + { + Err(why) => panic!("Can't deserialize digits.xy. {}", why), + Ok((x, y, num_samples, num_features)) => (x, y, num_samples, num_features), + }; + + Dataset { + data: x, + target: y, + num_samples: num_samples, + num_features: num_features, + feature_names: vec![ + "sepal length (cm)", + "sepal width (cm)", + "petal length (cm)", + "petal width (cm)", + ] + .iter() + .map(|s| s.to_string()) + .collect(), + target_names: vec!["setosa", "versicolor", "virginica"] + .iter() + .map(|s| s.to_string()) + .collect(), + description: "Digits dataset: https://archive.ics.uci.edu/ml/datasets/Optical+Recognition+of+Handwritten+Digits".to_string(), + } +} + +#[cfg(test)] +mod tests { + + use super::super::*; + use super::*; + + #[test] + #[ignore] + fn refresh_digits_dataset() { + // run this test to generate digits.xy file. + let dataset = load_dataset(); + assert!(serialize_data(&dataset, "digits.xy").is_ok()); + } + + #[test] + fn digits_dataset() { + let dataset = load_dataset(); + assert_eq!(dataset.data.len(), 1797 * 64); + assert_eq!(dataset.target.len(), 1797); + assert_eq!(dataset.num_features, 64); + assert_eq!(dataset.num_samples, 1797); + } +} diff --git a/src/dataset/digits.xy b/src/dataset/digits.xy new file mode 100644 index 0000000000000000000000000000000000000000..0a6e7e944b329d943a6db2227a0aa99137f80bf3 GIT binary patch literal 467236 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�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 literal 0 HcmV?d00001 diff --git a/src/dataset/mod.rs b/src/dataset/mod.rs index b3a7972..8d7a4e2 100644 --- a/src/dataset/mod.rs +++ b/src/dataset/mod.rs @@ -4,6 +4,7 @@ pub mod boston; pub mod breast_cancer; pub mod diabetes; +pub mod digits; pub mod iris; use crate::math::num::RealNumber; diff --git a/src/linalg/mod.rs b/src/linalg/mod.rs index ec7b320..3937b47 100644 --- a/src/linalg/mod.rs +++ b/src/linalg/mod.rs @@ -110,10 +110,20 @@ pub trait BaseMatrix: Clone + Debug { /// * `row` - row number fn get_row_as_vec(&self, row: usize) -> Vec; + /// Copies a vector with elements of the `row`'th row into `result` + /// * `row` - row number + /// * `result` - receiver for the row + fn copy_row_as_vec(&self, row: usize, result: &mut Vec); + /// Get a vector with elements of the `col`'th column /// * `col` - column number fn get_col_as_vec(&self, col: usize) -> Vec; + /// Copies a vector with elements of the `col`'th column into `result` + /// * `col` - column number + /// * `result` - receiver for the col + fn copy_col_as_vec(&self, col: usize, result: &mut Vec); + /// Set an element at `col`, `row` to `x` fn set(&mut self, row: usize, col: usize, x: T); diff --git a/src/linalg/naive/dense_matrix.rs b/src/linalg/naive/dense_matrix.rs index c2d7928..ae9d1d2 100644 --- a/src/linalg/naive/dense_matrix.rs +++ b/src/linalg/naive/dense_matrix.rs @@ -54,6 +54,16 @@ pub struct DenseMatrix { values: Vec, } +/// Column-major, dense matrix. See [Simple Dense Matrix](../index.html). +#[derive(Debug)] +pub struct DenseMatrixIterator<'a, T: RealNumber> { + cur_c: usize, + cur_r: usize, + max_c: usize, + max_r: usize, + m: &'a DenseMatrix, +} + impl fmt::Display for DenseMatrix { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut rows: Vec> = Vec::new(); @@ -162,6 +172,36 @@ impl DenseMatrix { values: values, } } + + /// Creates new column vector (_1xN_ matrix) from a vector. + /// * `values` - values to initialize the matrix. + pub fn iter<'a>(&'a self) -> DenseMatrixIterator<'a, T> { + DenseMatrixIterator { + cur_c: 0, + cur_r: 0, + max_c: self.ncols, + max_r: self.nrows, + m: &self, + } + } +} + +impl<'a, T: RealNumber> Iterator for DenseMatrixIterator<'a, T> { + type Item = T; + + fn next(&mut self) -> Option { + if self.cur_r * self.max_c + self.cur_c >= self.max_c * self.max_r { + None + } else { + let v = self.m.get(self.cur_r, self.cur_c); + self.cur_c += 1; + if self.cur_c >= self.max_c { + self.cur_c = 0; + self.cur_r += 1; + } + Some(v) + } + } } impl<'de, T: RealNumber + fmt::Debug + Deserialize<'de>> Deserialize<'de> for DenseMatrix { @@ -339,6 +379,12 @@ impl BaseMatrix for DenseMatrix { result } + fn copy_row_as_vec(&self, row: usize, result: &mut Vec) { + for c in 0..self.ncols { + result[c] = self.get(row, c); + } + } + fn get_col_as_vec(&self, col: usize) -> Vec { let mut result = vec![T::zero(); self.nrows]; for r in 0..self.nrows { @@ -347,6 +393,12 @@ impl BaseMatrix for DenseMatrix { result } + fn copy_col_as_vec(&self, col: usize, result: &mut Vec) { + for r in 0..self.nrows { + result[r] = self.get(r, col); + } + } + fn set(&mut self, row: usize, col: usize, x: T) { self.values[col * self.nrows + row] = x; } @@ -852,6 +904,13 @@ mod tests { ); } + #[test] + fn iter() { + let vec = vec![1., 2., 3., 4., 5., 6.]; + let m = DenseMatrix::from_array(3, 2, &vec); + assert_eq!(vec, m.iter().collect::>()); + } + #[test] fn v_stack() { let a = DenseMatrix::from_2d_array(&[&[1., 2., 3.], &[4., 5., 6.], &[7., 8., 9.]]); diff --git a/src/linalg/nalgebra_bindings.rs b/src/linalg/nalgebra_bindings.rs index cf9d358..5e52d14 100644 --- a/src/linalg/nalgebra_bindings.rs +++ b/src/linalg/nalgebra_bindings.rs @@ -102,10 +102,26 @@ impl) { + let mut r = 0; + for e in self.row(row).iter() { + result[r] = *e; + r += 1; + } + } + fn get_col_as_vec(&self, col: usize) -> Vec { self.column(col).iter().map(|v| *v).collect() } + fn copy_col_as_vec(&self, col: usize, result: &mut Vec) { + let mut r = 0; + for e in self.column(col).iter() { + result[r] = *e; + r += 1; + } + } + fn set(&mut self, row: usize, col: usize, x: T) { *self.get_mut((row, col)).unwrap() = x; } @@ -563,6 +579,17 @@ mod tests { assert_eq!(m.get_col_as_vec(1), vec!(2., 5., 8.)); } + #[test] + fn copy_row_col_as_vec() { + let m = DMatrix::from_row_slice(3, 3, &[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]); + let mut v = vec![0f32; 3]; + + m.copy_row_as_vec(1, &mut v); + assert_eq!(v, vec!(4., 5., 6.)); + m.copy_col_as_vec(1, &mut v); + assert_eq!(v, vec!(2., 5., 8.)); + } + #[test] fn element_add_sub_mul_div() { let mut m = DMatrix::from_row_slice(2, 2, &[1.0, 2.0, 3.0, 4.0]); diff --git a/src/linalg/ndarray_bindings.rs b/src/linalg/ndarray_bindings.rs index 890550c..c6324eb 100644 --- a/src/linalg/ndarray_bindings.rs +++ b/src/linalg/ndarray_bindings.rs @@ -109,10 +109,26 @@ impl) { + let mut r = 0; + for e in self.row(row).iter() { + result[r] = *e; + r += 1; + } + } + fn get_col_as_vec(&self, col: usize) -> Vec { self.column(col).to_vec() } + fn copy_col_as_vec(&self, col: usize, result: &mut Vec) { + let mut r = 0; + for e in self.column(col).iter() { + result[r] = *e; + r += 1; + } + } + fn set(&mut self, row: usize, col: usize, x: T) { self[[row, col]] = x; } @@ -669,6 +685,17 @@ mod tests { assert_eq!(res, vec![2., 5., 8.]); } + #[test] + fn copy_row_col_as_vec() { + let m = arr2(&[[1., 2., 3.], [4., 5., 6.], [7., 8., 9.]]); + let mut v = vec![0f32; 3]; + + m.copy_row_as_vec(1, &mut v); + assert_eq!(v, vec!(4., 5., 6.)); + m.copy_col_as_vec(1, &mut v); + assert_eq!(v, vec!(2., 5., 8.)); + } + #[test] fn col_mean() { let a = arr2(&[[1., 2., 3.], [4., 5., 6.], [7., 8., 9.]]); diff --git a/src/math/distance/euclidian.rs b/src/math/distance/euclidian.rs index 42688c6..4ec0ad0 100644 --- a/src/math/distance/euclidian.rs +++ b/src/math/distance/euclidian.rs @@ -29,6 +29,7 @@ use super::Distance; pub struct Euclidian {} impl Euclidian { + #[inline] pub(crate) fn squared_distance(x: &Vec, y: &Vec) -> T { if x.len() != y.len() { panic!("Input vector sizes are different."); @@ -36,7 +37,8 @@ impl Euclidian { let mut sum = T::zero(); for i in 0..x.len() { - sum = sum + (x[i] - y[i]).powf(T::two()); + let d = x[i] - y[i]; + sum = sum + d * d; } sum diff --git a/src/math/mod.rs b/src/math/mod.rs index 7093dd7..e7e6467 100644 --- a/src/math/mod.rs +++ b/src/math/mod.rs @@ -1,3 +1,4 @@ /// Multitude of distance metrics are defined here pub mod distance; pub mod num; +pub(crate) mod vector; diff --git a/src/math/vector.rs b/src/math/vector.rs new file mode 100644 index 0000000..accfed6 --- /dev/null +++ b/src/math/vector.rs @@ -0,0 +1,40 @@ +use crate::math::num::RealNumber; +use std::collections::HashMap; + +pub trait RealNumberVector { + fn unique(&self) -> (Vec, Vec); +} + +impl RealNumberVector for Vec { + fn unique(&self) -> (Vec, Vec) { + let mut unique = self.clone(); + unique.sort_by(|a, b| a.partial_cmp(b).unwrap()); + unique.dedup(); + + let mut index = HashMap::with_capacity(unique.len()); + for (i, u) in unique.iter().enumerate() { + index.insert(u.to_i64().unwrap(), i); + } + + let mut unique_index = Vec::with_capacity(self.len()); + for e in self { + unique_index.push(index[&e.to_i64().unwrap()]); + } + + (unique, unique_index) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn unique() { + let v1 = vec![0.0, 0.0, 1.0, 1.0, 2.0, 0.0, 4.0]; + assert_eq!( + (vec!(0.0, 1.0, 2.0, 4.0), vec!(0, 0, 1, 1, 2, 0, 3)), + v1.unique() + ); + } +} diff --git a/src/metrics/cluster_hcv.rs b/src/metrics/cluster_hcv.rs new file mode 100644 index 0000000..e1b112e --- /dev/null +++ b/src/metrics/cluster_hcv.rs @@ -0,0 +1,54 @@ +use serde::{Deserialize, Serialize}; + +use crate::linalg::BaseVector; +use crate::math::num::RealNumber; +use crate::metrics::cluster_helpers::*; + +#[derive(Serialize, Deserialize, Debug)] +/// Mean Absolute Error +pub struct HCVScore {} + +impl HCVScore { + /// Computes mean absolute error + /// * `y_true` - Ground truth (correct) target values. + /// * `y_pred` - Estimated target values. + pub fn get_score>( + &self, + labels_true: &V, + labels_pred: &V, + ) -> (T, T, T) { + let labels_true = labels_true.to_vec(); + let labels_pred = labels_pred.to_vec(); + let entropy_c = entropy(&labels_true); + let entropy_k = entropy(&labels_pred); + let contingency = contingency_matrix(&labels_true, &labels_pred); + let mi: T = mutual_info_score(&contingency); + + let homogeneity = entropy_c.map(|e| mi / e).unwrap_or(T::one()); + let completeness = entropy_k.map(|e| mi / e).unwrap_or(T::one()); + + let v_measure_score = if homogeneity + completeness == T::zero() { + T::zero() + } else { + T::two() * homogeneity * completeness / (T::one() * homogeneity + completeness) + }; + + (homogeneity, completeness, v_measure_score) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn homogeneity_score() { + let v1 = vec![0.0, 0.0, 1.0, 1.0, 2.0, 0.0, 4.0]; + let v2 = vec![1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0]; + let scores = HCVScore {}.get_score(&v1, &v2); + + assert!((0.2548f32 - scores.0).abs() < 1e-4); + assert!((0.5440f32 - scores.1).abs() < 1e-4); + assert!((0.3471f32 - scores.2).abs() < 1e-4); + } +} diff --git a/src/metrics/cluster_helpers.rs b/src/metrics/cluster_helpers.rs new file mode 100644 index 0000000..3086315 --- /dev/null +++ b/src/metrics/cluster_helpers.rs @@ -0,0 +1,127 @@ +use std::collections::HashMap; + +use crate::math::num::RealNumber; +use crate::math::vector::RealNumberVector; + +pub fn contingency_matrix( + labels_true: &Vec, + labels_pred: &Vec, +) -> Vec> { + let (classes, class_idx) = labels_true.unique(); + let (clusters, cluster_idx) = labels_pred.unique(); + + let mut contingency_matrix = Vec::with_capacity(classes.len()); + + for _ in 0..classes.len() { + contingency_matrix.push(vec![0; clusters.len()]); + } + + for i in 0..class_idx.len() { + contingency_matrix[class_idx[i]][cluster_idx[i]] += 1; + } + + contingency_matrix +} + +pub fn entropy(data: &Vec) -> Option { + let mut bincounts = HashMap::with_capacity(data.len()); + + for e in data.iter() { + let k = e.to_i64().unwrap(); + bincounts.insert(k, bincounts.get(&k).unwrap_or(&0) + 1); + } + + let mut entropy = T::zero(); + let sum = T::from_usize(bincounts.values().sum()).unwrap(); + + for &c in bincounts.values() { + if c > 0 { + let pi = T::from_usize(c).unwrap(); + entropy = entropy - (pi / sum) * (pi.ln() - sum.ln()); + } + } + + Some(entropy) +} + +pub fn mutual_info_score(contingency: &Vec>) -> T { + let mut contingency_sum = 0; + let mut pi = vec![0; contingency.len()]; + let mut pj = vec![0; contingency[0].len()]; + let (mut nzx, mut nzy, mut nz_val) = (Vec::new(), Vec::new(), Vec::new()); + + for r in 0..contingency.len() { + for c in 0..contingency[0].len() { + contingency_sum += contingency[r][c]; + pi[r] += contingency[r][c]; + pj[c] += contingency[r][c]; + if contingency[r][c] > 0 { + nzx.push(r); + nzy.push(c); + nz_val.push(contingency[r][c]); + } + } + } + + let contingency_sum = T::from_usize(contingency_sum).unwrap(); + let contingency_sum_ln = contingency_sum.ln(); + let pi_sum_l = T::from_usize(pi.iter().sum()).unwrap().ln(); + let pj_sum_l = T::from_usize(pj.iter().sum()).unwrap().ln(); + + let log_contingency_nm: Vec = nz_val + .iter() + .map(|v| T::from_usize(*v).unwrap().ln()) + .collect(); + let contingency_nm: Vec = nz_val + .iter() + .map(|v| T::from_usize(*v).unwrap() / contingency_sum) + .collect(); + let outer: Vec = nzx + .iter() + .zip(nzy.iter()) + .map(|(&x, &y)| pi[x] * pj[y]) + .collect(); + let log_outer: Vec = outer + .iter() + .map(|&o| -T::from_usize(o).unwrap().ln() + pi_sum_l + pj_sum_l) + .collect(); + + let mut result = T::zero(); + + for i in 0..log_outer.len() { + result = result + + ((contingency_nm[i] * (log_contingency_nm[i] - contingency_sum_ln)) + + contingency_nm[i] * log_outer[i]) + } + + result.max(T::zero()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn contingency_matrix_test() { + let v1 = vec![0.0, 0.0, 1.0, 1.0, 2.0, 0.0, 4.0]; + let v2 = vec![1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0]; + + println!("{:?}", contingency_matrix(&v1, &v2)); + } + + #[test] + fn entropy_test() { + let v1 = vec![0.0, 0.0, 1.0, 1.0, 2.0, 0.0, 4.0]; + + println!("{:?}", entropy(&v1)); + } + + #[test] + fn mutual_info_score_test() { + let v1 = vec![0.0, 0.0, 1.0, 1.0, 2.0, 0.0, 4.0]; + let v2 = vec![1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0]; + let s: f32 = mutual_info_score(&contingency_matrix(&v1, &v2)); + + println!("{}", s); + } +} diff --git a/src/metrics/mod.rs b/src/metrics/mod.rs index 148f271..821b3f1 100644 --- a/src/metrics/mod.rs +++ b/src/metrics/mod.rs @@ -54,6 +54,8 @@ pub mod accuracy; /// Computes Area Under the Receiver Operating Characteristic Curve (ROC AUC) from prediction scores. pub mod auc; +pub mod cluster_hcv; +pub(crate) mod cluster_helpers; /// F1 score, also known as balanced F-score or F-measure. pub mod f1; /// Mean absolute error regression loss. @@ -76,6 +78,9 @@ pub struct ClassificationMetrics {} /// Metrics for regression models. pub struct RegressionMetrics {} +/// Cluster metrics. +pub struct ClusterMetrics {} + impl ClassificationMetrics { /// Accuracy score, see [accuracy](accuracy/index.html). pub fn accuracy() -> accuracy::Accuracy { @@ -120,6 +125,13 @@ impl RegressionMetrics { } } +impl ClusterMetrics { + /// Mean squared error, see [mean squared error](mean_squared_error/index.html). + pub fn hcv_score() -> cluster_hcv::HCVScore { + cluster_hcv::HCVScore {} + } +} + /// Function that calculated accuracy score, see [accuracy](accuracy/index.html). /// * `y_true` - cround truth (correct) labels /// * `y_pred` - predicted labels, as returned by a classifier. @@ -175,3 +187,30 @@ pub fn mean_absolute_error>(y_true: &V, y_pred: pub fn r2>(y_true: &V, y_pred: &V) -> T { RegressionMetrics::r2().get_score(y_true, y_pred) } + +/// Computes R2 score, see [R2](r2/index.html). +/// * `y_true` - Ground truth (correct) target values. +/// * `y_pred` - Estimated target values. +pub fn homogeneity_score>(labels_true: &V, labels_pred: &V) -> T { + ClusterMetrics::hcv_score() + .get_score(labels_true, labels_pred) + .0 +} + +/// Computes R2 score, see [R2](r2/index.html). +/// * `y_true` - Ground truth (correct) target values. +/// * `y_pred` - Estimated target values. +pub fn completeness_score>(labels_true: &V, labels_pred: &V) -> T { + ClusterMetrics::hcv_score() + .get_score(labels_true, labels_pred) + .1 +} + +/// Computes R2 score, see [R2](r2/index.html). +/// * `y_true` - Ground truth (correct) target values. +/// * `y_pred` - Estimated target values. +pub fn v_measure_score>(labels_true: &V, labels_pred: &V) -> T { + ClusterMetrics::hcv_score() + .get_score(labels_true, labels_pred) + .2 +}