时间序列模型!(新手教程,特征工程讲解,两个模型通用代码)

Time is relative. Your body hasn't even hit the floor yet. I've spent so many years...peering through time...looking at this exact moment. But I can't see past it.

简介:(新手向)

        时间序列模型在生活中的各个部分都参了一脚,从股票走势到商品销售额的预测,都无法离开时间序列模型,于是,在参加完厦门大学时间序列模型预测课程的大作业后,写下一些帮助时间序列模型建设的blog,谨此纪念第一次正式的建模。

        本文章不注重于深究模型是如何建立,更加注重于模型的实战运用与分析

        如下为训练集,所有测试都放在kaggle上,所以暂无测试集数据,可以通过sklearn的timeseriessplit进行交叉验证观察模型的拟合效果,需要预测未来三天的走势

链接:https://pan.baidu.com/s/1wR7-w3vGKv03FzQPR3KqhA?pwd=Data 
提取码:Data

任务与如何建模

        任务:建立一个时间序列模型并预测接下来三天的数据

        听起来是不是非常简单的样子?只要建立模型,再根据模型把接下来的三天都预测下来,这不就结束了嘛,甚至我自己大概看看数据的走向都能做成这样的事~

        当然,这只是表层的,使用读者自己的神经网络实现的模型预测

        但是当数据量很大的时候自己的神经网络够用去计算这些所有的值?显然会先让自己的🧠过载力。于是乎,这种计算量很大的事情自然要交给计算机来算力

        建模の步骤

        那么又得如何交给计算机处理呢,这其中就大有门路力

        1. 数据清洗,进行数据预处理

               就像我们煮饭做菜一般,在拿到食材之后,要先看看食材新不新鲜,将坏掉的食材🚮。那么在我们的数据集中,数据预处理可以认为是对食材的初步处理,可以看土豆长不长芽来判断有没有毒,那么在数据集中就是判断有没有NaN从数据集中长了出来。

                如果NaN长出来了怎么办呢,这里的解决方法可以是,插值法,删除法

                        插值法:根据缺失数据的时间节点往前推,取某个区间的平均值或者插入上一个值,例如:周三数据缺失,可以使用上周三数据填充,或者过去一个月的周三平均数据填充等。
                        删除法:头疼砍头的毫方法,根据实际数据需要决定是否这么做

                感谢老师的手下留情,文中这份数据集已经经过数据清洗,请放心食用

                数据预处理方面主要包括训练集验证集划分,按需要取就可以,可以自己敲截取,也可以使用函数。注意:时间序列模型无法通过sklearn的traintestsplit,只能使用timeseriessplit,因为要按照时间顺序截取,不能打乱

        2. 特征工程

                特征工程就犹如刀工,好的刀工在食材处理中起着不可或缺的作用

                对于传统ARIMA,SARIMA则不需要特征处理

                而在机器学习中,特征工程就非常非常滴重要,本篇文章也会在下面详细讲述特征工程

        3. 建模

                建模就是选择合适的模型进行预测,常用模型有

                传统模型:AR(自回归),MA(移动平均),ARIMA(自回归差分移动平均),SARIMA(ARIMA + 季节性),简单线性回归

                机器学习:LightGBM,XGBoost, 决策树,随机森林,LSTM(深度学习) 

                在建模过程中多尝试一些模型总是好的,多试试才知道最适合的模型,这里我使用xgboost进行建模

        4. 预测

                预测的方式有,逐步预测(单模型预测,预测到后期会导致残差叠加),直接预测(多模型直接预测,在后期的数据少,预测效果差)

建模の关键

机器学习建模的关键在于特征工程

特征工程

        1.时间戳特征:

                时间戳特征是所有时间序列的通用特征,通常可以调用接口实现,以下为代码实例,grid_df 可以认为是特征列表

