本文共 11613 字,大约阅读时间需要 38 分钟。
最近要用ARIMA模型预测用户的数量变化,所以调研了一下ARIMA模型,最后用JAVA实现了ARIMA算法。
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 VectorARmodel() { Vector v=new Vector (); 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 VectorMAmodel() { Vector v=new Vector (); 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 VectorARMAmodel() { double[] arcoe=armamath.parcorrCompute(stdoriginalData, p, q); double[] autocorData=getautocorofMA(p, q, stdoriginalData, arcoe); double[] macoe=armamath.getMApara(autocorData, q);//得到MA模型里面的参数值 Vector v=new Vector (); 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
(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; VectorarmaARMAcoe=new Vector (); Vector bestarmaARMAcoe=new Vector (); 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 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 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 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 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 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 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 para; public modelandpara(int[] model,Vector 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; Hashtableht=new Hashtable (); Hashtable ht2=new Hashtable (); double thresvalue=0; public ARIMAiFlex(double []dataArray) { //模型训练 System.out.println("begin to train..."); Vector trainResult=this.Train(dataArray); //预测数据初始化 int tempPredict=0; System.out.println("begin to predict..."); for(int i=0;i
(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;i0;j--) { toplizeMatrix[i-1][j-1]=atuocorr[k++]; } toplizeMatrix[i-1][i-1]=1; int kk=1; for(int j=i;j 0) { temp=0; for(int i=1;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
(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 { /*********************************************************/ ArrayListarraylist=new ArrayList (); 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
完整代码托管在gitHub:
转载地址:http://midgi.baihongyu.com/