12class simple_multi_classification {
14 double learning_rate_;
17 std::vector<std::vector<double>> predictors_;
18 std::vector<std::vector<double>> data_;
19 std::vector<double> labels_;
21 void verbose_acc_step_() {
22 std::vector<double> y_pred;
24 for (
int i = 0; i < this->data_.size(); i++) {
25 std::vector<double> class_probs(this->predictors_.size());
28 for (
int c = 0; c < this->predictors_.size(); c++) {
30 exp(std::inner_product(this->predictors_[c].begin(), this->predictors_[c].end(),
31 this->data_[i].begin(), 0.0) +
33 denom += class_probs[c];
36 for (
int c = 0; c < this->predictors_.size(); c++) {
37 class_probs[c] /= denom;
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);
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;
60 this->data_.resize(data.size(), std::vector<double>(data[0].size() - 1));
61 this->labels_.resize(data.size());
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();
68 std::random_device rd;
69 std::mt19937 gen(rd());
70 std::uniform_real_distribution<double> dist(-1.0, 1.0);
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) {
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_));
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_));
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));
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);
107 for (
int w = 0; w < this->data_[j].size(); w++) {
108 gradients[i][w] += diff * this->data_[j][w];
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();
121 std::cout <<
"Epoch: " << (epoch + 1) <<
": ";