Giter Club home page Giter Club logo

arima's Introduction

ARIMA. Time-series forecasting in browsers and Node.js

Emscripten port of the native C package ctsa for time series analysis and forecasting

This CommonJS module includes:

  • ARIMA (Autoregressive Integrated Moving Average)
  • SARIMA (Seasonal ARIMA)
  • SARIMAX (Seasonal ARIMA with exogenous variables)
  • AutoARIMA (ARIMA with automatic parameters)

Installation of the ARIMA module

npm install arima

Initialization

const ARIMA = require('arima')
const arima = new ARIMA(options)

Where the options object can include:

  • auto - automatic ARIMA (default: false)
  • p, d, q params for ARIMA (default: p: 1, d: 0, q: 1)
  • P, D, Q, s seasonal params (default: 0s). Setting them to non-zero values makes the ARIMA model seasonal
  • method - ARIMA method (default: 0, described below)
  • optimizer - optimization method (default: 6, described below)
  • transpose - transpose exogenous array when fitting SARIMAX (default: false)
  • verbose - verbose output (default: true)

Also for AutoARIMA only:

  • approximation - approximation method (default: 1),
  • search - search method (default: 1)
  • p, d, q, P, D, Q params define max values for a search algorithm

Train/Predict

ARIMA, SARIMA, AutoARIMA:

arima.train(ts) // Or arima.fit(ts)
arima.predict(10) // Predict 10 steps forward

SARIMAX:

arima.train(ts, exog) // or arima.fit(ts, exog)
arima.predict(10, exognew) // Predict 10 steps forwars using new exogenous variables

Running in browsers

As described in the issue #10 Chrome prevents compilation of wasm modules >4kB. There are two ways to overcome this:

  • Load arima in a Web Worker
  • Use the arima/async module

Example of async loading:

const ARIMAPromise = require('arima/async')

ARIMAPromise.then(ARIMA => {
  const ts = Array(10).fill(0).map((_, i) => i + Math.random() / 5)
  const arima = new ARIMA({ p: 2, d: 1, q: 2, P: 0, D: 0, Q: 0, S: 0, verbose: false }).train(ts)
  const [pred, errors] = arima.predict(10)
})

All following examples use synchronous compilation (Node.js, Firefox). They will not work in Chrome.

Example: ARIMA

// Load package
const ARIMA = require('arima')

// Synthesize timeseries
const ts = Array(24).fill(0).map((_, i) => i + Math.random() / 5)

// Init arima and start training
const arima = new ARIMA({
  p: 2,
  d: 1,
  q: 2,
  verbose: false
}).train(ts)

// Predict next 12 values
const [pred, errors] = arima.predict(12)

Example: SARIMA

// Init sarima and start training
const sarima = new ARIMA({
  p: 2,
  d: 1,
  q: 2,
  P: 1,
  D: 0,
  Q: 1,
  s: 12,
  verbose: false
}).train(ts)

// Predict next 12 values
const [pred, errors] = sarima.predict(12)

Example: SARIMAX

// Generate timeseries using exogenous variables
const f = (a, b) => a * 2 + b * 5
const exog = Array(30).fill(0).map(x => [Math.random(), Math.random()])
const exognew = Array(10).fill(0).map(x => [Math.random(), Math.random()])
const ts = exog.map(x => f(x[0], x[1]) + Math.random() / 5)

// Init and fit sarimax
const sarimax = new ARIMA({
  p: 1,
  d: 0,
  q: 1,
  transpose: true,
  verbose: false
}).fit(ts, exog)

// Predict next 12 values using exognew
const [pred, errors] = sarimax.predict(12, exognew)

Example: AutoARIMA

const autoarima = new ARIMA({ auto: true }).fit(ts)
const [pred, errors] = autoarima.predict(12)

ARIMA Method (method)

0 - Exact Maximum Likelihood Method (Default)
1 - Conditional Method - Sum Of Squares
2 - Box-Jenkins Method

Optimization Method (optimizer)

Method 0 - Nelder-Mead
Method 1 - Newton Line Search
Method 2 - Newton Trust Region - Hook Step
Method 3 - Newton Trust Region - Double Dog-Leg
Method 4 - Conjugate Gradient
Method 5 - BFGS
Method 6 - Limited Memory BFGS (Default)
Method 7 - BFGS Using More Thuente Method

