亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

有什么方法可以在 python 中使用 scikit-learn 預測每月的時間序列?

有什么方法可以在 python 中使用 scikit-learn 預測每月的時間序列?

呼啦一陣風 2023-06-13 16:22:20
我想product' sales_index通過使用每月時間序列中的多個功能進行預測。一開始,我開始使用ARMA,ARIMA來執行此操作,但輸出對我來說不是很令人滿意。在我的嘗試中,我只是使用dates和sales列進行預測,輸出對我來說并不現實。我想我應該包括更多的特征列來預測sales_index列。但是,我想知道是否有任何方法可以通過使用每月時間序列中的多個特征來進行此預測。我沒有使用scikit-learn.?誰能指出我這樣做的任何可能方法?任何可能的想法?我嘗試使用 ARMA/ARIMA:這是關于這個要點的可重現的月度時間序列數據,這是我目前的嘗試:import pandas as pdfrom statsmodels.tsa.arima_model import ARMAfrom statsmodels.tsa.arima_model import ARIMAfrom statsmodels.tsa.statespace.sarimax import SARIMAXimport matplotlib.pyplot as pltdf = pd.read_csv("tsdf.csv", sep=",")dates = pd.date_range(start='2015-01', freq='MS', periods=len(df))df.set_index(dates,inplace=True)train = df[df.index < '2019-01']test = df[df.index >= '2019-01']model = ARMA(train['sales_index'],order=(2,0))model_fit = model.fit()predictions = model_fit.predict(start=len(train), end=len(train)+len(test)-1, dynamic=False)# plot resultsplt.figure(figsize=(12,6))plt.plot(test['sales_index'])plt.plot(predictions, color='red')plt.show()這是我當前嘗試的輸出:在我的嘗試中,我只是簡單地使用df['sales_index]anddf['dates']作為ARMA模型。顯然這樣做,預測輸出不是很真實和信息豐富。我在想是否有任何方法可以將所有功能列提供給df['sales_index']模型進行預測df['sales_index']。我想不出用ARMA模型做這件事的更好方法。也許scikit-learn可以為這個預測提供更好的作用。我不確定如何使用sklearn此時間序列分析來實現此目的。誰能指出sklearn這個時間序列的可能解決方案?有沒有可能這樣做sklearn?任何可能的想法?謝謝
查看完整描述

3 回答

?
桃花長相依

TA貢獻1860條經驗 獲得超8個贊

概述

通過使用Scikit-Learn庫,可以考慮使用不同的決策樹來預測數據。在此示例中,我們將使用AdaBoostRegressor,但也可以切換到RandomForestRegressor或任何其他可用的樹。因此,通過選擇樹,我們應該意識到去除數據的趨勢,通過這種方式,我們說明了通過分別對數據進行差分和對數變換來控制時間序列的均值和方差的示例。

準備數據

時間序列有兩個基本組成部分,即均值和方差。理想情況下,我們希望控制這些組件,對于可變性,我們可以簡單地對數據應用對數變換,對于趨勢我們可以區分它,我們稍后會看到。

此外,對于這種方法,我們考慮實際值 y_t 可以用兩個先驗值 y_t-1 和 y_t-2 來解釋。您可以通過修改函數的輸入來處理這些滯后值range。

# Load data

tsdf = pd.read_csv('tsdf.csv', sep="\t")


# For simplicity I just take the target variable and the date

tsdf = tsdf[['sales_index', 'dates']]


# Log value

tsdf['log_sales_index'] = np.log(tsdf.sales_index)


# Add previous n-values

for i in range(3):

? ??

? ? tsdf[f'sales_index_lag_{i+1}'] = tsdf.sales_index.shift(i+1)

? ??

? ? # For simplicity we drop the null values?

? ? tsdf.dropna(inplace=True)

? ??

? ? tsdf[f'log_sales_index_lag_{i+1}'] = np.log(tsdf[f'sales_index_lag_{i+1}'])

? ??

? ? tsdf[f'log_difference_{i+1}'] = tsdf.log_sales_index - tsdf[f'log_sales_index_lag_{i+1}']

一旦我們的數據準備就緒,我們就會得到類似于下圖的結果。

http://img2.sycdn.imooc.com/6488279a0001bdcb13420191.jpg

數據是固定的嗎?

為了控制時間序列的平均分量,我們應該對數據進行一些差分。為了確定是否需要執行此步驟,我們可以執行單位根測試。為簡單起見,我們將考慮 KPSS 檢驗,我們假設數據是平穩的零假設,特別是,它假設圍繞均值或線性趨勢平穩。

from arch.unitroot import KPSS


# Test for stationary

kpss_test = KPSS(tsdf.sales_index)


# Test summary?

print(kpss_test.summary().as_text())

