实现了感知机模型,K最近邻模型,朴素贝叶斯模型

This commit is contained in:
2026-09-14 08:49:12 +08:00
commit 44fe496a21
19 changed files with 700 additions and 0 deletions
+146
View File
@@ -0,0 +1,146 @@
use ml_learn::{KNNModel, Model, NaiveBayesClassifier, Perceptron, TestDataSet, TrainDataset};
use ndarray::Array2;
#[test]
fn perceptron_fit_and_predict() {
// 线性可分数据:x1 + x2 > 2 为正类
let input_data = Array2::from_shape_vec((6, 2), vec![
2.0, 2.0, 3.0, 1.0, 2.0, 3.0, // "pos"
0.0, 0.0, 1.0, 0.0, 0.0, 1.0, // "neg"
]).unwrap();
let output_data = vec![
"pos".to_string(), "pos".to_string(), "pos".to_string(),
"neg".to_string(), "neg".to_string(), "neg".to_string(),
];
let train = TrainDataset { input_data, output_data };
let mut model = Perceptron::new(1.0, 1000);
model.fit(&train);
assert_eq!(model.score(&train), 1.0);
let test = TestDataSet {
input_data: Array2::from_shape_vec((2, 2), vec![4.0, 4.0, -1.0, 0.0]).unwrap(),
};
let result = model.predict(&test);
assert_eq!(result.output_data, vec!["pos".to_string(), "neg".to_string()]);
}
#[test]
fn knn_fit_and_predict() {
let input_data = Array2::from_shape_vec((6, 2), vec![
1.0, 1.0, 1.2, 0.8, 0.8, 1.2, // "A"
5.0, 5.0, 5.2, 4.8, 4.8, 5.2, // "B"
]).unwrap();
let output_data = vec![
"A".to_string(), "A".to_string(), "A".to_string(),
"B".to_string(), "B".to_string(), "B".to_string(),
];
let train = TrainDataset { input_data, output_data };
let mut model = KNNModel::new("base", 3);
model.fit(&train);
assert_eq!(model.score(&train), 1.0);
let test = TestDataSet {
input_data: Array2::from_shape_vec((2, 2), vec![1.1, 0.9, 5.1, 5.1]).unwrap(),
};
let result = model.predict(&test);
assert_eq!(result.output_data, vec!["A".to_string(), "B".to_string()]);
}
#[test]
fn gaussian_naive_bayes_fit_and_predict() {
// 两个类别,单一连续特征,分布明显分开
let input_data = Array2::from_shape_vec((6, 1), vec![
1.0, 1.2, 0.8, // "A"
5.0, 5.2, 4.8, // "B"
]).unwrap();
let output_data = vec![
"A".to_string(), "A".to_string(), "A".to_string(),
"B".to_string(), "B".to_string(), "B".to_string(),
];
let train = TrainDataset { input_data, output_data };
let mut clf = NaiveBayesClassifier::new();
clf.create_classifier(vec!["GNB"]);
clf.fit(&train);
assert_eq!(clf.score(&train), 1.0);
let test = TestDataSet {
input_data: Array2::from_shape_vec((2, 1), vec![1.1, 5.1]).unwrap(),
};
let result = clf.predict(&test);
assert_eq!(result.output_data, vec!["A".to_string(), "B".to_string()]);
}
#[test]
fn poisson_naive_bayes_fit_and_predict() {
// 计数特征:A 类 λ≈1,B 类 λ≈5
let input_data = Array2::from_shape_vec((6, 1), vec![
0.0, 1.0, 2.0, // "A"
4.0, 5.0, 6.0, // "B"
]).unwrap();
let output_data = vec![
"A".to_string(), "A".to_string(), "A".to_string(),
"B".to_string(), "B".to_string(), "B".to_string(),
];
let train = TrainDataset { input_data, output_data };
let mut clf = NaiveBayesClassifier::new();
clf.create_classifier(vec!["PoissonNB"]);
clf.fit(&train);
assert_eq!(clf.score(&train), 1.0);
let test = TestDataSet {
input_data: Array2::from_shape_vec((2, 1), vec![1.0, 5.0]).unwrap(),
};
let result = clf.predict(&test);
assert_eq!(result.output_data, vec!["A".to_string(), "B".to_string()]);
}
#[test]
fn bernoulli_naive_bayes_fit_and_predict() {
// 0/1 特征:A 类大概率为 1,B 类大概率为 0
let input_data = Array2::from_shape_vec((6, 1), vec![
1.0, 1.0, 1.0, // "A"
0.0, 0.0, 0.0, // "B"
]).unwrap();
let output_data = vec![
"A".to_string(), "A".to_string(), "A".to_string(),
"B".to_string(), "B".to_string(), "B".to_string(),
];
let train = TrainDataset { input_data, output_data };
let mut clf = NaiveBayesClassifier::new();
clf.create_classifier(vec!["BernoulliNB"]);
clf.fit(&train);
let test = TestDataSet {
input_data: Array2::from_shape_vec((2, 1), vec![1.0, 0.0]).unwrap(),
};
let result = clf.predict(&test);
assert_eq!(result.output_data, vec!["A".to_string(), "B".to_string()]);
}
#[test]
fn naive_bayes_mixed_layers() {
// 两个特征列分别用不同层:连续特征 GNB + 计数特征 PoissonNB
let input_data = Array2::from_shape_vec((6, 2), vec![
1.0, 0.0,
1.2, 1.0,
0.8, 2.0, // "A"
5.0, 4.0,
5.2, 5.0,
4.8, 6.0, // "B"
]).unwrap();
let output_data = vec![
"A".to_string(), "A".to_string(), "A".to_string(),
"B".to_string(), "B".to_string(), "B".to_string(),
];
let train = TrainDataset { input_data, output_data };
let mut clf = NaiveBayesClassifier::new();
clf.create_classifier(vec!["GNB", "PoissonNB"]);
clf.fit(&train);
assert_eq!(clf.score(&train), 1.0);
}