Old functional API (still works)

The old interface of the arima package was only one function that took 3 arguments:

  • a 1D array with observations over time
  • a number of time steps to predict
  • a javascript object with ARIMA parameters p, d, q and other options

It returned two vectors - predictions and mean square errors.

const arima = require('arima')
const [pred, errors] = arima(ts, 20, {
  method: 0, // ARIMA method (Default: 0)
  optimizer: 6, // Optimization method (Default: 6)
  p: 1, // Number of Autoregressive coefficients
  d: 0, // Number of times the series needs to be differenced
  q: 1, // Number of Moving Average Coefficients
  verbose: true // Output model analysis to console
})

Web demo

You can try ARIMA online in the StatSim Forecast app: https://statsim.com/forecast/. It uses the arima package under the hood and applies random search to find the best values of p, d and q.

arima's People

Contributors

zemlyansky avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

arima's Issues

Need fix for broken prediction

I tried to train/fit ARIMA & Auto ARIMA model with sin pattern datasets but it gives an invalid prediction, even in the first data point is invalid/not meaningful at all. can I get the solution or someone helps me out? I truly need this fix.

  const model = new ARIMA({
    auto: true,
    verbose: true,
  });

  model.train(trainDatasets);

  const [preds, errors] = model.predict(testLen);

below is the plotted data.

image

Module will crash if few values are given

Following example will exit with an error (crash). This error can't be even handled with try/catch:

const arima = require('arima');

let pVals = [0, 0, 0, 0, 12, 9.55, 12];

const [pred, errors] = arima(pVals, 2, {
    method: 0,
    optimizer: 6,
    p: 3,
    q: 0,
    d: 1,
    verbose: true
});
console.log(pred);

wasm failed

On running server in my Vue2 application using yarn serve locally :
Uncaught RuntimeError: abort(sync fetching of the wasm failed: you can preload it to Module['wasmBinary'] manually, or emcc.py will do that for you when generating HTML (but not JS)). Build with -s ASSERTIONS=1 for more info.

Typescript types

Hi, thanks for the gread lib!

Do u plan to add typescript types?

I allready created a minimal index.d.ts to satisify my local compiler.
But it is by far not complete.

declare class ArimaClass {
	predict(steps: number, exog: Array<Array<number>>): Array<Array<number>>
	fit(values: Array<number>, exog: Array<Array<number>>): ArimaClass
}

type ArimaConstructor = new (args: any) => ArimaClass
declare const arimaConstructorConst: ArimaConstructor

declare module 'arima' {
	export = arimaConstructorConst
}

Issue with prediction. Model is not creating from beginning. It retrain the existing one.

How to reproduce ?
`const ARIMA = require('arima')

for(let i of Array(50)) {
const ts = [81, 123, 175, 174, 130, 134, 150, 211, 240, 222, 159, 219, 109, 128, 155, 149, 98, 116, 93, 136, 201, 194, 195, 308];

const arima = new ARIMA({
    "verbose": false,
    "p": 1,
    "d": 1,
    "q": 1,
    "method": 0,
    "optimizer": 6,
    "P": 2,
    "D": 1,
    "Q": 2,
    "s": 12
}).train(ts)
const [pred, errors] = arima.predict(24)
console.log(pred);

}`

Like you see i create the new model each time. And the data set does not change.
i got two times correct result :

[
  216.08903590342277,  239.6406144569421,
  267.89498883554035,  262.1911453749664,
   211.3076749524534, 229.21478456387018,
  206.51948092058473,  249.6593046446444,
   314.3816613182281,  307.2968154245733,
   307.8028675181308,  420.3938562984081,
   328.3435169837437, 351.86064907178456,
   380.1060861812425,  374.4001057582379,
   323.5159444064528, 341.42335397740834,
   318.7268602179344, 361.86614087453273,
   426.5895682189373,  419.5050495675654,
  420.01300790199423,  532.6055751648078
]

After third time i got the wrong one

[
  196.74715368116387,  204.3729118507515,
   218.9898465482616,  210.5132908879587,
  156.04610733420577, 180.98047432406986,
   138.6633091404668, 172.74769444027885,
   255.5789238451663, 254.02735473863788,
   286.7273390737301,  425.9774642880317,
  314.19852555182104, 313.04656994897863,
  318.11449634155883, 307.72816230422285,
  250.58728673912913,  280.8690377039543,
  223.65558859109467, 250.86476592356135,
   347.4464112630595, 350.09635814212993,
    407.241525988272,  566.7353441379937
]

