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

2021-01-10 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

相關焦點

  • 第四十講 R-線性回歸:預測模型及可信區間
    那麼,當我們取得了預測模型後,根據該預測模型對新數據進行預測得出的預測值是什麼?這個預測值的可信度如何呢?今天的講解中,我們會給出答案。我們首先建立一個簡單的線性回歸模型,該模型根據速度預測汽車的停車距離。
  • 使用LSTM深度學習模型進行溫度的時間序列單步和多步預測
    本文的目的是提供代碼示例,並解釋使用python和TensorFlow建模時間序列數據的思路。本文展示了如何進行多步預測並在模型中使用多個特徵。本文的簡單版本是,使用過去48小時的數據和對未來1小時的預測(一步),我獲得了溫度誤差的平均絕對誤差0.48(中值0.34)度。
  • PyTorch:Bi-LSTM的文本生成
    到目前為止,我們已經演示了如何加載文本並以字符列表的形式保存它,我們還創建了兩個字典來幫助我們對每個字符進行編碼和解碼。序列生成序列生成的方式完全取決於我們要實現的模型類型。如前所述,我們將使用LSTM類型的循環神經網絡,它按順序接收數據(時間步長)。
  • 置信區間與串行數據鏈路如何關聯
    ziZedncziZednc從表中的數據可以看出,只有當無誤碼觀察間隔達到5E12個比特,才可以斷言一條鏈路以等於或小於1E-12的BER運行的確定性高於99%。ziZednc有誤碼的置信區間如果我們增大觀察間隔會發生什麼?如果觀察間隔足夠大,我們會看到很少的誤碼。這對置信區間有什麼影響呢?
  • R語言做生存分析:繪製 Kaplan-Meirer生存曲線和實現Log-rank檢驗
    如一個工人從下崗後到實現再就業的時間;一臺汽車從開始使用到發生第一次故障的時間;一個病人從確診患病到死亡的時間等。Kaplan-Meier法簡稱K-M法,又稱乘積極限法(Product-limit Estimate)是生存分析方法中最常用的一種,主要用於估計患者生存率和繪製生存曲線。
  • 區間估計、置信區間
    點估計與區間估計刮獎猜測點估計就是單猜某一張彩票是大獎,區間估計就是將點估計的範圍擴大,可以一盒一盒、一個區域、一座城市,說白了就是設置一個半徑。下面採用置信區間構造區間估計但是這個區間多大會影響到所有估計中包含真值的比例,比如由樣本均值的抽樣分布可知,在重複抽樣或者無限總體抽樣的情況下,樣本均值的期望等於總體均值。無數個樣本均值最終可以構造成下面的圖形,但是實際中只能有有限個數據。均值與單個值的距離是相對的,如果某個值在均值的半徑範圍內,則均值也在這個值的對應半徑範圍內。
  • 線性回歸分析詳解9:顯著性水平、置信度、置信區間及其計算方法
    許栩原創專欄《從入門到高手:線性回歸分析詳解》第9章,總體回歸、置信度、置信區間及其計算方法。多元回歸方程求解後,我們分別確認了回歸方程的精度和進行了回歸方程的顯著性驗證,接下來,需要計算置信區間。置信區間是回歸分析的一個重要概念,但是,將回歸分析應用到需求預測時,並不強求引入置信區間,也就是說,用回歸分析做需求預測時,可以不進行置信區間的計算,而直接進行後續的預測步驟。所以,從這一點來說,大家可以跳過本章,直接進入專欄的第10章,用線性回歸分析進行預測。
  • 如何使用LSTM在Keras中快速實現情感分析任務
    本文對 LSTM 進行了簡單介紹,並講述了如何使用 LSTM 在 Keras 中快速實現情感分析任務。長短期記憶網絡通常被稱為 LSTM,它是由 Hochreiter 和 Schmiduber 提出的,被廣泛地應用在語音識別、語言建模、情感分析和文本預測中。
  • 金融時序預測:狀態空間模型和卡爾曼濾波
    在今天的推文中,我們將使用狀態空間模型對單變量時間序列數據進行預測分析。該模型具有連續的隱狀態和觀測狀態。 1 狀態空間模型 基於狀態空間模型對問題進行了結構分析。
  • 通俗易懂告訴你:何為95%置信區間?
    CDA數據分析師 出品置信區間的概念是由原籍波蘭的美國統計學家耶日·奈曼提出的。簡單理解,比如從北京到張家界旅遊5天,你恐怕不能準確說出要花多少錢,但你可以給出一個範圍,比如10000—13000,你會覺得比較可信。
  • 60 題 PyTorch 簡易入門指南,做技術的弄潮兒
    /zh/latest/改編自:https://pytorch.org/tutorials/beginner/deep_learning_60min_blitz.html#deep-learning-with-pytorch-a-60-minute-blitz1 初識PyTorch
  • 《PyTorch中文手冊》來了
    這是一本開源的書籍,目標是幫助那些希望和使用 PyTorch 進行深度學習開發和研究的朋友快速入門,其中包含的 Pytorch 教程全部通過測試保證可以成功運行。>書籍介紹這是一本開源的書籍,目標是幫助那些希望和使用 PyTorch 進行深度學習開發和研究的朋友快速入門。
  • 【乾貨】你明白臨床試驗中的P值和置信區間的含義嗎?
    P值或者置信區間上。那麼P值和置信區間代表什麼意思呢?為什麼我們要做計算P值或置信區間來做統計推斷呢?在講P值和置信區間之前,我們先講講樣本與總體。在《醫學統計學》中,根據研究目的而確定的同質觀察單位的全體成為總體。觀察單位,又稱個體,是統計研究中的基本單位,他可以是一個人、一個器官、一個細胞。
  • 置信區間t分布
    1.陳述t分布的形狀和正態分布之間的差異2.說明t分布的形狀與正態分布之間的差異如何受自由度的影響3.在表格中使用以查找在置信區間中使用的t的值4.使用t計算器查找置信區間中使用的t的值在正態分布的介紹中顯示,95%的正態分布面積在平均值的1.96個標準偏差內。
  • 金融時序預測:狀態空間模型和卡爾曼濾波(附代碼)
    作者 | arit Maitra編譯 | 1+1=60 前言時間序列由四個主要成分組成: 季節變化、趨勢變化、周期變化和隨機變化。在今天的推文中,我們將使用狀態空間模型對單變量時間序列數據進行預測分析。
  • 我們常聽說的置信區間與置信度到底是什麼?
    這裡就涉及到統計學裡面的置信區間與置信度,本文簡要介紹了置信區間這一核心概念,它有助於我們從直觀上理解評價估計優劣的度量方法。本文討論了統計學中的一個基本術語 :置信區間。我們僅以一種非常友好的方式討論一般概念,沒有太多花哨的統計術語,同時還會使用 Python 完成簡單的實現!
  • 時間序列的LSTM模型預測——基於Keras
    一、問題背景    現實生活中,在一系列時間點上觀測數據是司空見慣的活動,在農業、商業、氣象軍事和醫療等研究領域都包含大量的時間序列數據。時間序列的預測指的是基於序列的歷史數據,以及可能對結果產生影響的其他相關序列,對序列未來的可能取值做出預測。
  • 推論統計 | 抽樣分布,中心極限定理和置信區間
    因此,我們用置信區間回答的問題是:對於任何給定的估計(樣本),我們對樣本周圍的一定範圍實際上包含真實人口比例的信心如何?注意:1.置信度「級別」是指該方法的長期成功率,即這種類型的間隔多久捕獲一次感興趣的參數。2.一個特定的置信區間給出了相關參數的合理值範圍。
  • R語言中使用stem函數繪製莖葉圖
    前面的文章中介紹了均值、方差、全距、幾何平均數等的計算方法,還給出了繪製條形圖,直方圖,散點圖,餅圖,箱線圖等的繪製方法,本文將介紹統計學中的另外一種圖的繪製方法:莖葉圖。歡迎感興趣的讀者關注本號,本號會詳細介紹R在各個方面的使用方法。
  • PyTorch實現TPU版本CNN模型
    為了得到更準確的結果,數據的大小是非常重要的,但是當這個大小影響到機器學習模型的訓練時間時,這一直是一個值得關注的問題。為了克服訓練時間的問題,我們使用TPU運行時環境來加速訓練。為此,PyTorch一直在通過提供最先進的硬體加速器來支持機器學習的實現。