Pytorch貝葉斯庫BLiTZ實現使用LSTM預測時序數據和繪製置信區間

2021-02-07 deephub

本文將主要講述如何使用BLiTZ(PyTorch貝葉斯深度學習庫)來建立貝葉斯LSTM模型,以及如何在其上使用序列數據進行訓練與推理。

在本文中,我們將解釋貝葉斯長期短期記憶模型(LSTM)是如何工作的,然後通過一個Kaggle數據集進行股票置信區間的預測。

貝葉斯LSTM層

眾所周知,LSTM結構旨在解決使用標準的循環神經網絡(RNN)處理長序列數據時發生的信息消失問題。

在數學上,LSTM結構的描述如下:

我們知道,貝葉斯神經網絡的核心思想是,相比設定一個確定的權重,我們可以通過一個概率密度分布來對權重進行採樣,然後優化分布參數。

利用這一點,就有可能衡量我們所做的預測的置信度和不確定性,這些數據與預測本身一樣,都是非常有用的數據。

從數學上講,我們只需要在上面的方程中增加一些額外的步驟,也即權值和偏置的採樣,這發生在前向傳播之前。

這表示在第i次在模型第N層上權重的採樣。

這表示在第i次在模型第N層上偏置的採樣。

當然,我們的可訓練參數是和,用來表示不同的權重分布。 BLiTZ具有內置的BayesianLSTM層,可以為您完成所有這些艱苦的工作,因此您只需要關注您的網絡結構設計與網絡的訓練/測試。

現在我們看一個例子。

第一步,先導入庫

除了導入深度學習中最常用的庫外,我們還需要從blitz.modules中導入BayesianLSTM,並從blitz.utils導入variational_estimator,後者是一個用於變量訓練與複雜度計算的裝飾器。

我們還要導入collections.deque來執行時間序列數據的預處理。

import pandas as pdimport numpy as npimport torchimport torch.nn as nnimport torch.optim as optimimport torch.nn.functional as Ffrom blitz.modules import BayesianLSTMfrom blitz.utils import variational_estimatorfrom sklearn.model_selection import train_test_splitfrom sklearn.preprocessing import StandardScalerimport matplotlib.pyplot as plt%matplotlib inlinefrom collections import deque

數據預處理

現在,我們將創建並預處理數據集以將其輸入到網絡。 我們將從Kaggle數據集中導入Amazon股票定價,獲取其「收盤價」數據並將其標準化。

我們的數據集將由標準化股票價格的時間戳組成,並且具有一個形如(batch_size,sequence_length,observation_length)的shape。

下面我們導入數據並對其預處理:

#importing the datasetamazon="data/AMZN_2006-01-01_to_2018-01-01.csv"ibm="data/IBM_2006-01-01_to_2018-01-01.csv"df = pd.read_csv(ibm)#scaling and selecting dataclose_prices = df["Close"]scaler = StandardScaler()close_prices_arr = np.array(close_prices).reshape(-1, 1)close_prices = scaler.fit_transform(close_prices_arr)close_prices_unscaled = df["Close"]

我們還必須創建一個函數來按照時間戳轉換我們的股價歷史記錄。 為此,我們將使用最大長度等於我們正在使用的時間戳大小的雙端隊列,我們將每個數據點添加到雙端隊列,然後將其副本附加到主時間戳列表:

def create_timestamps_ds(series, timestep_size=window_size): time_stamps = [] labels = [] aux_deque = deque(maxlen=timestep_size) #starting the timestep deque for i in range(timestep_size): aux_deque.append(0) #feed the timestamps list for i in range(len(series)-1): aux_deque.append(series[i]) time_stamps.append(list(aux_deque)) #feed the labels lsit for i in range(len(series)-1): labels.append(series[i + 1]) assert len(time_stamps) == len(labels), "Something went wrong" #torch-tensoring it features = torch.tensor(time_stamps[timestep_size:]).float() labels = torch.tensor(labels[timestep_size:]).float() return features, labels

創建神經網絡類