And fourth is completly broken:

[
  NaN, NaN, NaN, NaN, NaN,
  NaN, NaN, NaN, NaN, NaN,
  NaN, NaN, NaN, NaN, NaN,
  NaN, NaN, NaN, NaN, NaN,
  NaN, NaN, NaN, NaN
]

It's critical issue in my opinion.
I created the arima web worker. So for each data set i create new worker. and I terminate old one. I removed the console.logs too.
But for the optimization to not create and compile arima for each data set it should be resolved.

Unexpected prediction output

Environment

Lib version: [email protected]
Node version: v14.18.2
OS: Linux and macOS

Description

Hi @zemlyansky, we have been happily using your library without issue for some time to forecast some monthly cost data until the beginning of this month, when the predictions have suddenly become wildly inaccurate.

Below is a snippet of js which demonstrates our problem:

const Arima = require('Arima');

const inputA = [
  105.82911266800008, 191.51075963815438, 124.22193611229298, 88.42792338363537,
  85.84729763073994, 88.41525425858667, 72.47634627063404, 68.10950727140339,
  50.184748575943566, 41.052736303601996, 49.81397574690716, 64.4913229728772
];

const inputB = [ // FYI this is the same as inputA, except the first element is removed and a new element has been appended
  191.51075963815438, 124.22193611229298, 88.42792338363537, 85.84729763073994,
  88.41525425858667, 72.47634627063404, 68.10950727140339, 50.184748575943566,
  41.052736303601996, 49.81397574690716, 64.4913229728772, 24.585994644050356
];

for (const input of [inputA, inputB]) {
  const autoArima = new Arima({ auto: true, verbose: false }).fit(input);

  // Predict next 3 values
  const [pred, errors] = autoArima.predict(3);
  console.log('pred', pred, 'errors', errors);
}

If you run this snippet, you should get the following output:

0.05 
pred [ 79.41748022969402, 83.61169866651056, 83.61169866651056 ] errors [ 962.4714568849391, 1393.6548836716488, 1393.6548836716488 ]
0.05 
pred [ -2906.1716859202693, -1885.065226527455, -1340.891848101933 ] errors [ 3.8195924253e-313, 88.41525425858667, 3.8195924261e-313 ]

As you can see, the predictions for inputA look sensible, but the ones for inputB do not.

If it assists, when you set verbose to true, you get the following output:

0.05 
p: 2 d: 0 q: 2 P: 0 D: 0 Q: 0 Drift/Mean: 1 ic: 1.79769e+308 
p: 0 d: 0 q: 0 P: 0 D: 0 Q: 0 Drift/Mean: 1 ic: 127.525 
p: 1 d: 0 q: 0 P: 0 D: 0 Q: 0 Drift/Mean: 1 ic: 126.271 
p: 0 d: 0 q: 1 P: 0 D: 0 Q: 0 Drift/Mean: 1 ic: 126.178 
p: 0 d: 0 q: 0 P: 0 D: 0 Q: 0 Drift/Mean: 0 ic: 145.608 
p: 1 d: 0 q: 1 P: 0 D: 0 Q: 0 Drift/Mean: 1 ic: 1.79769e+308 
p: 0 d: 0 q: 2 P: 0 D: 0 Q: 0 Drift/Mean: 1 ic: 130.095 
p: 1 d: 0 q: 2 P: 0 D: 0 Q: 0 Drift/Mean: 1 ic: 1.79769e+308 

 AutoARIMA summary: 


 Exit Status 
Return Code : 1 
Exit Message : Probable Success

  ARIMA Seasonal Order : ( 0, 0, 1) * (0, 0, 0) 

Coefficients        Value               Standard Error       

MA1              -0.669343           0.251052             

MEAN             83.6117             14.5387              
TREND            0                    

SIGMA^2          1154.95              

ESTIMATION METHOD : CSS-MLE

OPTIMIZATION METHOD : L-BFGS

AIC criterion : 123.083 

BIC criterion : 124.537 

AICC criterion : 126.083 

Log Likelihood : -58.5413 

