【深度學習】在PyTorch中使用 LSTM 進行新冠病例預測
時間序列數(shù)據(jù),顧名思義是一種隨時間變化的數(shù)據(jù)。例如,24 小時時間段內(nèi)的溫度,一個月內(nèi)各種產(chǎn)品的價格,特定公司一年內(nèi)的股票價格。長短期記憶網(wǎng)絡(luò)(LSTM)等高級深度學習模型能夠捕捉時間序列數(shù)據(jù)中的模式,因此可用于對數(shù)據(jù)的未來趨勢進行預測。在本文中,我們將一起學習如何使用 LSTM 算法使用時間序列數(shù)據(jù)進行未來預測。
本案例并不是試圖建立一個模型,并以盡可能最好的方式預測Covid-19。而這也僅僅是一個示例,說明如何使用 PyTorch 在一些真實數(shù)據(jù)的時間序列數(shù)據(jù)上使用循環(huán)神經(jīng)網(wǎng)絡(luò)LSTM。當然,如果你有更好的模型來預測每日確診病例的數(shù)量,歡迎聯(lián)系小猴子,一起研習呀。

寫在前面

什么是 LSTM
長短期記憶網(wǎng)絡(luò)Long Short Term Memory Networks (LSTM)[2]是一種循環(huán)神經(jīng)網(wǎng)絡(luò),旨在克服基本 RNN 的問題,因此網(wǎng)絡(luò)可以學習長期依賴關(guān)系。具體來說,它解決了梯度消失和爆炸的問題——當你通過時間反向傳播太多時間步長時,梯度要么消失(變?yōu)榱悖┮幢ǎㄗ兊梅浅4螅?,因為它變成了?shù)字的乘積。
循環(huán)神經(jīng)網(wǎng)絡(luò)都具有神經(jīng)網(wǎng)絡(luò)重復模塊鏈的形式,LSTM 也有這種類似鏈的結(jié)構(gòu),但重復模塊與標準 RNN 相比有不同的結(jié)構(gòu)。不是只有一個神經(jīng)網(wǎng)絡(luò)層,而是有四個,以一種非常特殊的方式進行交互。典型的圖如下所示。

可以從Chris Olah的博客[3]中了解有關(guān) LSTM 的更多信息。
為什么選用LSTM處理數(shù)據(jù)序列
許多經(jīng)典方法(例如 ARIMA)嘗試以不同的成功率處理時間序列數(shù)據(jù)(并不是說它們不擅長)。在過去幾年中,長短期記憶網(wǎng)絡(luò)模型在處理這些類型的數(shù)據(jù)時已成為一種非常有用的方法。
循環(huán)神經(jīng)網(wǎng)絡(luò)(LSTM 是其中一種)非常擅長處理數(shù)據(jù)序列。他們可以“回憶”過去(或未來)數(shù)據(jù)中的模式。在本次案例中,將學習如何基于真實世界的數(shù)據(jù)使用 LSTM 來預測未來的冠狀病毒病例。

PyTorch 中的 LSTM

