Как я могу использовать эту библиотеку Node.js для вычисления полиномиальной регрессии?

Мне нужен алгоритм для вычисления полиномиальной регрессии с учетом входного вектора. Я нашел эту библиотеку Node.js, которая, кажется, предоставляет то, что мне нужно.

Глядя на документацию, я вижу, что мне нужно передать двумерный массив данных:

var data = [[0,1],[32, 67] .... [12, 79]];
var result = regression('polynomial', data, 4);

Но мне непонятно

  1. Почему входные данные двумерные?
  2. Какими должны быть значения в каждом массиве? В примере, что представляет [0,1] (какая переменная равна 0 и какая переменная равна 1?).

В основном этот алгоритм предназначен для расчета данных для индикатора, используемого в анализе фондового рынка. Итак, мой ввод — это массив цен: [14.26, 14.27, 14.27, 14.28, 14.29, 14.27, 14.27, 14.28. ...].


person Chad Johnson    schedule 16.08.2015    source источник
comment
Я добавляю комментарий, потому что это не решает вашу проблему, но действительно ли Node.js — лучшая технология для решения вашей проблемы? Это может быть проблематично, поскольку он однопоточный и основан на цикле событий. Это отлично подходит для ввода-вывода, но не для работы, связанной с процессором. Если вы знаете, что делаете, это здорово, и не обращайте внимания на это сообщение. В противном случае я бы посоветовал вам поискать другой язык для выполнения работы, связанной с процессором, даже несмотря на то, что в Node.js есть способы обойти эту проблему.   -  person gretro    schedule 16.08.2015
comment
Это хорошее предложение. Хотя я просто тестирую торговую стратегию, поэтому пока не беспокоюсь об оптимизации. Если мне когда-нибудь понадобится что-то масштабировать, я обязательно рассмотрю это.   -  person Chad Johnson    schedule 16.08.2015
comment
Моя математика заржавела, но разве целью полиномиальной регрессии не является моделирование отношений между x и y? Если бы я делал ставки, я бы поспорил, что массивы должны быть парами (x, y). Похоже, что цены ваших акций — это y, зависимая переменная, так что же такое x, независимая переменная? Мои деньги вовремя, так сказать.   -  person Jordan Running    schedule 16.08.2015
comment
Тяжелые математические вычисления в Node.js? это как делать веб-сервер на C   -  person webduvet    schedule 16.08.2015
comment
@webduvet еще раз, это только для простого тестирования на истории, а не для производства.   -  person Chad Johnson    schedule 16.08.2015


Ответы (1)


Немного поздно в игре, но это может быть полезно другим.

Я бы посоветовал немного почитать о том, что такое регрессии и как они рассчитываются. Сделай что-нибудь своими руками...

https://www.khanacademy.org/math/statistics-probability/describing-relationships-quantitative-data

Короткий ответ — создать массив со значениями x и y:

for(var i=data.length-1; i>=0 ; i--){
    data[i] = [i,data[i]];
}

Большая проблема, которую я вижу с исходными данными, заключается в том, что они полностью игнорируют «x». В данном случае «x», вероятно, является датой, но, сохраняя данные в массиве, мы предполагаем непрерывные даты. Это кажется маловероятным, учитывая данные, с которыми вы работаете: я ожидаю пробелов в данных в выходные и праздничные дни.

Исходя из этого предположения, вот пример того, как достичь того, о чем вы говорите. Это было бы полезно во многих типах данных:

debugger;
// get some stock data: daily close prices
var data = [{Date:"2016-09-23",Close:85.81},{Date:"2016-09-22",Close:86.35},...];

// Before we can use this data, we need to format 
// it for display and processing. Basically, just 
// make sure that everything is in the right order 
// and such...
var metrics = {
    mindate : moment(data[0].Date),
    maxdate : moment(data[0].Date),
};
data.forEach(function(rec){
    // cast the date to something more friendly
    rec.Date = moment(rec.Date);
    // get the min and max
    if(metrics.mindate.isAfter (rec.Date)){ metrics.mindate = moment(rec.Date); }
    if(metrics.maxdate.isBefore(rec.Date)){ metrics.maxdate = rec.Date; }
});
metrics.days = metrics.maxdate.diff(metrics.mindate,'days');

// One thing you will notice about stock data
// is that the markets are not open on holidays
// this means that we do not have data about 
// what the price was during those days, also
// the distance between our datapoints Friday and 
// Monday is not 1 day. Some work is necessary to 
// make it clear that there is a gap
data.forEach(function(rec){
    rec.day = rec.Date.diff(metrics.mindate,'days');
});

// At this point the data is probably ready
// for the regression library, we just need
// to format it correclty
var d = [];
data.forEach(function(rec){
    var x = rec.day;
    var y = rec.Close;
    d.push([x,y]);
});
var result = regression('polynomial', d, 4);


// Now that the regressino has been calculated, we
// can make use of it. First let's determine what
// data was missing from our original dataset
// (basically teh weekends and holidays)
for(var i=data.length-2; i>=0;i--){
    for(var day=data[i+1].day-1;day>data[i].day;day--){
        data.push({
            day:day,
            Date:moment(metrics.mindate).add(day,'days'),
            Close:null,
            Est:null
        });
    }
}
// While we are at, let's project a couple days into 
// the future
var lastday = metrics.days;
for(var day=metrics.days+30; day>=metrics.days; day--){
        data.push({
            day:day,
            Date:moment(metrics.mindate).add(day,'days'),
            Close:null,
            Est:null
        });
}

// for convenience sake, copy it back into our 
// original dataset
data.forEach(function(rec){
    rec.Est = 0;
    for(var i=result.equation.length-1; i>=0; i--){
        rec.Est += result.equation[i] * Math.pow(rec.day,i);
    }
});

// better sort it at this point
data.sort(function(a,b){
    if(a.day < b.day) return -1;
    if(a.day > b.day) return 1;
    return 0;
});
// Now that processing is complete, we can use
// the data in some manner that is meaningful
// in this case, I display the data with the
// gaps filled in, as well as a projection
data.forEach(function(rec){
    $('table#prices').append(
            '<tr><td>{{day}}</td><td>{{Date}}</td><td>{{Close}}</td><td>{{Est}}</td></tr>'
.replace(/{{day}}/g,rec.day)                .replace(/{{Date}}/g,rec.Date.format('YYYY-MM-DD'))
                .replace(/{{Close}}/g,rec.Close || '')
                .replace(/{{Est}}/g,rec.Est || '')
        );
});
$('pre#est').html(
    metrics.mindate.format('YYYY-MM-DD') 
    + ' -> ' + metrics.maxdate.format('YYYY-MM-DD') 
    + ' (' + metrics.days + ' days)'
    + '\n' + result.string
);

Это много, чтобы справиться, так что вот скрипка:

https://jsfiddle.net/v95evuv8/6/

Это зависит от regression.js и moment.js (для обработки даты)

Комментарии содержат вопросы о полезности doint this. Я делаю что-то подобное в CouchDB при агрегировании наборов результатов (сокращаю до параметра регрессии и отслеживаю регрессии, которые отклоняются от ожиданий), а также часто отображаю линию регрессии на диаграммах в веб-отчетах.

person Jefferey Cave    schedule 25.09.2016