Auto ARIMA Parameters 

Approximation: TRUE 
pred [ 79.41748022969402, 83.61169866651056, 83.61169866651056 ] errors [ 962.4714568849391, 1393.6548836716488, 1393.6548836716488 ]
Stepwise: TRUE0.05 
p: 2 d: 1 q: 2 P: 0 D: 0 Q: 0 Drift/Mean: 1 ic: 121.451 
p: 0 d: 1 q: 0 P: 0 D: 0 Q: 0 Drift/Mean: 1 ic: 99.1227 
p: 1 d: 1 q: 0 P: 0 D: 0 Q: 0 Drift/Mean: 1 ic: 102.541 
p: 0 d: 1 q: 1 P: 0 D: 0 Q: 0 Drift/Mean: 1 ic: 100.922 
p: 0 d: 1 q: 0 P: 0 D: 0 Q: 0 Drift/Mean: 0 ic: 100.024 

 AutoARIMA summary: 


 Exit Status 
Return Code : 1 
Exit Message : Probable Success

  ARIMA Seasonal Order : ( 0, 1, 0) * (0, 0, 0) 

Coefficients        Value               Standard Error       


MEAN             0                    
TREND            0                    
EXOG             -15.175             6.95421              

SIGMA^2          585.16               

ESTIMATION METHOD : CSS-MLE

OPTIMIZATION METHOD : L-BFGS

AIC criterion : 104.259 

BIC criterion : 105.055 

AICC criterion : 105.759 

Log Likelihood : -50.1295 

Auto ARIMA Parameters 

Approximation: TRUE 
pred [ -2906.1716859202693, -1885.065226527455, -1340.891848101933 ] errors [ 3.8195924253e-313, 88.41525425858667, 3.8195924261e-313 ]

Please could you assist me in understanding this dramatic change in prediction? Is it a bug?

Many thanks in advance for your time.

Miles

Auto arima produces logs

Hi, thanks for the gread library!

The following call produces a console.log which is not ideal in my case since i love a clean console ;).

Call:

static forecastTimeseriesNpmArima({ts, exog, newExog, forecastHorizon}: ForecastArguments): Array<Array<number>> {

		// Init and fit sarimax
		const sarimax = new ARIMA({
			auto: true,
			transpose: false,
			verbose: false
		}).fit(ts, exog)

		return sarimax.predict(forecastHorizon, newExog)
	}

Log:

0.05

      at Object.printChar (../node_modules/arima/wasm/native.js:9:14612)
          at wasm-function[173]:0x1b591
          at wasm-function[70]:0x942d
          at wasm-function[21]:0x3e4b
          at wasm-function[72]:0x95ea
          at wasm-function[105]:0xfd0c

Arguments to the function:

{
      args: {
        forecastHorizon: 24,
        ts: [
            -1.3218134721103225,  5.402732981816372, 11.994985179193174,
             17.251233364558672, 27.918535436034198, 33.663998749376425,
              37.40250522110233,  45.88332535115516,  54.63113638724488,
             59.396328386032614,  64.48860471187179,  72.31638867650383,
              69.42073816816638,  65.62843331042902,  61.62907309148302,
             62.296603419396845, 44.495230513590144,  40.05695375648077,
             38.408008406341246, 31.578441456483517, 25.567934069804355,
              21.68860153033101, 15.293043989021381,  8.399252785372369,
              6.189879772888429,  3.493364310438718,  3.433373296228903,
               0.87996779604127, 4.4859112456723915,  4.536935267618869,
              4.236849557182065,  7.466436534775678,  9.498055009414607,
              11.47632364410014, 15.569494898507319,  17.67094703582015,
             20.575811635614794,  23.66550570546584,  22.96313167300972,
             24.276368316366792, 25.091757726854812, 25.887536187031124,
              27.53074419573853, 27.264400951382473, 30.806624159636044,
              32.27615214781896,     32.60034307113,  35.34624576189487,
              36.74175183865871, 37.368658445938905,  45.82184802280855,
             48.422008095788385, 51.261887437126184,  51.56174133874234,
              49.98035900463187,  47.74559330768086,  40.98075557680516,
              39.66895599919573,  38.53111178358073,  38.83802388163839,
              36.63894916189736,  34.99460043197398,  23.49473869759815,
             20.609852646973415, 19.899640918226645, 20.158389927033248,
             21.472083359464158,  22.65749599365079, 26.580690395434956,
             25.867244997693906,  23.04889599475246, 18.156063652284526,
              16.27163534215159, 13.877019507665999, 16.281019929314766,
             16.256807599982427,  9.364818197617941,  5.506147787799653,
          0.0017394231295098095, -3.151708823228039, -7.421134271637109,
             -9.121630467226948,  -8.19553134001647, -4.084845977909756,
            -3.3471405705705615, -0.609890765045118, 0.6064547579733404,
            -1.0472245501352617, 3.1033971660887394,  5.195470965021043,
             11.298653672855519, 13.326694113397973, 16.179313543651787,
              17.45005665622008, 16.700312024566877, 10.155839492293905
        ],
        exog: [ [Array] ],
        newExog: [ [Array] ]
      },
      result: [
        [
           23.834858289310922,  25.616766483546634,
           26.649978366484927,  28.149767139089793,
            29.80090299478742,   30.63404061398223,
           31.099174549544646,  30.796995327647913,
            29.63344461358344,  27.384883597474058,
           24.258592508764057,   20.66523012516985,
           16.461959335877612,  10.778594630082804,
            4.729207102716685, -1.4051787201827333,
           -7.147559941166158,  -12.25851653703733,
          -17.166871897789875,  -20.69421099265017,
          -23.436964816708677, -24.512538585109148,
          -25.417778886566403, -25.845485052675407
        ],
        [
          32.383248623448466,  86.93430506599908,
          167.69195231439193,  284.9795214568142,
           428.9110178991678,  597.7124419561235,
           789.5493024371243, 1000.1221976608723,
           1226.777212174488,  1467.063091676959,
          1718.5876954922085,  1979.461856116068,
           2248.065993010299,  2523.017193595188,
           2803.181980100002, 3087.6176823478645,
           3375.544221405373,  3666.321970160712,
           3959.425624267539, 4254.4248681057115,
           4550.968124509848,  4848.768271513382,
           5147.591108282911,  5447.245791436911
        ]
      ]
    }

Chrome 4kB size limit

When loading a bundled script with the arima module Chrome throws:

Uncaught RangeError: WebAssembly.Compile is disallowed on the main thread, if the buffer size is larger than 4KB. Use WebAssembly.compile, or compile on a worker thread.

Related: webpack/webpack#6475

I quite agree with the @jdalton reply there:

Imposing arbitrary limits on APIs is a bad practice. Super disappointed in Chrome's direction on this. It's fine to encourage async use but to offer a sync API and then make it broken is super wonky.

But we have what we have. So current workaround is to use WebWorkers as suggested previously (#8) or update the package to use async loading. What do you think?

Any way to serialize or rehydrate without retraining?

I need to be able to do the following:

  1. Train on one computer and upload the model for prediction on a server.
  2. Repeatedly apply a model to different circumstances.

I think I could solve both problems if there were a way to serialize and deserialize ARIMA instances.

I experimented with serializing ARIMA instances via JSON.stringify and deserializing them into stub ARIMA instances, but the resulting predictions are wildly different, so that didn't work.

When I run command 'npm install arima',throw error.

When I run command 'npm install arima',throw error.
wyf@wyf-virtual-machine:~/arima-master$ npm install arima
npm ERR! code ENOSELF
npm ERR! Refusing to install package with name "arima" under a package
npm ERR! also called "arima". Did you name your project the same
npm ERR! as the dependency you're installing?
npm ERR!
npm ERR! For more information, see:
npm ERR! https://docs.npmjs.com/cli/install#limitations-of-npms-install-algorithm

npm ERR! A complete log of this run can be found in:
npm ERR! /home/wyf/.npm/_logs/2024-03-17T12_41_50_999Z-debug.log

Can I train on more than one time series?

In the examples in the code, it looks like I can only feed it one time series (contrary to say a tensorflow neural net, where I feed it many time series).

What if my dataset is something like:

  • Series 1: 1,2,3,300
  • Series 2: 4,5,6,600
  • Series 3: 10,11,12,1200

How do I get this library to provide useful predictions?

Would just "stitching"/concatenating the series together into a single series work? That somehow feels wrong.

Thanks for anyone with any idea about this.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.