最近要用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(); } } }
时间: 2024-11-12 10:13:49