http://img2.sycdn.imooc.com/648827a900015ea406240257.jpg

我們看到P-value = .280大于通常的約定0.05。因此,我們需要對數據應用一階差分。作為旁注,可以迭代地執行此測試以了解應將多少差異應用于數據。

在下圖中,我們看到了原始數據與對數一階差分的比較,注意時間序列的這些最后值突然發生變化,這似乎是結構性變化,但我們不會深入潛入其中。如果您想深入了解這個主題,布魯斯·漢森 (Bruce Hansen) 提供的這些幻燈片很有用。

plt.figure(figsize=(12,?6))
plt.subplot(1,2,1)
plt.plot(tsdf.sales_index)
plt.title('Original?Time?Series')
plt.subplot(1,2,2)
plt.plot(tsdf.log_difference_1)
plt.title('Log?first?difference?Time?Series')

http://img1.sycdn.imooc.com/648827bb00016bbc06500313.jpg

決策樹模型

正如我們之前所說,我們正在考慮決策樹模型,在使用它們時應該注意從時間序列中刪除趨勢。例如,如果你有上升趨勢,tress 不擅長預測下降趨勢。在下面的代碼示例中,我選擇了AdaBoostRegressor,但您可以自由選擇其他樹模型。另外,注意 被?log_difference_1認為是由log_difference_2和解釋的log_difference_3

注意。您的數據集還有其他協變量 或aus_avg_rain,slg_adt_ctl因此考慮將它們用于預測,您也可以對它們應用滯后值。

from sklearn.model_selection import train_test_split

from sklearn.ensemble import AdaBoostRegressor


# Forecast difference of log values

X, Y = tsdf[['log_difference_2', 'log_difference_3']], tsdf['log_difference_1']


# Split in train-test

X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, shuffle=False, random_state=0)


# Initialize the estimator

mdl_adaboost = AdaBoostRegressor(n_estimators=500, learning_rate=0.05)


# Fit the data

mdl_adaboost.fit(X_train, Y_train)


# Make predictions

pred = mdl_adaboost.predict(X_test)


test_size = X_test.shape[0]

評估預測

test_size = X_test.shape[0]

plt.plot(list(range(test_size)), np.exp(tsdf.tail(test_size).log_sales_index_lag_1? + pred), label='predicted', color='red')

plt.plot(list(range(test_size)), tsdf.tail(test_size).sales_index, label='real', color='blue')

plt.legend(loc='best')

plt.title('Predicted vs Real with log difference values')

http://img1.sycdn.imooc.com/648827ce000101f905450357.jpg

決策樹模型似乎準確地預測了真實值。我將使用TimeSeriesSplitfrom 函數scikit-learn通過平均絕對誤差來評估模型的誤差。


from sklearn.model_selection import TimeSeriesSplit

from sklearn.metrics import mean_absolute_error


X, Y = np.array(tsdf[['log_difference_2', 'log_difference_3']]), np.array(tsdf['log_difference_1'])


# Initialize a TimeSeriesSplitter

tscv = TimeSeriesSplit(n_splits=5)


# Retrieve log_sales_index and sales_index to unstransform data

tsdf_log_sales_index = np.array(tsdf.copy().reset_index().log_sales_index_lag_1)

tsdf_sales_index = np.array(tsdf.copy().reset_index().sales_index_lag_1)


# Dict to store metric value at every iteration

metric_iter = {}



for idx, val in enumerate(tscv.split(X)):

? ??

? ? ? ? train_i, test_i = val

? ??

? ? ? ? X_train, X_test = X[train_i], X[test_i]

? ? ? ? Y_train, Y_test = Y[train_i], Y[test_i]


? ? ? ? # Initialize the estimator

? ? ? ? mdl_adaboost = AdaBoostRegressor(n_estimators=500, learning_rate=0.05)


? ? ? ? # Fit the data

? ? ? ? mdl_adaboost.fit(X_train, Y_train)


? ? ? ? # Make predictions

? ? ? ? pred = mdl_adaboost.predict(X_test)

? ? ? ??

? ? ? ? # Unstransform predictions

? ? ? ? pred_untransform = [np.exp(val_test + val_pred) for val_test, val_pred in zip(tsdf_log_sales_index[test_i], pred)]

? ? ? ??

? ? ? ? # Real value

? ? ? ? real = tsdf_sales_index[test_i]

? ? ? ??

? ? ? ? # Store metric

? ? ? ? metric_iter[f'iter_{idx + 1}'] = mean_absolute_error(real, pred_untransform)? ? ? ? ? ? ?

現在我們看到平均MAE誤差非常低。


print(f'Average MAE error: {np.mean(list(metric_iter.values()))}')

>>> Average MAE error: 17.631090959806535


查看完整回答
反對 回復 2023-06-13
?
冉冉說

