请帮忙修改python实现的ARIMA模型代码

查看 76|回复 4
作者:SailZhao520   
我正在使用Python中的ARIMA模型尝试预测未来GMV成交额,但是我发现我的代码无法成功预测结果,并且最终输出不是我想要的2023年3月到2023年12月的GMV数据。
为了帮助理解代码,这是我的代码大概逻辑:
数据预处理
[ol]
  • 首先读取数据,数据的时间序列索引为日期;
  • 数据预处理包括以下步骤:
  • 根据具体情况截取需要预测部分的数据;
  • 将需要聚合的多个时间序列相加,得到总时间序列(即 GMV);
  • 对总时间序列进行差分操作,使其变得平稳,并进行 ADF 检验,确保差分后的时间序列是平稳的;
  • 最后为差分后的时间序列设置频率信息。

    [/ol]
    建立 ARIMA 模型
    [ol]
  • 确定 ARIMA 模型的阶数,即 AR、MA 和差分阶数;
  • 建立 ARIMA 模型并拟合;
  • 对未来需要预测的时间段进行预测,并得到未来时间段中 GMV 部分的预测结果。
    [/ol]
    输出预测结果并进行可视化
    [ol]
  • 对预测结果进行逆变换,还原出 GMV 部分的预测结果;
  • 对还原后的预测结果进行可视化,并和实际值进行对比。
    [/ol]
    这是源代码
    import pandas as pd
    import matplotlib
    matplotlib.use('TkAgg')
    import matplotlib.pyplot as plt
    from statsmodels.tsa.stattools import adfuller
    from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
    from statsmodels.tsa.arima.model import ARIMA
    import matplotlib.dates as mdates
    class ARIMAModel:
        def __init__(self, data_path):
            """
            通过指定数据文件路径初始化 ARIMA 模型类
            :param data_path: 数据文件路径
            """
            self.df = pd.read_csv(data_path, parse_dates=['date'], index_col='date')
        def preprocess_data(self):
            """
            对数据进行预处理,包括数据截取、聚合、差分以及数据检验
            """
            # 截取2021年4月到2023年2月的数据
            self.df = self.df.loc['2021-04':'2023-02']
            # 将 buyer_num 和 sales quantity 相乘得到总交易额
            self.df['GMV'] = self.df['buyer_num'] * self.df['sales quantity']
            # 聚合各个时间序列得到 GMV
            self.series = (
                    self.df['GMV']
                    + self.df['avg_purchase_freq']
                    + self.df['avg_purchase_volume']
                    + self.df['industry_count']
                    + self.df['avg_price']
            )
            # 执行差分
            self.diff_series = self.series.diff().dropna()
            # ADF 检验
            result = adfuller(self.diff_series.values.ravel())
            while result[1] > 0.05:
                print('差分后数据是非平稳的!')
                self.diff_series = self.diff_series.diff().dropna()
                result = adfuller(self.diff_series.values.ravel())
            if result[1]
    我已经尝试了一些方法,如适当调整模型参数、进行数据预处理等等,但是仍然无法得到预期的结果。我不确定是否我使用的库函数可能有问题,或者我的数据不适用于这种模型。如果有谁能够帮我修改代码,或者提供一些解决方案以解决这个问题,我将非常感激。非常感谢!
    这是我的数据集链接:https://pan.baidu.com/s/1RnznygK5dnlnTlleJX0eaQ?pwd=lsae
    提取码:lsae

    数据, 模型

  • SailZhao520
    OP
      

    如果CB不够可以再追加,辛苦懂的大佬帮忙看看。使用过这个模型的应该是很简单的问题
    jamstory   

    在您的代码中,您已经进行了数据预处理和模型训练。我注意到在您的predict方法中,逆差分和预测值的计算可能存在问题。以下是我对您代码的一些建议和修正。
    在inverse_transform方法中,您需要对gmv_preds的索引进行相应的更新,以便预测值与正确的日期对应。这是修改后的inverse_transform方法:
    def inverse_transform(self, predicted):
        """
        逆变换得到 GMV 部分的预测结果
        """
        # 对预测结果进行逆差分
        preds_diff_cumsum = predicted.cumsum()
        preds_diff_recover = self.series.iloc[-1] + preds_diff_cumsum
        # 更新预测值的索引
        preds_diff_recover.index = pd.date_range(start=self.diff_series.index[-1] + pd.DateOffset(months=1), periods=len(preds_diff_cumsum), freq='M')
        return preds_diff_recover
    在predict方法中,我们需要将预测值与原始数据进行对比。您可以使用inverse_transform方法还原预测值,并将还原后的预测值与原始数据进行比较。这是修改后的predict方法:
    def predict(self, start_date, end_date):
        """
        对未来 GMV 进行预测
        :param start_date: 预测开始日期
        :param end_date: 预测结束日期
        :return: 预测结果(GMV部分)
        """
        # 使用拟合的模型进行预测
        preds = self.model_fit.predict(start=start_date, end=end_date, dynamic=False)
        # 获取 GMV 部分的预测结果
        gmv_preds = self.inverse_transform(preds)
        # 修改 x 轴时间间隔
        plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%y-%m'))
        plt.gca().xaxis.set_major_locator(mdates.MonthLocator(interval=1))
        # 可视化预测结果
        plt.plot(self.series.loc['2021-04':'2023-02'], label='Historical')
        plt.plot(self.series.loc['2023-03':end_date], label='Actual')
        plt.plot(self.df.loc['2021-04':'2023-12', 'GMV'].iloc[:-1], label='GMV')
        plt.plot(gmv_preds, label='Prediction')
        plt.title('GMV Forecasts')
        plt.rcParams['font.size'] = 12
        plt.legend(loc='upper left')
        plt.tight_layout()
        plt.show()
        return gmv_preds
    这些更改应该会使您的代码生成更接近预期的预测结果。然而,仍然需要注意的是,对于时间序列预测,选择合适的模型和参数是非常重要的。您可以考虑使用诸如自动ARIMA之类的方法,以确定最佳模型参数。此外,您还可以考虑将模型与其他时间序列模型进行对比,以了解哪种模型在您的数据集上表现最好。
    jamstory   


    jamstory 发表于 2023-3-31 15:26
    在您的代码中,您已经进行了数据预处理和模型训练。我注意到在您的predict方法中,逆差分和预测值的计算可 ...

    这个发出来排版乱了,你注意每行代码的缩进问题
    SailZhao520
    OP
      


    jamstory 发表于 2023-3-31 15:27
    这个发出来排版乱了,你注意每行代码的缩进问题

    这个跑出来历史销售额和预测的销售额线没有拟合呀,是错开的
    您需要登录后才可以回帖 登录 | 立即注册

    返回顶部