0
1

More than 1 year has passed since last update.

言語処理100本ノック(2020)-81: RNNによる予測(keras)

Posted at

言語処理100本ノック 2020 (Rev2)「第9章: RNN, CNN」81本目「RNNによる予測」記録です。今回は過去に私が経験したことのある内容の延長なので簡単です。RNNにはLSTMより軽いGRUを使っています(今回程度の内容であれば、十分なはず)。
記事「まとめ: 言語処理100本ノックで学べることと成果」言語処理100本ノック 2015についてはまとめていますが、追加で差分の言語処理100本ノック 2020 (Rev2)についても更新します。

参考リンク

リンク 備考
81_RNNによる予測.ipynb 回答プログラムのGitHubリンク
言語処理100本ノック 2020 第9章: RNN, CNN (PyTorchだけど)解き方の参考
【言語処理100本ノック 2020】第9章: RNN, CNN (PyTorchだけど)解き方の参考
まとめ: 言語処理100本ノックで学べることと成果 言語処理100本ノックまとめ記事
【Keras入門(5)】単純なRNNモデル定義 前にKerasとRNN勉強したときの記事
【Keras入門(6)】単純なRNNモデル定義(最終出力のみ使用) 前にKerasとRNN勉強したときの記事
【TensorFlow公式ガイド】単語の埋め込み Embeddingのガイド
【TensorFlow公式サンプル】トークンインデックスのシーケンスとしてテキストをエンコードする Embeddingの使い方サンプル

環境

後々GPUを使わないと厳しいので、Google Colaboratory使いました。Pythonやそのパッケージでより新しいバージョンありますが、新機能使っていないので、プリインストールされているものをそのまま使っています。

種類 バージョン 内容
Python 3.7.12 Google Colaboratoryのバージョン
google 2.0.3 Google Driveのマウントに使用
tensorflow 2.7.0 ディープラーニングの主要処理
nltk 3.2.5 Tokenの辞書作成に使用
pandas 1.1.5 行列に関する処理に使用

第8章: ニューラルネット

学習内容

深層学習フレームワークを用い,再帰型ニューラルネットワーク(RNN)や畳み込みニューラルネットワーク(CNN)を実装します.

81. RNNによる予測

ID番号で表現された単語列$\boldsymbol{x} = (x_1, x_2, \dots, x_T)$がある.ただし,$T$は単語列の長さ,$x_t \in \mathbb{R}^{V}$は単語のID番号のone-hot表記である($V$は単語の総数である).再帰型ニューラルネットワーク(RNN: Recurrent Neural Network)を用い,単語列$\boldsymbol{x}$からカテゴリ$y$を予測するモデルとして,次式を実装せよ.
$
\overrightarrow h_0 = 0, \
\overrightarrow h_t = {\rm \overrightarrow{RNN}}(\mathrm{emb}(x_t), \overrightarrow h_{t-1}), \
y = {\rm softmax}(W^{(yh)} \overrightarrow h_T + b^{(y)})
$
ただし,$\mathrm{emb}(x) \in \mathbb{R}^{d_w}$は単語埋め込み(単語のone-hot表記から単語ベクトルに変換する関数),$\overrightarrow h_t \in \mathbb{R}^{d_h}$は時刻$t$の隠れ状態ベクトル,${\rm \overrightarrow{RNN}}(x,h)$は入力$x$と前時刻の隠れ状態$h$から次状態を計算するRNNユニット,$W^{(yh)} \in \mathbb{R}^{L \times d_h}$は隠れ状態ベクトルからカテゴリを予測するための行列,$b^{(y)} \in \mathbb{R}^{L}$はバイアス項である($d_w, d_h, L$はそれぞれ,単語埋め込みの次元数,隠れ状態ベクトルの次元数,ラベル数である).RNNユニット${\rm \overrightarrow{RNN}}(x,h)$には様々な構成が考えられるが,典型例として次式が挙げられる.
$
{\rm \overrightarrow{RNN}}(x,h) = g(W^{(hx)} x + W^{(hh)}h + b^{(h)})
$
ただし,$W^{(hx)} \in \mathbb{R}^{d_h \times d_w},W^{(hh)} \in \mathbb{R}^{d_h \times d_h}, b^{(h)} \in \mathbb{R}^{d_h}$はRNNユニットのパラメータ,$g$は活性化関数(例えば$\tanh$やReLUなど)である.
なお,この問題ではパラメータの学習を行わず,ランダムに初期化されたパラメータで$y$を計算するだけでよい.次元数などのハイパーパラメータは,$d_w = 300, d_h=50$など,適当な値に設定せよ(以降の問題でも同様である).

