/
linear-model.cc
88 lines (72 loc) · 2.59 KB
/
linear-model.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include "linear-model.h"
#include <cassert>
#include <tuple>
namespace ml {
namespace {
Vector linear_hypothesis(const Ref<const Matrix> &X,
const Ref<const Vector> &theta, double bias) {
return X * theta + Vector::Ones(X.rows()) * bias;
}
Vector logistic_hypothesis(const Ref<const Matrix> &X,
const Ref<const Vector> &theta, double bias) {
return sigmoid(linear_hypothesis(X, theta, bias));
}
template <typename H>
std::tuple<Vector, double>
minimize_mean_squared_error(const Ref<const Matrix> &X,
const Ref<const Vector> &y, const double alpha,
const H &hypothesis) {
assert(X.rows() == y.rows());
Vector theta = Vector::Random(X.cols());
double bias = 0.0;
double previous_error;
double current_error = mean_squared_error(hypothesis(X, theta, bias), y);
const auto X_transpose = X.transpose();
do {
previous_error = current_error;
const auto h = hypothesis(X, theta, bias);
const auto diff = X_transpose * (h - y);
theta -= alpha * diff;
current_error = mean_squared_error(hypothesis(X, theta, bias), y);
} while (!about_equal(previous_error, current_error)); // convergence
return std::make_tuple(theta, bias);
}
}
LinearRegression::LinearRegression(double alpha)
: _is_fitted(false), _alpha(alpha) {}
void LinearRegression::fit(const Ref<const Matrix> &X,
const Ref<const Vector> &y) {
assert(X.rows() == y.rows());
_is_fitted = true;
auto result = minimize_mean_squared_error(X, y, _alpha, linear_hypothesis);
_theta = std::get<0>(result);
_bias = std::get<1>(result);
}
Vector LinearRegression::predict(const Ref<const Matrix> &X) const {
assert(_is_fitted);
return linear_hypothesis(X, _theta, _bias);
}
const Ref<const Vector> LinearRegression::coefficients() const {
assert(_is_fitted);
return _theta;
}
LogisticRegression::LogisticRegression(double alpha)
: _is_fitted(false), _alpha(alpha) {}
void LogisticRegression::fit(const Ref<const Matrix> &X,
const Ref<const IVector> &y) {
assert(X.rows() == y.rows());
_is_fitted = true;
auto result = minimize_mean_squared_error(X, y.cast<double>(), _alpha,
logistic_hypothesis);
_theta = std::get<0>(result);
_bias = std::get<1>(result);
}
Vector LogisticRegression::predict(const Ref<const Matrix> &X) const {
assert(_is_fitted);
return logistic_hypothesis(X, _theta, _bias);
}
const Ref<const Vector> LogisticRegression::coefficients() const {
assert(_is_fitted);
return _theta;
}
}