成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

時間序列預測:探索性數據分析和特征工程的實用指南

人工智能
時間序列分析是數據科學和機器學習領域最廣泛的主題之一:無論是預測金融事件、能源消耗、產品銷售還是股票市場趨勢,這一領域一直是企業非常感興趣的領域。

時間序列分析是數據科學和機器學習領域最廣泛的主題之一:無論是預測金融事件、能源消耗、產品銷售還是股票市場趨勢,這一領域一直是企業非常感興趣的領域。

隨著機器學習模型的不斷進步,使除了傳統的統計預測方法(如回歸模型、ARIMA模型、指數平滑)外,與機器學習(如基于樹的模型)和深度學習(如LSTM網絡、cnn、基于Transformer的模型)相關的技術已經出現了一段時間。

盡管這些技術之間存在巨大差異,但無論模型是什么,都必須完成一個初步步驟:探索性數據分析。

在統計學中,探索性數據分析(Exploratory Data Analysis, EDA)是對數據進行分析和可視化,以總結數據的主要特征并從中獲得相關信息的一門學科。這在數據科學領域非常重要,因為它可以為另一個重要步驟奠定基礎:特征工程。

所以我們今天這篇文章將總結一個時間序列數據的分析模板,可以總結和突出數據集的最重要特征。我們將使用一些常見的Python庫,如Pandas、Seaborn和Statsmodel。

為了方便演示,將使用Kaggle的小時能耗數據。該數據集與PJM小時能源消耗數據有關,PJM是美國的一個區域輸電組織,為幾個州提供電力。每小時的電力消耗數據來自PJM的網站,單位是兆瓦。

我在本文中我們將EDA總結為六個步驟:描述性統計、時間圖、季節圖、箱形圖、時間序列分解、滯后分析。

描述性統計

描述性統計是一種匯總統計,用于定量地描述或總結結構化數據集合中的特征。

一些通常用于描述數據集的度量是:集中趨勢度量(例如平均值,中位數),分散度量(例如范圍,標準差)和位置度量(例如百分位數,四分位數)。所有這些都可以用所謂的五數總結來概括,即分布的最小值、第一四分位數(Q1)、中位數或第二四分位數(Q2)、第三四分位數(Q3)和最大值。

在Python中,這些信息可以使用Pandas中眾所周知的describe方法輕松檢索:

import pandas as pd
 
 # Loading and preprocessing steps
 df = pd.read_csv('../input/hourly-energy-consumption/PJME_hourly.csv')
 df = df.set_index('Datetime')
 df.index = pd.to_datetime(df.index)
 
 df.describe()

時間曲線圖

最明顯且直觀的圖表是時間圖。觀測結果是根據觀測時間繪制的,連續的觀測結果用線條連接起來。

在Python中,我們可以使用Pandas和Matplotlib:

import matplotlib.pyplot as plt
 
 # Set pyplot style
 plt.style.use("seaborn")
 
 # Plot
 df['PJME_MW'].plot(title='PJME - Time Plot', figsize=(10,6))
 plt.ylabel('Consumption [MW]')
 plt.xlabel('Date')

這張圖可以為我們提供一下的信息:

  • 模式顯示出每年的季節性。
  • 如果只關注一年,似乎會發現更多的規律。由于用電量較大,冬季和夏季的用電量可能會出現高峰。
  • 這個數據多年來沒有明顯的增加/減少趨勢,平均消費量保持平穩。
  • 2013年前后有一個異常值,可以進行特殊的分析

季節性

季節性圖基本上是一個時間圖,其中數據是根據它們所屬的系列的各個“季節”繪制的。

關于能源消耗,我們通常有每小時可用的數據,因此可以有幾個季節性:每年,每周,每天。在深入研究這些圖之前,讓我們首先在Pandas中設置一些變量:

# Defining required fields
 df['year'] = [x for x in df.index.year]
 df['month'] = [x for x in df.index.month]
 df = df.reset_index()
 df['week'] = df['Datetime'].apply(lambda x:x.week)
 df = df.set_index('Datetime')
 df['hour'] = [x for x in df.index.hour]
 df['day'] = [x for x in df.index.day_of_week]
 df['day_str'] = [x.strftime('%a') for x in df.index]
 df['year_month'] = [str(x.year) + '_' + str(x.month) for x in df.index]

1、年消耗量

一個非常有趣的圖是按年按月分組的能源消耗,這突出了年度季節性,可以告訴我們多年來的上升/下降趨勢。

