als-statistics
Version:
Modular JS statistics toolkit for Node.js and the browser: descriptive stats, correlations (Pearson/Spearman/Kendall), t-tests & ANOVA (Student/Welch), reliability (Cronbach’s alpha), regression (linear/logistic), clustering (DBSCAN/HDBSCAN), and table/co
52 lines (44 loc) • 2.03 kB
JavaScript
import CDF from '../cdf/index.js';
import MatrixUtils from './matrix-utils.js';
import { RegressionBase } from './regression-base.js';
class LinearRegression extends RegressionBase {
constructor(table, yName, xNames, step) {
super(table, yName, xNames, step)
}
calculate() {
super.calculate()
this.residuals = this.y.map((yi, i) => yi - this.yHat[i]);
this.r2 = this.computeR2();
this.standardErrors = this.computeStandardErrors();
this.pValues = this.computePValues();
if (this.n < this.k) throw new Error('Not enough observations for regression (n < predictors + 1)');
return this;
}
computeCoefficients() {
const XT = MatrixUtils.transpose(this.X);
const XTX = MatrixUtils.multiply(XT, this.X);
const XTy = MatrixUtils.multiplyVec(XT, this.y);
this.coefficients = MatrixUtils.solve ? MatrixUtils.solve(XTX, XTy) : MatrixUtils.multiplyVec(MatrixUtils.inverse(XTX), XTy);
}
predict(X) { return X.map(row => row.reduce((acc, val, j) => acc + val * this.coefficients[j], 0)) }
computeR2() {
const yMean = this.y.reduce((a, b) => a + b, 0) / this.n;
const ssTot = this.y.reduce((acc, yi) => acc + (yi - yMean) ** 2, 0);
const ssRes = this.residuals.reduce((acc, e) => acc + e ** 2, 0);
return 1 - ssRes / ssTot;
}
computeStandardErrors() {
const XT = MatrixUtils.transpose(this.X);
const XTX = MatrixUtils.multiply(XT, this.X);
const invXTX = MatrixUtils.inverse(XTX);
const mse = this.residuals.reduce((acc, e) => acc + e ** 2, 0) / (this.n - this.k);
return invXTX.map((row, i) => Math.sqrt(row[i] * mse));
}
computePValues() {
return this.standardErrors.map((se, i) => {
return 2 * (1 - CDF.t(Math.abs(this.coefficients[i] / se), this.n - this.k));
});
}
get result() { return { ...super.result, StdError: this.standardErrors, pValue: this.pValues } }
}
export default LinearRegression