1次元畳み込みニューラルネットワーク（自然言語処理）

#はじめに

今回は自然言語処理でよく使われる「1次元畳み込みニューラルネットワーク」の実装をしていきます。


🌟リカレントニューラルネットワーク（RNN）まとめ（数式なし）
https://qiita.com/hara_tatsu/items/5304479f64297221135d

🌟LSTMの実装（RNN・自然言語処理の前処理）
https://qiita.com/hara_tatsu/items/c3ba100e95e600846125

🌟双方向LSTM（Bidirectional LSTM）の実装
https://qiita.com/hara_tatsu/items/d1ddb5f1e0dee55dcdfa

#1次元畳み込みニューラルネットワークとは

2次元畳み込みニューラルネットワークは、画像処理分野で利用されている。

1次元畳み込みニューラルネットワークはテキスト分類や時系列予測で成果を出しているモデル。
また、RNNやLSTMよりも計算コストが非常に少ない。


#実装
今回は題材としてkaggleの「映画レビューの感情分析」を利用します。
https://www.kaggle.com/c/sentiment-analysis-on-movie-reviews/data?select=sampleSubmission.csv

細かいフレーズに分割された映画レビューの感情を分析するモデルを構築します。

🌟自然言語処理の前処理はこちらの記事で詳しく解説していますので参照してください！！
https://qiita.com/hara_tatsu/items/c3ba100e95e600846125

##1次元畳み込みニューラルネットワークの実装

```python.py
#モデルの構築

from tensorflow.keras.layers import LSTM, Embedding, Dense, Conv1D, MaxPooling1D, GlobalMaxPooling1D

model = keras.Sequential()

model.add(Embedding(17781, 64, mask_zero = True))
#１次元の畳み込み層
model.add(Conv1D(64, 7, activation = 'relu'))
#１次元のプーリング層
model.add(MaxPooling1D(5))
model.add(Conv1D(32, 7, activation = 'relu'))
#時系列データのためのグローバルなマックスプーリング層
model.add(GlobalMaxPooling1D())
model.add(Dense(5, activation = 'sigmoid'))

model.summary()


Layer (type)                 Output Shape              Param #   
=================================================================
embedding_4 (Embedding)      (None, None, 64)          1137984   
_________________________________________________________________
conv1d_7 (Conv1D)            (None, None, 64)          28736     
_________________________________________________________________
max_pooling1d_4 (MaxPooling1 (None, None, 64)          0         
_________________________________________________________________
conv1d_8 (Conv1D)            (None, None, 32)          14368     
_________________________________________________________________
global_max_pooling1d_2 (Glob (None, 32)                0         
_________________________________________________________________
dense_3 (Dense)              (None, 5)                 165       
=================================================================
Total params: 1,181,253
Trainable params: 1,181,253
Non-trainable params: 0

```

```python.py
model.compile(loss= 'categorical_crossentropy',
              optimizer= 'rmsprop',
              metrics = ['accuracy'])

log = model.fit(X_train, Y_train, epochs = 100, batch_size = 2048,
                callbacks=[keras.callbacks.EarlyStopping(monitor='val_loss',
                                                         min_delta=0, patience=20,
                                                         verbose=1)],
               validation_data=(X_valid, Y_valid))
```

###結果の確認

```python.py
import matplotlib.pyplot as plt

acc = log.history['accuracy']
val_acc = log.history['val_accuracy']

loss = log.history['loss']
val_loss = log.history['val_loss']

epochs_range = range(29)

plt.figure(figsize=(8, 8))
plt.subplot(1, 2, 1)
plt.plot(epochs_range, acc, label='Training Accuracy')
plt.plot(epochs_range, val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Accuracy')

plt.subplot(1, 2, 2)
plt.plot(epochs_range, loss, label='Training Loss')
plt.plot(epochs_range, val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Loss')
plt.show()
```

![スクリーンショット 2021-04-04 14.05.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672827/76782df0-11f9-a3f5-98b5-4aaa44c54c84.png)


テストデータを用いて結果を確認

```python.py
# テスト用データ(Y_test)をダミー変数から通常の数値へ復元
Y_test_ = np.argmax(Y_test, axis=1)

from sklearn.metrics import classification_report

Y_pred = model.predict_classes(X_test)
print(classification_report(Y_test_, Y_pred))

      precision    recall  f1-score   support

           0       0.53      0.34      0.41      1504
           1       0.54      0.49      0.51      5453
           2       0.72      0.81      0.76     15982
           3       0.56      0.55      0.56      6441
           4       0.57      0.32      0.41      1832

    accuracy                           0.65     31212
   macro avg       0.58      0.50      0.53     31212
weighted avg       0.64      0.65      0.64     31212

```

正解率　65％！！！
学習時間 3分31秒

【参考】
🌟双方向LSTM　
正解率　65% 
学習時間　２３分11秒

✅双方LSTMと比べると正解率は変わらないのに学習時間が大幅に少なくなりました。


##LSTM層の追加

最後に１次元畳み込みニューラルネットワークにLSTM層を追加して見ようと思います。

```python.py
model = keras.Sequential()

model.add(Embedding(17781, 64, mask_zero = True))
model.add(Conv1D(64, 7, activation = 'relu'))
model.add(MaxPooling1D(5))
model.add(Conv1D(32, 7, activation = 'relu'))
#LSTM層
model.add(LSTM(64,
               dropout=0.1,
               recurrent_dropout=0.5))
model.add(Dense(5, activation = 'sigmoid'))

model.summary()

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding_5 (Embedding)      (None, None, 64)          1137984   
_________________________________________________________________
conv1d_9 (Conv1D)            (None, None, 64)          28736     
_________________________________________________________________
max_pooling1d_5 (MaxPooling1 (None, None, 64)          0         
_________________________________________________________________
conv1d_10 (Conv1D)           (None, None, 32)          14368     
_________________________________________________________________
lstm_2 (LSTM)                (None, 64)                24832     
_________________________________________________________________
dense_4 (Dense)              (None, 5)                 325       
=================================================================
Total params: 1,206,245
Trainable params: 1,206,245
Non-trainable params: 0
_________________________________________________________________
```

```python.py
model.compile(loss= 'categorical_crossentropy',
              optimizer= 'rmsprop',
              metrics = ['accuracy'])

log = model.fit(X_train, Y_train, epochs = 100, batch_size = 2048,
                callbacks=[keras.callbacks.EarlyStopping(monitor='val_loss',
                                                         min_delta=0, patience=20,
                                                         verbose=1)],
               validation_data=(X_valid, Y_valid))
```

###結果の確認

```python.py
Y_pred = model.predict_classes(X_test)
print(classification_report(Y_test_, Y_pred))

precision    recall  f1-score   support

           0       0.38      0.46      0.42      1504
           1       0.48      0.50      0.49      5453
           2       0.75      0.73      0.74     15982
           3       0.53      0.51      0.52      6441
           4       0.47      0.48      0.47      1832

    accuracy                           0.62     31212
   macro avg       0.52      0.54      0.53     31212
weighted avg       0.62      0.62      0.62     31212
```
正解率 62%!!


#おわりに

今回は、自然言語処理で１次元畳み込みニューラルネットを実装してみました。

正解率は、LSTMや双方向LSTMと変わりませんでしたが、学習時間が大幅に短縮できました！！