import numpy as np
 
 # Defining colors palette
 np.random.seed(42)
 df_plot = df[['month', 'year', 'PJME_MW']].dropna().groupby(['month', 'year']).mean()[['PJME_MW']].reset_index()
 years = df_plot['year'].unique()
 colors = np.random.choice(list(mpl.colors.XKCD_COLORS.keys()), len(years), replace=False)
 
 # Plot
 plt.figure(figsize=(16,12))
 for i, y in enumerate(years):
    if i > 0:        
        plt.plot('month', 'PJME_MW', data=df_plot[df_plot['year'] == y], color=colors[i], label=y)
        if y == 2018:
            plt.text(df_plot.loc[df_plot.year==y, :].shape[0]+0.3, df_plot.loc[df_plot.year==y, 'PJME_MW'][-1:].values[0], y, fnotallow=12, color=colors[i])
        else:
            plt.text(df_plot.loc[df_plot.year==y, :].shape[0]+0.1, df_plot.loc[df_plot.year==y, 'PJME_MW'][-1:].values[0], y, fnotallow=12, color=colors[i])
 
 # Setting labels
 plt.gca().set(ylabel= 'PJME_MW', xlabel = 'Month')
 plt.yticks(fnotallow=12, alpha=.7)
 plt.title("Seasonal Plot - Monthly Consumption", fnotallow=20)
 plt.ylabel('Consumption [MW]')
 plt.xlabel('Month')
 plt.show()

這張圖顯示,每年都有一個預定義的模式:冬季消耗顯著增加,夏季達到峰值(由于供暖/制冷系統),而春季和秋季通常不需要供暖或制冷時消耗最小。這張圖還告訴我們,在多年的總消費量中,并沒有明顯的增加/減少模式。

2、周消耗量

另一個有用的圖表是每周圖表,它描述了幾個月來每周的消費情況,還可以表明每周在一年內是否以及如何變化。

# Defining colors palette
 np.random.seed(42)
 df_plot = df[['month', 'day_str', 'PJME_MW', 'day']].dropna().groupby(['day_str', 'month', 'day']).mean()[['PJME_MW']].reset_index()
 df_plot = df_plot.sort_values(by='day', ascending=True)
 
 months = df_plot['month'].unique()
 colors = np.random.choice(list(mpl.colors.XKCD_COLORS.keys()), len(months), replace=False)
 
 # Plot
 plt.figure(figsize=(16,12))
 for i, y in enumerate(months):
    if i > 0:        
        plt.plot('day_str', 'PJME_MW', data=df_plot[df_plot['month'] == y], color=colors[i], label=y)
        if y == 2018:
            plt.text(df_plot.loc[df_plot.mnotallow==y, :].shape[0]-.9, df_plot.loc[df_plot.mnotallow==y, 'PJME_MW'][-1:].values[0], y, fnotallow=12, color=colors[i])
        else:
            plt.text(df_plot.loc[df_plot.mnotallow==y, :].shape[0]-.9, df_plot.loc[df_plot.mnotallow==y, 'PJME_MW'][-1:].values[0], y, fnotallow=12, color=colors[i])
 
 
 # Setting Labels
 plt.gca().set(ylabel= 'PJME_MW', xlabel = 'Month')
 plt.yticks(fnotallow=12, alpha=.7)
 plt.title("Seasonal Plot - Weekly Consumption", fnotallow=20)
 plt.ylabel('Consumption [MW]')
 plt.xlabel('Month')
 plt.show()

3、每日消費量

最后,我們看看每日消費量。它代表了一天中消費的變化。數據首先按星期進行分組,然后按平均值進行匯總。

import seaborn as sns
 
 # Defining the dataframe
 df_plot = df[['hour', 'day_str', 'PJME_MW']].dropna().groupby(['hour', 'day_str']).mean()[['PJME_MW']].reset_index()
 
 # Plot using Seaborn
 plt.figure(figsize=(10,8))
 sns.lineplot(data = df_plot, x='hour', y='PJME_MW', hue='day_str', legend=True)
 plt.locator_params(axis='x', nbins=24)
 plt.title("Seasonal Plot - Daily Consumption", fnotallow=20)
 plt.ylabel('Consumption [MW]')
 plt.xlabel('Hour')
 plt.legend()

這張圖顯示了一個非常典型的模式,有人稱之為“M輪廓”,因為日消耗似乎描繪了一個“M”。有時這種模式是清晰的

這些圖通常在一天的中間(從上午10點到下午2點)顯示一個相對峰值,然后是一個相對最小值(從下午2點到下午6點)和另一個峰值(從下午6點到晚上8點)。它還顯示了周末和其他日期的消費差異。

4、特征工程

