天天看點

時間序列分析之 ARIMA 模型的JAVA實作

最近要用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

-------------------------------------------------------------------------------------------------

時間序列分析之 ARIMA 模型的JAVA實作
時間序列分析之 ARIMA 模型的JAVA實作

            您的支援是對我最大的鼓勵!