1use holos_core::{Classifier, Hypervector, ItemMemory, LevelEncoder, Rng};
7
8fn main() {
9 let csv = include_str!("data/digits.csv");
11 let mut rows: Vec<(Vec<f64>, String)> = Vec::new();
12 for line in csv.lines() {
13 if line.trim().is_empty() {
14 continue;
15 }
16 let mut nums: Vec<i64> = line.split(',').map(|t| t.trim().parse().unwrap()).collect();
17 let label = nums.pop().unwrap().to_string();
18 let features: Vec<f64> = nums.iter().map(|&v| v as f64).collect();
19 rows.push((features, label));
20 }
21
22 let mut rng = Rng::new(7);
24 for k in (1..rows.len()).rev() {
25 let j = (rng.next_u64() as usize) % (k + 1);
26 rows.swap(k, j);
27 }
28 let n_train = rows.len() * 7 / 10;
29 let (train, test) = rows.split_at(n_train);
30
31 let d = 10_000;
33 let enc = LevelEncoder::new(d, 64, 0.0, 16.0, 16, &mut rng);
34
35 let train_hv: Vec<Hypervector> = train.iter().map(|(f, _)| enc.encode(f)).collect();
36 let train_labels: Vec<&str> = train.iter().map(|(_, l)| l.as_str()).collect();
37 let test_hv: Vec<Hypervector> = test.iter().map(|(f, _)| enc.encode(f)).collect();
38 let test_labels: Vec<&str> = test.iter().map(|(_, l)| l.as_str()).collect();
39
40 let accuracy = |model: &ItemMemory| -> f64 {
41 let correct = test_hv
42 .iter()
43 .zip(&test_labels)
44 .filter(|(hv, &truth)| model.cleanup(hv).unwrap().0 == truth)
45 .count();
46 correct as f64 / test_hv.len() as f64
47 };
48
49 let mut clf = Classifier::new(d);
51 for (hv, &l) in train_hv.iter().zip(&train_labels) {
52 clf.train(hv, l);
53 }
54 let acc_oneshot = accuracy(&clf.build());
55
56 let mut clf2 = Classifier::new(d);
58 clf2.fit(&train_hv, &train_labels, 20);
59 let acc_retrained = accuracy(&clf2.build());
60
61 println!(
62 "Handwritten digits: {} train / {} test, 10 classes",
63 train.len(),
64 test.len()
65 );
66 println!("HDC one-shot : {:.1}%", 100.0 * acc_oneshot);
67 println!("HDC + retraining : {:.1}%", 100.0 * acc_retrained);
68}