我們的網絡類接收variantal_estimator裝飾器,該裝飾器可簡化對貝葉斯神經網絡損失的採樣。我們的網絡具有一個貝葉斯LSTM層,參數設置為in_features = 1以及out_features = 10,後跟一個nn.Linear(10, 1),該層輸出股票的標準化價格。

@variational_estimatorclass NN(nn.Module):def __init__(self): super(NN, self).__init__() self.lstm_1 = BayesianLSTM(1, 10) self.linear = nn.Linear(10, 1) def forward(self, x): x_, _ = self.lstm_1(x) #gathering only the latent end-of-sequence for the linear layer x_ = x_[:, -1, :] x_ = self.linear(x_) return x_

如您所見,該網絡可以正常工作,唯一的不同點是BayesianLSTM層和variantal_estimator裝飾器,但其行為與一般的Torch對象相同。

完成後,我們可以創建我們的神經網絡對象,分割數據集並進入訓練循環:

創建對象

我們現在可以創建損失函數、神經網絡、優化器和dataloader。請注意,我們不是隨機分割數據集,因為我們將使用最後一批時間戳來計算模型。由於我們的數據集很小,我們不會對訓練集創建dataloader。

Xs, ys = create_timestamps_ds(close_prices)X_train, X_test, y_train, y_test = train_test_split(Xs,ys, test_size=.25, random_state=42, shuffle=False)ds = torch.utils.data.TensorDataset(X_train, y_train)dataloader_train = torch.utils.data.DataLoader(ds, batch_size=8, shuffle=True)net = NN()criterion = nn.MSELoss()optimizer = optim.Adam(net.parameters(), lr=0.001)

我們將使用MSE損失函數和學習率為0.001的Adam優化器

訓練循環

對於訓練循環,我們將使用添加了variational_estimator的sample_elbo方法。 它對X個樣本的損失進行平均,並幫助我們輕鬆地用蒙特卡洛估計來計算損失。

為了使網絡正常工作,網絡forward方法的輸出必須與傳入損失函數對象的標籤的形狀一致。

iteration = 0for epoch in range(10):for i, (datapoints, labels) in enumerate(dataloader_train): optimizer.zero_grad() loss = net.sample_elbo(inputs=datapoints, labels=labels, criterion=criterion, sample_nbr=3) loss.backward() optimizer.step() iteration += 1 if iteration%250==0: preds_test = net(X_test)[:,0].unsqueeze(1) loss_test = criterion(preds_test, y_test) print("Iteration: {} Val-loss: {:.4f}".format(str(iteration), loss_test))

評估模型並計算置信區間

我們將首先創建一個具有要繪製的真實數據的dataframe:

original = close_prices_unscaled[1:][window_size:]df_pred = pd.DataFrame(original)df_pred["Date"] = df.Datedf["Date"] = pd.to_datetime(df_pred["Date"])df_pred = df_pred.reset_index()

要預測置信區間,我們必須創建一個函數來預測同一數據X次,然後收集其均值和標準差。 同時,在查詢真實數據之前,我們必須設置將嘗試預測的窗口大小。

讓我們看一下預測函數的代碼:

def pred_stock_future(X_test,future_length, sample_nbr=10): #sorry for that, window_size is a global variable, and so are X_train and Xs global window_size global X_train global Xs global scaler #creating auxiliar variables for future prediction preds_test = [] test_begin = X_test[0:1, :, :] test_deque = deque(test_begin[0,:,0].tolist(), maxlen=window_size) idx_pred = np.arange(len(X_train), len(Xs)) #predict it and append to list for i in range(len(X_test)): #print(i) as_net_input = torch.tensor(test_deque).unsqueeze(0).unsqueeze(2) pred = [net(as_net_input).cpu().item() for i in range(sample_nbr)] test_deque.append(torch.tensor(pred).mean().cpu().item()) preds_test.append(pred) if i % future_length == 0: #our inptus become the i index of our X_test #That tweak just helps us with shape issues test_begin = X_test[i:i+1, :, :] test_deque = deque(test_begin[0,:,0].tolist(), maxlen=window_size) #preds_test = np.array(preds_test).reshape(-1, 1) #preds_test_unscaled = scaler.inverse_transform(preds_test) return idx_pred, preds_test

我們要將置信區間保存下來,確定我們置信區間的寬度。