TA貢獻1877條經驗 獲得超1個贊

這有兩個部分:

  1. 一個有效的預測代碼解決方案。

  2. 幾個話題的簡單討論

解決方案

我將建議一種略有不同且更抽象的方法:使用構建在 scikit-learn 之上的Darts 。它包括您期望的“列表”庫(例如,pandas 和 NumPy),但也包括一些您需要對該領域有相當深入的了解才能考慮包含的庫(例如,Torch、Prophet 和 Holidays)。此外,它已經包含了許多模型。重要說明:特定庫是 u8darts,而不是飛鏢。它們很相似——并且具有相似的依賴關系——但它們并不相同。

使用它,您可以輕松地開發出具有相當不錯結果的預測模型。例如,整個代碼,包括合并重命名的列標題(以及刪除未重命名的列和重復的行)只是幾行。

import pandas as pd

import matplotlib.pyplot as plt


from darts import TimeSeries

from darts.models import ExponentialSmoothing


df = pd.read_csv("../data/tsdf.csv", sep="\t")

df.drop(['Unnamed: 0', 'aus_slg_fmCatl'], axis=1, inplace = True)


df.columns = ['Date', 'adult_cattle(head)','Bulls Bullocks & Steers(head)', 'Cows&Heifers(head)',

? ? ? ? ? ? ? 'Calves(head)', 'Beef(tonnes)', 'Veal(tonnes)','Adult cattle(kg/head)', 'Calves(kg/head)',

? ? ? ? ? ? ? 'aust-avg_rain','US/AUS_ExchangeRate', 'sales_index', 'retail_sales_index']


df.drop_duplicates(subset=['Date'], inplace=True)


series = TimeSeries.from_dataframe(df, 'Date', 'Beef(tonnes)').values


train, val = series.split_before(pd.Timestamp('2019-01-01'))

model = ExponentialSmoothing()

model.fit(train)

prediction = model.predict(len(val))


series.plot(label='actual')

prediction.plot(label='forecast', lw=2)

plt.legend()

此外,他們的 repo 有一個帶有額外模型和示例的筆記本

結果

http://img4.sycdn.imooc.com/648827f20001a6cd06450436.jpg

討論

針對我們收到的評論中的討論,我認為有幾點需要說明。

去除季節性

如果您正在為預測模型拍攝,這是您很少想做的事情。如果你知道每年冬天家庭/辦公室供暖的燃料價格都會上漲,但決定將其排除在外——你會被交易員活活吃掉,他們很樂意拿走你的錢。

虛擬數據

這里的訣竅是您不知道您的虛擬數據是否與真實數據看起來足夠相似。然而,解決方案是一個不同的問題。

“在 Python 中使用 R 庫……”

ARMA 和 ARIMA

...不太可能產生豐碩的結果,部分原因是誤差項假設誤差是IID,但市場存在偏差。指數平滑效果很好,因為它替代了

“但是當我針對 sales_index 運行它時……”

sales_index 將由幾個自變量組成。正如您所期望的那樣,肉類生產(奇怪的是與降雨量呈負相關)和匯率。但是,您的模型中未包含其他國家/地區的生產數據(100% 純有機、草料、“AAA”艾伯塔牛肉)、稅收、國內牛肉生產、運輸等。這就是您可能不想要的原因對抗既有寬客又有專業領域專業知識的專業交易員。最后,我要指出的是,時間上沒有任何跡象表明這是正常的還是不正常的。

http://img4.sycdn.imooc.com/648827fe0001ab9e06480313.jpg

從 2015 年到 2017 年,似乎出現了 1.5 年的上升,隨后一直下降到 2019 年。這似乎在重復,但 2020 年的突然變化讓人相信這是一種失常。但數據太小,很難判斷任何有效性。在這種情況下,趨勢線或通道會更好。



查看完整回答
反對 回復 2023-06-13
?
MYYA

TA貢獻1868條經驗 獲得超4個贊

在初始化模型和進行預測時,您可以ARMA使用可選參數向模型添加其他功能。exog


例如,要添加一些您的功能:


# initialize the model

model = ARMA(train['sales_index'], 

             exog=train[['slg_adt_ctl', 'slg_bbs', 'retail_sales_index']],

             order=(2,0))


model_fit = model.fit() # fit the model


# make predictions

predictions = model_fit.predict(start=len(train), 

                                end=len(train)+len(test)-1, 

                                exog=test[['slg_adt_ctl', 'slg_bbs', 'retail_sales_index']], 

                                dynamic=False)

當我們制作預測圖時,我們現在獲得了一些額外的預測能力。

http://img1.sycdn.imooc.com//648828110001dede07070355.jpg

查看完整回答
反對 回復 2023-06-13
  • 3 回答
  • 0 關注
  • 242 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號