回答

回答結果

未学習状態なので、4値分類でほぼ同じ確率です。

結果
array([[0.2583952 , 0.25148967, 0.22984934, 0.2602658 ]], dtype=float32)

回答プログラム 81_RNNによる予測.ipynb

GitHubには確認用コードも含めていますが、ここには必要なものだけ載せています。

import nltk
import pandas as pd
import tensorflow as tf
from google.colab import drive

drive.mount('/content/drive')

BASE_PATH = '/content/drive/MyDrive/ColabNotebooks/ML/NLP100_2020/06.MachineLearning/'
max_len = 0


def get_vocabulary(type_):
    global max_len
    df = pd.read_table(BASE_PATH+type_+'.feature.txt')
    df.info()
    sr_title = df['title'].str.split().explode()
    max_len_ = df['title'].map(lambda x: len(x.split())).max()
    if max_len < max_len_:
        max_len = max_len_
    fdist = nltk.FreqDist(sr_title)
    print(f'Top 3 tokens: {fdist.most_common(3)}')
    return [k for k, v in fdist.items() if v > 1]


vocabulary = get_vocabulary('train')
vocabulary.extend(get_vocabulary('valid'))
vocabulary.extend(get_vocabulary('test')) # あまりこだわらずにテストデータセットも追加

# setで重複削除し、タプル形式に設定
tup_voc = tuple(set(vocabulary))

print(f'vocabulary size before removing duplicates: {len(vocabulary)}')
print(f'vocabulary size after removing duplicates: {len(tup_voc)}')
print(f'sample vocabulary: {tup_voc[:10]}')
print(f'max length is {max_len}')

vectorize_layer = tf.keras.layers.TextVectorization(
 output_mode='int',
 vocabulary=tup_voc,
 output_sequence_length=max_len)

print(f'sample vocabulary: {vectorize_layer.get_vocabulary()[:10]}')

model = tf.keras.models.Sequential()
model.add(tf.keras.Input(shape=(1,), dtype=tf.string))
model.add(vectorize_layer)
model.add(tf.keras.layers.Embedding(vectorize_layer.vocabulary_size(), 300, mask_zero=True))
model.add(tf.keras.layers.GRU(50))
model.add(tf.keras.layers.Dense(4, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='sgd')
model.summary()
model.predict([['this is a pen']])

回答解説

以前KerasとRNNは以下の記事で書いたので解説をかなり割愛します。記事は少し古いですが、基本的に変わっていません。

Embedding

Ebmedding(単語埋め込み)についてです。
単語数をTextVectorizationvocabulary_sizeで取得しています。maskと未知語(UNK)も含まれる数をくれるので、mask_zeroTrueにしてもその値でOKです。
後にGPUを使うのでRNN(GRU)のパラメータはデフォルト値にしておきます。GPU使用注意点は公式tf.keras.layers.GRUに記載があります。

model = tf.keras.models.Sequential()
model.add(tf.keras.Input(shape=(1,), dtype=tf.string))
model.add(vectorize_layer)
model.add(tf.keras.layers.Embedding(vectorize_layer.vocabulary_size(), 300, mask_zero=True))
model.add(tf.keras.layers.GRU(50))
model.add(tf.keras.layers.Dense(4, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='sgd')
model.summary()

TensorFlow公式ガイド「単語の埋め込み」に記載がありますが、ローカルのTensorBoardまたはインターネット上のプロジェクターでEmbeddingの視覚化ができます。そのためのファイル出力方法もガイド内に記載があります。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1