Линейная регрессия в Javascript
Я хочу сделать установку наименьших квадратов в Javascript в веб-браузере.
В настоящее время пользователи вводят информацию о точках данных с помощью текстовых входов HTML, а затем я беру данные с помощью jQuery и рисую их с помощью Flot.
После того, как пользователь ввел свои точки данных, я хотел бы представить их с "линией наилучшего соответствия". Я предполагаю, что я бы вычислил линейные, полиномиальные, экспоненциальные и логарифмические уравнения, а затем выберем тот, который имеет наибольшее значение R^2
.
Кажется, я не могу найти библиотеки, которые помогут мне это сделать. Я наткнулся на jStat, но он полностью не хватает документации (насколько я могу найти), и после копания в исходном коде, похоже, любые встроенные функции линейной регрессии - я основываю это исключительно на именах функций.
Кто-нибудь знает библиотеки Javascript, которые предлагают простой регрессионный анализ?
Надеюсь, что я смогу использовать библиотеку так...
Если бы у меня был некоторый набор точек рассеяния в массиве var points = [[3,4],[15,45],...[23,78]]
, я мог бы передать это некоторой функции, например lin_reg(points)
, и она вернет нечто вроде [7.12,3]
, если линейное уравнение было y = 7.12 x + 3
.
Ответы
Ответ 1
Какая линейная регрессия? Для чего-то простого, как наименьшие квадраты, я просто запрограммировал его сам:
http://mathworld.wolfram.com/LeastSquaresFitting.html
Математика не слишком сложна, чтобы следить за ней, дать ей выстрел в течение часа или около того, и дайте мне знать, если это слишком сложно, я могу попробовать.
EDIT:
Найден кого-то, кто сделал это:
http://dracoblue.net/dev/linear-least-squares-in-javascript/159/
Ответ 2
Отъезд
https://cgwb.nci.nih.gov/cgwbreg.html (javascript-регрессионный калькулятор) - чистый JavaScript, а не вызовы CGI на сервер. Данные и обработка остаются на вашем компьютере. Полный результат R-стиля и R-код для проверки работы и визуализации результатов.
См. исходный код встроенных реализаций JavaScript в OLS и статистику, связанную с результатами.
Этот код - это мои усилия по переносу функций библиотеки GSL на JavaScript.
Коды выпускаются под GPL, потому что в основном это линия для переноса строки лицензированного GPL-кода Gnu Scientific Library (GSL).
EDIT: Пол Лутус также предоставляет некоторый код GPL для регрессии по адресу: http://arachnoid.com/polysolve/index.html
Ответ 3
Я нашел эту замечательную библиотеку JavaScript.
Это очень просто и, кажется, работает отлично.
Я также не могу рекомендовать Math.JS достаточно.
Ответ 4
Самое простое решение, которое я нашел для данного вопроса, можно найти в следующем сообщении:
http://trentrichardson.com/2010/04/06/compute-linear-regressions-in-javascript/
Обратите внимание, что в дополнение к линейному уравнению он также возвращает оценку R2, которая может быть полезна.
** РЕДАКТИРОВАТЬ **
Вот фрагмент кода:
function linearRegression(y,x){
var lr = {};
var n = y.length;
var sum_x = 0;
var sum_y = 0;
var sum_xy = 0;
var sum_xx = 0;
var sum_yy = 0;
for (var i = 0; i < y.length; i++) {
sum_x += x[i];
sum_y += y[i];
sum_xy += (x[i]*y[i]);
sum_xx += (x[i]*x[i]);
sum_yy += (y[i]*y[i]);
}
lr['slope'] = (n * sum_xy - sum_x * sum_y) / (n*sum_xx - sum_x * sum_x);
lr['intercept'] = (sum_y - lr.slope * sum_x)/n;
lr['r2'] = Math.pow((n*sum_xy - sum_x*sum_y)/Math.sqrt((n*sum_xx-sum_x*sum_x)*(n*sum_yy-sum_y*sum_y)),2);
return lr;
}
Чтобы использовать это, вам просто нужно передать ему два массива, known_y и known_x, так что это то, что вы могли бы передать:
var known_y = [1, 2, 3, 4];
var known_x = [5.2, 5.7, 5.0, 4.2];
var lr = linearRregression(known_y, known_x);
// now you have:
// lr.slope
// lr.intercept
// lr.r2
Ответ 5
Вот фрагмент, который возьмет массив триплетов (x, y, r), где r - вес точки данных (x, y) и return [a, b], такой, что Y = a * X + b приближают данные.
// return (a, b) that minimize
// sum_i r_i * (a*x_i+b - y_i)^2
function linear_regression( xyr )
{
var i,
x, y, r,
sumx=0, sumy=0, sumx2=0, sumy2=0, sumxy=0, sumr=0,
a, b;
for(i=0;i<xyr.length;i++)
{
// this is our data pair
x = xyr[i][0]; y = xyr[i][1];
// this is the weight for that pair
// set to 1 (and simplify code accordingly, ie, sumr becomes xy.length) if weighting is not needed
r = xyr[i][2];
// consider checking for NaN in the x, y and r variables here
// (add a continue statement in that case)
sumr += r;
sumx += r*x;
sumx2 += r*(x*x);
sumy += r*y;
sumy2 += r*(y*y);
sumxy += r*(x*y);
}
// note: the denominator is the variance of the random variable X
// the only case when it is 0 is the degenerate case X==constant
b = (sumy*sumx2 - sumx*sumxy)/(sumr*sumx2-sumx*sumx);
a = (sumr*sumxy - sumx*sumy)/(sumr*sumx2-sumx*sumx);
return [a, b];
}
Ответ 6
Несколько на основе ответа Ника Мабона.
function linearRegression(x, y)
{
var xs = 0; // sum(x)
var ys = 0; // sum(y)
var xxs = 0; // sum(x*x)
var xys = 0; // sum(x*y)
var yys = 0; // sum(y*y)
var n = 0;
for (; n < x.length && n < y.length; n++)
{
xs += x[n];
ys += y[n];
xxs += x[n] * x[n];
xys += x[n] * y[n];
yys += y[n] * y[n];
}
var div = n * xxs - xs * xs;
var gain = (n * xys - xs * ys) / div;
var offset = (ys * xxs - xs * xys) / div;
var correlation = Math.abs((xys * n - xs * ys) / Math.sqrt((xxs * n - xs * xs) * (yys * n - ys * ys)));
return { gain: gain, offset: offset, correlation: correlation };
}
Тогда y '= x * gain + offset.
Ответ 7
Простая линейная регрессия с мерами вариации (Общая сумма квадратов = Сумма регрессии квадратов + Сумма ошибок квадратов), Стандартная ошибка оценки SEE (Остаточная стандартная ошибка) и коэффициенты определения R2 и корреляция R.
const regress = (x, y) => {
const n = y.length;
let sx = 0;
let sy = 0;
let sxy = 0;
let sxx = 0;
let syy = 0;
for (let i = 0; i < n; i++) {
sx += x[i];
sy += y[i];
sxy += x[i] * y[i];
sxx += x[i] * x[i];
syy += y[i] * y[i];
}
const mx = sx / n;
const my = sy / n;
const yy = n * syy - sy * sy;
const xx = n * sxx - sx * sx;
const xy = n * sxy - sx * sy;
const slope = xy / xx;
const intercept = my - slope * mx;
const r = xy / Math.sqrt(xx * yy);
const r2 = Math.pow(r,2);
let sst = 0;
for (let i = 0; i < n; i++) {
sst += Math.pow((y[i] - my), 2);
}
const sse = sst - r2 * sst;
const see = Math.sqrt(sse / (n - 2));
const ssr = sst - sse;
return {slope, intercept, r, r2, sse, ssr, sst, sy, sx, see};
}
regress([1, 2, 3, 4, 5], [1, 2, 3, 4, 3]);