← back to Watches
services/ml/linear-regression.js
59 lines
/**
* Linear Regression Model for Price Prediction
*/
export class LinearRegression {
constructor() {
this.slope = 0;
this.intercept = 0;
this.rSquared = 0;
this.rmse = 0;
}
fit(X, y) {
const n = X.length;
const sumX = X.reduce((a, b) => a + b, 0);
const sumY = y.reduce((a, b) => a + b, 0);
const sumXY = X.reduce((acc, x, i) => acc + x * y[i], 0);
const sumXX = X.reduce((acc, x) => acc + x * x, 0);
this.slope = (n * sumXY - sumX * sumY) / (n * sumXX - sumX * sumX);
this.intercept = (sumY - this.slope * sumX) / n;
// Calculate R-squared
const yMean = sumY / n;
const ssTotal = y.reduce((acc, yi) => acc + Math.pow(yi - yMean, 2), 0);
const ssRes = y.reduce((acc, yi, i) => acc + Math.pow(yi - this.predict(X[i]), 2), 0);
this.rSquared = 1 - (ssRes / ssTotal);
this.rmse = Math.sqrt(ssRes / n);
return { slope: this.slope, intercept: this.intercept, rSquared: this.rSquared, rmse: this.rmse };
}
predict(x) {
return this.slope * x + this.intercept;
}
predictFuture(currentYear, yearsAhead) {
return Array.from({ length: yearsAhead }, (_, i) => ({
year: currentYear + i + 1,
price: Math.round(this.predict(currentYear + i + 1))
}));
}
toJSON() {
return { type: 'linear', slope: this.slope, intercept: this.intercept, rSquared: this.rSquared, rmse: this.rmse };
}
static fromJSON(data) {
const model = new LinearRegression();
model.slope = data.slope;
model.intercept = data.intercept;
model.rSquared = data.rSquared;
model.rmse = data.rmse;
return model;
}
}
export default LinearRegression;