深度學(xué)習(xí)神經(jīng)網(wǎng)絡(luò)的預(yù)測(cè)間隔
預(yù)測(cè)間隔為回歸問題的預(yù)測(cè)提供了不確定性度量。
例如,95%的預(yù)測(cè)間隔表示100次中的95次,真實(shí)值將落在該范圍的下限值和上限值之間。這不同于可能表示不確定性區(qū)間中心的簡單點(diǎn)預(yù)測(cè)。沒有用于計(jì)算深度學(xué)習(xí)神經(jīng)網(wǎng)絡(luò)關(guān)于回歸預(yù)測(cè)建模問題的預(yù)測(cè)間隔的標(biāo)準(zhǔn)技術(shù)。但是,可以使用一組模型來估計(jì)快速且骯臟的預(yù)測(cè)間隔,這些模型又提供了點(diǎn)預(yù)測(cè)的分布,可以從中計(jì)算間隔。
在本教程中,您將發(fā)現(xiàn)如何計(jì)算深度學(xué)習(xí)神經(jīng)網(wǎng)絡(luò)的預(yù)測(cè)間隔。完成本教程后,您將知道:
- 預(yù)測(cè)間隔為回歸預(yù)測(cè)建模問題提供了不確定性度量。
- 如何在標(biāo)準(zhǔn)回歸問題上開發(fā)和評(píng)估簡單的多層感知器神經(jīng)網(wǎng)絡(luò)。
- 如何使用神經(jīng)網(wǎng)絡(luò)模型集成來計(jì)算和報(bào)告預(yù)測(cè)間隔。
教程概述
本教程分為三個(gè)部分:他們是:
- 預(yù)測(cè)間隔
- 回歸神經(jīng)網(wǎng)絡(luò)
- 神經(jīng)網(wǎng)絡(luò)預(yù)測(cè)間隔
預(yù)測(cè)間隔
通常,用于回歸問題的預(yù)測(cè)模型(即預(yù)測(cè)數(shù)值)進(jìn)行點(diǎn)預(yù)測(cè)。這意味著他們可以預(yù)測(cè)單個(gè)值,但不能提供任何有關(guān)該預(yù)測(cè)的不確定性的指示。根據(jù)定義,預(yù)測(cè)是估計(jì)值或近似值,并且包含一些不確定性。不確定性來自模型本身的誤差和輸入數(shù)據(jù)中的噪聲。該模型是輸入變量和輸出變量之間關(guān)系的近似值。預(yù)測(cè)間隔是對(duì)預(yù)測(cè)不確定性的量化。它為結(jié)果變量的估計(jì)提供了概率上限和下限。
預(yù)測(cè)間隔是在預(yù)測(cè)數(shù)量的回歸模型中進(jìn)行預(yù)測(cè)或預(yù)測(cè)時(shí)最常使用的時(shí)間間隔。預(yù)測(cè)間隔圍繞模型所做的預(yù)測(cè),并希望覆蓋真實(shí)結(jié)果的范圍。有關(guān)一般的預(yù)測(cè)間隔的更多信息,請(qǐng)參見教程:
《機(jī)器學(xué)習(xí)的預(yù)測(cè)間隔》:
https://machinelearningmastery.com/prediction-intervals-for-machine-learning/
既然我們熟悉了預(yù)測(cè)間隔,那么我們可以考慮如何計(jì)算神經(jīng)網(wǎng)絡(luò)的間隔。首先定義一個(gè)回歸問題和一個(gè)神經(jīng)網(wǎng)絡(luò)模型來解決這個(gè)問題。
回歸神經(jīng)網(wǎng)絡(luò)
在本節(jié)中,我們將定義回歸預(yù)測(cè)建模問題和神經(jīng)網(wǎng)絡(luò)模型來解決該問題。首先,讓我們介紹一個(gè)標(biāo)準(zhǔn)回歸數(shù)據(jù)集。我們將使用住房數(shù)據(jù)集。住房數(shù)據(jù)集是一個(gè)標(biāo)準(zhǔn)的機(jī)器學(xué)習(xí)數(shù)據(jù)集,包括506行數(shù)據(jù),其中包含13個(gè)數(shù)字輸入變量和一個(gè)數(shù)字目標(biāo)變量。
使用具有三個(gè)重復(fù)的重復(fù)分層10倍交叉驗(yàn)證的測(cè)試工具,一個(gè)樸素的模型可以實(shí)現(xiàn)約6.6的平均絕對(duì)誤差(MAE)。在大約1.9的相同測(cè)試工具上,性能最高的模型可以實(shí)現(xiàn)MAE。這為該數(shù)據(jù)集提供了預(yù)期性能的界限。該數(shù)據(jù)集包括根據(jù)美國波士頓市房屋郊區(qū)的詳細(xì)信息來預(yù)測(cè)房價(jià)。
房屋數(shù)據(jù)集(housing.csv):
https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.csv
房屋描述(房屋名稱):
https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.names
無需下載數(shù)據(jù)集;作為我們工作示例的一部分,我們將自動(dòng)下載它。
下面的示例將數(shù)據(jù)集下載并加載為Pandas DataFrame,并概述了數(shù)據(jù)集的形狀和數(shù)據(jù)的前五行。
- # load and summarize the housing dataset
- from pandas import read_csv
- from matplotlib import pyplot
- # load dataset
- url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.csv'
- dataframe = read_csv(url, header=None)
- # summarize shape
- print(dataframe.shape)
- # summarize first few lines
- print(dataframe.head())
運(yùn)行示例將確認(rèn)506行數(shù)據(jù)和13個(gè)輸入變量以及一個(gè)數(shù)字目標(biāo)變量(總共14個(gè))。我們還可以看到所有輸入變量都是數(shù)字。
- (506, 14)
- 0 1 2 3 4 5 ... 8 9 10 11 12 13
- 0 0.00632 18.0 2.31 0 0.538 6.575 ... 1 296.0 15.3 396.90 4.98 24.0
- 1 0.02731 0.0 7.07 0 0.469 6.421 ... 2 242.0 17.8 396.90 9.14 21.6
- 2 0.02729 0.0 7.07 0 0.469 7.185 ... 2 242.0 17.8 392.83 4.03 34.7
- 3 0.03237 0.0 2.18 0 0.458 6.998 ... 3 222.0 18.7 394.63 2.94 33.4
- 4 0.06905 0.0 2.18 0 0.458 7.147 ... 3 222.0 18.7 396.90 5.33 36.2
- [5 rows x 14 columns]
接下來,我們可以準(zhǔn)備用于建模的數(shù)據(jù)集。首先,可以將數(shù)據(jù)集拆分為輸入和輸出列,然后可以將行拆分為訓(xùn)練和測(cè)試數(shù)據(jù)集。在這種情況下,我們將使用約67%的行來訓(xùn)練模型,而其余33%的行用于估計(jì)模型的性能。
- # split into input and output values
- X, y = values[:,:-1], values[:,-1]
- # split into train and test sets
- X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.67)
您可以在本教程中了解有關(guān)訓(xùn)練測(cè)試拆分的更多信息:訓(xùn)練測(cè)試拆分以評(píng)估機(jī)器學(xué)習(xí)算法然后,我們將所有輸入列(變量)縮放到0-1范圍,稱為數(shù)據(jù)歸一化,這在使用神經(jīng)網(wǎng)絡(luò)模型時(shí)是一個(gè)好習(xí)慣。
- # scale input data
- scaler = MinMaxScaler()
- scaler.fit(X_train)
- X_train = scaler.transform(X_train)
- X_test = scaler.transform(X_test)
您可以在本教程中了解有關(guān)使用MinMaxScaler標(biāo)準(zhǔn)化輸入數(shù)據(jù)的更多信息:《如何在Python中使用StandardScaler和MinMaxScaler轉(zhuǎn)換 》:
https://machinelearningmastery.com/standardscaler-and-minmaxscaler-transforms-in-python/
下面列出了準(zhǔn)備用于建模的數(shù)據(jù)的完整示例。
- # load and prepare the dataset for modeling
- from pandas import read_csv
- from sklearn.model_selection import train_test_split
- from sklearn.preprocessing import MinMaxScaler
- # load dataset
- url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.csv'
- dataframe = read_csv(url, header=None)
- values = dataframe.values
- # split into input and output values
- X, y = values[:,:-1], values[:,-1]
- # split into train and test sets
- X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.67)
- # scale input data
- scaler = MinMaxScaler()
- scaler.fit(X_train)
- X_train = scaler.transform(X_train)
- X_test = scaler.transform(X_test)
- # summarize
- print(X_train.shape, X_test.shape, y_train.shape, y_test.shape)
運(yùn)行示例像以前一樣加載數(shù)據(jù)集,然后將列拆分為輸入和輸出元素,將行拆分為訓(xùn)練集和測(cè)試集,最后將所有輸入變量縮放到[0,1]范圍。列印了訓(xùn)練圖和測(cè)試集的形狀,顯示我們有339行用于訓(xùn)練模型,有167行用于評(píng)估模型。
- (339, 13) (167, 13) (339,) (167,)
接下來,我們可以在數(shù)據(jù)集中定義,訓(xùn)練和評(píng)估多層感知器(MLP)模型。我們將定義一個(gè)簡單的模型,該模型具有兩個(gè)隱藏層和一個(gè)預(yù)測(cè)數(shù)值的輸出層。我們將使用ReLU激活功能和“ he”權(quán)重初始化,這是一個(gè)好習(xí)慣。經(jīng)過一些反復(fù)試驗(yàn)后,選擇了每個(gè)隱藏層中的節(jié)點(diǎn)數(shù)。
- # define neural network model
- features = X_train.shape[1]
- model = Sequential()
- model.add(Dense(20, kernel_initializer='he_normal', activation='relu', input_dim=features))
- model.add(Dense(5, kernel_initializer='he_normal', activation='relu'))
- model.add(Dense(1))
我們將使用具有接近默認(rèn)學(xué)習(xí)速率和動(dòng)量值的高效亞當(dāng)版隨機(jī)梯度下降法,并使用均方誤差(MSE)損失函數(shù)(回歸預(yù)測(cè)建模問題的標(biāo)準(zhǔn))擬合模型。
- # compile the model and specify loss and optimizer
- opt = Adam(learning_rate=0.01, beta_1=0.85, beta_2=0.999)
- model.compile(optimizer=opt, loss='mse')
您可以在本教程中了解有關(guān)Adam優(yōu)化算法的更多信息:
《從頭開始編寫代碼Adam梯度下降優(yōu)化》
https://machinelearningmastery.com/adam-optimization-from-scratch/
然后,該模型將適合300個(gè)紀(jì)元,批處理大小為16個(gè)樣本。經(jīng)過一番嘗試和錯(cuò)誤后,才選擇此配置。
- # fit the model on the training dataset
- model.fit(X_train, y_train, verbose=2, epochs=300, batch_size=16)
您可以在本教程中了解有關(guān)批次和紀(jì)元的更多信息:
《神經(jīng)網(wǎng)絡(luò)中批次與時(shí)期之間的差異》
https://machinelearningmastery.com/difference-between-a-batch-and-an-epoch/
最后,該模型可用于在測(cè)試數(shù)據(jù)集上進(jìn)行預(yù)測(cè),我們可以通過將預(yù)測(cè)值與測(cè)試集中的預(yù)期值進(jìn)行比較來評(píng)估預(yù)測(cè),并計(jì)算平均絕對(duì)誤差(MAE),這是模型性能的一種有用度量。
- # make predictions on the test set
- yhat = model.predict(X_test, verbose=0)
- # calculate the average error in the predictions
- mae = mean_absolute_error(y_test, yhat)
- print('MAE: %.3f' % mae)
完整實(shí)例如下:
- # train and evaluate a multilayer perceptron neural network on the housing regression dataset
- from pandas import read_csv
- from sklearn.model_selection import train_test_split
- from sklearn.metrics import mean_absolute_error
- from sklearn.preprocessing import MinMaxScaler
- from tensorflow.keras.models import Sequential
- from tensorflow.keras.layers import Dense
- from tensorflow.keras.optimizers import Adam
- # load dataset
- url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.csv'
- dataframe = read_csv(url, header=None)
- values = dataframe.values
- # split into input and output values
- X, y = values[:, :-1], values[:,-1]
- # split into train and test sets
- X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.67, random_state=1)
- # scale input data
- scaler = MinMaxScaler()
- scaler.fit(X_train)
- X_train = scaler.transform(X_train)
- X_test = scaler.transform(X_test)
- # define neural network model
- features = X_train.shape[1]
- model = Sequential()
- model.add(Dense(20, kernel_initializer='he_normal', activation='relu', input_dim=features))
- model.add(Dense(5, kernel_initializer='he_normal', activation='relu'))
- model.add(Dense(1))
- # compile the model and specify loss and optimizer
- opt = Adam(learning_rate=0.01, beta_1=0.85, beta_2=0.999)
- model.compile(optimizer=opt, loss='mse')
- # fit the model on the training dataset
- model.fit(X_train, y_train, verbose=2, epochs=300, batch_size=16)
- # make predictions on the test set
- yhat = model.predict(X_test, verbose=0)
- # calculate the average error in the predictions
- mae = mean_absolute_error(y_test, yhat)
- print('MAE: %.3f' % mae)
運(yùn)行示例將加載并準(zhǔn)備數(shù)據(jù)集,在訓(xùn)練數(shù)據(jù)集上定義MLP模型并將其擬合,并在測(cè)試集上評(píng)估其性能。
注意:由于算法或評(píng)估程序的隨機(jī)性,或者數(shù)值精度的差異,您的結(jié)果可能會(huì)有所不同。考慮運(yùn)行該示例幾次并比較平均結(jié)果。
在這種情況下,我們可以看到該模型實(shí)現(xiàn)的平均絕對(duì)誤差約為2.3,這比樸素的模型要好,并且接近于最佳模型。
毫無疑問,通過進(jìn)一步調(diào)整模型,我們可以達(dá)到接近最佳的性能,但這對(duì)于我們研究預(yù)測(cè)間隔已經(jīng)足夠了。
- Epoch 296/300
- 22/22 - 0s - loss: 7.1741
- Epoch 297/300
- 22/22 - 0s - loss: 6.8044
- Epoch 298/300
- 22/22 - 0s - loss: 6.8623
- Epoch 299/300
- 22/22 - 0s - loss: 7.7010
- Epoch 300/300
- 22/22 - 0s - loss: 6.5374
- MAE: 2.300
接下來,讓我們看看如何使用住房數(shù)據(jù)集上的MLP模型計(jì)算預(yù)測(cè)間隔。
神經(jīng)網(wǎng)絡(luò)預(yù)測(cè)間隔
在本節(jié)中,我們將使用上一節(jié)中開發(fā)的回歸問題和模型來開發(fā)預(yù)測(cè)間隔。
與像線性回歸這樣的線性方法(預(yù)測(cè)間隔計(jì)算很簡單)相比,像神經(jīng)網(wǎng)絡(luò)這樣的非線性回歸算法的預(yù)測(cè)間隔計(jì)算具有挑戰(zhàn)性。沒有標(biāo)準(zhǔn)技術(shù)。有許多方法可以為神經(jīng)網(wǎng)絡(luò)模型計(jì)算有效的預(yù)測(cè)間隔。我建議“更多閱讀”部分列出的一些論文以了解更多信息。
在本教程中,我們將使用一種非常簡單的方法,該方法具有很大的擴(kuò)展空間。我將其稱為“快速且骯臟的”,因?yàn)樗焖偾乙子谟?jì)算,但有一定的局限性。它涉及擬合多個(gè)最終模型(例如10到30)。來自集合成員的點(diǎn)預(yù)測(cè)的分布然后用于計(jì)算點(diǎn)預(yù)測(cè)和預(yù)測(cè)間隔。
例如,可以將點(diǎn)預(yù)測(cè)作為來自集合成員的點(diǎn)預(yù)測(cè)的平均值,并且可以將95%的預(yù)測(cè)間隔作為與該平均值的1.96標(biāo)準(zhǔn)偏差。這是一個(gè)簡單的高斯預(yù)測(cè)間隔,盡管可以使用替代方法,例如點(diǎn)預(yù)測(cè)的最小值和最大值。或者,可以使用自舉方法在不同的自舉樣本上訓(xùn)練每個(gè)合奏成員,并且可以將點(diǎn)預(yù)測(cè)的第2.5個(gè)百分點(diǎn)和第97.5個(gè)百分點(diǎn)用作預(yù)測(cè)間隔。
有關(guān)bootstrap方法的更多信息,請(qǐng)參見教程:
《Bootstrap方法的簡要介紹》
https://machinelearningmastery.com/a-gentle-introduction-to-the-bootstrap-method/
這些擴(kuò)展保留為練習(xí);我們將堅(jiān)持簡單的高斯預(yù)測(cè)區(qū)間。
假設(shè)在上一部分中定義的訓(xùn)練數(shù)據(jù)集是整個(gè)數(shù)據(jù)集,并且我們正在對(duì)該整個(gè)數(shù)據(jù)集訓(xùn)練一個(gè)或多個(gè)最終模型。然后,我們可以在測(cè)試集上使用預(yù)測(cè)間隔進(jìn)行預(yù)測(cè),并評(píng)估該間隔在將來的有效性。
我們可以通過將上一節(jié)中開發(fā)的元素劃分為功能來簡化代碼。首先,讓我們定義一個(gè)函數(shù),以加載和準(zhǔn)備由URL定義的回歸數(shù)據(jù)集。
- # load and prepare the dataset
- def load_dataset(url):
- dataframe = read_csv(url, header=None)
- values = dataframe.values
- # split into input and output values
- X, y = values[:, :-1], values[:,-1]
- # split into train and test sets
- X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.67, random_state=1)
- # scale input data
- scaler = MinMaxScaler()
- scaler.fit(X_train)
- X_train = scaler.transform(X_train)
- X_test = scaler.transform(X_test)
- return X_train, X_test, y_train, y_test
接下來,我們可以定義一個(gè)函數(shù),該函數(shù)將在給定訓(xùn)練數(shù)據(jù)集的情況下定義和訓(xùn)練MLP模型,然后返回適合進(jìn)行預(yù)測(cè)的擬合模型。
- # define and fit the model
- def fit_model(X_train, y_train):
- # define neural network model
- features = X_train.shape[1]
- model = Sequential()
- model.add(Dense(20, kernel_initializer='he_normal', activation='relu', input_dim=features))
- model.add(Dense(5, kernel_initializer='he_normal', activation='relu'))
- model.add(Dense(1))
- # compile the model and specify loss and optimizer
- opt = Adam(learning_rate=0.01, beta_1=0.85, beta_2=0.999)
- model.compile(optimizer=opt, loss='mse')
- # fit the model on the training dataset
- model.fit(X_train, y_train, verbose=0, epochs=300, batch_size=16)
- return model
我們需要多個(gè)模型來進(jìn)行點(diǎn)預(yù)測(cè),這些模型將定義點(diǎn)預(yù)測(cè)的分布,從中可以估計(jì)間隔。
因此,我們需要在訓(xùn)練數(shù)據(jù)集上擬合多個(gè)模型。每個(gè)模型必須不同,以便做出不同的預(yù)測(cè)。在訓(xùn)練MLP模型具有隨機(jī)性,隨機(jī)初始權(quán)重以及使用隨機(jī)梯度下降優(yōu)化算法的情況下,可以實(shí)現(xiàn)這一點(diǎn)。模型越多,點(diǎn)預(yù)測(cè)將更好地估計(jì)模型的功能。我建議至少使用10種型號(hào),而超過30種型號(hào)可能不會(huì)帶來太多好處。下面的函數(shù)適合模型的整體,并將其存儲(chǔ)在返回的列表中。出于興趣,還對(duì)測(cè)試集評(píng)估了每個(gè)擬合模型,并在擬合每個(gè)模型后報(bào)告了該測(cè)試集。我們希望每個(gè)模型在保持測(cè)試集上的估計(jì)性能會(huì)略有不同,并且報(bào)告的分?jǐn)?shù)將有助于我們確認(rèn)這一期望。
- # fit an ensemble of models
- def fit_ensemble(n_members, X_train, X_test, y_train, y_test):
- ensemble = list()
- for i in range(n_members):
- # define and fit the model on the training set
- model = fit_model(X_train, y_train)
- # evaluate model on the test set
- yhat = model.predict(X_test, verbose=0)
- mae = mean_absolute_error(y_test, yhat)
- print('>%d, MAE: %.3f' % (i+1, mae))
- # store the model
- ensemble.append(model)
- return ensemble
最后,我們可以使用訓(xùn)練有素的模型集合進(jìn)行點(diǎn)預(yù)測(cè),可以將其總結(jié)為一個(gè)預(yù)測(cè)區(qū)間。
下面的功能實(shí)現(xiàn)了這一點(diǎn)。首先,每個(gè)模型對(duì)輸入數(shù)據(jù)進(jìn)行點(diǎn)預(yù)測(cè),然后計(jì)算95%的預(yù)測(cè)間隔,并返回該間隔的下限值,平均值和上限值。
該函數(shù)被設(shè)計(jì)為將單行作為輸入,但是可以很容易地適應(yīng)于多行。
- # make predictions with the ensemble and calculate a prediction interval
- def predict_with_pi(ensemble, X):
- # make predictions
- yhat = [model.predict(X, verbose=0) for model in ensemble]
- yhat = asarray(yhat)
- # calculate 95% gaussian prediction interval
- interval = 1.96 * yhat.std()
- lower, upper = yhat.mean() - interval, yhat.mean() + interval
- return lower, yhat.mean(), upper
最后,我們可以調(diào)用這些函數(shù)。首先,加載并準(zhǔn)備數(shù)據(jù)集,然后定義并擬合集合。
- # load dataset
- url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.csv'
- X_train, X_test, y_train, y_test = load_dataset(url)
- # fit ensemble
- n_members = 30
- ensemble = fit_ensemble(n_members, X_train, X_test, y_train, y_test)
然后,我們可以使用測(cè)試集中的一行數(shù)據(jù),并以預(yù)測(cè)間隔進(jìn)行預(yù)測(cè),然后報(bào)告結(jié)果。
我們還報(bào)告了預(yù)期的期望值,該期望值將在預(yù)測(cè)間隔內(nèi)涵蓋(可能接近95%的時(shí)間;這并不完全準(zhǔn)確,而是粗略的近似值)。
- # make predictions with prediction interval
- newX = asarray([X_test[0, :]])
- lower, mean, upper = predict_with_pi(ensemble, newX)
- print('Point prediction: %.3f' % mean)
- print('95%% prediction interval: [%.3f, %.3f]' % (lower, upper))
- print('True value: %.3f' % y_test[0])
綜上所述,下面列出了使用多層感知器神經(jīng)網(wǎng)絡(luò)以預(yù)測(cè)間隔進(jìn)行預(yù)測(cè)的完整示例。
- # prediction interval for mlps on the housing regression dataset
- from numpy import asarray
- from pandas import read_csv
- from sklearn.model_selection import train_test_split
- from sklearn.metrics import mean_absolute_error
- from sklearn.preprocessing import MinMaxScaler
- from tensorflow.keras.models import Sequential
- from tensorflow.keras.layers import Dense
- from tensorflow.keras.optimizers import Adam
- # load and prepare the dataset
- def load_dataset(url):
- dataframe = read_csv(url, header=None)
- values = dataframe.values
- # split into input and output values
- X, y = values[:, :-1], values[:,-1]
- # split into train and test sets
- X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.67, random_state=1)
- # scale input data
- scaler = MinMaxScaler()
- scaler.fit(X_train)
- X_train = scaler.transform(X_train)
- X_test = scaler.transform(X_test)
- return X_train, X_test, y_train, y_test
- # define and fit the model
- def fit_model(X_train, y_train):
- # define neural network model
- features = X_train.shape[1]
- model = Sequential()
- model.add(Dense(20, kernel_initializer='he_normal', activation='relu', input_dim=features))
- model.add(Dense(5, kernel_initializer='he_normal', activation='relu'))
- model.add(Dense(1))
- # compile the model and specify loss and optimizer
- opt = Adam(learning_rate=0.01, beta_1=0.85, beta_2=0.999)
- model.compile(optimizer=opt, loss='mse')
- # fit the model on the training dataset
- model.fit(X_train, y_train, verbose=0, epochs=300, batch_size=16)
- return model
- # fit an ensemble of models
- def fit_ensemble(n_members, X_train, X_test, y_train, y_test):
- ensemble = list()
- for i in range(n_members):
- # define and fit the model on the training set
- model = fit_model(X_train, y_train)
- # evaluate model on the test set
- yhat = model.predict(X_test, verbose=0)
- mae = mean_absolute_error(y_test, yhat)
- print('>%d, MAE: %.3f' % (i+1, mae))
- # store the model
- ensemble.append(model)
- return ensemble
- # make predictions with the ensemble and calculate a prediction interval
- def predict_with_pi(ensemble, X):
- # make predictions
- yhat = [model.predict(X, verbose=0) for model in ensemble]
- yhat = asarray(yhat)
- # calculate 95% gaussian prediction interval
- interval = 1.96 * yhat.std()
- lower, upper = yhat.mean() - interval, yhat.mean() + interval
- return lower, yhat.mean(), upper
- # load dataset
- url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.csv'
- X_train, X_test, y_train, y_test = load_dataset(url)
- # fit ensemble
- n_members = 30
- ensemble = fit_ensemble(n_members, X_train, X_test, y_train, y_test)
- # make predictions with prediction interval
- newX = asarray([X_test[0, :]])
- lower, mean, upper = predict_with_pi(ensemble, newX)
- print('Point prediction: %.3f' % mean)
- print('95%% prediction interval: [%.3f, %.3f]' % (lower, upper))
- print('True value: %.3f' % y_test[0])
運(yùn)行示例依次適合每個(gè)集合成員,并在保留測(cè)試集上報(bào)告其估計(jì)性能;最后,做出并預(yù)測(cè)一個(gè)具有預(yù)測(cè)間隔的預(yù)測(cè)。
注意:由于算法或評(píng)估程序的隨機(jī)性,或者數(shù)值精度的差異,您的結(jié)果可能會(huì)有所不同??紤]運(yùn)行該示例幾次并比較平均結(jié)果。
在這種情況下,我們可以看到每個(gè)模型的性能略有不同,這證實(shí)了我們對(duì)模型確實(shí)有所不同的期望。
最后,我們可以看到該合奏以95%的預(yù)測(cè)間隔[26.287,34.822]進(jìn)行了約30.5的點(diǎn)預(yù)測(cè)。我們還可以看到,真實(shí)值為28.2,并且間隔確實(shí)捕獲了該值,這非常好。
- >1, MAE: 2.259
- >2, MAE: 2.144
- >3, MAE: 2.732
- >4, MAE: 2.628
- >5, MAE: 2.483
- >6, MAE: 2.551
- >7, MAE: 2.505
- >8, MAE: 2.299
- >9, MAE: 2.706
- >10, MAE: 2.145
- >11, MAE: 2.765
- >12, MAE: 3.244
- >13, MAE: 2.385
- >14, MAE: 2.592
- >15, MAE: 2.418
- >16, MAE: 2.493
- >17, MAE: 2.367
- >18, MAE: 2.569
- >19, MAE: 2.664
- >20, MAE: 2.233
- >21, MAE: 2.228
- >22, MAE: 2.646
- >23, MAE: 2.641
- >24, MAE: 2.492
- >25, MAE: 2.558
- >26, MAE: 2.416
- >27, MAE: 2.328
- >28, MAE: 2.383
- >29, MAE: 2.215
- >30, MAE: 2.408
- Point prediction: 30.555
- 95% prediction interval: [26.287, 34.822]
- True value: 28.200
True value: 28.200