nn.LSTM 中每一維代表什么意思
Pytorch 中的 LSTM 期望其所有輸入都是三維張量。這些張量的軸的語義很重要。第一個軸是序列本身,第二個索引是小批量中的實例,第三個索引是輸入的元素。具體來講:
第一維體現(xiàn)的是序列(sequence)結(jié)構(gòu),也就是序列的個數(shù),用文章來說,就是每個句子的長度,因為是喂給網(wǎng)絡(luò)模型,一般都設(shè)定為確定的長度,也就是我們喂給LSTM神經(jīng)元的每個句子的長度,當然,如果是其他的帶有序列形式的數(shù)據(jù),則表示一個明確分割單位長度,
例如是如果是股票數(shù)據(jù)內(nèi),這表示特定時間單位內(nèi),有多少條數(shù)據(jù)。這個參數(shù)也就是明確這個層中有多少個確定的單元來處理輸入的數(shù)據(jù)。
第二維度體現(xiàn)的是batch_size,也就是一次性喂給網(wǎng)絡(luò)多少條句子,或者股票數(shù)據(jù)中的,一次性喂給模型多少是個時間單位的數(shù)據(jù),具體到每個時刻,也就是一次性喂給特定時刻處理的單元的單詞數(shù)或者該時刻應(yīng)該喂給的股票數(shù)據(jù)的條數(shù)。
第三位體現(xiàn)的是輸入的元素(elements of input),也就是,每個具體的單詞用多少維向量來表示,或者股票數(shù)據(jù)中 每一個具體的時刻的采集多少具體的值,比如最低價,最高價,均價,5日均價,10均價,等等。
nn.LSTM參數(shù)詳解
通過源代碼中可以看到nn.LSTM繼承自nn.RNNBase,其需要關(guān)注的參數(shù)以及其含義解釋如下:
input_size?– 輸入數(shù)據(jù)的大小,就是你輸入x的向量大?。▁向量里有多少個元素)
hidden_size?– 隱藏層的大?。措[藏層節(jié)點數(shù)量),輸出向量的維度等于隱藏節(jié)點數(shù)。就是LSTM在運行時里面的維度。隱藏層狀態(tài)的維數(shù),即隱藏層節(jié)點的個數(shù),這個和單層感知器的結(jié)構(gòu)是類似的。
num_layers?– LSTM 堆疊的層數(shù),默認值是1層,如果設(shè)置為2,第二個LSTM接收第一個LSTM的計算結(jié)果。
bias?– 隱層狀態(tài)是否帶bias,默認為true。bias是偏置值,或者偏移值。沒有偏置值就是以0為中軸,或以0為起點。偏置值的作用請參考單層感知器相關(guān)結(jié)構(gòu)。
batch_first?– 判斷輸入輸出的第一維是否為 batch_size,默認值 False。故此參數(shù)設(shè)置可以將 batch_size 放在第一維度。因為 Torch 中,人們習慣使用Torch中帶有的dataset,dataloader向神經(jīng)網(wǎng)絡(luò)模型連續(xù)輸入數(shù)據(jù),這里面就有一個 batch_size 的參數(shù),表示一次輸入多少個數(shù)據(jù)。
在 LSTM 模型中,輸入數(shù)據(jù)必須是一批數(shù)據(jù),為了區(qū)分LSTM中的批量數(shù)據(jù)和dataloader中的批量數(shù)據(jù)是否相同意義,LSTM 模型就通過這個參數(shù)的設(shè)定來區(qū)分。如果是相同意義的,就設(shè)置為True,如果不同意義的,設(shè)置為False。torch.LSTM 中 batch_size 維度默認是放在第二維度,故此參數(shù)設(shè)置可以將 batch_size 放在第一維度。
dropout?– 默認值0。是否在除最后一個 RNN 層外的其他 RNN 層后面加 dropout 層。輸入值是 0-1 之間的小數(shù),表示概率。0表示0概率dripout,即不dropout?。
bidirectional?– 是否是雙向 RNN,默認為:false,若為 true,則:num_directions=2,否則為1。
下面介紹一下輸入數(shù)據(jù)的維度要求(batch_first=False)。輸入數(shù)據(jù)需要按如下形式傳入input, (h_0,c_0)
input: 輸入數(shù)據(jù),即上面例子中的一個句子(或者一個batch的句子),其維度形狀為 (seq_len, batch, input_size)
seq_len: 句子長度,即單詞數(shù)量,這個是需要固定的。當然假如你的一個句子中只有2個單詞,但是要求輸入10個單詞,這個時候可以用torch.nn.utils.rnn.pack_padded_sequence(),或者torch.nn.utils.rnn.pack_sequence()來對句子進行填充或者截斷。 batch:就是你一次傳入的句子的數(shù)量 input_size: 每個單詞向量的長度,這個必須和你前面定義的網(wǎng)絡(luò)結(jié)構(gòu)保持一致
h_0:維度形狀為 (num_layers * num_directions, batch, hidden_size)。
結(jié)合下圖應(yīng)該比較好理解第一個參數(shù)的含義num_layers * num_directions,即LSTM的層數(shù)乘以方向數(shù)量。這個方向數(shù)量是由前面介紹的bidirectional決定,如果為False,則等于1;反之等于2。 batch:同上 hidden_size: 隱藏層節(jié)點數(shù)
c_0:維度形狀為 (num_layers * num_directions, batch, hidden_size),各參數(shù)含義和h_0類似。
當然,如果你沒有傳入(h_0, c_0),那么這兩個參數(shù)會默認設(shè)置為0。
output:維度和輸入數(shù)據(jù)類似,只不過最后的feature部分會有點不同,即 (seq_len, batch, num_directions * hidden_size)。這個輸出tensor包含了LSTM模型最后一層每個time step的輸出特征,比如說LSTM有兩層,那么最后輸出的是[h10,h11,...,h1l],表示第二層LSTM每個time step對應(yīng)的輸出。
h_n:(num_layers * num_directions, batch, hidden_size), 只會輸出最后一個time step的隱狀態(tài)結(jié)果。
c_n?:(num_layers * num_directions, batch, hidden_size),只會輸出最后個time step的cell狀態(tài)結(jié)果。

