Cpp ML Library  1.0.0
A library of Machine Learning Algorithmns seen from the Udemy course Machine Learning A to Z.
PolynomialRegression.hpp
Go to the documentation of this file.
1 #ifndef POLYNOMIAL_REGRESSION_HPP
2 #define POLYNOMIAL_REGRESSION_HPP
3 
4 #include <vector>
5 #include <cmath>
6 #include <stdexcept>
7 #include <algorithm>
8 #include <numeric>
9 
20 public:
26  PolynomialRegression(int degree, double regularizationParameter = 0.0)
27  : degree_(degree), lambda_(regularizationParameter) {
28  if (degree_ < 0) {
29  throw std::invalid_argument("Degree of the polynomial must be non-negative.");
30  }
31  if (lambda_ < 0.0) {
32  throw std::invalid_argument("Regularization parameter must be non-negative.");
33  }
34  }
35 
41  void train(const std::vector<double>& x, const std::vector<double>& y) {
42  if (x.size() != y.size()) {
43  throw std::invalid_argument("Feature and target vectors must have the same length.");
44  }
45  if (x.empty()) {
46  throw std::invalid_argument("Input vectors must not be empty.");
47  }
48  if (x.size() <= static_cast<size_t>(degree_)) {
49  throw std::invalid_argument("Number of data points must be greater than the polynomial degree.");
50  }
51  computeCoefficients(x, y);
52  }
53 
59  double predict(double x) const {
60  // Use Horner's method for efficient polynomial evaluation
61  double result = coefficients_.back();
62  for (int i = coefficients_.size() - 2; i >= 0; --i) {
63  result = result * x + coefficients_[i];
64  }
65  return result;
66  }
67 
72  std::vector<double> getCoefficients() const {
73  return coefficients_;
74  }
75 
76 private:
77  int degree_;
78  double lambda_;
79  std::vector<double> coefficients_;
80 
86  void computeCoefficients(const std::vector<double>& x, const std::vector<double>& y) {
87  size_t n = x.size();
88  int m = degree_ + 1;
89 
90  // Precompute powers of x
91  std::vector<std::vector<double>> X(n, std::vector<double>(m));
92  for (size_t i = 0; i < n; ++i) {
93  X[i][0] = 1.0;
94  for (int j = 1; j < m; ++j) {
95  X[i][j] = X[i][j - 1] * x[i];
96  }
97  }
98 
99  // Construct matrices for normal equations: (X^T X + lambda * I) * w = X^T y
100  std::vector<std::vector<double>> XtX(m, std::vector<double>(m, 0.0));
101  std::vector<double> Xty(m, 0.0);
102 
103  for (int i = 0; i < m; ++i) {
104  for (size_t k = 0; k < n; ++k) {
105  Xty[i] += X[k][i] * y[k];
106  }
107  for (int j = i; j < m; ++j) {
108  for (size_t k = 0; k < n; ++k) {
109  XtX[i][j] += X[k][i] * X[k][j];
110  }
111  XtX[j][i] = XtX[i][j]; // Symmetric matrix
112  }
113  // Add regularization term
114  if (i > 0) { // Do not regularize bias term
115  XtX[i][i] += lambda_;
116  }
117  }
118 
119  // Solve the system using a more stable method (e.g., Cholesky decomposition)
120  coefficients_ = solveLinearSystem(XtX, Xty);
121  }
122 
129  std::vector<double> solveLinearSystem(const std::vector<std::vector<double>>& A, const std::vector<double>& b) {
130  int n = A.size();
131  std::vector<std::vector<double>> L(n, std::vector<double>(n, 0.0));
132 
133  // Cholesky decomposition: A = L * L^T
134  for (int i = 0; i < n; ++i) {
135  for (int k = 0; k <= i; ++k) {
136  double sum = 0.0;
137  for (int j = 0; j < k; ++j) {
138  sum += L[i][j] * L[k][j];
139  }
140  if (i == k) {
141  double val = A[i][i] - sum;
142  if (val <= 0.0) {
143  throw std::runtime_error("Matrix is not positive-definite.");
144  }
145  L[i][k] = std::sqrt(val);
146  } else {
147  L[i][k] = (A[i][k] - sum) / L[k][k];
148  }
149  }
150  }
151 
152  // Solve L * y = b
153  std::vector<double> y(n);
154  for (int i = 0; i < n; ++i) {
155  double sum = 0.0;
156  for (int k = 0; k < i; ++k) {
157  sum += L[i][k] * y[k];
158  }
159  y[i] = (b[i] - sum) / L[i][i];
160  }
161 
162  // Solve L^T * x = y
163  std::vector<double> x(n);
164  for (int i = n - 1; i >= 0; --i) {
165  double sum = 0.0;
166  for (int k = i + 1; k < n; ++k) {
167  sum += L[k][i] * x[k];
168  }
169  x[i] = (y[i] - sum) / L[i][i];
170  }
171 
172  return x;
173  }
174 };
175 
176 #endif // POLYNOMIAL_REGRESSION_HPP
Polynomial Regression model for fitting polynomial curves.
Definition: PolynomialRegression.hpp:19
std::vector< double > getCoefficients() const
Get the coefficients of the fitted polynomial.
Definition: PolynomialRegression.hpp:72
PolynomialRegression(int degree, double regularizationParameter=0.0)
Constructor initializing the polynomial degree.
Definition: PolynomialRegression.hpp:26
void train(const std::vector< double > &x, const std::vector< double > &y)
Train the model using features and target values.
Definition: PolynomialRegression.hpp:41
double predict(double x) const
Predicts the output for a given input value.
Definition: PolynomialRegression.hpp:59