最近要用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 ARmodel()
{
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 Vector MAmodel()
{
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 Vector ARMAmodel()
{
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
{
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 armaARMAcoe=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
{
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
{
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[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)
{
o