導入相關(guān)模塊

import?torch
import?os
import?numpy?as?np
import?pandas?as?pd
from?tqdm?import?tqdm
import?seaborn?as?sns
from?pylab?import?rcParams
import?matplotlib.pyplot?as?plt
from?matplotlib?import?rc
from?sklearn.preprocessing?import?MinMaxScaler
from?pandas.plotting?import?register_matplotlib_converters
from?torch?import?nn,?optim
%matplotlib?inline
%config?InlineBackend.figure_format='retina'
sns.set(style='whitegrid',?palette='muted',?font_scale=1.2)
HAPPY_COLORS_PALETTE?=?["#01BEFE",?"#FFDD00",?"#FF7D00",?"#FF006D",?"#93D30C",?"#8F00FF"]
sns.set_palette(sns.color_palette(HAPPY_COLORS_PALETTE))
rcParams['figure.figsize']?=?14,?6
register_matplotlib_converters()
RANDOM_SEED?=?42
np.random.seed(RANDOM_SEED)
torch.manual_seed(RANDOM_SEED)

每日數(shù)據(jù)集

這些數(shù)據(jù)由約翰·霍普金斯大學系統(tǒng)科學與工程中心(JHU CSSE)提供,包含按國家/地區(qū)報告的每日病例數(shù)。數(shù)據(jù)集可在GitHub上獲得[5],并定期更新。
我們將只使用確診病例的時間序列數(shù)據(jù)(也提供死亡和康復病例數(shù)):

探索性數(shù)據(jù)分析

首先導入數(shù)據(jù)集
df?=?pd.read_csv('./data/time_series_covid19_confirmed_global.csv')
df.head()

這里要注意兩點:
數(shù)據(jù)包含省、國家/地區(qū)、緯度和經(jīng)度。但我們不需要這些數(shù)據(jù)。 病例數(shù)是累積的。我們需要撤消累積。
從去掉前四列我們不需要的數(shù)據(jù),可以通過切片直接獲取第五列之后的數(shù)據(jù)。
df?=?df.iloc[:,?4:]
df.head()

接下來檢查缺失值。
df.isnull().sum().sum()
0
一切都已就位。我們對所有行求和,這樣就得到了每日累計案例:
daily_cases?=?df.sum(axis=0)
daily_cases.index?=?pd.to_datetime(daily_cases.index)
daily_cases.head()
2020-01-22 557
2020-01-23 655
2020-01-24 941
2020-01-25 1434
2020-01-26 2118
dtype: int64
plt.plot(daily_cases)
plt.title("Cumulative?daily?cases");