我們如何將這些信息用于特征工程呢?假設我們正在使用一些需要高質量特征的ML模型(例如ARIMA模型或基于樹的模型)。

  • 年消費量多年來變化不大這表明如果可能的話,可以使用來自滯后或外生變量的年季節性特征。
  • 每周消費在幾個月內遵循相同的模式,可以使用來自滯后或外生變量的每周特征。
  • 每天的消費可以使用工作日和周末的分類特征來進行編碼

箱線圖

箱線圖是識別數據分布的有效方法。箱線圖描繪了百分位數,它代表了分布的第一個(Q1)、第二個(Q2/中位數)和第三個(Q3)四分位數,而箱須則代表了數據的范圍。超過須的每一個值都可以被認為是一個離群值,更深入地說,須通常被計算為:

讓我們首先計算總消耗的箱線圖,這可以很容易地在Seaborn中完成:

plt.figure(figsize=(8,5))
 sns.boxplot(data=df, x='PJME_MW')
 plt.xlabel('Consumption [MW]')
 plt.title(f'Boxplot - Consumption Distribution');

這個圖看起來沒有多少信息,但是它能告訴我們數據是一個類似高斯分布的分布,尾巴更向右突出。

下面是日/月箱形圖。它是通過創建一個“日/月”變量并根據它對消費進行分組而獲得的。以下是2017年以后的代碼

df['year'] = [x for x in df.index.year]
 df['month'] = [x for x in df.index.month]
 df['year_month'] = [str(x.year) + '_' + str(x.month) for x in df.index]
 
 df_plot = df[df['year'] >= 2017].reset_index().sort_values(by='Datetime').set_index('Datetime')
 plt.title(f'Boxplot Year Month Distribution');
 plt.xticks(rotatinotallow=90)
 plt.xlabel('Year Month')
 plt.ylabel('MW')
 
 sns.boxplot(x='year_month', y='PJME_MW', data=df_plot)
 plt.ylabel('Consumption [MW]')
 plt.xlabel('Year Month')

可以看到,在夏季/冬季(即當我們有高峰時)的不確定性較小,而在春季/秋季(即當溫度變化較大時)則更加分散。2018年夏季的消費量高于2017年,這可能是由于夏季更溫暖。當進行特征工程時,記得包括(如果可用的話)溫度曲線,可能它可以用作外生變量。

另一個有用的圖是一周內的分布,這類似于每周消費季節性圖。

df_plot = df[['day_str', 'day', 'PJME_MW']].sort_values(by='day')
 plt.title(f'Boxplot Day Distribution')
 plt.xlabel('Day of week')
 plt.ylabel('MW')
 sns.boxplot(x='day_str', y='PJME_MW', data=df_plot)
 plt.ylabel('Consumption [MW]')
 plt.xlabel('Day of week')

如前所述,周末的消費明顯較低。有幾個異常值能夠看到,像“星期幾”這樣的日歷特征肯定是有用的,但又不能完全解釋。

最后我們來看小時圖。它類似于日消費季節性圖,因為它提供了一天中消費的分布情況。代碼如下:

plt.title(f'Boxplot Hour Distribution');
 plt.xlabel('Hour')
 plt.ylabel('MW')
 sns.boxplot(x='hour', y='PJME_MW', data=df)
 plt.ylabel('Consumption [MW]')
 plt.xlabel('Hour')

之前看到的“M”形現在更碎了。此外,還有很多異常值,這告訴我們數據不僅依賴于日常季節性(例如,今天12點的消費量與昨天12點的消費量相似),還依賴于其他一些東西,可能是一些外生氣候特征,如溫度或濕度。

時間序列分解

時間序列數據可以顯示各種模式。將時間序列分成幾個組件是有幫助的,每個組件表示一個潛在的模式類別。

我們可以認為一個時間序列由三個部分組成:趨勢部分,季節部分和剩余(偏差)部分(包含時間序列中的任何其他部分)。對于某些時間序列(例如,能源消耗序列),可以有多個季節分量,對應于不同的季節周期(日、周、月、年)。

分解有兩種主要類型:加性分解和乘法分解。

對于加性分解,我們將一個序列(整數)表示為季節分量(??)、趨勢分量(??)和余數(??)的和:

類似地,乘法分解可以寫成:

一般來說,加性分解最適合方差恒定的序列,而乘法分解最適合方差非平穩的時間序列。

在Python中,時間序列分解可以通過Statsmodel庫輕松實現:

df_plot = df[df['year'] == 2017].reset_index()
 df_plot = df_plot.drop_duplicates(subset=['Datetime']).sort_values(by='Datetime')
 df_plot = df_plot.set_index('Datetime')
 df_plot['PJME_MW - Multiplicative Decompose'] = df_plot['PJME_MW']
 df_plot['PJME_MW - Additive Decompose'] = df_plot['PJME_MW']
 
 # Additive Decomposition
 result_add = seasonal_decompose(df_plot['PJME_MW - Additive Decompose'], model='additive', period=24*7)
 
 # Multiplicative Decomposition
 result_mul = seasonal_decompose(df_plot['PJME_MW - Multiplicative Decompose'], model='multiplicative', period=24*7)
 
 # Plot
 result_add.plot().suptitle('', fnotallow=22)
 plt.xticks(rotatinotallow=45)
 result_mul.plot().suptitle('', fnotallow=22)
 plt.xticks(rotatinotallow=45)
 plt.show()

以上圖為2017年的數據。我們看到趨勢有幾個局部峰值,夏季的值更高。從季節成分來看,可以看到實際上有幾個周期性,該圖更突出了周周期性,但如果我們關注同年的一個特定月份(1月),也會出現日季節性:

df_plot = df[(df['year'] == 2017)].reset_index()
 df_plot = df_plot[df_plot['month'] == 1]
 df_plot['PJME_MW - Multiplicative Decompose'] = df_plot['PJME_MW']
 df_plot['PJME_MW - Additive Decompose'] = df_plot['PJME_MW']
 
 df_plot = df_plot.drop_duplicates(subset=['Datetime']).sort_values(by='Datetime')
 df_plot = df_plot.set_index('Datetime')
 
 # Additive Decomposition
 result_add = seasonal_decompose(df_plot['PJME_MW - Additive Decompose'], model='additive', period=24*7)
 
 # Multiplicative Decomposition
 result_mul = seasonal_decompose(df_plot['PJME_MW - Multiplicative Decompose'], model='multiplicative', period=24*7)
 
 # Plot
 result_add.plot().suptitle('', fnotallow=22)
 plt.xticks(rotatinotallow=45)
 result_mul.plot().suptitle('', fnotallow=22)
 plt.xticks(rotatinotallow=45)
 plt.show()

滯后分析

在時間序列預測中,滯后僅僅是序列的過去值。例如,對于每日序列,第一個滯后是指該序列前一天的值,第二個滯后是指再前一天的值,以此類推。

滯后分析是基于計算序列和序列本身的滯后版本之間的相關性,這也稱為自相關。對于一個序列的k滯后版本,我們定義自相關系數為:

其中y 表示序列的平均值,k表示滯后值。

自相關系數構成了序列的自相關函數(ACF),描繪了自相關系數與考慮的滯后數的關系。

當數據具有趨勢時,小滯后的自相關通常很大且為正,因為時間上接近的觀測值在值上也相近。當數據顯示季節性時,季節性滯后(及其季節周期的倍數)的自相關值會比其他滯后的大。具有趨勢和季節性的數據將顯示這些效應的組合。

在實踐中,更有用的函數是偏自相關函數(PACF)。它類似于ACF但是它只顯示兩個滯后之間的直接自相關。例如,滯后3的偏自相關指的是滯后1和2無法解釋的唯一相關性。或者說偏相關指的是某個滯后對當前時間值的直接影響。

如果序列是平穩的,則自相關系數會更清晰地顯現,因此通常最好先對序列進行差分以穩定信號。

下面是繪制一天中不同時段PACF的代碼:

from statsmodels.graphics.tsaplots import plot_pacf
 
 actual = df['PJME_MW']
 hours = range(0, 24, 4)
 
 for hour in hours:
    plot_pacf(actual[actual.index.hour == hour].diff().dropna(), lags=30, alpha=0.01)
    plt.title(f'PACF - h = {hour}')
    plt.ylabel('Correlation')
    plt.xlabel('Lags')
    plt.show()

PACF只是繪制不同滯后的Pearson偏自相關系數。非滯后序列顯示出與自身完美的自相關,因此滯后0將始終為1。藍色帶表示置信區間:如果滯后超過該帶,則它具有統計顯著性,我們可以斷言它具有非常重要的意義。

工程特性

滯后分析是時間序列特征工程中最具影響力的研究之一。具有高相關性的滯后是序列中重要的特征,因此應該考慮在內。

一個廣泛使用的特征工程技術是對數據集進行按小時劃分。將數據分成24個子集,每個子集對應一天中的一個小時。這樣做可以規范和平滑信號,使預測變得更簡單。

然后應對每個子集進行特征工程、訓練和微調。最終的預測將通過結合這24個模型的結果來實現。每個小時模型都有其特點,大多數將涉及重要的滯后。