def get_confidence_intervals(preds_test, ci_multiplier):global scaler preds_test = torch.tensor(preds_test) pred_mean = preds_test.mean(1) pred_std = preds_test.std(1).detach().cpu().numpy() pred_std = torch.tensor((pred_std)) upper_bound = pred_mean + (pred_std * ci_multiplier) lower_bound = pred_mean - (pred_std * ci_multiplier) #gather unscaled confidence intervals pred_mean_final = pred_mean.unsqueeze(1).detach().cpu().numpy() pred_mean_unscaled = scaler.inverse_transform(pred_mean_final) upper_bound_unscaled = upper_bound.unsqueeze(1).detach().cpu().numpy() upper_bound_unscaled = scaler.inverse_transform(upper_bound_unscaled) lower_bound_unscaled = lower_bound.unsqueeze(1).detach().cpu().numpy() lower_bound_unscaled = scaler.inverse_transform(lower_bound_unscaled) return pred_mean_unscaled, upper_bound_unscaled, lower_bound_unscaled

由於我們使用的樣本數量很少,因此用一個很高的標準差對其進行了補償。 我們的網絡將嘗試預測7天,然後將參考數據:

future_length=7sample_nbr=4ci_multiplier=10idx_pred, preds_test = pred_stock_future(X_test, future_length, sample_nbr)pred_mean_unscaled, upper_bound_unscaled, lower_bound_unscaled = get_confidence_intervals(preds_test,ci_multiplier)

我們可以通過查看實際值是否低於上限並高於下限來檢查置信區間。 設置好參數後,您應該擁有95%的置信區間,如下所示:

y = np.array(df.Close[-750:]).reshape(-1, 1)under_upper = upper_bound_unscaled > yover_lower = lower_bound_unscaled < ytotal = (under_upper == over_lower)print("{} our predictions are in our confidence interval".format(np.mean(total)))

檢查輸出圖形

現在,我們將把預測結果繪製為可視化圖形來檢查我們的網絡是否運行的很順利,我們將在置信區間內繪製真實值與預測值。

params = {"ytick.color" : "w","xtick.color" : "w", "axes.labelcolor" : "w", "axes.edgecolor" : "w"}plt.rcParams.update(params)plt.title("IBM Stock prices", color="white")plt.plot(df_pred.index, df_pred.Close, color='black', label="Real")plt.plot(idx_pred, pred_mean_unscaled, label="Prediction for {} days, than consult".format(future_length), color="red")plt.fill_between(x=idx_pred, y1=upper_bound_unscaled[:,0], y2=lower_bound_unscaled[:,0], facecolor='green', label="Confidence interval", alpha=0.5)plt.legend()

最後,我們放大一下著重看看預測部分。

params = {"ytick.color" : "w","xtick.color" : "w", "axes.labelcolor" : "w", "axes.edgecolor" : "w"}plt.rcParams.update(params)plt.title("IBM Stock prices", color="white")plt.fill_between(x=idx_pred, y1=upper_bound_unscaled[:,0], y2=lower_bound_unscaled[:,0], facecolor='green', label="Confidence interval", alpha=0.75)plt.plot(idx_pred, df_pred.Close[-len(pred_mean_unscaled):], label="Real", alpha=1, color='black', linewidth=0.5)plt.plot(idx_pred, pred_mean_unscaled, label="Prediction for {} days, than consult".format(future_length), color="red", alpha=0.5)plt.legend()

總結

我們看到BLiTZ內置的貝葉斯LSTM使得貝葉斯深度學習的所有功能都變得非常簡單,並且可以順利地在時間序列上進行迭代。 我們還看到,貝葉斯LSTM已與Torch很好地集成在一起,並且易於使用,你可以在任何工作或研究中使用它。

我們還可以非常準確地預測IBM股票價格的置信區間,而且這比一般的點估計可能要有用的多。

作者:Piero Esposito

deephub翻譯組:Alenander Zhao