我們將通過從前一個值中減去當前值來撤消累加。我們將保留序列的第一個值。
daily_cases?=?daily_cases.diff().fillna(daily_cases[0]).astype(np.int64)
daily_cases.head()
2020-01-22 557
2020-01-23 98
2020-01-24 286
2020-01-25 493
2020-01-26 684
dtype: int64
plt.plot(daily_cases)
plt.title("Daily?cases");

從圖中可以看出有一個巨大的峰值,這主要是由于中國檢測患者的標準發(fā)生了變化。這對我們的模型來說肯定是一個挑戰(zhàn)。
讓我們檢查一下我們擁有的數(shù)據(jù)量。
daily_cases.shape
(622,)
我們有 622 天的數(shù)據(jù)。讓我們看看我們能用它做什么。

數(shù)據(jù)預處理

我們將保留前 467 天用于訓練,其余時間用于測試。
test_data_size?=?155
train_data?=?daily_cases[:-test_data_size]
test_data?=?daily_cases[-test_data_size:]
train_data.shape
(467,)
如果我們想提高模型的訓練速度和性能,我們必須縮放數(shù)據(jù)(將值按比例壓縮在 0 和 1 之間)。我們將使用來自?scikit-learn?的MinMaxScaler。
scaler?=?MinMaxScaler()
scaler?=?scaler.fit(np.expand_dims(train_data,?axis=1))
train_data?=?scaler.transform(np.expand_dims(train_data,?axis=1))
test_data?=?scaler.transform(np.expand_dims(test_data,?axis=1))
這份數(shù)據(jù)中,每天都有大量的病例??梢詫阉D(zhuǎn)換成更小的條數(shù)。
def?create_sequences(data,?seq_length):
????xs?=?[]
????ys?=?[]
????for?i?in?range(len(data)-seq_length-1):
????????x?=?data[i:(i+seq_length)]
????????y?=?data[i+seq_length]
????????xs.append(x)
????????ys.append(y)
????return?np.array(xs),?np.array(ys)
seq_length?=?7
X_train,?y_train?=?create_sequences(train_data,?seq_length)
X_test,?y_test?=?create_sequences(test_data,?seq_length)
X_train?=?torch.from_numpy(X_train).float()
y_train?=?torch.from_numpy(y_train).float()
X_test?=?torch.from_numpy(X_test).float()
y_test?=?torch.from_numpy(y_test).float()
每個訓練示例包含7個歷史數(shù)據(jù)點序列和一個標簽,該標簽表示我們的模型需要預測的真實值。接下來看看我們轉(zhuǎn)換后的數(shù)據(jù)的樣貌。
X_train.shape
torch.Size([459, 7, 1])
X_train[:2]
tensor([[[0.0003],
[0.0000],
[0.0001],
[0.0003],
[0.0004],
[0.0005],
[0.0017]],
[[0.0000],
[0.0001],
[0.0003],
[0.0004],
[0.0005],
[0.0017],
[0.0003]]])
y_train.shape
torch.Size([459, 1])
y_train[:2]
tensor([[0.0003],
[0.0013]])
train_data[:10]
array([[0.00030585],
[0. ],
[0.00012527],
[0.0002632 ],
[0.00039047],
[0.00047377],
[0.00170116],
[0.00032717],
[0.00131268],
[0.00106214]])
建立模型