# 提取时间戳对象属性,记住要想用时间接口,需要先把时间列转换为datetime类型
temp_dt = grid_df['timestamp'].dt  # 这个dt是高级接口,可以通过temp_dt获得所有的时间戳特征,不过它只是接口,无法print
# 以下为统一处理,这里和上面的为预测值创建NaN一样,是字典添加元素的想法
grid_df['month'] = temp_dt.month  # 月, int
grid_df['day'] = temp_dt.day  # 日, int
grid_df['dayofweek'] = temp_dt.dayofweek  # 星期几, int
grid_df['is_month_start'] = temp_dt.is_month_start  # 是否是本月第一天, bool
grid_df['is_month_end'] = temp_dt.is_month_end  # 是否是本月最后一天, bool

        2.时变特征:

                时变特征是时间序列的重要组成部分,本质上来说,时变特征是以过去的时间数据作为自己预测的依据

                A:滚动窗口(data.shift().rolling(n), 防止数据泄露,不能取自己,取n天的滑动窗口)

                滚动窗口是指一个窗口在数据集中滑动截取数据,如果有学过算法的小伙伴应该很熟悉一种滑动窗口,最小矩阵乘积(通过滑动窗口+动态规划确定乘积最小)。这里更简单一点,此时的窗口只需要沿着时间一条轴向后滑动就可以

                通常一个窗口是一个小的时间序列,于是可以包括平均值,总和,标准差,最大最小值这几个时变特征

                B:滞后项(data.shift(n), n为滞后的第几天)

                滞后项通常是指将过去的时间点数据作为现在的特征,就像一个周期为7天的时间序列模型,在周三的时候就可以将上周三的数据作为我的一个预测特征(毕竟刚好过去一个周期)

                滞后项可以取过去三天,或者某个特定时间的(例如只取过去第七天)

                C:拓展窗口:(data.shift().expanding(n),思想同上的滑动窗口,不过expanding是一次将窗口延展n天)

                拓展窗口和滚动窗口有相同的思想,可以认为是窗口的左侧(时间最小端)不进行移动,只是将窗口的右端不断向右边延申

                一次延申的长度也有讲究,一般采用7天时间端会比较好,对窗口处理的方法和滚动窗口一摸一样

                D:季节性趋势项(选用)(可采用statsmodel的STL,seasonal_decompose函数进行分解,前者使用Loess平滑可对付噪音,后者适合强季节性稳定序列分解,按需取用)

                对于一些时间序列模型,其可能会有季节性,可能有的人会问,季节性是什么呀?季节性可以认为是将一段区间分为许多小的区间,所有小的区间都展示出一样的变化趋势,小区间的范围固定,也就是时间频率固定(相同的周期)。

                那么季节性和周期性是不是同一个东西呢?答案是❌的,周期性是没有一个固定的时间频率,而季节性有(这也是为什么春夏秋冬季节各3个月,这就是季节 性)

模型选用:

        ARIMA模型通用代码,请注意修改部分内容以不会报错,这里是通用代码。                        

import statsmodels.api as sm
import numpy as np
import pandas as pd
from itertools import product

data = pd.DataFrame()  # 中间放入你的数据集,对于一个传统ARIMA模型有以下步骤

# ADF检验,ARIMA需要序列平稳,不平稳则通过差分平稳
adf = sm.tsa.adfuller(data)  # 返回值会是一个列表,直接取出p值即可
p = adf[1]
while p > 0.05:
    # p > 0.05代表原假设成立,说明原序列不平稳,进行差分
    data = data.diff()
    p = sm.tsa.adfuller(data)[1]
        
# 进行ARIMA模型的参数选取, ARIMA参数的判断主要是通过看图认为判断拖尾截尾
# 但是电脑没办法代替我们的眼睛看拖尾截尾,于是只能暴力破解出最优组合,通过bic确定最优解
p = d = q = range(2)
pdq = list(product(p, d, q))

# 数据量较小情况下,我们可以对所有不同类型的数据都建立模型,以达到最精准的状态
for n in range():  # 放入你的不同类型数量
    best_bic = np.inf  # 记住,bic越小说明模型越好
    best_param = []
    for i in pdq:
        try:
            model = sm.tsa.ARIMA(data, order=i)
            bic = model.fit().bic  # 先拟合后获取bic
            if bic < best_bic:  # 更优质的组合代替原有内容
                best_bic = bic
                best_param = i
        except:
            continue

    model = sm.tsa.ARIMA(data, order=best_param).fit()
    model.predict()  # 放入你的测试集
    print(model.summary())  # 此为描述你的模型特征

         XGBoost模型代码

from sklearn.metrics import mean_squared_error
from xgboost import XGBRegressor, plot_importance  # plot_importance 用于观察特征的重要性,对特征筛选起着重要作用
from sklearn.model_selection import GridSearchCV
import numpy as np
import pandas as pd


data = pd.DataFrame()  # 中间放入你的数据集,对于一个传统ARIMA模型有以下步骤
feat = pd.DataFrame()  # 请进行你的特征工程,机器学习中特征工程是必须的
X_train = pd.DataFrame()  # X_train是你划分的训练集,其中的内容来自于特征工程!!!!!!!!!
Y_train = pd.DataFrame()  # Y_train是销售额用于模型拟合
X_val = pd.DataFrame()  # Y_train是验证集特征
Y_val = pd.DataFrame()  # Y_val是验证集的值,负责与预测值对比查看模型拟合精度,越小越好

# 这个是参数列表,用于求出最优解,分别是学习率,树深度,样本采样率
param_grid = {
    "learning_rate": [0.01, 0.1, 0.2, 0.05],
    "max_depth": [3, 5, 7],
    "subsample": [0.8, 0.9, 1.0]
}
grid_search = GridSearchCV(XGBRegressor(), param_grid, cv=3)  # 使用网格暴力搜索得到最优参数
grid_search.fit(X_train, Y_train)  # 模型拟合
best_params = grid_search.best_params_  # 提取最优参数

xgb_model = XGBRegressor(**best_params)  # 模型实例化
xgb_model.fit(X_train, Y_train)  # 建立模型

predictions = xgb_model.predict(X_val)  # 预测
rmse = np.sqrt(mean_squared_error(Y_val, predictions))
print(rmse)  # 相对的,也有mse这种检测方法,有很多种方法可以用于观察模型的拟合程度,小例子就是rmse和mse
# 均方根误差

Summary

        数据清洗,特征工程,模型选择,进行预测,掌握了这四个步骤,那么也就大概入门机器学习啦~

        这只是我们的开胃前菜,快准备把我们的实战时间序列模型预测端上来罢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值