AlgoPlus v0.1.0
Loading...
Searching...
No Matches
simple_multiclass.h
1#ifndef SIMPLE_MULTICLASS
2#define SIMPLE_MULTICLASS
3
4#ifdef __cplusplus
5#include <cassert>
6#include <iostream>
7#include <random>
8#include <vector>
9#include "../../metrics/metrics.h"
10#endif
11
12class simple_multi_classification {
13 private:
14 double learning_rate_;
15 double bias_;
16 int epochs_;
17 std::vector<std::vector<double>> predictors_;
18 std::vector<std::vector<double>> data_;
19 std::vector<double> labels_;
20
21 void verbose_acc_step_() {
22 std::vector<double> y_pred;
23
24 for (int i = 0; i < this->data_.size(); i++) {
25 std::vector<double> class_probs(this->predictors_.size());
26
27 double denom = 0.0;
28 for (int c = 0; c < this->predictors_.size(); c++) {
29 class_probs[c] =
30 exp(std::inner_product(this->predictors_[c].begin(), this->predictors_[c].end(),
31 this->data_[i].begin(), 0.0) +
32 this->bias_);
33 denom += class_probs[c];
34 }
35
36 for (int c = 0; c < this->predictors_.size(); c++) {
37 class_probs[c] /= denom;
38 }
39
40 int pred_class = std::distance(
41 class_probs.begin(), std::max_element(class_probs.begin(), class_probs.end()));
42 y_pred.push_back(pred_class);
43 }
44
45 std::cout << "Accuracy: " << metrics::accuracy_score(this->labels_, y_pred)
46 << " | F1 Score: " << metrics::f1_score(this->labels_, y_pred)
47 << " | Recall: " << metrics::recall(this->labels_, y_pred)
48 << " | Precision: " << metrics::precision(this->labels_, y_pred) << '\n';
49 }
50
51 public:
52 explicit simple_multi_classification(const std::vector<std::vector<double>> data,
53 const int num_classes = 2, const double lr = 0.001,
54 const double bias = 0.001, const int epochs = 10) {
55 assert(!data.empty());
56 this->learning_rate_ = lr;
57 this->epochs_ = epochs;
58 this->bias_ = bias;
59
60 this->data_.resize(data.size(), std::vector<double>(data[0].size() - 1));
61 this->labels_.resize(data.size());
62
63 for (size_t i = 0; i < data.size(); i++) {
64 std::copy(data[i].begin(), data[i].end() - 1, this->data_[i].begin());
65 this->labels_[i] = data[i].back();
66 }
67
68 std::random_device rd;
69 std::mt19937 gen(rd());
70 std::uniform_real_distribution<double> dist(-1.0, 1.0);
71
72 this->predictors_ = std::vector<std::vector<double>>(
73 num_classes, std::vector<double>(this->data_[0].size() - 1));
74 for (auto& weights : this->predictors_) {
75 for (double& weight : weights) {
76 weight = dist(gen);
77 }
78 }
79 }
80
81 inline void fit() {
82 auto phi__ = [&](int class_, int j) -> double {
83 double nom = std::exp(std::inner_product(this->predictors_[class_].begin(),
84 this->predictors_[class_].end(),
85 this->data_[j].begin(), this->bias_));
86
87 double denom = 0.0;
88 for (size_t i = 0; i < this->predictors_.size(); i++) {
89 denom += std::exp(std::inner_product(this->predictors_[i].begin(),
90 this->predictors_[i].end(),
91 this->data_[j].begin(), this->bias_));
92 }
93
94 return nom / denom;
95 };
96
97 for (int epoch = 0; epoch < this->epochs_; epoch++) {
98 std::vector<std::vector<double>> gradients(
99 this->predictors_.size(), std::vector<double>(this->data_[0].size(), 0.0));
100
101 for (int j = 0; j < this->data_.size(); j++) {
102 int true_class = static_cast<int>(this->labels_[j]);
103 for (int i = 0; i < this->predictors_.size(); i++) {
104 double phi_ = phi__(i, j);
105 double diff = phi_ - (true_class == i ? 1.0 : 0.0);
106
107 for (int w = 0; w < this->data_[j].size(); w++) {
108 gradients[i][w] += diff * this->data_[j][w];
109 }
110 }
111 }
112
113 // perform stochastic gradient descent
114 for (int i = 0; i < this->predictors_.size(); i++) {
115 for (int w = 0; w < this->data_[0].size(); w++) {
116 this->predictors_[i][w] -=
117 this->learning_rate_ * gradients[i][w] / this->data_.size();
118 }
119 }
120
121 std::cout << "Epoch: " << (epoch + 1) << ": ";
122 verbose_acc_step_();
123 }
124 }
125};
126
127#endif
double f1_score(const std::vector< double > &y, const std::vector< double > &y_pred)
f1 score function: [2 * precision * recall / precision + recall]
Definition metrics.h:99
double accuracy_score(const std::vector< double > &y, const std::vector< double > &y_pred)
accuracy score function[(tp + tn) / (tp + tn + fp + fn)]
Definition metrics.h:81
double recall(const std::vector< double > &y, const std::vector< double > &y_pred)
recall function[tp / tp + fn]
Definition metrics.h:72
double precision(const std::vector< double > &y, const std::vector< double > &y_pred)
precision function[tp / tp + fp]
Definition metrics.h:90