时间序列分析之 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();
		}
	}
	
}



郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。