我們將把模型封裝到一個自torch.nn.Module的類中。
class?CoronaVirusPredictor(nn.Module):
????def?__init__(self,?n_features,?n_hidden,?seq_len,?n_layers=2):
????????super(CoronaVirusPredictor,?self).__init__()
????????self.n_hidden?=?n_hidden
????????self.seq_len?=?seq_len
????????self.n_layers?=?n_layers
????????self.lstm?=?nn.LSTM(
??????????input_size=n_features,
??????????hidden_size=n_hidden,
??????????num_layers=n_layers,
??????????dropout=0.5
????????)
????????self.linear?=?nn.Linear(in_features=n_hidden,?out_features=1)
????def?reset_hidden_state(self):
????????self.hidden?=?(
????????????torch.zeros(self.n_layers,?self.seq_len,?self.n_hidden),
????????????torch.zeros(self.n_layers,?self.seq_len,?self.n_hidden)
????????)
????def?forward(self,?sequences):
????????lstm_out,?self.hidden?=?self.lstm(
??????????sequences.view(len(sequences),?self.seq_len,?-1),
??????????self.hidden
????????)
????????last_time_step?=?\
??????????lstm_out.view(self.seq_len,?len(sequences),?self.n_hidden)[-1]
????????y_pred?=?self.linear(last_time_step)
????????return?y_pred
我們CoronaVirusPredictor?包含 3 個方法:
構(gòu)造函數(shù) - 初始化所有輔助數(shù)據(jù)并創(chuàng)建層。 reset_hidden_state?- 我們將使用無狀態(tài) LSTM,因此我們需要在每個示例之后重置狀態(tài)。forward- 獲取序列,一次將所有序列通過 LSTM 層。我們采用最后一個時間步的輸出并將其傳遞給我們的線性層以獲得預測。

訓練模型

為模型訓練構(gòu)建一個輔助函數(shù)。
def?train_model(
??????model,?
??????train_data,?
??????train_labels,?
??????test_data=None,?
??????test_labels=None
????):
????loss_fn?=?torch.nn.MSELoss(reduction='sum')
????optimiser?=?torch.optim.Adam(model.parameters(),?lr=1e-3)
????num_epochs?=?100
????train_hist?=?np.zeros(num_epochs)
????test_hist?=?np.zeros(num_epochs)
????for?t?in?range(num_epochs):
????????model.reset_hidden_state()
????????y_pred?=?model(X_train)
????????loss?=?loss_fn(y_pred.float(),?y_train)
????????if?test_data?is?not?None:
????????????with?torch.no_grad():
????????????????y_test_pred?=?model(X_test)
????????????????test_loss?=?loss_fn(y_test_pred.float(),?y_test)
????????????test_hist[t]?=?test_loss.item()
????????????if?t?%?10?==?0:??
????????????????print(f'Epoch?{t}?train?loss:?{loss.item()}?test?loss:?{test_loss.item()}')
????????elif?t?%?10?==?0:
????????????print(f'Epoch?{t}?train?loss:?{loss.item()}')
????????train_hist[t]?=?loss.item()
????????optimiser.zero_grad()
????????loss.backward()
????????optimiser.step()
????return?model.eval(),?train_hist,?test_hist
注意,隱藏層的狀態(tài)在每個epoch開始時被重置。我們不使用批量的數(shù)據(jù),模型可以一次看到每個樣本。將使用均方誤差來測量我們的訓練和測試誤差,并將兩者都記錄下來。
接下來創(chuàng)建一個模型的實例并訓練它。
model?=?CoronaVirusPredictor(
??n_features=1,?
??n_hidden=512,?
??seq_len=seq_length,?
??n_layers=2
)
model,?train_hist,?test_hist?=?train_model(
??model,?
??X_train,?
??y_train,?
??X_test,?
??y_test
)
Epoch 0 train loss: 36.648155212402344 test loss: 19.638214111328125
Epoch 10 train loss: 15.204809188842773 test loss: 1.5947879552841187
Epoch 20 train loss: 12.796365737915039 test loss: 2.8455893993377686
Epoch 30 train loss: 13.453448295593262 test loss: 5.292770862579346
Epoch 40 train loss: 13.023208618164062 test loss: 2.4893276691436768
Epoch 50 train loss: 12.724889755249023 test loss: 4.096951007843018
Epoch 60 train loss: 12.620814323425293 test loss: 3.4106807708740234
Epoch 70 train loss: 12.63078498840332 test loss: 3.245408296585083
Epoch 80 train loss: 12.615142822265625 test loss: 3.529395341873169
Epoch 90 train loss: 12.61486530303955 test loss: 3.571239948272705
如何解決神經(jīng)網(wǎng)絡(luò)訓練時loss不下降的問題?
由結(jié)果可以看出,本次訓練的網(wǎng)絡(luò)效果并不是很好,可以通過一定的方法對模型進行進一步優(yōu)化。這里建議參考該博客:如何解決神經(jīng)網(wǎng)絡(luò)訓練時loss不下降的問題[6]
訓練集loss不下降
1.模型結(jié)構(gòu)和特征工程存在問題
2.權(quán)重初始化方案有問題
3.正則化過度
4.選擇合適的激活函數(shù)、損失函數(shù)
5.選擇合適的優(yōu)化器和學習速率
6.訓練時間不足
7.模型訓練遇到瓶頸:梯度消失、大量神經(jīng)元失活、梯度爆炸和彌散、學習率過大或過小等
8.batch size過大
9.數(shù)據(jù)集未打亂
10.數(shù)據(jù)集有問題
11.未進行歸一化
12.特征工程中對數(shù)據(jù)特征的選取有問題驗證集loss不下降
1.適當?shù)恼齽t化和降維
2.適當降低模型的規(guī)模
3.獲取更多的數(shù)據(jù)集
來看看訓練和測試損失。
plt.plot(train_hist,?label="Training?loss")
plt.plot(test_hist,?label="Test?loss")
plt.ylim((0,?100))
plt.legend();

