卷積神經網路處理文字序列
阿新 • • 發佈:2020-03-19
我們之前討論了卷積神經網路,從區域性可以提取出特徵,用於小貓小狗的圖片識別處理,非常有效;也討論了迴圈神經網路進行文字的處理,因為文字的順序是順序相關的。基於以上特點,我們把時間或者說文字的前後看做一個維度,那一段文字就是一個一維空間,相比圖片的二維空間,變得更加簡單了,那捲積神經網路是否可以處理這樣的情況呢?
先亮出結論,答案是肯定的。圖片是二維的資料,文字是一維的資料,因此我們可以對訓練的神經網路進行簡化,讓網路去提取一維的特徵。既然如此,一維神經網路與二維的神經網路是類似的,因此我們可以把二維卷積神經網路的特性遷移到一維的卷積神經網路上。
我們在討論神經網路的時候,我們知道了卷積神經網路具有平移不變性,非常好的特性,這個特性可以抓住問題的關鍵,識別出特殊的特徵。在一維的卷積神經網路(用到的方法:Conv1D)中,一小段文字所具有的特性,進行學習後,在文字的其他位置仍然可以被識別出來。可以這樣理解,一句話在開頭說與在結束的時候說,表達的感情應該是一致的,效果也是一樣的(絕大多數情況下),這就是文字的平移不變性。
同樣的,在處理圖片的時候,為了防止資料量過大,防止過擬合,我們需要進行池化的操作,在一維的神經網路中,我們也需要進行池化操作(用到的方法:MaxPooling1D)。
說到這裡,大概的主要內容我們就說完了,比較簡單,我們該舉一個例子了,我們還用之前用到的 IMDB 評論情感分析的資料集,看看效果怎麼樣,老規矩,看看結果然後最後給出完整程式碼:
![驗證](https://imgconvert.csdnimg.cn/aHR0cHM6Ly91cGxvYWQtaW1hZ2VzLmppYW5zaHUuaW8vdXBsb2FkX2ltYWdlcy8yMDIzNTY5LWI5YzlkZWM4ZjMyOGNkNDc?x-oss-process=image/format,png)
![損失](https://imgconvert.csdnimg.cn/aHR0cHM6Ly91cGxvYWQtaW1hZ2VzLmppYW5zaHUuaW8vdXBsb2FkX2ltYWdlcy8yMDIzNTY5LTQ1YmY1ZWFkZDBiZmQ4NTU?x-oss-process=image/format,png)
我不知道你是否實踐了我前面所有的程式碼,如果你實踐了,你可能知道在最近的迴圈神經網路的執行時間有的超過了一小時(之前的 LSTM),確實太慢了,這是迴圈神經網路的弊端。這個網路幾分鐘就完成了,並且我們看到在第四次左右就開始過擬合了,因此其實只需要訓練四次這個網路就可以了,並且我們發現相比 LSTM 的準確率下降的幅度非常小,是可以接受的範圍,因此這個網路有其獨特的優越性。下面看程式碼,注意,程式碼後面還有非常重要的內容。
```python
#!/usr/bin/env python3
import time
import matplotlib.pyplot as plt
from keras import layers
from keras.datasets import imdb
from keras.models import Sequential
from keras.optimizers import RMSprop
from keras.preprocessing import sequence
def imdb_run():
max_features = 10000
max_len = 500
(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=max_features)
x_train = sequence.pad_sequences(x_train, maxlen=max_len)
x_test = sequence.pad_sequences(x_test, maxlen=max_len)
model = Sequential()
model.add(layers.Embedding(max_features, 128, input_length=max_len))
model.add(layers.Conv1D(32, 7, activation='relu'))
model.add(layers.MaxPooling1D(5))
model.add(layers.Conv1D(32, 7, activation='relu'))
model.add(layers.GlobalMaxPooling1D())
model.add(layers.Dense(1))
model.summary()
model.compile(optimizer=RMSprop(lr=1e-4), loss='binary_crossentropy', metrics=['acc'])
history = model.fit(x_train, y_train, epochs=10, batch_size=128, validation_split=0.2)
# 畫圖
acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(1, len(loss) + 1)
plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.legend()
plt.show()
plt.figure()
plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()
plt.show()
if __name__ == "__main__":
time_start = time.time()
imdb_run()
time_end = time.time()
print('Time Used: ', time_end - time_start)
```
我們知道卷積神經網路是用於提取特徵的,準確點說是用於提取區域性特徵的,因此對於這種文字序列,能提取一小段序列的特徵,範圍無法過長,這是它的一點侷限性,迴圈神經網路的優勢是能獲取較長範圍內的關聯性,那如何將這兩者的優勢結合起來,即可以在較長範圍內將其關聯起來,又可以有一個比較好的訓練速度呢?
沒錯,就是將兩者結合起來,這是個大招,首先用一維卷積神經網路去提取特徵,然後將提取出的特徵用迴圈神經網路將前後相關聯,這既能減少資料量,又能兼顧前後的聯絡,非常高階的用法。
![image](https://imgconvert.csdnimg.cn/aHR0cHM6Ly91cGxvYWQtaW1hZ2VzLmppYW5zaHUuaW8vdXBsb2FkX2ltYWdlcy8yMDIzNTY5LTA0NDdlNTI0YmIyZWVjMGE?x-oss-process=image/format,png)
網路結構類似於這種:
```python
model = Sequential()
model.add(layers.Conv1D(32, 5, activation='relu',input_shape=(None, float_data.shape[-1])))
model.add(layers.MaxPooling1D(3))
model.add(layers.Conv1D(32, 5, activation='relu'))
model.add(layers.GRU(32, dropout=0.1, recurrent_dropout=0.5))
model.add(layers.Dense(1))
```
本篇討論的問題是將一維卷積神經網路用於文字序列的處理,就到這裡,文字的處理也將算是告一段落,接下來後續的文章將討論一些其他的問題。
- 本文首發自微信公眾號:[RAIS]([https://ai.renyuzhuo.cn/](https://ai.renyuzhuo