我們簡單介紹在進行滯后分析時可以處理的兩種類型的滯后:

  1. 自回歸滯后:接近滯后0的滯后,我們預期這些滯后值較高(最近的滯后更有可能預測當前值)。它們是序列顯示趨勢的表現。
  2. 季節性滯后:指季節周期的滯后。在按小時分割數據時,它們通常代表周度季節性。

自回歸滯后1也可以被認為是序列的日度季節性滯后。

以我們看到的上圖為例:

夜間時間(0,4)的消耗更多地依賴于自回歸,而不是每周滯后,因為最相關的都在前五個小時。像7、14、21、28這樣的季節似乎并不太重要,所以特征工程師時特別注意滯后1到滯后5。

白天時間(8,12,16,20)的消耗表現出自回歸和季節性滯后。這在8小時和12小時尤其如此,因為這兩個小時的消耗量特別高,而隨著夜幕降臨,季節性滯后變得不那么重要了。對于這些子集,我們還應該包括季節性滯后和自回歸。

最后還有一些特征工程滯后的提示:

不要考慮太多的滯后,因為這可能會導致過度擬合。一般自回歸滯后為1 ~ 7,周滯后為7、14、21、28。但并不是必須把它們都當作特征。

考慮非自回歸或季節性的滯后通常是一個壞主意,因為它們也可能導致過擬合。

對滯后進行一些簡單的轉換通常可以產生更強大的特征。例如,季節性滯后可以使用加權平均值進行匯總,以創建代表該系列季節性的單個特征。

總結

本文的目的是為時間序列預測提供一個全面的探索性數據分析模板。

EDA是任何類型的數據科學研究的基本步驟,它允許理解數據的性質和特性,并為特征工程奠定基礎,而特征工程反過來又可以顯著提高模型性能。

我們描述了一些最常用的時間序列EDA分析,這些分析可以是統計/數學和圖形。這項工作的目的只是提供一個實用的框架來開始,后續的調查需要根據所檢查的歷史系列的類型和業務背景進行。

責任編輯:華軒 來源: DeepHub IMBA
相關推薦

2024-06-12 11:57:51

2020-05-13 11:32:28

數據分析數值分析

2020-10-28 18:28:12

Pandas數據分析GUI

2022-11-11 11:35:14

2023-12-22 09:14:48

EDA數據分析探索性數據分析

2024-07-30 12:10:22

2012-09-04 09:20:26

測試軟件測試探索測試

2023-11-30 07:23:53

數據分析EDA

2016-10-11 15:32:26

探索性大數據

2017-04-25 18:35:47

硅谷數據科學家數據分析

2023-05-11 13:39:39

EDA數據分析

2022-12-05 16:38:48

Python統計信息預測模型

2021-09-06 09:00:00

大數據大數據分析技術

2021-09-10 14:05:14

預測分析大數據分析大數據

2020-08-18 13:30:01

Python命令數據分析

2021-08-02 18:04:25

機器學習數據集工具

2021-09-23 18:12:09

大數據分析預測分析

2021-04-28 16:00:55

數據分析人工智能機器學習

2016-08-27 16:16:40

大數據

2024-03-04 11:10:01

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日本色综合 | 中文av在线播放 | 日韩中文字幕区 | 中文字幕在线国产 | 国产午夜精品理论片a大结局 | 久久九九99 | 日本精品一区二区三区在线观看视频 | 一区二区三区小视频 | 蜜桃视频在线观看免费视频网站www | 久久免费精品视频 | 久久精品欧美一区二区三区不卡 | 亚洲淫视频 | 一区二区在线视频 | 国产一级免费在线观看 | 久久久久黄色 | 国产精品视频在线观看 | 国产精品久久久久久久久 | 亚洲天堂二区 | 亚洲人精品午夜 | 久久精品亚洲成在人线av网址 | 国产中文字幕在线 | 国产一区二区三区四区在线观看 | 精品视频www | 久久在线看 | 在线欧美视频 | 欧美日韩在线一区二区 | 亚洲福利视频一区二区 | 伊人久久一区二区 | av天天爽 | 精品视频在线播放 | 国产精品高潮呻吟久久av黑人 | 亚洲视频免费在线观看 | 国产欧美日韩一区二区三区在线观看 | 欧美亚洲另类在线 | 午夜国产在线 | 久久精品亚洲 | 欧美一区二区大片 | 人人干免费 | 国产亚洲精品久久午夜玫瑰园 | 久久成人在线视频 | 欧美激情国产精品 |