概述
許多技術文章都關注於二維卷積神經網路(2D CNN)的使用,特別是在影象識別中的應用。而一維卷積神經網路(1D CNNs)只在一定程度上有所涉及,比如在自然語言處理(NLP)中的應用。目前很少有文章能夠提供關於如何構造一維卷積神經網路來解決你可能正面臨的一些機器學習問題。本文試圖補上這樣一個短板。
何時應用 1D CNN?
CNN 可以很好地識別出資料中的簡單模式,然後使用這些簡單模式在更高階的層中生成更復雜的模式。當你希望從整體資料集中較短的(固定長度)片段中獲得感興趣特徵,並且該特性在該資料片段中的位置不具有高度相關性時,1D CNN 是非常有效的。
1D CNN 可以很好地應用於感測器資料的時間序列分析(比如陀螺儀或加速度計資料);同樣也可以很好地用於分析具有固定長度週期的訊號資料(比如音訊訊號)。此外,它還能應用於自然語言處理的任務(由於單詞的接近性可能並不總是一個可訓練模式的好指標,因此 LSTM 網路在 NLP 中的應用更有前途)。
1D CNN 和 2D CNN 之間有什麼區別?
無論是一維、二維還是三維,卷積神經網路(CNNs)都具有相同的特點和相同的處理方法。關鍵區別在於輸入資料的維數以及特徵檢測器(或濾波器)如何在資料之間滑動:
“一維和二維卷積神經網路” 由 Nils Ackermann 在知識共享許可 CC BY-ND 4.0 下授權。
問題描述
在本文中,我們將專注於基於時間片的加速度感測器資料的處理,這些資料來自於使用者的腰帶式智慧手機裝置。基於 x、y 和 z 軸的加速度計資料,1D CNN 用來預測使用者正在進行的活動型別(比如“步行”、“慢跑”或“站立”)。你可以在我的另外兩篇文章中找到更多的資訊 這裡 和 這裡。對於各種活動,在每個時間間隔上的資料看起來都與此類似。
來自加速度計資料的時間序列樣例
如何在 Python 中構造一個 1D CNN?
目前已經有許多得標準 CNN 模型可用。我選擇了 Keras 網站 上描述的一個模型,並對它進行了微調,以適應前面描述的問題。下面的圖片對構建的模型進行一個高階概述。其中每一層都將會進一步加以解釋。
“一維卷積神經網路示例”由 Nils Ackermann 在知識共享許可 CC BY-ND 4.0 下授權。
讓我們先來看一下對應的 Python 程式碼,以便構建這個模型:
model_m = Sequential()
model_m.add(Reshape((TIME_PERIODS, num_sensors), input_shape=(input_shape,)))
model_m.add(Conv1D(100, 10, activation='relu', input_shape=(TIME_PERIODS, num_sensors)))
model_m.add(Conv1D(100, 10, activation='relu'))
model_m.add(MaxPooling1D(3))
model_m.add(Conv1D(160, 10, activation='relu'))
model_m.add(Conv1D(160, 10, activation='relu'))
model_m.add(GlobalAveragePooling1D())
model_m.add(Dropout(0.5))
model_m.add(Dense(num_classes, activation='softmax'))
print(model_m.summary())
複製程式碼
執行這段程式碼將得到如下的深層神經網路:
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
reshape_45 (Reshape) (None, 80, 3) 0
_________________________________________________________________
conv1d_145 (Conv1D) (None, 71, 100) 3100
_________________________________________________________________
conv1d_146 (Conv1D) (None, 62, 100) 100100
_________________________________________________________________
max_pooling1d_39 (MaxPooling (None, 20, 100) 0
_________________________________________________________________
conv1d_147 (Conv1D) (None, 11, 160) 160160
_________________________________________________________________
conv1d_148 (Conv1D) (None, 2, 160) 256160
_________________________________________________________________
global_average_pooling1d_29 (None, 160) 0
_________________________________________________________________
dropout_29 (Dropout) (None, 160) 0
_________________________________________________________________
dense_29 (Dense) (None, 6) 966
=================================================================
Total params: 520,486
Trainable params: 520,486
Non-trainable params: 0
_________________________________________________________________
None
複製程式碼
讓我們深入到每一層中,看看到底發生了什麼:
- 輸入資料: 資料經過預處理後,每條資料記錄中包含有 80 個時間片(資料是以 20Hz 的取樣頻率進行記錄的,因此每個時間間隔中就包含有 4 秒的加速度計資料)。在每個時間間隔內,儲存加速度計的 x 軸、 y 軸和 z 軸的三個資料。這樣就得到了一個 80 x 3 的矩陣。由於我通常是在 iOS 系統中使用神經網路的,所以資料必須平展成長度為 240 的向量後傳入神經網路中。網路的第一層必須再將其變形為原始的 80 x 3 的形狀。
- 第一個 1D CNN 層: 第一層定義了高度為 10(也稱為卷積核大小)的濾波器(也稱為特徵檢測器)。只有定義了一個濾波器,神經網路才能夠在第一層中學習到一個單一的特徵。這可能還不夠,因此我們會定義 100 個濾波器。這樣我們就在網路的第一層中訓練得到 100 個不同的特性。第一個神經網路層的輸出是一個 71 x 100 的矩陣。輸出矩陣的每一列都包含一個濾波器的權值。在定義核心大小並考慮輸入矩陣長度的情況下,每個過濾器將包含 71 個權重值。
- 第二個 1D CNN 層: 第一個 CNN 的輸出結果將被輸入到第二個 CNN 層中。我們將在這個網路層上再次定義 100 個不同的濾波器進行訓練。按照與第一層相同的邏輯,輸出矩陣的大小為 62 x 100。
- 最大值池化層: 為了減少輸出的複雜度和防止資料的過擬合,在 CNN 層之後經常會使用池化層。在我們的示例中,我們選擇了大小為 3 的池化層。這意味著這個層的輸出矩陣的大小隻有輸入矩陣的三分之一。
- 第三和第四個 1D CNN 層: 為了學習更高層次的特徵,這裡又使用了另外兩個 1D CNN 層。這兩層之後的輸出矩陣是一個 2 x 160 的矩陣。
- 平均值池化層: 多新增一個池化層,以進一步避免過擬合的發生。這次的池化不是取最大值,而是取神經網路中兩個權重的平均值。輸出矩陣的大小為 1 x 160 。每個特徵檢測器在神經網路的這一層中只剩下一個權重。
- Dropout 層: Dropout 層會隨機地為網路中的神經元賦值零權重。由於我們選擇了 0.5 的比率,則 50% 的神經元將會是零權重的。通過這種操作,網路對資料的微小變化的響應就不那麼敏感了。因此,它能夠進一步提高對不可見資料處理的準確性。這個層的輸出仍然是一個 1 x 160 的矩陣。
- 使用 Softmax 啟用的全連線層: 最後一層將會把長度為 160 的向量降為長度為 6 的向量,因為我們有 6 個類別要進行預測(即 “慢跑”、“坐下”、“走路”、“站立”、“上樓”、“下樓”)。這裡的維度下降是通過另一個矩陣乘法來完成的。Softmax 被用作啟用函式。它強制神經網路的所有六個輸出值的加和為一。因此,輸出值將表示這六個類別中的每個類別出現的概率。
訓練和測試該神經網路
下面是一段用以訓練模型的 Python 程式碼,批大小為 400,其中訓練集和驗證集的分割比例是 80 比 20。
callbacks_list = [
keras.callbacks.ModelCheckpoint(
filepath='best_model.{epoch:02d}-{val_loss:.2f}.h5',
monitor='val_loss', save_best_only=True),
keras.callbacks.EarlyStopping(monitor='acc', patience=1)
]
model_m.compile(loss='categorical_crossentropy',
optimizer='adam', metrics=['accuracy'])
BATCH_SIZE = 400
EPOCHS = 50
history = model_m.fit(x_train,
y_train,
batch_size=BATCH_SIZE,
epochs=EPOCHS,
callbacks=callbacks_list,
validation_split=0.2,
verbose=1)
複製程式碼
該模型在訓練資料上的準確率可達 97%。
...
Epoch 9/50
16694/16694 [==============================] - 16s 973us/step - loss: 0.0975 - acc: 0.9683 - val_loss: 0.7468 - val_acc: 0.8031
Epoch 10/50
16694/16694 [==============================] - 17s 989us/step - loss: 0.0917 - acc: 0.9715 - val_loss: 0.7215 - val_acc: 0.8064
Epoch 11/50
16694/16694 [==============================] - 17s 1ms/step - loss: 0.0877 - acc: 0.9716 - val_loss: 0.7233 - val_acc: 0.8040
Epoch 12/50
16694/16694 [==============================] - 17s 1ms/step - loss: 0.0659 - acc: 0.9802 - val_loss: 0.7064 - val_acc: 0.8347
Epoch 13/50
16694/16694 [==============================] - 17s 1ms/step - loss: 0.0626 - acc: 0.9799 - val_loss: 0.7219 - val_acc: 0.8107
複製程式碼
根據測試集資料進行測試,其準確率為 92%。
Accuracy on test data: 0.92
Loss on test data: 0.39
複製程式碼
考慮到我們使用的是標準的 1D CNN 模型,得到這樣的結果已經很好了。我們的模型在精度(precision)、召回率(recall)和 f1 值(f1-score)上的得分也很高。
precision recall f1-score support
0 0.76 0.78 0.77 650
1 0.98 0.96 0.97 1990
2 0.91 0.94 0.92 452
3 0.99 0.84 0.91 370
4 0.82 0.77 0.79 725
5 0.93 0.98 0.95 2397
avg / total 0.92 0.92 0.92 6584
複製程式碼
下面對這些分數的含義做一個簡要回顧:
“預測和結果矩陣”由 Nils Ackermann 在知識共享 CC BY-ND 4.0 許可下授權。
- 精確度(Accuracy): 正確預測的結果與所有預測的結果總和之比。即 ((TP + TN) / (TP + TN + FP + FN))
- 精度(Precision): 當模型預測為正樣本時,它是對的嗎?所有的正確預測的正樣本除以所有的正樣本預測。即 (TP / (TP + FP))
- 召回率(Recall): 為模型識別出的所有正樣本中有多少是正確預測的正樣本?正確預測的正樣本除以所有的正樣本預測。即 (TP / (TP + FN))
- F1值(F1-score): 是精度和召回率的加權平均值。即 (2 x recall x precision / (recall + precision))
測試資料上對應的混淆矩陣如下所示。
總結
本文通過以智慧手機的加速度計資料來預測使用者的行為為例,紹瞭如何使用 1D CNN 來訓練網路。完整的 Python 程式碼可以在 github 上找到。
連結與引用
免責宣告
網站帖文屬於自己,不代表僱傭者的文章、策略或意見。
聯絡 Raven 團隊 Telegram
如果發現譯文存在錯誤或其他需要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可獲得相應獎勵積分。文章開頭的 本文永久連結 即為本文在 GitHub 上的 MarkDown 連結。
掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。