Skip to content

Commit 604bb21

Browse files
committed
Create regression_models.cpp
1 parent 692d05c commit 604bb21

File tree

1 file changed

+204
-0
lines changed

1 file changed

+204
-0
lines changed
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
#include <iostream>
2+
#include <vector>
3+
#include <cmath>
4+
#include <random>
5+
#include <fstream>
6+
#include <numeric>
7+
#include <Eigen/Dense>
8+
9+
using namespace std;
10+
using namespace Eigen;
11+
12+
// Utility functions
13+
double mean_squared_error(const VectorXd& y_true, const VectorXd& y_pred) {
14+
return (y_true - y_pred).squaredNorm() / y_true.size();
15+
}
16+
17+
double r2_score(const VectorXd& y_true, const VectorXd& y_pred) {
18+
double mean_y = y_true.mean();
19+
double total = (y_true.array() - mean_y).square().sum();
20+
double residual = (y_true - y_pred).squaredNorm();
21+
return 1.0 - residual / total;
22+
}
23+
24+
void save_csv(const string& filename, const MatrixXd& X, const VectorXd& y_true, const VectorXd& y_pred) {
25+
ofstream file(filename);
26+
file << "X,True Y,Predicted Y\n";
27+
for (int i = 0; i < X.rows(); ++i) {
28+
file << X(i, 0) << "," << y_true(i) << "," << y_pred(i) << "\n";
29+
}
30+
file.close();
31+
}
32+
33+
// Linear Regression
34+
class LinearRegression {
35+
public:
36+
VectorXd weights;
37+
38+
void fit(const MatrixXd& X, const VectorXd& y) {
39+
MatrixXd X_bias(X.rows(), X.cols() + 1);
40+
X_bias << MatrixXd::Ones(X.rows(), 1), X;
41+
weights = (X_bias.transpose() * X_bias).ldlt().solve(X_bias.transpose() * y);
42+
}
43+
44+
VectorXd predict(const MatrixXd& X) const {
45+
MatrixXd X_bias(X.rows(), X.cols() + 1);
46+
X_bias << MatrixXd::Ones(X.rows(), 1), X;
47+
return X_bias * weights;
48+
}
49+
};
50+
51+
// Ridge Regression
52+
class RidgeRegression {
53+
public:
54+
VectorXd weights;
55+
double alpha;
56+
57+
RidgeRegression(double alpha = 1.0) : alpha(alpha) {}
58+
59+
void fit(const MatrixXd& X, const VectorXd& y) {
60+
MatrixXd X_bias(X.rows(), X.cols() + 1);
61+
X_bias << MatrixXd::Ones(X.rows(), 1), X;
62+
MatrixXd I = MatrixXd::Identity(X_bias.cols(), X_bias.cols());
63+
I(0, 0) = 0; // Don't regularize bias
64+
weights = (X_bias.transpose() * X_bias + alpha * I).ldlt().solve(X_bias.transpose() * y);
65+
}
66+
67+
VectorXd predict(const MatrixXd& X) const {
68+
MatrixXd X_bias(X.rows(), X.cols() + 1);
69+
X_bias << MatrixXd::Ones(X.rows(), 1), X;
70+
return X_bias * weights;
71+
}
72+
};
73+
74+
// Kernel Ridge Regression (RBF kernel)
75+
class KernelRidgeRegression {
76+
public:
77+
double alpha, gamma;
78+
MatrixXd X_train;
79+
VectorXd alpha_vec;
80+
81+
KernelRidgeRegression(double alpha = 1.0, double gamma = 1.0) : alpha(alpha), gamma(gamma) {}
82+
83+
MatrixXd rbf_kernel(const MatrixXd& A, const MatrixXd& B) const {
84+
MatrixXd K(A.rows(), B.rows());
85+
for (int i = 0; i < A.rows(); ++i) {
86+
for (int j = 0; j < B.rows(); ++j) {
87+
K(i, j) = exp(-gamma * (A.row(i) - B.row(j)).squaredNorm());
88+
}
89+
}
90+
return K;
91+
}
92+
93+
void fit(const MatrixXd& X, const VectorXd& y) {
94+
X_train = X;
95+
MatrixXd K = rbf_kernel(X, X);
96+
alpha_vec = (K + alpha * MatrixXd::Identity(K.rows(), K.cols())).ldlt().solve(y);
97+
}
98+
99+
VectorXd predict(const MatrixXd& X) const {
100+
MatrixXd K = rbf_kernel(X, X_train);
101+
return K * alpha_vec;
102+
}
103+
};
104+
105+
int main() {
106+
// Generate synthetic data
107+
int n_samples = 100;
108+
MatrixXd X(n_samples, 1);
109+
VectorXd y(n_samples);
110+
std::mt19937 gen(42);
111+
std::uniform_real_distribution<> dist(0, 2);
112+
std::normal_distribution<> noise(0, 0.5);
113+
114+
for (int i = 0; i < n_samples; ++i) {
115+
X(i, 0) = dist(gen);
116+
y(i) = 4.0 + 3.0 * X(i, 0) + noise(gen);
117+
}
118+
119+
// Train and evaluate models
120+
LinearRegression linear;
121+
RidgeRegression ridge(1.0);
122+
KernelRidgeRegression kernel_ridge(1.0, 5.0);
123+
124+
linear.fit(X, y);
125+
ridge.fit(X, y);
126+
kernel_ridge.fit(X, y);
127+
128+
VectorXd y_pred_linear = linear.predict(X);
129+
VectorXd y_pred_ridge = ridge.predict(X);
130+
VectorXd y_pred_kernel = kernel_ridge.predict(X);
131+
132+
cout << "Linear -> MSE: " << mean_squared_error(y, y_pred_linear) << ", R2: " << r2_score(y, y_pred_linear) << endl;
133+
cout << "Ridge -> MSE: " << mean_squared_error(y, y_pred_ridge) << ", R2: " << r2_score(y, y_pred_ridge) << endl;
134+
cout << "Kernel -> MSE: " << mean_squared_error(y, y_pred_kernel) << ", R2: " << r2_score(y, y_pred_kernel) << endl;
135+
136+
save_csv("predictions_linear.csv", X, y, y_pred_linear);
137+
save_csv("predictions_ridge.csv", X, y, y_pred_ridge);
138+
save_csv("predictions_kernel_ridge.csv", X, y, y_pred_kernel);
139+
140+
return 0;
141+
}
142+
143+
144+
// Lasso Regression (Coordinate Descent)
145+
class LassoRegression {
146+
public:
147+
VectorXd weights;
148+
double alpha;
149+
int max_iter;
150+
double tol;
151+
152+
LassoRegression(double alpha = 0.1, int max_iter = 1000, double tol = 1e-4)
153+
: alpha(alpha), max_iter(max_iter), tol(tol) {}
154+
155+
void fit(const MatrixXd& X, const VectorXd& y) {
156+
MatrixXd X_bias(X.rows(), X.cols() + 1);
157+
X_bias << MatrixXd::Ones(X.rows(), 1), X;
158+
int n_samples = X_bias.rows();
159+
int n_features = X_bias.cols();
160+
weights = VectorXd::Zero(n_features);
161+
162+
for (int iter = 0; iter < max_iter; ++iter) {
163+
VectorXd weights_old = weights;
164+
for (int j = 0; j < n_features; ++j) {
165+
double tmp = 0.0;
166+
for (int i = 0; i < n_samples; ++i) {
167+
double dot = 0.0;
168+
for (int k = 0; k < n_features; ++k) {
169+
if (k != j)
170+
dot += X_bias(i, k) * weights(k);
171+
}
172+
tmp += X_bias(i, j) * (y(i) - dot);
173+
}
174+
double rho = tmp;
175+
double norm_sq = X_bias.col(j).squaredNorm();
176+
177+
if (j == 0) {
178+
weights(j) = rho / norm_sq;
179+
} else {
180+
if (rho < -alpha / 2)
181+
weights(j) = (rho + alpha / 2) / norm_sq;
182+
else if (rho > alpha / 2)
183+
weights(j) = (rho - alpha / 2) / norm_sq;
184+
else
185+
weights(j) = 0.0;
186+
}
187+
}
188+
if ((weights - weights_old).lpNorm<1>() < tol)
189+
break;
190+
}
191+
}
192+
193+
VectorXd predict(const MatrixXd& X) const {
194+
MatrixXd X_bias(X.rows(), X.cols() + 1);
195+
X_bias << MatrixXd::Ones(X.rows(), 1), X;
196+
return X_bias * weights;
197+
}
198+
};
199+
200+
LassoRegression lasso(0.1);
201+
lasso.fit(X, y);
202+
VectorXd y_pred_lasso = lasso.predict(X);
203+
cout << "Lasso -> MSE: " << mean_squared_error(y, y_pred_lasso) << ", R2: " << r2_score(y, y_pred_lasso) << endl;
204+
save_csv("predictions_lasso.csv", X, y, y_pred_lasso);

0 commit comments

Comments
 (0)