ARIMA模型预测产品销量

任务:做出一个时间序列预测模型,从而实现对一系列产品销量的月预测

你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。

方法:针对数据特征,采用了ARIMA模型。并成功实现了任务

在这里预设了8种数据预处理模型,从而使数据平稳,保证尽可能预测更多产品

`

# -*- coding: utf-8 -*-
import os
import math
import pandas as pd
import numpy as np
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
from statsmodels.tsa.stattools import adfuller
from statsmodels.tsa import arima_model
from statsmodels.stats.diagnostic import acorr_ljungbox
import warnings
warnings.filterwarnings("ignore")


def ARIMA_M0(series,n=3):
    '''
    只讨论ARIMA模型,预测,数字索引从1开始
    series:时间序列,值以月为单位输出,原始数据应该超过160天,不然可能报错
    n:需要往后预测的月个数
    '''
    #数据预处理与清洗
    series.index=pd.to_datetime(series.index)    
    series=series.resample('D').asfreq().fillna(0)
    series[(series/series.mean())>10]=int(4*series.mean())
    series=series.resample('M').sum()
    series[series<=0]=1
    #对清洗后的数据处理
    series = np.array(series)
    series = pd.Series(series.reshape(-1))
    currentDir = os.getcwd()#获得当前工作路径
    #差分数据处理
    ser_sqrt=np.sqrt(series)
    ser_sqrt1=ser_sqrt.diff(1)[1:]
    ser_sqrt2=ser_sqrt1.diff(1)[1:]
    ser_1=series.diff(1)[1:]
    ser_2=ser_1.diff(1)[1:]
    ser_pow=series**2
    ser_pow1=ser_pow.diff(1)[1:]
    ser_pow2=ser_pow1.diff(1)[1:]
    ser_log=np.log(series)
    ser_log1=ser_log.diff(1).dropna()
    ser_log2=ser_log1.diff(1).dropna()
    #创建数据列表
    SERIES={'原数1差':ser_1,'原数2差':ser_2,'原对1差':ser_log1,'原对2差':ser_log2,'原开1差':ser_sqrt1,'原开2差':ser_sqrt2,'原乘1差':ser_pow1,'原乘2差':ser_pow2}
    cont0=[]
    cont=[]
    for i in SERIES:
        #plot_acf(SERIES[i]).savefig(currentDir+'/一阶差分自相关图.png')
        #plot_pacf(SERIES[i]).savefig(currentDir+'/一阶差分偏自相关图.png')
        #单位根检验+白噪声检验
        unitP = adfuller(SERIES[i])
        noiseP = max(acorr_ljungbox(SERIES[i], lags=3)[-1])
        if unitP[1]<0.05 and unitP[0]<min(unitP[4].values()) and noiseP<=0.05:
            unitAssess = '单位根检验中p值为%f,小于0.05,白噪声检验中p值为%f,小于0.05,认为该序列判断为非白噪声平稳序列'%(unitP[1],noiseP)
            cont0.append(i)
        else:
            unitAssess = '单位根检验中p值为%f,白噪声检验中p值为%f,认为该序列不适合做ARIMA时间预测序列'%(unitP[1],noiseP)
            cont.append((i,unitAssess))
            
            #BIC准则确定p、q值
    for i in cont0:
        bics = list()
        for p in range(8):
            tmp = list()
            for q in range(5):
                if i=='原数1差':
                    try:
                        tmp.append(arima_model.ARIMA(series, (p, 1, q)).fit().bic)
                    except Exception as e:
                        #print(str(e))
                        tmp.append(1e+10)#加入一个很大的数
                elif i=='原开1差':
                    try:
                        tmp.append(arima_model.ARIMA(ser_sqrt, (p, 1, q)).fit().bic)
                    except Exception as e:
                        #print(str(e))
                        tmp.append(1e+10)#加入一个很大的数
                elif i=='原开2差':
                    try:
                        tmp.append(arima_model.ARIMA(ser_sqrt, (p, 2, q)).fit().bic)
                    except Exception as e:
                        #print(str(e))
                        tmp.append(1e+10)#加入一个很大的数
                elif i=='原乘1差':
                    try:
                        tmp.append(arima_model.ARIMA(ser_pow, (p, 1, q)).fit().bic)
                    except Exception as e:
                        #print(str(e))
                        tmp.append(1e+10)#加入一个很大的数
                elif i=='原乘2差':
                    try:
                        tmp.append(arima_model.ARIMA(ser_pow, (p, 2, q)).fit().bic)
                    except Exception as e:
                        #print(str(e))
                        tmp.append(1e+10)#加入一个很大的数
                elif i=='原对1差':
                    try:
                        tmp.append(arima_model.ARIMA(ser_log, (p, 1, q)).fit().bic)
                    except Exception as e:
                        #print(str(e))
                        tmp.append(1e+10)#加入一个很大的数
                elif i=='原对2差':
                    try:
                        tmp.append(arima_model.ARIMA(ser_log, (p, 2, q)).fit().bic)
                    except Exception as e:
                        #print(str(e))
                        tmp.append(1e+10)#加入一个很大的数
                else:
                    try:
                        tmp.append(arima_model.ARIMA(series, (p, 2, q)).fit().bic)
                    except Exception as e:
                        #print(str(e))
                        tmp.append(1e+10)#加入一个很大的数        
            bics.append(tmp)
        bics = pd.DataFrame(bics)
        p, q = bics.stack().idxmin()
        #print('BIC准则下确定p,q为%s,%s'%(p,q))
        #建模
        if i=='原数1差':
            model = arima_model.ARIMA(series,order=(p, 1, q)).fit()
        elif i=='原开1差':
            model = arima_model.ARIMA(ser_sqrt,order=(p, 1, q)).fit()
        elif i=='原开2差':   
            model = arima_model.ARIMA(ser_sqrt,order=(p, 2, q)).fit()
        elif i=='原乘1差':
            model = arima_model.ARIMA(ser_pow,order=(p, 1, q)).fit()
        elif i=='原乘2差':   
            model = arima_model.ARIMA(ser_pow,order=(p, 2, q)).fit()
        elif i=='原对1差':
            model = arima_model.ARIMA(ser_log,order=(p, 1, q)).fit()
        elif i=='原对2差':   
            model = arima_model.ARIMA(ser_log,order=(p, 2, q)).fit()
        else:
            model = arima_model.ARIMA(series,order=(p, 2, q)).fit()
        #白噪声残差检测
        noiseR = min(acorr_ljungbox(model.resid, lags=3)[-1])
        if noiseR>0.05:
            noiseAsse = '残差白噪声检验%f,大于0.05,认为该模型残差序列为白噪声.模型可用'%noiseR
            if i=='原开1差' or i=='原开2差':
                predict = (model.forecast(n)[0])**2
            elif i=='原对1差' or i=='原对2差':
                predict = np.exp(model.forecast(n)[0])
            elif i=='原乘1差' or i=='原乘2差':
                pdt_pow=model.forecast(n)[0]
                pdt_pow[pdt_pow<=0]=1
                predict =np.sqrt(pdt_pow)
            else:
                predict = model.forecast(n)[0]
            cont.append((i,'AR模型阶数p',p,'MA模型阶数q',q,'往后预测%d个月的序列'%(n),predict))
        else:
            noiseAsse = '残差白噪声检验中p值为%f,小于0.05,认为该模型残差序列为非白噪声,模型有待改进'%noiseR
            cont.append((i,'AR模型阶数p',p,'MA模型阶数q',q,noiseAsse))   
    return cont
  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值