<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # 如何開發卷積神經網絡用于多步時間序列預測 > 原文: [https://machinelearningmastery.com/how-to-develop-convolutional-neural-networks-for-multi-step-time-series-forecasting/](https://machinelearningmastery.com/how-to-develop-convolutional-neural-networks-for-multi-step-time-series-forecasting/) 鑒于智能電表的興起以及太陽能電池板等發電技術的廣泛采用,可提供大量的用電數據。 該數據代表了多變量時間序列的功率相關變量,而這些變量又可用于建模甚至預測未來的電力消耗。 與其他機器學習算法不同,卷積神經網絡能夠自動學習序列數據的特征,支持多變量數據,并且可以直接輸出向量用于多步預測。因此,已經證明一維 CNN 表現良好,甚至在挑戰性序列預測問題上實現了最先進的結果。 在本教程中,您將了解如何為多步時間序列預測開發一維卷積神經網絡。 完成本教程后,您將了解: * 如何開發 CNN 用于單變量數據的多步時間序列預測模型。 * 如何開發多變量數據的多通道多步時間序列預測模型。 * 如何開發多元數據的多頭多步時間序列預測模型。 讓我們開始吧。 ![How to Develop Convolutional Neural Networks for Multi-Step Time Series Forecasting](https://img.kancloud.cn/13/8e/138e850710b7c143cb8251ad11076260_640x428.jpg) 如何開發用于多步時間序列預測的卷積神經網絡 照片由 [Banalities](https://www.flickr.com/photos/richardsummers/4057257184/) ,保留一些權利。 ## 教程概述 本教程分為七個部分;他們是: 1. 問題描述 2. 加載并準備數據集 3. 模型評估 4. 用于多步預測的 CNN 5. 具有單變量 CNN 的多步時間序列預測 6. 使用多通道 CNN 的多步時間序列預測 7. 具有多頭 CNN 的多步時間序列預測 ## 問題描述 '[家庭用電量](https://archive.ics.uci.edu/ml/datasets/individual+household+electric+power+consumption)'數據集是一個多變量時間序列數據集,描述了四年內單個家庭的用電量。 該數據是在 2006 年 12 月至 2010 年 11 月之間收集的,并且每分鐘收集家庭內的能耗觀察結果。 它是一個多變量系列,由七個變量組成(除日期和時間外);他們是: * **global_active_power** :家庭消耗的總有功功率(千瓦)。 * **global_reactive_power** :家庭消耗的總無功功率(千瓦)。 * **電壓**:平均電壓(伏特)。 * **global_intensity** :平均電流強度(安培)。 * **sub_metering_1** :廚房的有功電能(瓦特小時的有功電能)。 * **sub_metering_2** :用于洗衣的有功能量(瓦特小時的有功電能)。 * **sub_metering_3** :氣候控制系統的有功電能(瓦特小時的有功電能)。 有功和無功電能參考[交流電](https://en.wikipedia.org/wiki/AC_power)的技術細節。 可以通過從總活動能量中減去三個定義的子計量變量的總和來創建第四個子計量變量,如下所示: ```py sub_metering_remainder = (global_active_power * 1000 / 60) - (sub_metering_1 + sub_metering_2 + sub_metering_3) ``` ## 加載并準備數據集 數據集可以從 UCI 機器學習庫下載為單個 20 兆字節的.zip 文件: * [household_power_consumption.zip](https://archive.ics.uci.edu/ml/machine-learning-databases/00235/household_power_consumption.zip) 下載數據集并將其解壓縮到當前工作目錄中。您現在將擁有大約 127 兆字節的文件“ _household_power_consumption.txt_ ”并包含所有觀察結果。 我們可以使用 _read_csv()_ 函數來加載數據,并將前兩列合并到一個日期時間列中,我們可以將其用作索引。 ```py # load all data dataset = read_csv('household_power_consumption.txt', sep=';', header=0, low_memory=False, infer_datetime_format=True, parse_dates={'datetime':[0,1]}, index_col=['datetime']) ``` 接下來,我們可以用'_ 標記所有[缺失值](https://machinelearningmastery.com/handle-missing-timesteps-sequence-prediction-problems-python/)?_ '具有 _NaN_ 值的字符,這是一個浮點數。 這將允許我們將數據作為一個浮點值數組而不是混合類型(效率較低)。 ```py # mark all missing values dataset.replace('?', nan, inplace=True) # make dataset numeric dataset = dataset.astype('float32') ``` 我們還需要填寫缺失值,因為它們已被標記。 一種非常簡單的方法是從前一天的同一時間復制觀察。我們可以在一個名為 _fill_missing()_ 的函數中實現它,該函數將從 24 小時前獲取數據的 NumPy 數組并復制值。 ```py # fill missing values with a value at the same time one day ago def fill_missing(values): one_day = 60 * 24 for row in range(values.shape[0]): for col in range(values.shape[1]): if isnan(values[row, col]): values[row, col] = values[row - one_day, col] ``` 我們可以將此函數直接應用于 DataFrame 中的數據。 ```py # fill missing fill_missing(dataset.values) ``` 現在,我們可以使用上一節中的計算創建一個包含剩余子計量的新列。 ```py # add a column for for the remainder of sub metering values = dataset.values dataset['sub_metering_4'] = (values[:,0] * 1000 / 60) - (values[:,4] + values[:,5] + values[:,6]) ``` 我們現在可以將清理后的數據集版本保存到新文件中;在這種情況下,我們只需將文件擴展名更改為.csv,并將數據集保存為“ _household_power_consumption.csv_ ”。 ```py # save updated dataset dataset.to_csv('household_power_consumption.csv') ``` 將所有這些結合在一起,下面列出了加載,清理和保存數據集的完整示例。 ```py # load and clean-up data from numpy import nan from numpy import isnan from pandas import read_csv from pandas import to_numeric # fill missing values with a value at the same time one day ago def fill_missing(values): one_day = 60 * 24 for row in range(values.shape[0]): for col in range(values.shape[1]): if isnan(values[row, col]): values[row, col] = values[row - one_day, col] # load all data dataset = read_csv('household_power_consumption.txt', sep=';', header=0, low_memory=False, infer_datetime_format=True, parse_dates={'datetime':[0,1]}, index_col=['datetime']) # mark all missing values dataset.replace('?', nan, inplace=True) # make dataset numeric dataset = dataset.astype('float32') # fill missing fill_missing(dataset.values) # add a column for for the remainder of sub metering values = dataset.values dataset['sub_metering_4'] = (values[:,0] * 1000 / 60) - (values[:,4] + values[:,5] + values[:,6]) # save updated dataset dataset.to_csv('household_power_consumption.csv') ``` 運行該示例將創建新文件' _household_power_consumption.csv_ ',我們可以將其用作建模項目的起點。 ## 模型評估 在本節中,我們將考慮如何開發和評估家庭電力數據集的預測模型。 本節分為四個部分;他們是: 1. 問題框架 2. 評估指標 3. 訓練和測試集 4. 前瞻性驗證 ### 問題框架 有許多方法可以利用和探索家庭用電量數據集。 在本教程中,我們將使用這些數據來探索一個非常具體的問題;那是: > 鑒于最近的耗電量,未來一周的預期耗電量是多少? 這要求預測模型預測未來七天每天的總有功功率。 從技術上講,考慮到多個預測步驟,這個問題的框架被稱為多步驟時間序列預測問題。利用多個輸入變量的模型可以稱為多變量多步時間序列預測模型。 這種類型的模型在規劃支出方面可能有助于家庭。在供應方面,它也可能有助于規劃特定家庭的電力需求。 數據集的這種框架還表明,將每分鐘功耗的觀察結果下采樣到每日總數是有用的。這不是必需的,但考慮到我們對每天的總功率感興趣,這是有道理的。 我們可以使用 pandas DataFrame 上的 [resample()函數](https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.resample.html)輕松實現這一點。使用參數' _D_ '調用此函數允許按日期時間索引的加載數據按天分組([查看所有偏移別名](http://pandas.pydata.org/pandas-docs/stable/timeseries.html#offset-aliases))。然后,我們可以計算每天所有觀測值的總和,并為八個變量中的每一個創建每日耗電量數據的新數據集。 下面列出了完整的示例。 ```py # resample minute data to total for each day from pandas import read_csv # load the new file dataset = read_csv('household_power_consumption.csv', header=0, infer_datetime_format=True, parse_dates=['datetime'], index_col=['datetime']) # resample data to daily daily_groups = dataset.resample('D') daily_data = daily_groups.sum() # summarize print(daily_data.shape) print(daily_data.head()) # save daily_data.to_csv('household_power_consumption_days.csv') ``` 運行該示例將創建一個新的每日總功耗數據集,并將結果保存到名為“ _household_power_consumption_days.csv_ ”的單獨文件中。 我們可以將其用作數據集,用于擬合和評估所選問題框架的預測模型。 ### 評估指標 預測將包含七個值,一個用于一周中的每一天。 多步預測問題通常分別評估每個預測時間步長。這有助于以下幾個原因: * 在特定提前期評論技能(例如+1 天 vs +3 天)。 * 在不同的交付時間基于他們的技能對比模型(例如,在+1 天的模型和在日期+5 的模型良好的模型)。 總功率的單位是千瓦,并且具有也在相同單位的誤差度量將是有用的。均方根誤差(RMSE)和平均絕對誤差(MAE)都符合這個要求,盡管 RMSE 更常用,將在本教程中采用。與 MAE 不同,RMSE 更能預測預測誤差。 此問題的表現指標是從第 1 天到第 7 天的每個提前期的 RMSE。 作為捷徑,使用單個分數總結模型的表現以幫助模型選擇可能是有用的。 可以使用的一個可能的分數是所有預測天數的 RMSE。 下面的函數 _evaluate_forecasts()_ 將實現此行為并基于多個七天預測返回模型的表現。 ```py # evaluate one or more weekly forecasts against expected values def evaluate_forecasts(actual, predicted): scores = list() # calculate an RMSE score for each day for i in range(actual.shape[1]): # calculate mse mse = mean_squared_error(actual[:, i], predicted[:, i]) # calculate rmse rmse = sqrt(mse) # store scores.append(rmse) # calculate overall RMSE s = 0 for row in range(actual.shape[0]): for col in range(actual.shape[1]): s += (actual[row, col] - predicted[row, col])**2 score = sqrt(s / (actual.shape[0] * actual.shape[1])) return score, scores ``` 運行該函數將首先返回整個 RMSE,無論白天,然后每天返回一系列 RMSE 分數。 ### 訓練和測試集 我們將使用前三年的數據來訓練預測模型和評估模型的最后一年。 給定數據集中的數據將分為標準周。這些是從周日開始到周六結束的周。 這是使用所選模型框架的現實且有用的方法,其中可以預測未來一周的功耗。它也有助于建模,其中模型可用于預測特定日期(例如星期三)或整個序列。 我們將數據拆分為標準周,從測試數據集向后工作。 數據的最后一年是 2010 年,2010 年的第一個星期日是 1 月 3 日。數據于 2010 年 11 月中旬結束,數據中最接近的最后一個星期六是 11 月 20 日。這給出了 46 周的測試數據。 下面提供了測試數據集的每日數據的第一行和最后一行以供確認。 ```py 2010-01-03,2083.4539999999984,191.61000000000055,350992.12000000034,8703.600000000033,3842.0,4920.0,10074.0,15888.233355799992 ... 2010-11-20,2197.006000000004,153.76800000000028,346475.9999999998,9320.20000000002,4367.0,2947.0,11433.0,17869.76663959999 ``` 每日數據從 2006 年底開始。 數據集中的第一個星期日是 12 月 17 日,這是第二行數據。 將數據組織到標準周內為訓練預測模型提供了 159 個完整的標準周。 ```py 2006-12-17,3390.46,226.0059999999994,345725.32000000024,14398.59999999998,2033.0,4187.0,13341.0,36946.66673200004 ... 2010-01-02,1309.2679999999998,199.54600000000016,352332.8399999997,5489.7999999999865,801.0,298.0,6425.0,14297.133406600002 ``` 下面的函數 _split_dataset()_ 將每日數據拆分為訓練集和測試集,并將每個數據組織成標準周。 使用特定行偏移來使用數據集的知識來分割數據。然后使用 NumPy [split()函數](https://docs.scipy.org/doc/numpy/reference/generated/numpy.split.html)將分割數據集組織成每周數據。 ```py # split a univariate dataset into train/test sets def split_dataset(data): # split into standard weeks train, test = data[1:-328], data[-328:-6] # restructure into windows of weekly data train = array(split(train, len(train)/7)) test = array(split(test, len(test)/7)) return train, test ``` 我們可以通過加載每日數據集并打印訓練和測試集的第一行和最后一行數據來測試此功能,以確認它們符合上述預期。 完整的代碼示例如下所示。 ```py # split into standard weeks from numpy import split from numpy import array from pandas import read_csv # split a univariate dataset into train/test sets def split_dataset(data): # split into standard weeks train, test = data[1:-328], data[-328:-6] # restructure into windows of weekly data train = array(split(train, len(train)/7)) test = array(split(test, len(test)/7)) return train, test # load the new file dataset = read_csv('household_power_consumption_days.csv', header=0, infer_datetime_format=True, parse_dates=['datetime'], index_col=['datetime']) train, test = split_dataset(dataset.values) # validate train data print(train.shape) print(train[0, 0, 0], train[-1, -1, 0]) # validate test print(test.shape) print(test[0, 0, 0], test[-1, -1, 0]) ``` 運行該示例表明,訓練數據集確實有 159 周的數據,而測試數據集有 46 周。 我們可以看到,第一行和最后一行的訓練和測試數據集的總有效功率與我們定義為每組標準周界限的特定日期的數據相匹配。 ```py (159, 7, 8) 3390.46 1309.2679999999998 (46, 7, 8) 2083.4539999999984 2197.006000000004 ``` ### 前瞻性驗證 將使用稱為[前進驗證](https://machinelearningmastery.com/backtest-machine-learning-models-time-series-forecasting/)的方案評估模型。 這是需要模型進行一周預測的地方,然后該模型的實際數據可用于模型,以便它可以用作在隨后一周進行預測的基礎。這對于如何在實踐中使用模型以及對模型有益,使其能夠利用最佳可用數據都是現實的。 我們可以通過分離輸入數據和輸出/預測數據來證明這一點。 ```py Input, Predict [Week1] Week2 [Week1 + Week2] Week3 [Week1 + Week2 + Week3] Week4 ... ``` 下面提供了評估此數據集上預測模型的前瞻性驗證方法,命名為 _evaluate_model()_。 標準周格式的訓練和測試數據集作為參數提供給函數。提供了另一個參數 _n_input_ ,用于定義模型將用作輸入以進行預測的先前觀察的數量。 調用兩個新函數:一個用于根據稱為 _build_model()_ 的訓練數據構建模型,另一個用于使用該模型對每個新標準周進行預測,稱為 _forecast()_ 。這些將在后續章節中介紹。 我們正在使用神經網絡,因此它們通常很難訓練但很快就能進行評估。這意味著模型的首選用法是在歷史數據上構建一次,并使用它們來預測前向驗證的每個步驟。模型在評估期間是靜態的(即未更新)。 這與訓練更快的其他模型不同,其中當新數據可用時,模型可以重新擬合或更新前進驗證的每個步驟。有了足夠的資源,就可以通過這種方式使用神經網絡,但在本教程中我們不會這樣做。 下面列出了完整的 _evaluate_model()_ 函數。 ```py # evaluate a single model def evaluate_model(train, test, n_input): # fit model model = build_model(train, n_input) # history is a list of weekly data history = [x for x in train] # walk-forward validation over each week predictions = list() for i in range(len(test)): # predict the week yhat_sequence = forecast(model, history, n_input) # store the predictions predictions.append(yhat_sequence) # get real observation and add to history for predicting the next week history.append(test[i, :]) # evaluate predictions days for each week predictions = array(predictions) score, scores = evaluate_forecasts(test[:, :, 0], predictions) return score, scores ``` 一旦我們對模型進行評估,我們就可以總結表現。 下面的函數名為 _summarize_scores()_,將模型的表現顯示為單行,以便與其他模型進行比較。 ```py # summarize scores def summarize_scores(name, score, scores): s_scores = ', '.join(['%.1f' % s for s in scores]) print('%s: [%.3f] %s' % (name, score, s_scores)) ``` 我們現在已經開始評估數據集上的預測模型的所有元素。 ## 用于多步預測的 CNN 卷積神經網絡模型(簡稱 CNN)是一種深度神經網絡,開發用于圖像數據,如手寫識別。 事實證明,它們在大規模訓練時可以有效地挑戰計算機視覺問題,例如識別和定位圖像中的對象并自動描述圖像內容。 它們是由兩種主要類型的元素組成的模型:卷積層和池化層。 **卷積層**使用內核讀取輸入,例如 2D 圖像或 1D 信號,該內核一次讀取小段并跨越整個輸入字段。每次讀取都會導致對投影到濾鏡圖上的輸入進行解釋,并表示對輸入的解釋。 **匯集層**采用特征映射投影并將它們提取到最基本的元素,例如使用信號平均或信號最大化過程。 卷積和合并層可以在深度重復,提供輸入信號的多層抽象。 這些網絡的輸出通常是一個或多個完全連接的層,用于解釋已讀取的內容并將此內部表示映射到類值。 有關卷積神經網絡的更多信息,您可以看到帖子: * [用于機器學習的卷積神經網絡的速成課程](https://machinelearningmastery.com/crash-course-convolutional-neural-networks/) 卷積神經網絡可用于多步時間序列預測。 * 卷積層可以讀取輸入數據的序列并自動提取特征。 * 匯集層可以提取提取的特征,并將注意力集中在最顯著的元素上。 * 完全連接的層可以解釋內部表示并輸出表示多個時間步長的向量。 該方法的主要優點是自動特征學習和模型直接輸出多步向量的能力。 CNN 可用于遞歸或直接預測策略,其中模型使得一步預測和輸出作為后續預測的輸入被饋送,并且其中一個模型被開發用于每個預測的時間步長。或者,CNN 可用于預測整個輸出序列,作為整個向量的一步預測。這是前饋神經網絡的一般優點。 使用 CNN 的一個重要的第二個好處是它們可以支持多個 1D 輸入以進行預測。如果多步輸出序列是多個輸入序列的函數,則這很有用。這可以使用兩種不同的模型配置來實現。 * **多輸入通道**。這是每個輸入序列作為單獨的通道讀取的地方,如圖像的不同通道(例如紅色,綠色和藍色)。 * **多輸入磁頭**。這是每個輸入序列由不同的 CNN 子模型讀取的地方,并且內部表示在被解釋并用于進行預測之前被組合。 在本教程中,我們將探討如何為多步時間序列預測開發三種不同類型的 CNN 模型;他們是: * CNN 用于使用單變量輸入數據進行多步時間序列預測。 * CNN 用于多步驟時間序列預測,通過信道提供多變量輸入數據。 * 通過子模型使用多變量輸入數據進行多步時間序列預測的 CNN。 將在家庭電力預測問題上開發和演示這些模型。如果一個模型比一個樸素的模型更好地實現表現,那么該模型被認為是技術性的,在 7 天的預測中,該模型的總體 RMSE 約為 465 千瓦。 我們不會專注于調整這些模型以實現最佳表現;相反,與樸素的預測相比,我們將在熟練的模型上停下來。選擇的結構和超參數通過一些試驗和錯誤來選擇。 ## 具有單變量 CNN 的多步時間序列預測 在本節中,我們將開發一個卷積神經網絡,用于僅使用每日功耗的單變量序列進行多步時間序列預測。 具體來說,問題的框架是: > 考慮到每日總耗電量的前幾天,預測下一個標準周的每日耗電量。 用作輸入的先前天數定義了 CNN 將讀取并學習提取特征的數據的一維(1D)子序列。關于此輸入的大小和性質的一些想法包括: * 所有前幾天,最多數年的數據。 * 前 7 天。 * 前兩周。 * 前一個月。 * 前一年。 * 前一周和一周從一年前預測。 沒有正確的答案;相反,可以測試每種方法和更多方法,并且可以使用模型的表現來選擇導致最佳模型表現的輸入的性質。 這些選擇定義了有關實現的一些內容,例如: * 如何準備訓練數據以適應模型。 * 如何準備測試數據以評估模型。 * 如何使用該模型在未來使用最終模型進行預測。 一個好的起點是使用前七天。 1D CNN 模型期望數據具有以下形狀: ```py [samples, timesteps, features] ``` 一個樣本將包含七個時間步驟,其中一個功能用于每日總耗電量的七天。 訓練數據集有 159 周的數據,因此訓練數據集的形狀為: ```py [159, 7, 1] ``` 這是一個好的開始。此格式的數據將使用先前的標準周來預測下一個標準周。一個問題是 159 個實例對于神經網絡來說并不是很多。 創建更多訓練數據的方法是在訓練期間更改問題,以預測前七天的下一個七天,無論標準周。 這僅影響訓練數據,測試問題保持不變:預測給定前一標準周的下一個標準周的每日功耗。 這將需要一點準備訓練數據。 訓練數據在標準周內提供八個變量,特別是形狀[159,7,8]。第一步是展平數據,以便我們有八個時間序列序列。 ```py # flatten data data = data.reshape((data.shape[0]*data.shape[1], data.shape[2])) ``` 然后,我們需要迭代時間步驟并將數據劃分為重疊窗口;每次迭代沿著一個時間步移動并預測隨后的七天。 例如: ```py Input, Output [d01, d02, d03, d04, d05, d06, d07], [d08, d09, d10, d11, d12, d13, d14] [d02, d03, d04, d05, d06, d07, d08], [d09, d10, d11, d12, d13, d14, d15] ... ``` 我們可以通過跟蹤輸入和輸出的開始和結束索引來實現這一點,因為我們在時間步長方面迭代展平數據的長度。 我們也可以通過參數化輸入和輸出的數量來實現這一點(例如 _n_input_ , _n_out_ ),這樣您就可以嘗試不同的值或根據自己的問題進行調整。 下面是一個名為 _to_supervised()_ 的函數,它采用周(歷史)列表和用作輸入和輸出的時間步數,并以重疊移動窗口格式返回數據。 ```py # convert history into inputs and outputs def to_supervised(train, n_input, n_out=7): # flatten data data = train.reshape((train.shape[0]*train.shape[1], train.shape[2])) X, y = list(), list() in_start = 0 # step over the entire history one time step at a time for _ in range(len(data)): # define the end of the input sequence in_end = in_start + n_input out_end = in_end + n_out # ensure we have enough data for this instance if out_end < len(data): x_input = data[in_start:in_end, 0] x_input = x_input.reshape((len(x_input), 1)) X.append(x_input) y.append(data[in_end:out_end, 0]) # move along one time step in_start += 1 return array(X), array(y) ``` 當我們在整個訓練數據集上運行此函數時,我們將 159 個樣本轉換為 1,099 個;具體地,變換的數據集具有形狀 _X = [1099,7,1]_ 和 _y = [1099,7]。_ 接下來,我們可以在訓練數據上定義和擬合 CNN 模型。 這個多步驟時間序列預測問題是一個自回歸。這意味著它可能最好建模,其中接下來的七天是先前時間步驟的觀測功能。這和相對少量的數據意味著需要一個小型號。 我們將使用一個具有一個卷積層的模型,其中包含 16 個濾波器,內核大小為 3.這意味著七次輸入序列將通過卷積操作一次讀取三個時間步,并且此操作將執行 16 次。在將內部表示展平為一個長向量之前,池化層將這些要素圖減小其大小的 1/4。然后,在輸出層預測序列中的下一個七天之前,由完全連接的層解釋。 我們將使用均方誤差損失函數,因為它與我們選擇的 RMSE 誤差度量非常匹配。我們將使用隨機梯度下降的有效 [Adam](https://machinelearningmastery.com/adam-optimization-algorithm-for-deep-learning/) 實現,并將模型擬合 20 個時期,批量大小為 4。 小批量大小和算法的隨機性意味著相同的模型將在每次訓練時學習輸入到輸出的略微不同的映射。這意味著[結果可能會在評估模型時發生變化](https://machinelearningmastery.com/randomness-in-machine-learning/)。您可以嘗試多次運行模型并計算模型表現的平均值。 下面的 _build_model()_ 準備訓練數據,定義模型,并將模型擬合到訓練數據上,使擬合模型準備好進行預測。 ```py # train the model def build_model(train, n_input): # prepare data train_x, train_y = to_supervised(train, n_input) # define parameters verbose, epochs, batch_size = 0, 20, 4 n_timesteps, n_features, n_outputs = train_x.shape[1], train_x.shape[2], train_y.shape[1] # define model model = Sequential() model.add(Conv1D(filters=16, kernel_size=3, activation='relu', input_shape=(n_timesteps,n_features))) model.add(MaxPooling1D(pool_size=2)) model.add(Flatten()) model.add(Dense(10, activation='relu')) model.add(Dense(n_outputs)) model.compile(loss='mse', optimizer='adam') # fit network model.fit(train_x, train_y, epochs=epochs, batch_size=batch_size, verbose=verbose) return model ``` 現在我們知道如何擬合模型,我們可以看看如何使用模型進行預測。 通常,模型期望數據在進行預測時具有相同的三維形狀。 在這種情況下,輸入模式的預期形狀是一個樣本,每天消耗的一個功能的七天: ```py [1, 7, 1] ``` 在對測試集進行預測時以及在將來使用最終模型進行預測時,數據必須具有此形狀。如果將輸入天數更改為 14,則必須相應更改訓練數據的形狀和進行預測時新樣本的形狀,以便有 14 個時間步長。在使用模型時,您必須繼續使用它。 我們正在使用前向驗證來評估模型,如上一節中所述。 這意味著我們有前一周的觀察結果,以預測下周。這些被收集到一系列標準周,稱為歷史。 為了預測下一個標準周,我們需要檢索觀察的最后幾天。與訓練數據一樣,我們必須首先展平歷史數據以刪除每周結構,以便最終得到八個平行時間序列。 ```py # flatten data data = data.reshape((data.shape[0]*data.shape[1], data.shape[2])) ``` 接下來,我們需要檢索每日總功耗的最后七天(功能編號 0)。我們將像對訓練數據那樣進行參數化,以便將來可以修改模型用作輸入的前幾天的數量。 ```py # retrieve last observations for input data input_x = data[-n_input:, 0] ``` 接下來,我們將輸入重塑為預期的三維結構。 ```py # reshape into [1, n_input, 1] input_x = input_x.reshape((1, len(input_x), 1)) ``` 然后,我們使用擬合模型和輸入數據進行預測,并檢索七天輸出的向量。 ```py # forecast the next week yhat = model.predict(input_x, verbose=0) # we only want the vector forecast yhat = yhat[0] ``` 下面的 _forecast()_ 函數實現了這個功能,并將模型擬合到訓練數據集,到目前為止觀察到的數據歷史以及模型預期的輸入時間步數。 ```py # make a forecast def forecast(model, history, n_input): # flatten data data = array(history) data = data.reshape((data.shape[0]*data.shape[1], data.shape[2])) # retrieve last observations for input data input_x = data[-n_input:, 0] # reshape into [1, n_input, 1] input_x = input_x.reshape((1, len(input_x), 1)) # forecast the next week yhat = model.predict(input_x, verbose=0) # we only want the vector forecast yhat = yhat[0] return yhat ``` 而已;我們現在擁有了所需的一切,我們需要通過 CNN 模型對單變量數據集的每日總功耗進行多步時間序列預測。 我們可以將所有這些結合在一起。下面列出了完整的示例。 ```py # univariate multi-step cnn from math import sqrt from numpy import split from numpy import array from pandas import read_csv from sklearn.metrics import mean_squared_error from matplotlib import pyplot from keras.models import Sequential from keras.layers import Dense from keras.layers import Flatten from keras.layers.convolutional import Conv1D from keras.layers.convolutional import MaxPooling1D # split a univariate dataset into train/test sets def split_dataset(data): # split into standard weeks train, test = data[1:-328], data[-328:-6] # restructure into windows of weekly data train = array(split(train, len(train)/7)) test = array(split(test, len(test)/7)) return train, test # evaluate one or more weekly forecasts against expected values def evaluate_forecasts(actual, predicted): scores = list() # calculate an RMSE score for each day for i in range(actual.shape[1]): # calculate mse mse = mean_squared_error(actual[:, i], predicted[:, i]) # calculate rmse rmse = sqrt(mse) # store scores.append(rmse) # calculate overall RMSE s = 0 for row in range(actual.shape[0]): for col in range(actual.shape[1]): s += (actual[row, col] - predicted[row, col])**2 score = sqrt(s / (actual.shape[0] * actual.shape[1])) return score, scores # summarize scores def summarize_scores(name, score, scores): s_scores = ', '.join(['%.1f' % s for s in scores]) print('%s: [%.3f] %s' % (name, score, s_scores)) # convert history into inputs and outputs def to_supervised(train, n_input, n_out=7): # flatten data data = train.reshape((train.shape[0]*train.shape[1], train.shape[2])) X, y = list(), list() in_start = 0 # step over the entire history one time step at a time for _ in range(len(data)): # define the end of the input sequence in_end = in_start + n_input out_end = in_end + n_out # ensure we have enough data for this instance if out_end < len(data): x_input = data[in_start:in_end, 0] x_input = x_input.reshape((len(x_input), 1)) X.append(x_input) y.append(data[in_end:out_end, 0]) # move along one time step in_start += 1 return array(X), array(y) # train the model def build_model(train, n_input): # prepare data train_x, train_y = to_supervised(train, n_input) # define parameters verbose, epochs, batch_size = 0, 20, 4 n_timesteps, n_features, n_outputs = train_x.shape[1], train_x.shape[2], train_y.shape[1] # define model model = Sequential() model.add(Conv1D(filters=16, kernel_size=3, activation='relu', input_shape=(n_timesteps,n_features))) model.add(MaxPooling1D(pool_size=2)) model.add(Flatten()) model.add(Dense(10, activation='relu')) model.add(Dense(n_outputs)) model.compile(loss='mse', optimizer='adam') # fit network model.fit(train_x, train_y, epochs=epochs, batch_size=batch_size, verbose=verbose) return model # make a forecast def forecast(model, history, n_input): # flatten data data = array(history) data = data.reshape((data.shape[0]*data.shape[1], data.shape[2])) # retrieve last observations for input data input_x = data[-n_input:, 0] # reshape into [1, n_input, 1] input_x = input_x.reshape((1, len(input_x), 1)) # forecast the next week yhat = model.predict(input_x, verbose=0) # we only want the vector forecast yhat = yhat[0] return yhat # evaluate a single model def evaluate_model(train, test, n_input): # fit model model = build_model(train, n_input) # history is a list of weekly data history = [x for x in train] # walk-forward validation over each week predictions = list() for i in range(len(test)): # predict the week yhat_sequence = forecast(model, history, n_input) # store the predictions predictions.append(yhat_sequence) # get real observation and add to history for predicting the next week history.append(test[i, :]) # evaluate predictions days for each week predictions = array(predictions) score, scores = evaluate_forecasts(test[:, :, 0], predictions) return score, scores # load the new file dataset = read_csv('household_power_consumption_days.csv', header=0, infer_datetime_format=True, parse_dates=['datetime'], index_col=['datetime']) # split into train and test train, test = split_dataset(dataset.values) # evaluate model and get scores n_input = 7 score, scores = evaluate_model(train, test, n_input) # summarize scores summarize_scores('cnn', score, scores) # plot scores days = ['sun', 'mon', 'tue', 'wed', 'thr', 'fri', 'sat'] pyplot.plot(days, scores, marker='o', label='cnn') pyplot.show() ``` 運行該示例適合并評估模型,在所有七天內打印整體 RMSE,以及每個提前期的每日 RMSE。 鑒于算法的隨機性,您的具體結果可能會有所不同。您可能想嘗試幾次運行該示例。 我們可以看到,在這種情況下,與樸素的預測相比,該模型是巧妙的,實現了大約 404 千瓦的總體 RMSE,小于 465 千瓦的樸素模型。 ```py cnn: [404.411] 436.1, 400.6, 346.2, 388.2, 405.5, 326.0, 502.9 ``` 還創建了每日 RMSE 的圖。該圖顯示,周二和周五可能比其他日子更容易預測,也許星期六在標準周結束時是最難預測的日子。 ![Line Plot of RMSE per Day for Univariate CNN with 7-day Inputs](https://img.kancloud.cn/cd/d7/cdd7b0c275f770b258702ba9a480f870_1280x960.jpg) 具有 7 天輸入的單變量 CNN 每日 RMSE 的線圖 我們可以通過更改 _n_input_ 變量來增加用作 7 到 14 之間輸入的前幾天的數量。 ```py # evaluate model and get scores n_input = 14 ``` 使用此更改重新運行示例首先會打印模型表現的摘要。 具體結果可能有所不同;嘗試運行幾次這個例子。 在這種情況下,我們可以看到整體 RMSE 進一步下降,這表明進一步調整輸入大小以及模型的內核大小可能會帶來更好的表現。 ```py cnn: [396.497] 392.2, 412.8, 384.0, 389.0, 387.3, 381.0, 427.1 ``` 比較每日 RMSE 分數,我們看到一些更好,有些比使用第七輸入更差。 這可以建議以某種方式使用兩個不同大小的輸入的益處,例如兩種方法的集合或者可能是以不同方式讀取訓練數據的單個模型(例如,多頭模型)。 ![Line Plot of RMSE per Day for Univariate CNN with 14-day Inputs](https://img.kancloud.cn/22/2a/222a0718a65d5103cbe3631f866a6ceb_1280x960.jpg) 單變量 CNN 每日 RMSE 的線圖,具有 14 天輸入 ## 使用多通道 CNN 的多步時間序列預測 在本節中,我們將更新上一節中開發的 CNN,以使用八個時間序列變量中的每一個來預測下一個標準周的每日總功耗。 我們將通過將每個一維時間序列作為單獨的輸入通道提供給模型來實現此目的。 然后,CNN 將使用單獨的內核并將每個輸入序列讀取到一組單獨的過濾器映射上,主要是從每個輸入時間序列變量中學習特征。 這對于那些輸出序列是來自多個不同特征的先前時間步驟的觀察的某些功能的問題是有幫助的,而不僅僅是(或包括)預測的特征。目前還不清楚功耗問題是否屬于這種情況,但我們仍可以探索它。 首先,我們必須更新訓練數據的準備工作,以包括所有八項功能,而不僅僅是每日消耗的一項功能。它需要一行: ```py X.append(data[in_start:in_end, :]) ``` 下面列出了具有此更改的完整 _to_supervised()_ 功能。 ```py # convert history into inputs and outputs def to_supervised(train, n_input, n_out=7): # flatten data data = train.reshape((train.shape[0]*train.shape[1], train.shape[2])) X, y = list(), list() in_start = 0 # step over the entire history one time step at a time for _ in range(len(data)): # define the end of the input sequence in_end = in_start + n_input out_end = in_end + n_out # ensure we have enough data for this instance if out_end < len(data): X.append(data[in_start:in_end, :]) y.append(data[in_end:out_end, 0]) # move along one time step in_start += 1 return array(X), array(y) ``` 我們還必須使用擬合模型更新用于進行預測的函數,以使用先前時間步驟中的所有八個特征。再次,另一個小變化: ```py # retrieve last observations for input data input_x = data[-n_input:, :] # reshape into [1, n_input, n] input_x = input_x.reshape((1, input_x.shape[0], input_x.shape[1])) ``` 具有此更改的完整 _forecast()_ 如下所示: ```py # make a forecast def forecast(model, history, n_input): # flatten data data = array(history) data = data.reshape((data.shape[0]*data.shape[1], data.shape[2])) # retrieve last observations for input data input_x = data[-n_input:, :] # reshape into [1, n_input, n] input_x = input_x.reshape((1, input_x.shape[0], input_x.shape[1])) # forecast the next week yhat = model.predict(input_x, verbose=0) # we only want the vector forecast yhat = yhat[0] return yhat ``` 我們將在前面部分的最后一部分中使用 14 天的先前觀察到 8 個輸入變量,這導致表現稍好一些。 ```py n_input = 14 ``` 最后,上一節中使用的模型在這個問題的新框架上表現不佳。 數據量的增加需要更大,更復雜的模型,這種模型需要更長時間的訓練。 通過一些試驗和錯誤,一個表現良好的模型使用兩個卷積層,32 個濾波器映射,然后匯集,然后另一個卷積層,16 個特征映射和匯集。解釋特征的完全連接層增加到 100 個節點,該模型適用于 70 個迭代,批量大小為 16 個樣本。 下面列出了更新的 _build_model()_ 函數,該函數定義并擬合訓練數據集上的模型。 ```py # train the model def build_model(train, n_input): # prepare data train_x, train_y = to_supervised(train, n_input) # define parameters verbose, epochs, batch_size = 0, 70, 16 n_timesteps, n_features, n_outputs = train_x.shape[1], train_x.shape[2], train_y.shape[1] # define model model = Sequential() model.add(Conv1D(filters=32, kernel_size=3, activation='relu', input_shape=(n_timesteps,n_features))) model.add(Conv1D(filters=32, kernel_size=3, activation='relu')) model.add(MaxPooling1D(pool_size=2)) model.add(Conv1D(filters=16, kernel_size=3, activation='relu')) model.add(MaxPooling1D(pool_size=2)) model.add(Flatten()) model.add(Dense(100, activation='relu')) model.add(Dense(n_outputs)) model.compile(loss='mse', optimizer='adam') # fit network model.fit(train_x, train_y, epochs=epochs, batch_size=batch_size, verbose=verbose) return model ``` 我們現在擁有為多變量輸入數據開發多通道 CNN 以進行多步時間序列預測所需的所有元素。 下面列出了完整的示例。 ```py # multichannel multi-step cnn from math import sqrt from numpy import split from numpy import array from pandas import read_csv from sklearn.metrics import mean_squared_error from matplotlib import pyplot from keras.models import Sequential from keras.layers import Dense from keras.layers import Flatten from keras.layers.convolutional import Conv1D from keras.layers.convolutional import MaxPooling1D # split a univariate dataset into train/test sets def split_dataset(data): # split into standard weeks train, test = data[1:-328], data[-328:-6] # restructure into windows of weekly data train = array(split(train, len(train)/7)) test = array(split(test, len(test)/7)) return train, test # evaluate one or more weekly forecasts against expected values def evaluate_forecasts(actual, predicted): scores = list() # calculate an RMSE score for each day for i in range(actual.shape[1]): # calculate mse mse = mean_squared_error(actual[:, i], predicted[:, i]) # calculate rmse rmse = sqrt(mse) # store scores.append(rmse) # calculate overall RMSE s = 0 for row in range(actual.shape[0]): for col in range(actual.shape[1]): s += (actual[row, col] - predicted[row, col])**2 score = sqrt(s / (actual.shape[0] * actual.shape[1])) return score, scores # summarize scores def summarize_scores(name, score, scores): s_scores = ', '.join(['%.1f' % s for s in scores]) print('%s: [%.3f] %s' % (name, score, s_scores)) # convert history into inputs and outputs def to_supervised(train, n_input, n_out=7): # flatten data data = train.reshape((train.shape[0]*train.shape[1], train.shape[2])) X, y = list(), list() in_start = 0 # step over the entire history one time step at a time for _ in range(len(data)): # define the end of the input sequence in_end = in_start + n_input out_end = in_end + n_out # ensure we have enough data for this instance if out_end < len(data): X.append(data[in_start:in_end, :]) y.append(data[in_end:out_end, 0]) # move along one time step in_start += 1 return array(X), array(y) # train the model def build_model(train, n_input): # prepare data train_x, train_y = to_supervised(train, n_input) # define parameters verbose, epochs, batch_size = 0, 70, 16 n_timesteps, n_features, n_outputs = train_x.shape[1], train_x.shape[2], train_y.shape[1] # define model model = Sequential() model.add(Conv1D(filters=32, kernel_size=3, activation='relu', input_shape=(n_timesteps,n_features))) model.add(Conv1D(filters=32, kernel_size=3, activation='relu')) model.add(MaxPooling1D(pool_size=2)) model.add(Conv1D(filters=16, kernel_size=3, activation='relu')) model.add(MaxPooling1D(pool_size=2)) model.add(Flatten()) model.add(Dense(100, activation='relu')) model.add(Dense(n_outputs)) model.compile(loss='mse', optimizer='adam') # fit network model.fit(train_x, train_y, epochs=epochs, batch_size=batch_size, verbose=verbose) return model # make a forecast def forecast(model, history, n_input): # flatten data data = array(history) data = data.reshape((data.shape[0]*data.shape[1], data.shape[2])) # retrieve last observations for input data input_x = data[-n_input:, :] # reshape into [1, n_input, n] input_x = input_x.reshape((1, input_x.shape[0], input_x.shape[1])) # forecast the next week yhat = model.predict(input_x, verbose=0) # we only want the vector forecast yhat = yhat[0] return yhat # evaluate a single model def evaluate_model(train, test, n_input): # fit model model = build_model(train, n_input) # history is a list of weekly data history = [x for x in train] # walk-forward validation over each week predictions = list() for i in range(len(test)): # predict the week yhat_sequence = forecast(model, history, n_input) # store the predictions predictions.append(yhat_sequence) # get real observation and add to history for predicting the next week history.append(test[i, :]) # evaluate predictions days for each week predictions = array(predictions) score, scores = evaluate_forecasts(test[:, :, 0], predictions) return score, scores # load the new file dataset = read_csv('household_power_consumption_days.csv', header=0, infer_datetime_format=True, parse_dates=['datetime'], index_col=['datetime']) # split into train and test train, test = split_dataset(dataset.values) # evaluate model and get scores n_input = 14 score, scores = evaluate_model(train, test, n_input) # summarize scores summarize_scores('cnn', score, scores) # plot scores days = ['sun', 'mon', 'tue', 'wed', 'thr', 'fri', 'sat'] pyplot.plot(days, scores, marker='o', label='cnn') pyplot.show() ``` 運行該示例適合并評估模型,在所有七天內打印整體 RMSE,以及每個提前期的每日 RMSE。 鑒于算法的隨機性,您的具體結果可能會有所不同。您可能想嘗試幾次運行該示例。 我們可以看到,在這種情況下,使用所有八個輸入變量確實導致整體 RMSE 分數的另一個小幅下降。 ```py cnn: [385.711] 422.2, 363.5, 349.8, 393.1, 357.1, 318.8, 474.3 ``` 對于每日 RMSE 分數,我們確實看到一些更好,一些比上一節中的單變量 CNN 更差。 最后一天,周六,仍然是充滿挑戰的預測日,周五是一個輕松的預測日。設計模型可能會有一些好處,專門用于減少更難預測天數的誤差。 可能有趣的是,可以通過調諧模型或者可能是多個不同模型的集合來進一步降低每日分數的方差。比較使用 7 天甚至 21 天輸入數據的模型的表現以查看是否可以進一步獲得也可能是有趣的。 ![Line Plot of RMSE per Day for a Multichannel CNN with 14-day Inputs](https://img.kancloud.cn/e8/9e/e89ecc6bdaf61dffb3fb30f55f528dc8_1280x960.jpg) 具有 14 天輸入的多通道 CNN 每天 RMSE 的線圖 ## 具有多頭 CNN 的多步時間序列預測 我們可以進一步擴展 CNN 模型,為每個輸入變量設置一個單獨的子 CNN 模型或頭部,我們可以將其稱為多頭 CNN 模型。 這需要修改模型的準備,進而修改訓練和測試數據集的準備。 從模型開始,我們必須為八個輸入變量中的每一個定義一個單獨的 CNN 模型。 模型的配置(包括層數及其超參數)也進行了修改,以更好地適應新方法。新配置不是最佳配置,只需稍加試錯即可找到。 使用更靈活的[功能 API 來定義多頭模型以定義 Keras 模型](https://machinelearningmastery.com/keras-functional-api-deep-learning/)。 我們可以遍歷每個變量并創建一個子模型,該子模型采用 14 天數據的一維序列,并輸出包含序列中學習特征摘要的平面向量。這些向量中的每一個可以通過串聯合并以產生一個非常長的向量,然后在進行預測之前由一些完全連接的層解釋。 在我們構建子模型時,我們會跟蹤輸入層并在列表中展平層。這樣我們就可以在模型對象的定義中指定輸入,并使用合并層中的展平層列表。 ```py # create a channel for each variable in_layers, out_layers = list(), list() for i in range(n_features): inputs = Input(shape=(n_timesteps,1)) conv1 = Conv1D(filters=32, kernel_size=3, activation='relu')(inputs) conv2 = Conv1D(filters=32, kernel_size=3, activation='relu')(conv1) pool1 = MaxPooling1D(pool_size=2)(conv2) flat = Flatten()(pool1) # store layers in_layers.append(inputs) out_layers.append(flat) # merge heads merged = concatenate(out_layers) # interpretation dense1 = Dense(200, activation='relu')(merged) dense2 = Dense(100, activation='relu')(dense1) outputs = Dense(n_outputs)(dense2) model = Model(inputs=in_layers, outputs=outputs) # compile model model.compile(loss='mse', optimizer='adam') ``` 使用該模型時,它將需要八個數組作為輸入:每個子模型一個。 在訓練模型,評估模型以及使用最終模型進行預測時,這是必需的。 我們可以通過創建一個 3D 數組列表來實現這一點,其中每個 3D 數組包含[_ 樣本,時間步長,1_ ],具有一個特征。 我們可以按以下格式準備訓練數據集: ```py input_data = [train_x[:,:,i].reshape((train_x.shape[0],n_timesteps,1)) for i in range(n_features)] ``` 下面列出了具有這些更改的更新的 _build_model()_ 函數。 ```py # train the model def build_model(train, n_input): # prepare data train_x, train_y = to_supervised(train, n_input) # define parameters verbose, epochs, batch_size = 0, 25, 16 n_timesteps, n_features, n_outputs = train_x.shape[1], train_x.shape[2], train_y.shape[1] # create a channel for each variable in_layers, out_layers = list(), list() for i in range(n_features): inputs = Input(shape=(n_timesteps,1)) conv1 = Conv1D(filters=32, kernel_size=3, activation='relu')(inputs) conv2 = Conv1D(filters=32, kernel_size=3, activation='relu')(conv1) pool1 = MaxPooling1D(pool_size=2)(conv2) flat = Flatten()(pool1) # store layers in_layers.append(inputs) out_layers.append(flat) # merge heads merged = concatenate(out_layers) # interpretation dense1 = Dense(200, activation='relu')(merged) dense2 = Dense(100, activation='relu')(dense1) outputs = Dense(n_outputs)(dense2) model = Model(inputs=in_layers, outputs=outputs) # compile model model.compile(loss='mse', optimizer='adam') # plot the model plot_model(model, show_shapes=True, to_file='multiheaded_cnn.png') # fit network input_data = [train_x[:,:,i].reshape((train_x.shape[0],n_timesteps,1)) for i in range(n_features)] model.fit(input_data, train_y, epochs=epochs, batch_size=batch_size, verbose=verbose) return model ``` 構建模型時,會創建模型結構圖并將其保存到文件中。 注意:對 plot_model()的調用要求安裝 pygraphviz 和 pydot。如果這是一個問題,您可以注釋掉這一行。 網絡結構如下。 ![Structure of the Multi Headed Convolutional Neural Network](https://img.kancloud.cn/d4/68/d4681408c670e26ef3a10c70fe27f5b7_3240x959.jpg) 多頭卷積神經網絡的結構 接下來,我們可以在對測試數據集進行預測時更新輸入樣本的準備。 我們必須執行相同的更改,其中[1,14,8]的輸入數組必須轉換為八個 3D 數組的列表,每個數組都帶有[1,14,1]。 ```py input_x = [input_x[:,i].reshape((1,input_x.shape[0],1)) for i in range(input_x.shape[1])] ``` 下面列出了具有此更改的 _forecast()_ 函數。 ```py # make a forecast def forecast(model, history, n_input): # flatten data data = array(history) data = data.reshape((data.shape[0]*data.shape[1], data.shape[2])) # retrieve last observations for input data input_x = data[-n_input:, :] # reshape into n input arrays input_x = [input_x[:,i].reshape((1,input_x.shape[0],1)) for i in range(input_x.shape[1])] # forecast the next week yhat = model.predict(input_x, verbose=0) # we only want the vector forecast yhat = yhat[0] return yhat ``` 而已。 我們可以將所有這些結合在一起;下面列出了完整的示例。 ```py # multi headed multi-step cnn from math import sqrt from numpy import split from numpy import array from pandas import read_csv from sklearn.metrics import mean_squared_error from matplotlib import pyplot from keras.models import Sequential from keras.layers import Dense from keras.layers import Flatten from keras.layers.convolutional import Conv1D from keras.layers.convolutional import MaxPooling1D from keras.models import Model from keras.layers import Input from keras.layers.merge import concatenate # split a univariate dataset into train/test sets def split_dataset(data): # split into standard weeks train, test = data[1:-328], data[-328:-6] # restructure into windows of weekly data train = array(split(train, len(train)/7)) test = array(split(test, len(test)/7)) return train, test # evaluate one or more weekly forecasts against expected values def evaluate_forecasts(actual, predicted): scores = list() # calculate an RMSE score for each day for i in range(actual.shape[1]): # calculate mse mse = mean_squared_error(actual[:, i], predicted[:, i]) # calculate rmse rmse = sqrt(mse) # store scores.append(rmse) # calculate overall RMSE s = 0 for row in range(actual.shape[0]): for col in range(actual.shape[1]): s += (actual[row, col] - predicted[row, col])**2 score = sqrt(s / (actual.shape[0] * actual.shape[1])) return score, scores # summarize scores def summarize_scores(name, score, scores): s_scores = ', '.join(['%.1f' % s for s in scores]) print('%s: [%.3f] %s' % (name, score, s_scores)) # convert history into inputs and outputs def to_supervised(train, n_input, n_out=7): # flatten data data = train.reshape((train.shape[0]*train.shape[1], train.shape[2])) X, y = list(), list() in_start = 0 # step over the entire history one time step at a time for _ in range(len(data)): # define the end of the input sequence in_end = in_start + n_input out_end = in_end + n_out # ensure we have enough data for this instance if out_end < len(data): X.append(data[in_start:in_end, :]) y.append(data[in_end:out_end, 0]) # move along one time step in_start += 1 return array(X), array(y) # plot training history def plot_history(history): # plot loss pyplot.subplot(2, 1, 1) pyplot.plot(history.history['loss'], label='train') pyplot.plot(history.history['val_loss'], label='test') pyplot.title('loss', y=0, loc='center') pyplot.legend() # plot rmse pyplot.subplot(2, 1, 2) pyplot.plot(history.history['rmse'], label='train') pyplot.plot(history.history['val_rmse'], label='test') pyplot.title('rmse', y=0, loc='center') pyplot.legend() pyplot.show() # train the model def build_model(train, n_input): # prepare data train_x, train_y = to_supervised(train, n_input) # define parameters verbose, epochs, batch_size = 0, 25, 16 n_timesteps, n_features, n_outputs = train_x.shape[1], train_x.shape[2], train_y.shape[1] # create a channel for each variable in_layers, out_layers = list(), list() for i in range(n_features): inputs = Input(shape=(n_timesteps,1)) conv1 = Conv1D(filters=32, kernel_size=3, activation='relu')(inputs) conv2 = Conv1D(filters=32, kernel_size=3, activation='relu')(conv1) pool1 = MaxPooling1D(pool_size=2)(conv2) flat = Flatten()(pool1) # store layers in_layers.append(inputs) out_layers.append(flat) # merge heads merged = concatenate(out_layers) # interpretation dense1 = Dense(200, activation='relu')(merged) dense2 = Dense(100, activation='relu')(dense1) outputs = Dense(n_outputs)(dense2) model = Model(inputs=in_layers, outputs=outputs) # compile model model.compile(loss='mse', optimizer='adam') # fit network input_data = [train_x[:,:,i].reshape((train_x.shape[0],n_timesteps,1)) for i in range(n_features)] model.fit(input_data, train_y, epochs=epochs, batch_size=batch_size, verbose=verbose) return model # make a forecast def forecast(model, history, n_input): # flatten data data = array(history) data = data.reshape((data.shape[0]*data.shape[1], data.shape[2])) # retrieve last observations for input data input_x = data[-n_input:, :] # reshape into n input arrays input_x = [input_x[:,i].reshape((1,input_x.shape[0],1)) for i in range(input_x.shape[1])] # forecast the next week yhat = model.predict(input_x, verbose=0) # we only want the vector forecast yhat = yhat[0] return yhat # evaluate a single model def evaluate_model(train, test, n_input): # fit model model = build_model(train, n_input) # history is a list of weekly data history = [x for x in train] # walk-forward validation over each week predictions = list() for i in range(len(test)): # predict the week yhat_sequence = forecast(model, history, n_input) # store the predictions predictions.append(yhat_sequence) # get real observation and add to history for predicting the next week history.append(test[i, :]) # evaluate predictions days for each week predictions = array(predictions) score, scores = evaluate_forecasts(test[:, :, 0], predictions) return score, scores # load the new file dataset = read_csv('household_power_consumption_days.csv', header=0, infer_datetime_format=True, parse_dates=['datetime'], index_col=['datetime']) # split into train and test train, test = split_dataset(dataset.values) # evaluate model and get scores n_input = 14 score, scores = evaluate_model(train, test, n_input) # summarize scores summarize_scores('cnn', score, scores) # plot scores days = ['sun', 'mon', 'tue', 'wed', 'thr', 'fri', 'sat'] pyplot.plot(days, scores, marker='o', label='cnn') pyplot.show() ``` 運行該示例適合并評估模型,在所有七天內打印整體 RMSE,以及每個提前期的每日 RMSE。 鑒于算法的隨機性,您的具體結果可能會有所不同。您可能想嘗試幾次運行該示例。 我們可以看到,在這種情況下,與樸素的預測相比,整體 RMSE 非常熟練,但是所選擇的配置可能不會比上一節中的多通道模型表現更好。 ```py cnn: [396.116] 414.5, 385.5, 377.2, 412.1, 371.1, 380.6, 428.1 ``` 我們還可以看到每日 RMSE 分數的不同,更明顯的概況,其中 Mon-Tue 和 Thu-Fri 可能比其他預測天更容易預測模型。 與其他預測模型結合使用時,這些結果可能很有用。 在架構中探索用于合并每個子模型的輸出的替代方法可能是有趣的。 ![Line Plot of RMSE per Day for a Multi-head CNN with 14-day Inputs](https://img.kancloud.cn/fe/00/fe004bf26ab31685541379ef0023a71e_1280x960.jpg) 具有 14 天輸入的多頭 CNN 每天 RMSE 的線圖 ## 擴展 本節列出了一些擴展您可能希望探索的教程的想法。 * **輸入大小**。探索用作模型輸入的更多或更少天數,例如三天,21 天,30 天等。 * **模型調整**。調整模型的結構和超參數,并進一步平均提升模型表現。 * **數據縮放**。探索數據擴展(例如標準化和規范化)是否可用于改善任何 CNN 模型的表現。 * **學習診斷**。使用診斷,例如訓練的學習曲線和驗證損失以及均方誤差,以幫助調整 CNN 模型的結構和超參數。 * **不同的內核大小**。將多通道 CNN 與多頭 CNN 結合使用,并為每個磁頭使用不同的內核大小,以查看此配置是否可以進一步提高表現。 如果你探索任何這些擴展,我很想知道。 ## 進一步閱讀 如果您希望深入了解,本節將提供有關該主題的更多資源。 ### API * [pandas.read_csv API](https://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_csv.html) * [pandas.DataFrame.resample API](https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.resample.html) * [重采樣偏移別名](http://pandas.pydata.org/pandas-docs/stable/timeseries.html#offset-aliases) * [sklearn.metrics.mean_squared_error API](http://scikit-learn.org/stable/modules/generated/sklearn.metrics.mean_squared_error.html) * [numpy.split API](https://docs.scipy.org/doc/numpy/reference/generated/numpy.split.html) ### 用品 * [個人家庭用電量數據集,UCI 機器學習庫](https://archive.ics.uci.edu/ml/datasets/individual+household+electric+power+consumption)。 * [交流電源,維基百科](https://en.wikipedia.org/wiki/AC_power)。 * [多步時間序列預測的 4 種策略](https://machinelearningmastery.com/multi-step-time-series-forecasting/) * [用于機器學習的卷積神經網絡的速成課程](https://machinelearningmastery.com/crash-course-convolutional-neural-networks/) ## 摘要 在本教程中,您了解了如何為多步時間序列預測開發一維卷積神經網絡。 具體來說,你學到了: * 如何開發 CNN 用于單變量數據的多步時間序列預測模型。 * 如何開發多變量數據的多通道多步時間序列預測模型。 * 如何開發多元數據的多頭多步時間序列預測模型。 你有任何問題嗎? 在下面的評論中提出您的問題,我會盡力回答。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看