我們的模型在50個時代之后并沒有改善?;叵胍幌拢覀冎挥泻苌俚臄?shù)據(jù),并且模型損失并未優(yōu)化至最佳。也許我們不該那么相信我們的模型?

預測未來幾天的病例

我們的所建立的模型(由于訓練它的方式)只能預測未來的某一天。我們將采用一個簡單的策略來克服這個限制。使用預測值作為預測未來幾天的輸入。
with?torch.no_grad():
????test_seq?=?X_test[:1]
????preds?=?[]
????for?_?in?range(len(X_test)):
????????y_test_pred?=?model(test_seq)
????????pred?=?torch.flatten(y_test_pred).item()
????????preds.append(pred)
????????new_seq?=?test_seq.numpy().flatten()
????????new_seq?=?np.append(new_seq,?[pred])
????????new_seq?=?new_seq[1:]
????????test_seq?=?torch.as_tensor(new_seq
???????????????????).view(1,?seq_length,?1).float()
這里需要撤銷測試數(shù)據(jù)和模型預測的縮放轉(zhuǎn)換比例,即使用逆縮放器變換,已得到原始數(shù)據(jù)。
true_cases?=?scaler.inverse_transform(
????np.expand_dims(y_test.flatten().numpy(),?axis=0)
).flatten()
predicted_cases?=?scaler.inverse_transform(
??np.expand_dims(preds,?axis=0)
).flatten()
一起看看結(jié)果,將訓練數(shù)據(jù)、測試數(shù)據(jù)及預測數(shù)據(jù)繪制在同一張畫布上,一起比較下預測結(jié)果。
plt.plot(
??daily_cases.index[:len(train_data)],?
??scaler.inverse_transform(train_data).flatten(),
??label='Historical?Daily?Cases')
plt.plot(
??daily_cases.index[len(train_data):len(train_data)?+?len(true_cases)],?
??true_cases,
??label='Real?Daily?Cases')
plt.plot(
??daily_cases.index[len(train_data):len(train_data)?+?len(true_cases)],?
??predicted_cases,?
??label='Predicted?Daily?Cases')
plt.legend();

