六種有效的時間序列數據特征工程技術(使用Python)
在商業分析中,"時間"是一個核心概念。我們基于時間組件來分析銷售數據、收入、利潤、增長,甚至進行預測。然而,對于初學者來說,這可能是一個復雜的主題。在處理時間敏感的數據集時,需要考慮時間序列數據的多個細微方面。
在這個領域,沒有放之四海而皆準的方法。我們不必總是強制使用傳統的時間序列技術,如ARIMA(從經驗中得出這個結論)。在某些項目中,如需求預測或點擊預測,可能需要依賴監督學習算法。這就是時間序列特征工程發揮作用的地方。它有潛力將時間序列模型從一個良好的模型提升為一個強大的預測工具。
在本文中,我們將探討使用日期時間列提取有用信息的各種特征工程技術。
1、時間序列簡介
在深入特征工程技術之前,讓我們先回顧一些基本的時間序列概念。這些概念將貫穿全文,因此提前熟悉它們很有幫助。是什么使時間序列項目區別于傳統機器學習問題呢?
在時間序列中,數據以等間隔捕獲,且序列中的每個連續數據點都依賴于其先前的值。
讓我們通過一個簡單的例子來理解這一點。如果想預測某公司今天的股票價格,了解昨天的收盤價會有幫助,這是肯定的,如果我們有過去幾個月或幾年的數據,預測網站的流量會容易得多。
我們還需要考慮另一個因素 - 時間序列數據可能存在某些趨勢或季節性。下面這張顯示某航空公司多年來預訂票數的圖表:
我們可以清晰地看到一個上升趨勢。這類信息可以用于做出更準確的預測。
2、設置時間序列數據的問題
我們將處理一個有趣的問題來學習時間序列的特征工程技術。
我們有'JetRail'的歷史數據,這是一種使用先進技術高速運行的公共鐵路交通系統。JetRail的使用量最近有所增加,我們需要根據過去的數據預測未來7個月JetRail的客流量。
加載數據集:
import pandas as pd
data = pd.read_csv('Train_SU63ISt.csv')
data.dtypes
這里有兩列 - 這是一個典型的單變量時間序列。日期變量的數據類型被識別為對象,即它被當作分類變量處理。我們需要將其轉換為DateTime變量。可以使用pandas中的datetime函數來實現這一點:
import pandas as pd
data = pd.read_csv('Train_SU63ISt.csv')
data['Datetime'] = pd.to_datetime(data['Datetime'],format='%d-%m-%Y %H:%M')
data.dtypes
現在已經準備好了數據,讓我們探討可以從這個變量中提取的不同特征。在介紹每種特征工程技術時,將討論該技術可能有用的不同場景。
注意:本文中使用了一個簡單的時間序列問題來演示不同的特征工程技術。只要存在日期時間列,就可以在自選的數據集上應用這些技術。
3、日期相關特征
如果你熟悉預測特定產品銷售的任務。我們就可以根據歷史數據分析工作日和周末的銷售模式,獲取關于日、月、年等的信息可能對預測值有重要意義。
我們的任務是預測未來7個月內每小時使用JetRail的人數。 這個數字在工作日可能會較高,而在周末或節假日期間可能會較低。因此一周中的具體日期(工作日或周末)或月份將是重要的因素。
在Python中提取這些特征相對簡單:
import pandas as pd
data = pd.read_csv('Train_SU63ISt.csv')
data['Datetime'] = pd.to_datetime(data['Datetime'],format='%d-%m-%Y %H:%M')
data['year']=data['Datetime'].dt.year
data['month']=data['Datetime'].dt.month
data['day']=data['Datetime'].dt.day
data['dayofweek_num']=data['Datetime'].dt.dayofweek
data['dayofweek_name']=data['Datetime'].dt.weekday_name
data.head()
4、 時間相關特征
如果有時間戳,就可以提取更細粒度的特征。例如可以確定記錄數據的一天中的具體小時或分鐘,并比較營業時間和非營業時間的趨勢。
如果能夠從時間戳中提取'小時'特征,就可以對數據進行更深入的分析。JetRail的客流量是在早晨、下午還是晚上更高,或者可以使用該值來計算整周的平均每小時客流量,即上午9-10點、10-11點等時間段(貫穿整周)使用JetRail的人數。
提取基于時間的特征與提取日期相關特征的方法類似。可以首先將列轉換為DateTime格式,然后使用.dt訪問器。以下是在Python中的實現方法:
import pandas as pd
data = pd.read_csv('Train_SU63ISt.csv')
data['Datetime'] = pd.to_datetime(data['Datetime'],format='%d-%m-%Y %H:%M')
data['Hour'] = data['Datetime'].dt.hour
data['minute'] = data['Datetime'].dt.minute
data.head()
同樣可以從日期列中提取多種特征。以下是可以生成的特征的完整列表:
5、滯后特征
在處理時間序列問題時,有一個關鍵點,可以利用目標變量進行特征工程!
考慮這樣一個場景 —正在預測一家公司的股票價格。那么前一天的股票價格對做出預測很重要,對吧?換句話說,t時刻的值極大地受到t-1時刻值的影響。這些過去的值被稱為滯后,所以t-1是滯后1,t-2是滯后2,依此類推。
import pandas as pd
data = pd.read_csv('Train_SU63ISt.csv')
data['Datetime'] = pd.to_datetime(data['Datetime'],format='%d-%m-%Y %H:%M')
data['lag_1'] = data['Count'].shift(1)
data = data[['Datetime', 'lag_1', 'Count']]
data.head()
我們為序列生成了滯后一特征。但為什么選擇滯后一?為什么不是五或七?這是一個值得思考的問題。
我們選擇的滯后值應該基于個別值與其過去值的相關性。
如果序列呈現每周趨勢,即上周一的值可以用來預測這周一的值,那么創建七天的滯后特征可能更合適。
還可以創建多個滯后特征!假設想要從滯后1到滯后7的特征則可以讓模型決定哪個是最有價值的。例如訓練一個線性回歸模型,它會為滯后特征分配適當的權重(或系數):
import pandas as pd
data = pd.read_csv('Train_SU63ISt.csv')
data['Datetime'] = pd.to_datetime(data['Datetime'],format='%d-%m-%Y %H:%M')
data['lag_1'] = data['Count'].shift(1)
data['lag_2'] = data['Count'].shift(2)
data['lag_3'] = data['Count'].shift(3)
data['lag_4'] = data['Count'].shift(4)
data['lag_5'] = data['Count'].shift(5)
data['lag_6'] = data['Count'].shift(6)
data['lag_7'] = data['Count'].shift(7)
data = data[['Datetime', 'lag_1', 'lag_2', 'lag_3', 'lag_4', 'lag_5', 'lag_6', 'lag_7', 'Count']]
data.head(10)
確定相關性顯著的滯后有多種方法。例如可以使用ACF(自相關函數)和PACF(偏自相關函數)圖。
- ACF: ACF圖衡量時間序列與其滯后版本之間的相關性
- PACF: PACF圖衡量時間序列與其滯后版本之間的相關性,但在消除了已由中間比較解釋的變異之后
對于我們的例子,這里是ACF和PACF圖:
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
plot_acf(data['Count'], lags=10)
plot_pacf(data['Count'], lags=10)
偏自相關函數顯示與第一個滯后高度相關,與第二個和第三個滯后的相關性較低。自相關函數顯示緩慢衰減,這表明未來值與其過去值有很強的相關性。
需要注意的是 — 移動的次數等于數據中減少的值的數量。這樣在開始處看到一些包含NaN的行。這是因為第一個觀察沒有滯后值。在訓練模型時,需要從訓練數據中移除這些行。
6. 滾動窗口特征
在上一節中,我們討論了如何使用前面的值作為特征。
那么,如何根據過去的值計算一些統計量呢?這種方法被稱為滾動窗口法,因為每個數據點的窗口都是不同的。
下面這個動圖很好地解釋了這個概念:
由于這看起來像是一個隨每個新數據點滑動的窗口,使用這種方法生成的特征被稱為"滾動窗口"特征。
現在需要考慮的問題是 — 如何在這里進行特征工程?讓我們從簡單的開始。將選擇一個窗口大小,計算窗口內值的平均值,并將其用作特征。下面是在Python中的實現:
import pandas as pd
data = pd.read_csv('Train_SU63ISt.csv')
data['Datetime'] = pd.to_datetime(data['Datetime'],format='%d-%m-%Y %H:%M')
data['rolling_mean'] = data['Count'].rolling(window=7).mean()
data = data[['Datetime', 'rolling_mean', 'Count']]
data.head(10)
類似地,可以考慮計算選定窗口內的總和、最小值、最大值等作為特征。
在時間序列中,近期性是一個重要因素。越接近當前日期的值通常包含更多相關信息。
因此我們可以使用加權平均值,給予最近的觀察值更高的權重。數學上,過去7個值在時間t的加權平均值可以表示為:
w_avg = w1(t-1) + w2(t-2) + . . . . + w7*(t-7)
其中,w1>w2>w3> . . . . >w7。
7、擴展窗口特征
這是滾動窗口技術的一個高級版本。在滾動窗口中,窗口的大小是固定的,而窗口隨時間推移而滑動。因此只考慮最近的一組固定數量的值,忽略了更早的數據。
擴展窗口特征的核心思想是考慮所有過去的值。
下圖展示了擴展窗口函數的工作原理:
每一步窗口的大小都會增加一個單位,因為它考慮了序列中的每個新值。這可以在Python中使用expanding()函數輕松實現。讓我們使用相同的數據來編寫代碼:
import pandas as pd
data = pd.read_csv('Train_SU63ISt.csv')
data['Datetime'] = pd.to_datetime(data['Datetime'],format='%d-%m-%Y %H:%M')
data['expanding_mean'] = data['Count'].expanding(2).mean()
data = data[['Datetime','Count', 'expanding_mean']]
data.head(10)
8、領域特定特征
這是特征工程的精髓所在。
對問題陳述有深入理解,對最終目標有清晰認識,以及對可用數據有充分了解,這些都是為模型設計有效的領域特定特征的關鍵。
讓我們通過一個例子來深入探討這一點。
以下是零售商提供的多個商店和產品的數據。我們的任務是預測產品的未來需求。可以考慮various characteristic,如lag特性或過去值的平均值等。
但是,讓我們思考一個問題 — 在整個數據集中從滯后1到滯后7構建滯后特征是否真的合適?
顯然不是。不同的商店和產品的需求模式可能有顯著差異。在這種情況下,我們可以考慮基于商店-產品組合來創建滯后特征。 此外,如果我們了解產品特性和市場趨勢,將能夠生成更準確、更有針對性的特征。
不僅如此,對領域和數據的深入理解還將幫助我們更好地選擇滯后值和窗口大小。基于領域知識,可能能夠引入外部數據集,為模型增添更多價值。
例如,可以考慮以下問題:銷售是否受當天天氣的影響?銷售是否會在國定假日期間出現顯著變化?如果是,那么可以利用外部數據集,將節假日信息作為一個特征納入模型。
時間序列的驗證技術
我們討論的所有特征工程技術都可以用來將時間序列問題轉化為監督機器學習問題。完成這一步后,就可以應用線性回歸和隨機森林等機器學習算法。但在進入模型構建過程之前,還有一個關鍵步驟需要注意 — 為時間序列創建合適的驗證集。
對于傳統的機器學習問題,我們通常隨機選擇數據子集作為驗證集和測試集。但在時間序列問題中,每個數據點都依賴于其過去的值。如果我們隨機打亂數據,我們可能會在未來數據上訓練模型,而用過去的數據進行預測,這顯然是不合理的。
在處理時間序列問題時,關鍵是要仔細構建驗證集,保持數據的時間順序。
讓我們為我們的問題創建一個驗證集。首先需要檢查擁有的數據跨度:
import pandas as pd
data = pd.read_csv('Train_SU63ISt.csv')
data['Datetime'] = pd.to_datetime(data['Datetime'],format='%d-%m-%Y %H:%M')
data['Datetime'].min(), data['Datetime'].max(), (data['Datetime'].max() -data['Datetime'].min())
(Timestamp('2012-08-25 00:00:00'), Timestamp('2014-09-25 23:00:00'), Timedelta('761 days 23:00:00'))
我們有大約25個月的數據。保留最后三個月的數據用于驗證,使用剩余的數據進行訓練:
data.index = data.Datetime
Train=data.loc['2012-08-25':'2014-06-24']
valid=data.loc['2014-06-25':'2014-09-25']
Train.shape, valid.shape
((16056, 3), (2232, 3))
很好!我們現在已經準備好了訓練集和驗證集。可以使用這些特征工程技術,并在這些數據上構建和評估機器學習模型了。
總結
時間序列分析常被視為一個具有挑戰性的主題。這是可以理解的,因為在處理日期和時間組件時涉及許多復雜的因素。但一旦掌握了基本概念并能夠熟練運用特征工程技術,將能夠更加得心應手地處理時間序列項目。
在本文中,我們討論了一些可以用來處理時間序列數據的實用技術。通過使用這些特征工程技術,可以將時間序列問題轉化為監督學習問題,并構建有效的回歸模型。