相關焦點

  • 使用LSTM深度學習模型進行溫度的時間序列單步和多步預測
    本文展示了如何進行多步預測並在模型中使用多個特徵。本文的簡單版本是,使用過去48小時的數據和對未來1小時的預測(一步),我獲得了溫度誤差的平均絕對誤差0.48(中值0.34)度。利用過去168小時的數據並提前24小時進行預測,平均絕對誤差為攝氏溫度1.69度(中值1.27)。所使用的特徵是過去每小時的溫度數據、每日及每年的循環信號、氣壓及風速。
  • 如何對方差構造置信區間
    那麼如何基於樣本方差對總體方差構造置信區間呢?當數據不是來自正態分布時,是否仍可採用該置信區間呢?這說明當數據偏離正態時,基於卡方分布構造的置信區間可能是錯誤的,應尋求其他的構造方法。那麼如何進行構造呢?我們將基於樣本方差的漸近分布進行構造。
  • 使用python+sklearn實現高斯過程回歸
    下圖以逐點95%置信區間的形式說明了高斯過程模型的插值性質(interpolating property)及其概率性質。注意,參數alpha 用作訓練點之間假定協方差的Tikhonov正則化。(0, 10, 1000)).T# 實例化高斯過程模型kernel = C(1.0, (1e-3, 1e3)) * RBF(10, (1e-2, 1e2))gp = GaussianProcessRegressor(kernel=kernel, n_restarts_optimizer=9)# 使用參數的最大似然估計來擬合數據gp.fit(X,
  • 金融計量R實戰(3)脈衝響應函數和預測誤差方差分解
    其中主要的參數包括,x是模型對象,impulse是表示脈衝變量,response是響應變量,n.head表示時間間隔,cumulative表示是否計算累積效應,boot是對脈衝響應係數自助置信帶,ci是這個置信帶的置信區間,
  • 深度運用LSTM神經網絡並與經典時序模型對比
    ##數據形狀轉換,很重要!!:%s,Y數據維度信息:%s;測試集X數據維度信息:%s,Y數據維度信息:%s\033[0m'%(transformer_selldata.shape, train_X.shape, train_y.shape, test_X.shape, test_y.shape))def buildmylstm(initactivation='relu',ininlr=0.001):
  • 漂亮,LSTM模型結構的可視化
    1、傳統的BP網絡和CNN網絡2、LSTM網絡3、LSTM的輸入結構4、pytorch中的LSTM4.1 pytorch中定義的LSTM模型4.2 餵給LSTM的數據格式4.3 LSTM的output格式5、LSTM和其他網絡組合BP網絡和CNN網絡沒有時間維,和傳統的機器學習算法理解起來相差無幾,CNN
  • 使用Pytorch訓練分類器詳解(附python演練)
    使用torchvision加載並且歸一化CIFAR10的訓練和測試數據集2. 定義一個卷積神經網絡3. 定義一個損失函數4. 在訓練樣本數據上訓練網絡5. 在測試樣本數據上測試網絡三.在GPU上訓練四.
  • 【數據可視化】統計圖繪製神器:Seaborn
    若要直觀地反應一組數據的統計特徵,一圖勝過千萬言語。近期小編有若干統計圖需要繪製,在學習的過程中發現了一個很好用的工具,它可以簡單直觀地繪製出常用的統計圖。它就是Seaborn庫。Seaborn是基於Matplotlib開發的高階Python數據可視化圖庫。用戶能夠做出各種有吸引力的統計圖表,例如條形圖、散點圖、箱線圖等。
  • 時間序列深度學習:狀態 LSTM 模型預測太陽黑子(中)
    ,我們將訓練和測試數據集合成一個數據集,並使用列 key 來標記它們來自哪個集合(training 或 testing)。我們可以使用 recipe 包預處理數據。我們用 step_sqrt 來轉換數據以減少異常值的影響,再結合 step_center 和 step_scale 對數據進行中心化和標度化。最後,數據使用 bake() 函數實現處理轉換。
  • 標準誤、標準差與參考範圍、置信區間
    統計學中,有兩個基本的概念:①標準差(SD,Standard Deviation)②標準誤(SEM,Standard
  • 教程 | Kaggle網站流量預測任務第一名解決方案:從模型到代碼詳解時序預測
    他們不僅公開了所有的實現代碼,同時還詳細解釋了實現的模型與經驗。機器之心簡要介紹了他們所實現的模型與經驗,更詳細的代碼請查看 GitHub 項目。GitHub 項目地址:https://github.com/Arturus/kaggle-web-traffic下面我們將簡要介紹 Artur Suilin 如何修正 GRU 以完成網站流量時序預測競賽。
  • 使用PyTorch建立您的第一個文本分類模型
    來源:analyticsvidhya編譯:X程序媛總覽掌握包裝填充特徵(Pack Padding feature)的重要性介紹我總是選擇最先進的體系結構來進行數據科學編程馬拉松的首次提交。由於PyTorch,Keras和TensorFlow等深度學習框架,實現最先進的體系結構已變得非常容易。
  • R語言時間序列預測模型:ARIMA vs KNN
    1總述要找到一個合適的模型來預測時間序列數據總是很困難。其中一個原因是,使用時間序列數據的模型往往會暴露出序列相關性。在這篇文章中,我們將比較數據集a101991年至2008年澳大利亞每月的抗糖尿病藥物補貼。
  • 學習歷史預測未來,國防科大新模型在多個數據集上實現未來事實預測SOTA
    時序知識的表徵和推理是一個具有挑戰性的問題。在本文中,來自國防科技大學等的研究者借鑑了自然語言生成(NLG)中的複製機制思路,並通過設計一種全新的基於時序知識圖譜嵌入(TKGE)的模型來更有效地建模時序知識圖譜。在多個公開時序知識圖譜(TKG)基準數據集上,新模型 CyGNet 在未來事實(連結)預測任務上均實現了 SOTA 結果。
  • 10分鐘了解Pytorch
    可以把 Pytorch 當做 Numpy 的替代方案使用,做科學計算,而且更強大。做 AI 任務的模型建模、訓練、部署等。這方面唯一能與其比肩的是 Google 家的 Tensorflow。並行計算# 獲取和設置 CPU 並行操作時的線程數torch.get_num_threadstorch.set_num_threads# 獲取和設置 CPU 上的互操作並行的線程數torch.get_num_interop_threadstorch.set_num_interop_threads
  • 輕鬆學pytorch之使用onnx runtime實現pytorch模型部署
    /paddle等深度學習框架訓練的模型都可以轉換為ONNX格式,然後ONNX格式模型可以通過ONNX runtime組件實現模型的推理預測並加速,從而實現不基於原來框架的模型部署。默認情況下,上述安裝的onnxruntime只支持CPU推理,也就是說模型是運行的CPU版本,支持的數據類型為Numpy的Map或者數組或者List類型,模型默認在CPU上推理執行。
  • 工業數據:基於統計和信號的特徵提取方法
    ,不能有效識別數據特徵與磨損度的關係,因此需要進行特徵提取,把原有的低維時序數據映射到高維表示,挖掘和構造輸入數據的新特徵,進而找出最能幫助模型擬合的輸入(X)和輸出(Y)特徵。在很多預測性維護的場景(如旋轉件、振動等)中,我們完全可以採用基於統計和信號的特徵提取方法就能得到一些較好的特徵。本文的特徵提取方法主要包含三個角度:基於統計的時域特徵,就是使用統計學方法如均方根、方差、最大值、最小值、偏斜度、峰度、峰峰值等提取出的新數據。
  • BiLSTM-CRF實現命名實體識別(NER)
    數據集說明2. BiLSTM-CRF實現說明3. 實驗環境說明4.代碼實現4.1 相關包及配置4.2 加載數據4.3 搭建模型4.4 模型訓練&保存模型4.5 測試4.6 預測4.7 待改進/完善完整代碼地址參考本博客中使用到的完整代碼請移步至我的github:https:/
  • 輕鬆學 Pytorch:使用 ResNet50 實現圖像分類
    Hello大家好,這篇文章給大家詳細介紹一下pytorch中最重要的組件torchvision,它包含了常見的數據集、模型架構與預訓練模型權重文件、常見圖像變換、計算機視覺任務訓練。可以是說是pytorch中非常有用的模型遷移學習神器。本文將會介紹如何使用torchvison的預訓練模型ResNet50實現圖像分類。