Skip to content

Commit

Permalink
redefine linear-regression() as a special case of multiple-regression()
Browse files Browse the repository at this point in the history
  • Loading branch information
ds26gte committed May 19, 2024
1 parent cb49a3f commit b9ea62d
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 32 deletions.
42 changes: 16 additions & 26 deletions src/arr/trove/statistics.arr
Original file line number Diff line number Diff line change
Expand Up @@ -184,39 +184,29 @@ fun stdev-sample(l :: List) -> Number:
num-sqrt(variance-sample(l))
end

fun linear-regression(x :: List<Number>, y :: List<Number>) -> (Number -> Number):
doc: "returns a linear predictor function calculated with ordinary least squares regression"
if x.length() <> y.length():
raise(E.message-exception("linear-regression: input lists must have equal lengths"))
else if x.length() < 2:
raise(E.message-exception("linear-regression: input lists must have at least 2 elements each"))
else:
shadow y = map(num-to-roughnum, y)
shadow x = map(num-to-roughnum, x)
xpt-xy = math.sum(map2(lam(xi, yi): xi * yi end, x, y))
xpt-x-xpt-y = (math.sum(x) * math.sum(y)) / x.length()
covariance = xpt-xy - xpt-x-xpt-y
v1 = math.sum(map(lam(n): n * n end, x))
v2 = (math.sum(x) * math.sum(x)) / x.length()
variance1 = v1 - v2
beta = covariance / variance1
alpha = mean(y) - (beta * mean(x))

fun predictor(in :: Number) -> Number:
(beta * in) + alpha
end

predictor
end
end

# please see: https://online.stat.psu.edu/stat462/

fun multiple-regression(x_s_s :: List<Any>, y_s :: List<Number>) -> (Any -> Number):
doc: "multiple-regression"
MR.multiple-regression(x_s_s, y_s)
end

fun linear-regression(x-s :: List<Number>, y-s :: List<Number>) -> (Number -> Number):
doc: "returns a linear predictor function for a single independent variable"
x-s-n = x-s.length()
if x-s-n <> y-s.length():
raise(E.message-exception("linear-regression: input lists must have equal lengths"))
else if x-s-n < 2:
raise(E.message-exception("linear-regression: input lists must have at least 2 elements each"))
else:
predictor1 = MR.multiple-regression(x-s.map(lam(x1 :: Number): {x1} end), y-s)
fun predictor2(x2 :: Number) -> Number:
predictor1({x2})
end
predictor2
end
end

fun r-squared(x :: List<Number>, y :: List<Number>, f :: (Number -> Number)) -> Number:
shadow x = map(num-to-roughnum, x)
shadow y = map(num-to-roughnum, y)
Expand Down
15 changes: 9 additions & 6 deletions src/js/trove/multiple-regression.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
}
let sign = (r + c) % 2;
sign = (sign === 0) ? 1 : -1;
return sign * matrixDeterminant(mm)
return sign * matrixDeterminant(mm);
}

function matrixAdjoint(m) {
Expand All @@ -84,7 +84,7 @@
mc[r][c] = matrixCofactor(m, r, c);
}
}
return matrixTranspose(mc)
return matrixTranspose(mc);
}

function matrixInverse(m) {
Expand All @@ -93,8 +93,8 @@
let size = m.length;
for (let r = 0; r < size; r++) {
for (let c = 0; c < size; c++) {
let x = mI[r][c]
mI[r][c] = x/det
let x = mI[r][c];
mI[r][c] = x/det;
}
}
return mI;
Expand Down Expand Up @@ -126,7 +126,10 @@
let js_y_s = runtime.ffi.toArray(y_s);
let num_mappings = js_x_s_s.length;
if (js_y_s.length !== num_mappings) {
throw runtime.ffi.throwMessageException("multiple-regression: number of inputs doesn't match number of outputs");
throw runtime.ffi.throwMessageException("multiple-regression: lists must have equal lengths");
if (num_mappings < 2) {
throw runtime.ffi.throwMessageException("multiple-regression: lists must have at least 2 elements each");
}
}
let X = new Array(num_mappings);
let Y = new Array(num_mappings);
Expand All @@ -140,7 +143,7 @@
} else if (x_s_n !== x_s_len) {
throw runtime.ffi.throwMessageException("multiple-regression: lengths of input tuples are different");
}
X[r] = new Array(x_s_len + 1)
X[r] = new Array(x_s_len + 1);
let Xr = X[r];
Xr[0] = 1;
js_x_s.forEach(function(x, c) {
Expand Down

0 comments on commit b9ea62d

Please sign in to comment.