最近要用ARIMA模型預測使用者的數量變化,是以調研了一下ARIMA模型,最後用JAVA實作了ARIMA算法。
一、ARIMA原理
ARIMA的原理主要參考的是ARIMA原理。
二、JAVA實作
弄懂了原理,用JAVA進行了實作,主要參考的步驟是ARIMA實作步驟, JAVA 代碼如下
(1)AR類,用于建構AR模型
package arima;
import java.util.*;
public class AR {
double[] stdoriginalData={};
int p;
ARMAMath armamath=new ARMAMath();
/**
* AR模型
* @param stdoriginalData
* @param p //p為MA模型階數
*/
public AR(double [] stdoriginalData,int p)
{
this.stdoriginalData=new double[stdoriginalData.length];
System.arraycopy(stdoriginalData, 0, this.stdoriginalData, 0, stdoriginalData.length);
this.p=p;
}
/**
* 傳回AR模型參數
* @return
*/
public Vector<double[]> ARmodel()
{
Vector<double[]> v=new Vector<double[]>();
v.add(armamath.parcorrCompute(stdoriginalData, p, 0));
return v;//得到了自回歸系數
}
}
(2)MA類,用于建構MA模型
package arima;
import java.util.Vector;
import arima.ARMAMath;
public class MA {
double[] stdoriginalData={};
int q;
ARMAMath armamath=new ARMAMath();
/** MA模型
* @param stdoriginalData //預處理過後的資料
* @param q //q為MA模型階數
*/
public MA(double [] stdoriginalData,int q)
{
this.stdoriginalData=new double[stdoriginalData.length];
System.arraycopy(stdoriginalData, 0, this.stdoriginalData, 0, stdoriginalData.length);
this.q=q;
}
/**
* 傳回MA模型參數
* @return
*/
public Vector<double[]> MAmodel()
{
Vector<double[]> v=new Vector<double[]>();
v.add(armamath.getMApara(armamath.autocorGrma(stdoriginalData,q), q));
return v;//拿到MA模型裡面的參數值
}
}
(3)ARMA類,用于建構ARMA模型
package arima;
import java.util.*;
public class ARMA {
double[] stdoriginalData={};
int p;
int q;
ARMAMath armamath=new ARMAMath();
/**
* ARMA模型
* @param stdoriginalData
* @param p,q //p,q為MA模型階數
*/
public ARMA(double [] stdoriginalData,int p,int q)
{
this.stdoriginalData=new double[stdoriginalData.length];
System.arraycopy(stdoriginalData, 0, this.stdoriginalData, 0, stdoriginalData.length);
this.p=p;
this.q=q;
}
public Vector<double[]> ARMAmodel()
{
double[] arcoe=armamath.parcorrCompute(stdoriginalData, p, q);
double[] autocorData=getautocorofMA(p, q, stdoriginalData, arcoe);
double[] macoe=armamath.getMApara(autocorData, q);//得到MA模型裡面的參數值
Vector<double[]> v=new Vector<double[]>();
v.add(arcoe);
v.add(macoe);
return v;
}
/**
* 得到MA的自相關系數
* @param p
* @param q
* @param stdoriginalData
* @param autoCordata
* @return
*/
public double[] getautocorofMA(int p,int q,double[] stdoriginalData,double[] autoRegress)
{
int temp=0;
double[] errArray=new double[stdoriginalData.length-p];
int count=0;
for(int i=p;i<stdoriginalData.length;i++)
{
temp=0;
for(int j=1;j<=p;j++)
temp+=stdoriginalData[i-j]*autoRegress[j-1];
errArray[count++]=stdoriginalData[i]-temp;//儲存估計殘差序列
}
return armamath.autocorGrma(errArray, q);
}
}
(4)ARIMA類,用于建構ARIMA模型
package arima;
import arima.ARMAMath;
import java.util.*;
public class ARIMA {
double[] originalData={};
double[] originalDatafirDif={};
double[] originalDatasecDif={};
double[] originalDatathiDif={};
double[] originalDataforDif={};
double[] originalDatafriDif={};
ARMAMath armamath=new ARMAMath();
double stderrDara=0;
double avgsumData=0;
Vector<double[]> armaARMAcoe=new Vector<double[]>();
Vector<double[]> bestarmaARMAcoe=new Vector<double[]>();
int typeofPredeal=0;
/**
* 構造函數
* @param originalData 原始時間序列資料
*/
public ARIMA(double [] originalData,int typeofPredeal)
{
this.originalData=originalData;
this.typeofPredeal=typeofPredeal;//資料預處理類型 1:一階普通查分7:季節性差分
}
/**
* 原始資料标準化處理:一階季節性差分
* @return 差分過後的資料
*/
public double[] preDealDif(double[] originalData)
{
//seasonal Difference:Peroid=7
double []tempData=new double[originalData.length-7];
for(int i=0;i<originalData.length-7;i++)
{
tempData[i]=originalData[i+7]-originalData[i];
}
return tempData;
}
/**
*
*/
public double[] preFirDif(double[] originalData)
{
// Difference:Peroid=1
double []tempData=new double[originalData.length-1];
for(int i=0;i<originalData.length-1;i++)
{
tempData[i]=originalData[i+1]-originalData[i];
}
return tempData;
}
/**
* 原始資料标準化處理:Z-Score歸一化
* @param 待處理資料
* @return 歸一化過後的資料
*/
public double[] preDealNor(double[] tempData)
{
//Z-Score
avgsumData=armamath.avgData(tempData);
stderrDara=armamath.stderrData(tempData);
for(int i=0;i<tempData.length;i++)
{
tempData[i]=(tempData[i]-avgsumData)/stderrDara;
}
return tempData;
}
public modelandpara getARIMAmodel(int[] bestmodel)
{
double[] stdoriginalData=null;
if(typeofPredeal==0)
{
stdoriginalData=new double[originalData.length];
System.arraycopy(originalData, 0, stdoriginalData, 0,originalData.length);
}
else if(typeofPredeal==1) //原始資料一階普通差分處理
{
originalDatafirDif=new double[this.preFirDif(originalData).length];//原始資料一階普通差分處理
System.arraycopy(this.preFirDif(originalData), 0, originalDatafirDif, 0,originalDatafirDif.length);
stdoriginalData=new double[originalDatafirDif.length];
System.arraycopy(originalDatafirDif, 0, stdoriginalData, 0,originalDatafirDif.length);
}
else if (typeofPredeal==2)
{
originalDatafirDif=new double[this.preFirDif(originalData).length];//原始資料一階普通差分處理
System.arraycopy(this.preFirDif(originalData), 0, originalDatafirDif, 0,originalDatafirDif.length);
originalDatasecDif=new double[this.preFirDif(originalDatafirDif).length];
System.arraycopy(this.preFirDif(originalDatafirDif), 0, originalDatasecDif, 0,originalDatasecDif.length);
stdoriginalData=new double[originalDatasecDif.length];
System.arraycopy(originalDatasecDif, 0, stdoriginalData, 0,originalDatasecDif.length);
}
else if(typeofPredeal==3)
{
originalDatafirDif=new double[this.preFirDif(originalData).length];//原始資料一階普通差分處理
System.arraycopy(this.preFirDif(originalData), 0, originalDatafirDif, 0,originalDatafirDif.length);
originalDatasecDif=new double[this.preFirDif(originalDatafirDif).length];
System.arraycopy(this.preFirDif(originalDatafirDif), 0, originalDatasecDif, 0,originalDatasecDif.length);
originalDatathiDif=new double[this.preFirDif(originalDatasecDif).length];
System.arraycopy(this.preFirDif(originalDatasecDif), 0, originalDatathiDif, 0,originalDatathiDif.length);
stdoriginalData=new double[originalDatathiDif.length];
System.arraycopy(originalDatathiDif, 0, stdoriginalData, 0,originalDatathiDif.length);
}
else if(typeofPredeal==4)
{
originalDatafirDif=new double[this.preFirDif(originalData).length];//原始資料一階普通差分處理
System.arraycopy(this.preFirDif(originalData), 0, originalDatafirDif, 0,originalDatafirDif.length);
originalDatasecDif=new double[this.preFirDif(originalDatafirDif).length];
System.arraycopy(this.preFirDif(originalDatafirDif), 0, originalDatasecDif, 0,originalDatasecDif.length);
originalDatathiDif=new double[this.preFirDif(originalDatasecDif).length];
System.arraycopy(this.preFirDif(originalDatasecDif), 0, originalDatathiDif, 0,originalDatathiDif.length);
originalDataforDif=new double[this.preFirDif(originalDatathiDif).length];
System.arraycopy(this.preFirDif(originalDatathiDif), 0, originalDataforDif, 0,originalDataforDif.length);
stdoriginalData=new double[originalDataforDif.length];
System.arraycopy(originalDataforDif, 0, stdoriginalData, 0,originalDataforDif.length);
}
else if(typeofPredeal==5)
{
originalDatafirDif=new double[this.preFirDif(originalData).length];//原始資料一階普通差分處理
System.arraycopy(this.preFirDif(originalData), 0, originalDatafirDif, 0,originalDatafirDif.length);
originalDatasecDif=new double[this.preFirDif(originalDatafirDif).length];
System.arraycopy(this.preFirDif(originalDatafirDif), 0, originalDatasecDif, 0,originalDatasecDif.length);
originalDatathiDif=new double[this.preFirDif(originalDatasecDif).length];
System.arraycopy(this.preFirDif(originalDatasecDif), 0, originalDatathiDif, 0,originalDatathiDif.length);
originalDataforDif=new double[this.preFirDif(originalDatathiDif).length];
System.arraycopy(this.preFirDif(originalDatathiDif), 0, originalDataforDif, 0,originalDataforDif.length);
originalDatafriDif=new double[this.preFirDif(originalDataforDif).length];
System.arraycopy(this.preFirDif(originalDataforDif), 0, originalDatafriDif, 0,originalDatafriDif.length);
stdoriginalData=new double[originalDatafriDif.length];
System.arraycopy(originalDatafriDif, 0, stdoriginalData, 0,originalDatafriDif.length);
}
else//原始資料季節性差分處理
{
stdoriginalData=new double[this.preDealDif(originalData).length];
System.arraycopy(this.preDealDif(originalData), 0, stdoriginalData, 0,this.preDealDif(originalData).length);
}
armaARMAcoe.clear();
bestarmaARMAcoe.clear();
if(bestmodel[0]==0)
{
MA ma=new MA(stdoriginalData, bestmodel[1]);
armaARMAcoe=ma.MAmodel(); //拿到ma模型的參數
}
else if(bestmodel[1]==0)
{
AR ar=new AR(stdoriginalData, bestmodel[0]);
armaARMAcoe=ar.ARmodel(); //拿到ar模型的參數
}
else
{
ARMA arma=new ARMA(stdoriginalData, bestmodel[0], bestmodel[1]);
armaARMAcoe=arma.ARMAmodel();//拿到arma模型的參數
}
bestarmaARMAcoe=armaARMAcoe;
modelandpara mp=new modelandpara(bestmodel, bestarmaARMAcoe);
return mp;
}
/**
* 得到ARMA模型=[p,q]
* @return ARMA模型的階數資訊
*//*
public modelandpara getARIMAmodel()
{
double[] stdoriginalData=null;
if(typeofPredeal==0)
{
stdoriginalData=new double[originalData.length];
System.arraycopy(originalData, 0, stdoriginalData, 0,originalData.length);
}
else if(typeofPredeal==1) //原始資料一階普通差分處理
{
originalDatafirDif=new double[this.preFirDif(originalData).length];//原始資料一階普通差分處理
System.arraycopy(this.preFirDif(originalData), 0, originalDatafirDif, 0,originalDatafirDif.length);
stdoriginalData=new double[originalDatafirDif.length];
System.arraycopy(originalDatafirDif, 0, stdoriginalData, 0,originalDatafirDif.length);
}
else if (typeofPredeal==2)
{
originalDatafirDif=new double[this.preFirDif(originalData).length];//原始資料一階普通差分處理
System.arraycopy(this.preFirDif(originalData), 0, originalDatafirDif, 0,originalDatafirDif.length);
originalDatasecDif=new double[this.preFirDif(originalDatafirDif).length];
System.arraycopy(this.preFirDif(originalDatafirDif), 0, originalDatasecDif, 0,originalDatasecDif.length);
stdoriginalData=new double[originalDatasecDif.length];
System.arraycopy(originalDatasecDif, 0, stdoriginalData, 0,originalDatasecDif.length);
}
else if(typeofPredeal==3)
{
originalDatafirDif=new double[this.preFirDif(originalData).length];//原始資料一階普通差分處理
System.arraycopy(this.preFirDif(originalData), 0, originalDatafirDif, 0,originalDatafirDif.length);
originalDatasecDif=new double[this.preFirDif(originalDatafirDif).length];
System.arraycopy(this.preFirDif(originalDatafirDif), 0, originalDatasecDif, 0,originalDatasecDif.length);
originalDatathiDif=new double[this.preFirDif(originalDatasecDif).length];
System.arraycopy(this.preFirDif(originalDatasecDif), 0, originalDatathiDif, 0,originalDatathiDif.length);
stdoriginalData=new double[originalDatathiDif.length];
System.arraycopy(originalDatathiDif, 0, stdoriginalData, 0,originalDatathiDif.length);
}
else if(typeofPredeal==4)
{
originalDatafirDif=new double[this.preFirDif(originalData).length];//原始資料一階普通差分處理
System.arraycopy(this.preFirDif(originalData), 0, originalDatafirDif, 0,originalDatafirDif.length);
originalDatasecDif=new double[this.preFirDif(originalDatafirDif).length];
System.arraycopy(this.preFirDif(originalDatafirDif), 0, originalDatasecDif, 0,originalDatasecDif.length);
originalDatathiDif=new double[this.preFirDif(originalDatasecDif).length];
System.arraycopy(this.preFirDif(originalDatasecDif), 0, originalDatathiDif, 0,originalDatathiDif.length);
originalDataforDif=new double[this.preFirDif(originalDatathiDif).length];
System.arraycopy(this.preFirDif(originalDatathiDif), 0, originalDataforDif, 0,originalDataforDif.length);
stdoriginalData=new double[originalDataforDif.length];
System.arraycopy(originalDataforDif, 0, stdoriginalData, 0,originalDataforDif.length);
}
else if(typeofPredeal==5)
{
originalDatafirDif=new double[this.preFirDif(originalData).length];//原始資料一階普通差分處理
System.arraycopy(this.preFirDif(originalData), 0, originalDatafirDif, 0,originalDatafirDif.length);
originalDatasecDif=new double[this.preFirDif(originalDatafirDif).length];
System.arraycopy(this.preFirDif(originalDatafirDif), 0, originalDatasecDif, 0,originalDatasecDif.length);
originalDatathiDif=new double[this.preFirDif(originalDatasecDif).length];
System.arraycopy(this.preFirDif(originalDatasecDif), 0, originalDatathiDif, 0,originalDatathiDif.length);
originalDataforDif=new double[this.preFirDif(originalDatathiDif).length];
System.arraycopy(this.preFirDif(originalDatathiDif), 0, originalDataforDif, 0,originalDataforDif.length);
originalDatafriDif=new double[this.preFirDif(originalDataforDif).length];
System.arraycopy(this.preFirDif(originalDataforDif), 0, originalDatafriDif, 0,originalDatafriDif.length);
stdoriginalData=new double[this.preFirDif(originalDatafriDif).length];
System.arraycopy(this.preFirDif(originalDatafriDif), 0, stdoriginalData, 0,originalDatafriDif.length);
}
else//原始資料季節性差分處理
{
stdoriginalData=new double[this.preDealDif(originalData).length];
System.arraycopy(this.preDealDif(originalData), 0, stdoriginalData, 0,this.preDealDif(originalData).length);
}
int paraType=0;
double minAIC=9999999;
int bestModelindex=0;
int[][] model=new int[][]{{0,1},{1,0},{1,1},{0,2},{2,0},{2,2},{1,2},{2,1},{3,0},{0,3},{3,1},{1,3},{3,2},{2,3},{3,3}};
//對模型進行疊代,選出平均預測誤差最小的模型作為我們的模型
for(int i=0;i<model.length;i++)
{
if(model[i][0]==0)
{
MA ma=new MA(stdoriginalData, model[i][1]);
armaARMAcoe=ma.MAmodel(); //拿到ma模型的參數
paraType=1;
}
else if(model[i][1]==0)
{
AR ar=new AR(stdoriginalData, model[i][0]);
armaARMAcoe=ar.ARmodel(); //拿到ar模型的參數
paraType=2;
}
else
{
ARMA arma=new ARMA(stdoriginalData, model[i][0], model[i][1]);
armaARMAcoe=arma.ARMAmodel();//拿到arma模型的參數
paraType=3;
}
double temp=getmodelAIC(armaARMAcoe,stdoriginalData,paraType);
if (temp<minAIC)
{
bestModelindex=i;
minAIC=temp;
bestarmaARMAcoe=armaARMAcoe;
}
}
modelandpara mp=new modelandpara(model[bestModelindex], bestarmaARMAcoe);
return mp;
}*/
/**
* 計算ARMA模型的AIC
* @param para 裝載模型的參數資訊
* @param stdoriginalData 預處理過後的原始資料
* @param type 1:MA;2:AR;3:ARMA
* @return 模型的AIC值
*/
public double getmodelAIC(Vector<double[]> para,double[] stdoriginalData,int type)
{
double temp=0;
double temp2=0;
double sumerr=0;
int p=0;//ar1,ar2,...,sig2
int q=0;//sig2,ma1,ma2...
int n=stdoriginalData.length;
Random random=new Random();
if(type==1)
{
double[] maPara=new double[para.get(0).length];
System.arraycopy(para.get(0), 0, maPara, 0, para.get(0).length);
q=maPara.length;
double[] err=new double[q]; //error(t),error(t-1),error(t-2)...
for(int k=q-1;k<n;k++)
{
temp=0;
for(int i=1;i<q;i++)
{
temp+=maPara[i]*err[i];
}
//産生各個時刻的噪聲
for(int j=q-1;j>0;j--)
{
err[j]=err[j-1];
}
err[0]=random.nextGaussian()*Math.sqrt(maPara[0]);
//估計的方差之和
sumerr+=(stdoriginalData[k]-(temp))*(stdoriginalData[k]-(temp));
}
//return (n-(q-1))*Math.log(sumerr/(n-(q-1)))+(q)*Math.log(n-(q-1));//AIC 最小二乘估計
return (n-(q-1))*Math.log(sumerr/(n-(q-1)))+(q+1)*2;
}
else if(type==2)
{
double[] arPara=new double[para.get(0).length];
System.arraycopy(para.get(0), 0, arPara, 0, para.get(0).length);
p=arPara.length;
for(int k=p-1;k<n;k++)
{
temp=0;
for(int i=0;i<p-1;i++)
{
temp+=arPara[i]*stdoriginalData[k-i-1];
}
//估計的方差之和
sumerr+=(stdoriginalData[k]-temp)*(stdoriginalData[k]-temp);
}
return (n-(q-1))*Math.log(sumerr/(n-(q-1)))+(p+1)*2;
//return (n-(p-1))*Math.log(sumerr/(n-(p-1)))+(p)*Math.log(n-(p-1));//AIC 最小二乘估計
}
else
{
double[] arPara=new double[para.get(0).length];
System.arraycopy(para.get(0), 0, arPara, 0, para.get(0).length);
double[] maPara=new double[para.get(1).length];
System.arraycopy(para.get(1), 0, maPara, 0, para.get(1).length);
p=arPara.length;
q=maPara.length;
double[] err=new double[q]; //error(t),error(t-1),error(t-2)...
for(int k=p-1;k<n;k++)
{
temp=0;
temp2=0;
for(int i=0;i<p-1;i++)
{
temp+=arPara[i]*stdoriginalData[k-i-1];
}
for(int i=1;i<q;i++)
{
temp2+=maPara[i]*err[i];
}
//産生各個時刻的噪聲
for(int j=q-1;j>0;j--)
{
err[j]=err[j-1];
}
//System.out.println("predictBeforeDiff="+1);
err[0]=random.nextGaussian()*Math.sqrt(maPara[0]);
//估計的方差之和
sumerr+=(stdoriginalData[k]-(temp2+temp))*(stdoriginalData[k]-(temp2+temp));
}
return (n-(q-1))*Math.log(sumerr/(n-(q-1)))+(p+q)*2;
//return (n-(p-1))*Math.log(sumerr/(n-(p-1)))+(p+q-1)*Math.log(n-(p-1));//AIC 最小二乘估計
}
}
/**
* 對預測值進行反差分處理
* @param predictValue 預測的值
* @return 反差分過後的預測值
*/
public int aftDeal(int predictValue)
{
int temp=0;
//System.out.println("predictBeforeDiff="+predictValue);
if(typeofPredeal==0)
temp=((int)predictValue);
else if(typeofPredeal==1)
temp=(int)(predictValue+originalData[originalData.length-1]);
else if(typeofPredeal==2)
temp=(int)(predictValue+originalDatafirDif[originalDatafirDif.length-1]+originalData[originalData.length-1]);
else if(typeofPredeal==3)
temp=(int)(predictValue+originalDatasecDif[originalDatasecDif.length-1]+originalDatafirDif[originalDatafirDif.length-1]+originalData[originalData.length-1]);
else if(typeofPredeal==4)
temp=(int)(predictValue+originalDatathiDif[originalDatathiDif.length-1]+originalDatasecDif[originalDatasecDif.length-1]+originalDatafirDif[originalDatafirDif.length-1]+originalData[originalData.length-1]);
else if(typeofPredeal==5)
temp=(int)(predictValue+originalDataforDif[originalDataforDif.length-1]+originalDatathiDif[originalDatathiDif.length-1]+originalDatasecDif[originalDatasecDif.length-1]+originalDatafirDif[originalDatafirDif.length-1]+originalData[originalData.length-1]);
else
temp=(int)(predictValue+originalData[originalData.length-7]);
return temp>0?temp:0;
}
/**
* 進行一步預測
* @param p ARMA模型的AR的階數
* @param q ARMA模型的MA的階數
* @return 預測值
*/
public int predictValue(int p,int q,Vector<double[]> bestpara)
{
double[] stdoriginalData=null;
if (typeofPredeal==0)
{
stdoriginalData=new double[originalData.length];
System.arraycopy(originalData, 0, stdoriginalData, 0, originalData.length);
}
else if(typeofPredeal==1)
{
stdoriginalData=new double[originalDatafirDif.length];
System.arraycopy(originalDatafirDif, 0, stdoriginalData, 0, originalDatafirDif.length);
}
else if(typeofPredeal==2)
{
stdoriginalData=new double[originalDatasecDif.length];//普通二階差分處理
System.arraycopy(originalDatasecDif, 0, stdoriginalData, 0, originalDatasecDif.length);
}
else if(typeofPredeal==3)
{
stdoriginalData=new double[originalDatathiDif.length];//普通三階差分處理
System.arraycopy(originalDatathiDif, 0, stdoriginalData, 0, originalDatathiDif.length);
}
else if(typeofPredeal==4)
{
stdoriginalData=new double[originalDataforDif.length];//普通四階差分處理
System.arraycopy(originalDataforDif, 0, stdoriginalData, 0, originalDataforDif.length);
}
else if(typeofPredeal==5)
{
stdoriginalData=new double[originalDatafriDif.length];//普通五階差分處理
System.arraycopy(originalDatafriDif, 0, stdoriginalData, 0, originalDatafriDif.length);
}
else
{
stdoriginalData=new double[this.preDealDif(originalData).length];//季節性一階差分
System.arraycopy(this.preDealDif(originalData), 0, stdoriginalData, 0, this.preDealDif(originalData).length);
}
//System.out.println("typeofPredeal= "+typeofPredeal+typeofPredeal);
// for(int i=0;i<originalDatafirDif.length;i++)
// System.out.println(originalDatafirDif[i]);
//
int predict=0;
int n=stdoriginalData.length;
double temp=0,temp2=0;
double[] err=new double[q+1];
Random random=new Random();
if(p==0)
{
double[] maPara=bestpara.get(0);
for(int k=q;k<n;k++)
{
temp=0;
for(int i=1;i<=q;i++)
{
temp+=maPara[i]*err[i];
}
//産生各個時刻的噪聲
for(int j=q;j>0;j--)
{
err[j]=err[j-1];
}
err[0]=random.nextGaussian()*Math.sqrt(maPara[0]);
}
predict=(int)(temp); //産生預測
//System.out.println("predict=q "+predict);
}
else if(q==0)
{
double[] arPara=bestpara.get(0);
for(int k=p;k<n;k++)
{
temp=0;
for(int i=0;i<p;i++)
{
temp+=arPara[i]*stdoriginalData[k-i-1];
}
}
predict=(int)(temp);
//System.out.println("predict= p"+predict);
}
else
{
double[] arPara=bestpara.get(0);
double[] maPara=bestpara.get(1);
err=new double[q+1]; //error(t),error(t-1),error(t-2)...
for(int k=p;k<n;k++)
{
temp=0;
temp2=0;
for(int i=0;i<p;i++)
{
temp+=arPara[i]*stdoriginalData[k-i-1];
}
for(int i=1;i<=q;i++)
{
temp2+=maPara[i]*err[i];
}
//産生各個時刻的噪聲
for(int j=q;j>0;j--)
{
err[j]=err[j-1];
}
err[0]=random.nextGaussian()*Math.sqrt(maPara[0]);
}
predict=(int)(temp2+temp);
//System.out.println("predict=p,q "+predict);
}
return predict;
}
}
class modelandpara
{
int[] model;
Vector<double[]> para;
public modelandpara(int[] model,Vector<double[]> para)
{
this.model=model;
this.para=para;
}
}
(5)ARIMAiFlex類,用于建構AR模型
package arima;
import java.util.Hashtable;
import java.util.*;
public class ARIMAiFlex {
int count=0;
int [] model=new int[2];
int[][] modelOri=new int[][]{{0,1},{1,0},{1,1},{0,2},{2,0},{2,2},{1,2},{2,1},{3,0},{0,3},{3,1},{1,3},{3,2},{2,3},{3,3}};
modelandpara mp=null;
int predictValuetemp=0;
int avgpredictValue=0;
int[] bestmodel=new int[2];
double[][] predictErr=new double[7][modelOri.length];
double minpreDicterr=9999999;
int bestpreDictValue=0;
int bestDif=0;
int memory=10;
double[] traindataArray=null;
double validate=0;
double[] predataArray=null;
double[] dataArrayPredict=null;
Hashtable<String,Integer> ht=new Hashtable<String,Integer>();
Hashtable<String,Integer> ht2=new Hashtable<String,Integer>();
double thresvalue=0;
public ARIMAiFlex(double []dataArray)
{
//模型訓練
System.out.println("begin to train...");
Vector<int[]> trainResult=this.Train(dataArray);
//預測資料初始化
int tempPredict=0;
System.out.println("begin to predict...");
for(int i=0;i<trainResult.size();i++)
{
thresvalue=0;
System.out.println("predict..."+i+"/"+trainResult.size());
tempPredict+=this.Predict(dataArray,memory,trainResult.get(i),0);
}
tempPredict=tempPredict/trainResult.size();
System.out.println("tempPredict="+tempPredict);
}
public void preData(double[] dataArray,int type,int memory)
{
// ++
//**********
//**********
this.traindataArray=new double[dataArray.length-memory];
System.arraycopy(dataArray, type, traindataArray, 0, traindataArray.length);
this.validate=dataArray[traindataArray.length+type];//最後一個值作為訓練時候的驗證值。
}
public int Predict(double[] dataArray,int memory,int[] trainResult,double fanwei)
{
if(memory<0)
return (int)(dataArray[dataArray.length-1]+dataArray[dataArray.length-2])/2;
this.predataArray=new double[dataArray.length-memory];
System.arraycopy(dataArray, memory, predataArray, 0, predataArray.length);
ARIMA arima=new ARIMA(predataArray,trainResult[0]); //對原始資料做幾階差分處理0,1,2,7
//參數初始化
int count=100;
int predictValuetemp=0;
//統計每種模型的預測平均值
while(count-->0)
{
mp=arima.getARIMAmodel(modelOri[trainResult[1]]);
predictValuetemp+=arima.aftDeal(arima.predictValue(mp.model[0],mp.model[1],mp.para));
}
predictValuetemp/=100;
//System.out.println("Predict value is:"+predictValuetemp);
if(Math.abs(predictValuetemp-predataArray[predataArray.length-1])/predataArray[predataArray.length-1]>(0.3+fanwei))
{
thresvalue++;
System.out.println("thresvalue="+thresvalue);
//重新訓練和預測
//模型訓練
Vector<int[]> trainResult2=this.Train(dataArray);
//預測資料初始化
int tempPredict=0;
for(int i=0;i<trainResult2.size();i++)
{
tempPredict+=this.Predict(dataArray,(memory-5),trainResult2.get(i),0.1*thresvalue);
}
tempPredict=tempPredict/trainResult2.size();
//System.out.println("tempPredict="+tempPredict);
return tempPredict;
}
else
{
return predictValuetemp;
}
}
public Vector<int[]> Train(double[] dataArray)
{
int memory=60;//訓練的時候預測的值的個數
for(int datai=0;datai<memory;datai++)
{
//System.out.println("train... "+datai+"/"+memory);
this.preData(dataArray, datai,memory);//準備訓練資料
for(int diedai=0;diedai<7;diedai++)
{
ARIMA arima=new ARIMA(traindataArray,diedai); //對原始資料做幾階差分處理0,1,2,7
//統計每種模型的預測平均值
for(int modeli=0;modeli<modelOri.length;modeli++)
{
//參數初始化
count=100;
predictValuetemp=0;
while(count-->0)
{
mp=arima.getARIMAmodel(modelOri[modeli]);
predictValuetemp+=arima.aftDeal(arima.predictValue(mp.model[0],mp.model[1],mp.para));
//System.out.println("predictValuetemp"+predictValuetemp);
}
predictValuetemp/=100;
//計算訓練誤差
predictErr[diedai][modeli]+=Math.abs(100*(predictValuetemp-validate)/validate);
}
}
}
double minvalue=10000000;
int tempi=0;
int tempj=0;
Vector<int[]> bestmodelVector=new Vector<int[]>();
int[][] flag=new int[7][modelOri.length];
for(int ii=0;ii<5;ii++)
{ minvalue=10000000;
for(int i=0;i<predictErr.length;i++)
{
for(int j=0;j<predictErr[i].length;j++)
{
if(flag[i][j]==0)
{
if(predictErr[i][j]<minvalue)
{
minvalue=predictErr[i][j];
tempi=i;
tempj=j;
flag[i][j]=1;
}
}
}
}
bestmodelVector.add(new int[]{tempi,tempj});
//System.out.println("best model:Dif="+tempi+"..."+"index of model="+tempj);
System.out.println("ARIMAAvgPredictErr="+minvalue/memory);
}
// for(int i=0;i<predictErr.length;i++)
// for(int j=0;j<predictErr[i].length;j++)
// {
// System.out.println("Dif "+i+" Model index"+j+"= "+predictErr[i][j]/memory);
// }
//System.out.println("--tempi="+tempi+"~~~"+"tempj="+tempj);
System.out.println("----------------------------------------");
return bestmodelVector;
}
}
(6)ARMAMath類,常見的資料計算任務
package arima;
import Jama.Matrix;
public class ARMAMath
{
public double avgData(double[] dataArray)
{
return this.sumData(dataArray)/dataArray.length;
}
public double sumData(double[] dataArray)
{
double sumData=0;
for(int i=0;i<dataArray.length;i++)
{
sumData+=dataArray[i];
}
return sumData;
}
public double stderrData(double[] dataArray)
{
return Math.sqrt(this.varerrData(dataArray));
}
public double varerrData(double[] dataArray)
{
double variance=0;
double avgsumData=this.avgData(dataArray);
for(int i=0;i<dataArray.length;i++)
{
dataArray[i]-=avgsumData;
variance+=dataArray[i]*dataArray[i];
}
return variance/dataArray.length;//variance error;
}
/**
* 計算自相關的函數 Tho(k)=Grma(k)/Grma(0)
* @param dataArray 數列
* @param order 階數
* @return
*/
public double[] autocorData(double[] dataArray,int order)
{
double[] autoCor=new double[order+1];
double varData=this.varerrData(dataArray);//标準化過後的方差
for(int i=0;i<=order;i++)
{
autoCor[i]=0;
for(int j=0;j<dataArray.length-i;j++)
{
autoCor[i]+=dataArray[j+i]*dataArray[j];
}
autoCor[i]/=(dataArray.length-i);
autoCor[i]/=varData;
}
return autoCor;
}
/**
* Grma
* @param dataArray
* @param order
* @return 序列的自相關系數
*/
public double[] autocorGrma(double[] dataArray,int order)
{
double[] autoCor=new double[order+1];
for(int i=0;i<=order;i++)
{
autoCor[i]=0;
for(int j=0;j<dataArray.length-i;j++)
{
autoCor[i]+=dataArray[j+i]*dataArray[j];
}
autoCor[i]/=(dataArray.length-i);
}
return autoCor;
}
/**
* 求偏自相關系數
* @param dataArray
* @param order
* @return
*/
public double[] parautocorData(double[] dataArray,int order)
{
double parautocor[]=new double[order];
for(int i=1;i<=order;i++)
{
parautocor[i-1]=this.parcorrCompute(dataArray, i,0)[i-1];
}
return parautocor;
}
/**
* 産生Toplize矩陣
* @param dataArray
* @param order
* @return
*/
public double[][] toplize(double[] dataArray,int order)
{//傳回toplize二維數組
double[][] toplizeMatrix=new double[order][order];
double[] atuocorr=this.autocorData(dataArray,order);
for(int i=1;i<=order;i++)
{
int k=1;
for(int j=i-1;j>0;j--)
{
toplizeMatrix[i-1][j-1]=atuocorr[k++];
}
toplizeMatrix[i-1][i-1]=1;
int kk=1;
for(int j=i;j<order;j++)
{
toplizeMatrix[i-1][j]=atuocorr[kk++];
}
}
return toplizeMatrix;
}
/**
* 解MA模型的參數
* @param autocorData
* @param q
* @return
*/
public double[] getMApara(double[] autocorData,int q)
{
double[] maPara=new double[q+1];//第一個存放噪聲參數,後面q個存放ma參數sigma2,ma1,ma2...
double[] tempmaPara=new double[q+1];
double temp=0;
boolean iterationFlag=true;
//解方程組
//疊代法解方程組
maPara[0]=1;//初始化
int count=10000;
while(iterationFlag&&count-->0)
{
temp=0;
for(int i=1;i<maPara.length;i++)
{
temp+=maPara[i]*maPara[i];
}
tempmaPara[0]=autocorData[0]/(1+temp);
for(int i=1;i<maPara.length;i++)
{
temp=0;
for(int j=1;j<maPara.length-i;j++)
{
temp+=maPara[j]*maPara[j+i];
}
tempmaPara[i]=-(autocorData[i]/tempmaPara[0]-temp);
}
iterationFlag=false;
for(int i=0;i<maPara.length;i++)
{
if(Math.abs(maPara[i]-tempmaPara[i])>0.00001)
{
iterationFlag=true;
break;
}
}
System.arraycopy(tempmaPara, 0, maPara, 0, tempmaPara.length);
}
return maPara;
}
/**
* 計算自回歸系數
* @param dataArray
* @param p
* @param q
* @return
*/
public double[] parcorrCompute(double[] dataArray,int p,int q)
{
double[][] toplizeArray=new double[p][p];//p階toplize矩陣;
double[] atuocorr=this.autocorData(dataArray,p+q);//傳回p+q階的自相關函數
double[] autocorrF=this.autocorGrma(dataArray, p+q);//傳回p+q階的自相關系數數
for(int i=1;i<=p;i++)
{
int k=1;
for(int j=i-1;j>0;j--)
{
toplizeArray[i-1][j-1]=atuocorr[q+k++];
}
toplizeArray[i-1][i-1]=atuocorr[q];
int kk=1;
for(int j=i;j<p;j++)
{
toplizeArray[i-1][j]=atuocorr[q+kk++];
}
}
Matrix toplizeMatrix = new Matrix(toplizeArray);//由二位數組轉換成二維矩陣
Matrix toplizeMatrixinverse=toplizeMatrix.inverse();//矩陣求逆運算
double[] temp=new double[p];
for(int i=1;i<=p;i++)
{
temp[i-1]=atuocorr[q+i];
}
Matrix autocorrMatrix=new Matrix(temp, p);
Matrix parautocorDataMatrix=toplizeMatrixinverse.times(autocorrMatrix); // [Fi]=[toplize]x[autocorr]';
//矩陣計算結果應該是按照[a b c]' 列向量存儲的
//System.out.println("row="+parautocorDataMatrix.getRowDimension()+" Col="+parautocorDataMatrix.getColumnDimension());
//parautocorDataMatrix.print(p, 2);//(輸出幾行,小數點後保留位數)
//System.out.println(parautocorDataMatrix.get(p-1,0));
double[] result=new double[parautocorDataMatrix.getRowDimension()+1];
for(int i=0;i<parautocorDataMatrix.getRowDimension();i++)
{
result[i]=parautocorDataMatrix.get(i,0);
}
//估算sigmat2
double sum2=0;
for(int i=0;i<p;i++)
for(int j=0;j<p;j++)
{
sum2+=result[i]*result[j]*autocorrF[Math.abs(i-j)];
}
result[result.length-1]=autocorrF[0]-sum2; //result數組最後一個存儲幹擾估計值
return result; //傳回0列的最後一個就是k階的偏自相關系數 pcorr[k]=傳回值
}
}
(7)test1,用于導入資料進行測試
package arima;
import java.io.*;
import java.util.ArrayList;
import java.util.Scanner;
public class test1 {
public static void main(String args[])
{
Scanner ino=null;
try {
/*********************************************************/
ArrayList<Double> arraylist=new ArrayList<Double>();
ino=new Scanner(new File("E:\\work\\Arima\\Arima\\Data\\ceshidata.txt"));
while(ino.hasNext())
{
arraylist.add(Double.parseDouble(ino.next()));
}
double[] dataArray=new double[arraylist.size()];
for(int i=0;i<dataArray.length;i++)
dataArray[i]=arraylist.get(i);
ARIMAiFlex myarima=new ARIMAiFlex(dataArray);
currentAlgorithm cc=new currentAlgorithm(dataArray);
/*********************************************************/
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
ino.close();
}
}
}
PS: 附上一個代碼的連結,希望能夠對需要的朋友有一點點幫助,收取了一分的資源下載下傳分,算是對作者的一點鼓勵,ARIMA JAVA實作,如有問題,可以在我的資料中找到聯系方式,望不吝賜教!
另外,完整的代碼已經托管到了gitHub: ARIMA github
-------------------------------------------------------------------------------------------------
您的支援是對我最大的鼓勵!