正如預期的那樣,我們的模型表現(xiàn)不佳。也就是說,預測似乎是正確的(可能是因為使用最后一個數(shù)據(jù)點作為下一個數(shù)據(jù)點的強預測器)。
使用所有數(shù)據(jù)來訓練
現(xiàn)在,我們將使用所有可用數(shù)據(jù)來訓練相同的模型。
scaler?=?MinMaxScaler()
scaler?=?scaler.fit(np.expand_dims(daily_cases,?axis=1))
all_data?=?scaler.transform(np.expand_dims(daily_cases,?axis=1))
all_data.shape
(622, 1)
預處理和訓練步驟相同。
X_all,?y_all?=?create_sequences(all_data,?seq_length)
X_all?=?torch.from_numpy(X_all).float()
y_all?=?torch.from_numpy(y_all).float()
model?=?CoronaVirusPredictor(
??n_features=1,?
??n_hidden=512,?
??seq_len=seq_length,?
??n_layers=2
)
model,?train_hist,?_?=?train_model(model,?X_all,?y_all)
Epoch 0 train loss: 28.981904983520508
Epoch 10 train loss: 12.115002632141113
Epoch 20 train loss: 10.47011661529541
Epoch 30 train loss: 18.45709991455078
Epoch 40 train loss: 14.793025016784668
Epoch 50 train loss: 12.061325073242188
Epoch 60 train loss: 11.918513298034668
Epoch 70 train loss: 11.55040168762207
Epoch 80 train loss: 10.834881782531738
Epoch 90 train loss: 15.602020263671875
預測未來病例
使用“完全訓練”的模型來預測未來 12 天的確診病例。
DAYS_TO_PREDICT?=?12
with?torch.no_grad():
????test_seq?=?X_all[:1]
????preds?=?[]
????for?_?in?range(DAYS_TO_PREDICT):
????????y_test_pred?=?model(test_seq)
????????pred?=?torch.flatten(y_test_pred).item()
????????preds.append(pred)
????????new_seq?=?test_seq.numpy().flatten()
????????new_seq?=?np.append(new_seq,?[pred])
????????new_seq?=?new_seq[1:]
????????test_seq?=?torch.as_tensor(new_seq).view(1,?seq_length,?1).float()
和以前一樣,我們將逆縮放器變換。
predicted_cases?=?scaler.inverse_transform(
??np.expand_dims(preds,?axis=0)
).flatten()
要使用歷史和預測案例創(chuàng)建一個很酷的圖表,我們需要擴展數(shù)據(jù)框的日期索引。
daily_cases.index[-1]
Timestamp('2020-03-02 00:00:00')
predicted_index?=?pd.date_range(
??start=daily_cases.index[-1],
??periods=DAYS_TO_PREDICT?+?1,
??closed='right'
)
predicted_cases?=?pd.Series(
??data=predicted_cases,
??index=predicted_index
)
plt.plot(predicted_cases,?label='Predicted?Daily?Cases')
plt.legend();

現(xiàn)在我們可以使用所有數(shù)據(jù)來繪制結(jié)果。
plt.plot(daily_cases,?label='Historical?Daily?Cases')
plt.plot(predicted_cases,?label='Predicted?Daily?Cases')
plt.legend();

從這里也能看,本次模型仍然有待優(yōu)化。至于如何優(yōu)化模型,待后續(xù)更新。

寫在最后

我們學習了如何使用 PyTorch 創(chuàng)建處理時間序列數(shù)據(jù)的循環(huán)神經(jīng)網(wǎng)絡(luò)。模型性能不是很好,但考慮到數(shù)據(jù)量很少,這是可以預期的。
預測每日 Covid-19 病例的問題確實是一個難題。同樣希望一段時間后一切都會恢復正常。
參考資料
參考原文:?https://curiousily.com/posts/time-series-forecasting-with-lstm-for-daily-coronavirus-cases/
[2]?Long Short Term Memory Networks (LSTM):?https://en.wikipedia.org/wiki/Long_short-term_memory
[3]?Chris Olah的博客:?http://colah.github.io/posts/2015-08-Understanding-LSTMs/
[4]?參數(shù)詳解:?https://blog.csdn.net/wangwangstone/article/details/90296461
[5]?數(shù)據(jù)集可在GitHub上獲得:?https://github.com/CSSEGISandData/COVID-19
[6]?如何解決神經(jīng)網(wǎng)絡(luò)訓練時loss不下降的問題:?https://blog.ailemon.net/2019/02/26/solution-to-loss-doesnt-drop-in-nn-train/
往期精彩回顧 本站qq群955171419,加入微信群請掃碼:
