いんでぃーづ

ゲームいろいろ、いろいろ自由

TensorFlow の勉強を始めたら2番目にやる機械学習:文章分類

前回のMNISTに引き続き、初歩的な機械学習を練習していきます。

前回まで

今回

今回はTensorFlow公式チュートリアルText classification をベースにしています。

今回使用するコード

今回もいきなり! コード全文です。

import tensorflow as tf
from tensorflow import keras

# 対象データ全文中の頻出上位10000語に対して処理する
vocab_size=10000

# データセットのロード
(train_data, train_labels), (test_data, test_labels) = keras.datasets.imdb.load_data(num_words=vocab_size)


# データ前処理(バラバラの長さの配列をパディングして同じ長さにする)
train_data = keras.preprocessing.sequence.pad_sequences(train_data,
                                                        value=0,
                                                        padding='post',
                                                        maxlen=256)

test_data = keras.preprocessing.sequence.pad_sequences(test_data,
                                                       value=0,
                                                       padding='post',
                                                       maxlen=256)

# モデルの構築
model = keras.Sequential()
model.add(keras.layers.Embedding(vocab_size, 16))
model.add(keras.layers.GlobalAveragePooling1D())
model.add(keras.layers.Dense(16, activation=tf.nn.relu))
model.add(keras.layers.Dense(1, activation=tf.nn.sigmoid))

# モデルのコンパイル
model.compile(optimizer=tf.train.AdamOptimizer(),
              loss='binary_crossentropy',
              metrics=['accuracy'])

# 検証用データの切り出し(テスト用データとは別)
x_val = train_data[:10000]
partial_x_train = train_data[10000:]

y_val = train_labels[:10000]
partial_y_train = train_labels[10000:]


# 学習の実行
history = model.fit(partial_x_train,
                    partial_y_train,
                    epochs=40,
                    batch_size=512,
                    validation_data=(x_val, y_val),
                    verbose=1)

# モデルの評価
results = model.evaluate(test_data, test_labels)

print(results)

コードの解説

データセットの準備

今回もTensorFlowにあらかじめ用意されているデータを使います。

Internet Movie Database にある映画レビューのデータ IMAB というものらしいです。

(train_data, train_labels), (test_data, test_labels) = keras.datasets.imdb.load_data(num_words=vocab_size)

データを覗いてみると下のようになっており、単語ではなく数字の配列になっていることがわかります。

print(train_data)
[list([1, 14, 22, 16, 43, 530, 973, 1622, 1385, 65, 458, 4468, 66, 3941, 4, 173, 36, 256, 5, 25, 100, 43, 838, 112, 50, 670, 2, 9, 35, 480, 284, 5, 150, 4, 172, 112, 167, 2, 336, 385, 39, 4, 172, 4536, 1111, 17, 546, 38, 13, 447, 4, 192, 50, 16, 6, 147, 2025, 19, 14, 22, 4, 1920, 4613, 469, 4, 22, 71, 87, 12, 16, 43, 530, 38, 76, 15, 13, 1247, 4, 22, 17, 515, 17, 12, 16, 626, 18, 2, 5, 62, 386, 12, 8, 316, 8, 106, 5, 4, 2223, 5244, 16, 480, 66, 3785, 33, 4, 130, 12, 16, 38, 619, 5, 25, 124, 51, 36, 135, 48, 25, 1415, 33, 6, 22, 12, 215, 28, 77, 52, 5, 14, 407, 16, 82, 2, 8, 4, 107, 117, 5952, 15, 256, 4, 2, 7, 3766, 5, 723, 36, 71, 43, 530, 476, 26, 400, 317, 46, 7, 4, 2, 1029, 13, 104, 88, 4, 381, 15, 297, 98, 32, 2071, 56, 26, 141, 6, 194, 7486, 18, 4, 226, 22, 21, 134, 476, 26, 480, 5, 144, 30, 5535, 18, 51, 36, 28, 224, 92, 25, 104, 4, 226, 65, 16, 38, 1334, 88, 12, 16, 283, 5, 16, 4472, 113, 103, 32, 15, 16, 5345, 19, 178, 32])
 list([1, 194, 1153, 194, 8255, 78, 228, 5, 6, 1463, 4369, 5012, 134, 26, 4, 715, 8, 118, 1634, 14, 394, 20, 13, 119, 954, 189, 102, 5, 207, 110, 3103, 21, 14, 69, 188, 8, 30, 23, 7, 4, 249, 126, 93, 4, 114, 9, 2300, 1523, 5, 647, 4, 116, 9, 35, 8163, 4, 229, 9, 340, 1322, 4, 118, 9, 4, 130, 4901, 19, 4, 1002, 5, 89, 29, 952, 46, 37, 4, 455, 9, 45, 43, 38, 1543, 1905, 398, 4, 1649, 26, 6853, 5, 163, 11, 3215, 2, 4, 1153, 9, 194, 775, 7, 8255, 2, 349, 2637, 148, 605, 2, 8003, 15, 123, 125, 68, 2, 6853, 15, 349, 165, 4362, 98, 5, 4, 228, 9, 43, 2, 1157, 15, 299, 120, 5, 120, 174, 11, 220, 175, 136, 50, 9, 4373, 228, 8255, 5, 2, 656, 245, 2350, 5, 4, 9837, 131, 152, 491, 18, 2, 32, 7464, 1212, 14, 9, 6, 371, 78, 22, 625, 64, 1382, 9, 8, 168, 145, 23, 4, 1690, 15, 16, 4, 1355, 5, 28, 6, 52, 154, 462, 33, 89, 78, 285, 16, 14
...

これは文章中の単語を、使用頻度が高いものから順に数字をつけていって、レビュー文章の単語をそれに置き換えて配列にしたものの ようです。

どんな罵詈雑言が含まれているのでしょうねえ、ふふふ。

vocab_size=10000 としてデータをロードしているので、頻出上位10000語が機械学習の対象となります。
データ配列中の最大値が10000以下であるということです。(同数出ている単語もあると思うので、実際は10000よりだいぶ小さいと思います。)

ちなみに文章に戻したい場合は、手順がここに書いてあります。

Text classification with movie reviews  |  TensorFlow

データの前処理

配列データをさらに前処理します。

それぞれのレビュー内の単語数はもちろんバラバラなので、パディングを入れて全て 同じ長さの配列 にしています。

train_data = keras.preprocessing.sequence.pad_sequences(train_data,
                                                        value=0,
                                                        padding='post',
                                                        maxlen=256)

test_data = keras.preprocessing.sequence.pad_sequences(test_data,
                                                       value=0,
                                                       padding='post',
                                                       maxlen=256)

シーケンスの前処理 - Keras Documentation

モデルの定義

さて今回もモデルを定義していきます。
ここはTensorFlow公式サイトからのコピペ。

Word Embedding

モデルの最初の層は Word Embedding という文章解析で有名なもののようで、

単語や文章を ベクトル としてあてはめる手法のようです。

model.add(keras.layers.Embedding(vocab_size, 16))

第一引数が単語数、第二引数が出力の次元数ということで、

まあ出力のイメージが想像もつきませんが 気にスンナ

Embeddingレイヤー - Keras Documentation

Poolingレイヤー

マックスプーリング演算

model.add(keras.layers.GlobalAveragePooling1D())

Poolingレイヤー - Keras Documentation

マックスプーリング演算

残りの層

残り二行は前回と同じですね。
よくある構成なのでしょうか。

model.add(keras.layers.Dense(16, activation=tf.nn.relu))
model.add(keras.layers.Dense(1, activation=tf.nn.sigmoid))

今回の出力層はポジティブ or ネガティブのboolなので、引数に1を指定しています。

モデルのコンパイル

モデルの定義が終わったら、学習プロセスを指定してコンパイルを実行。

model.compile(optimizer=tf.train.AdamOptimizer(),
              loss='binary_crossentropy',
              metrics=['accuracy'])

loss (損失関数) は前回と指定が違うのでわかったら追記。

学習の実行

fit メソッドで学習を実行します。

history = model.fit(partial_x_train,
                    partial_y_train,
                    epochs=40,
                    batch_size=512,
                    validation_data=(x_val, y_val),
                    verbose=1)

注意すべきは validation_data 引数ですかね。

学習用データの一部を切り出して指定しています。

引数の詳細は以下リンクから。

Sequentialモデル - Keras Documentation


今回はポジティブかネガティブかの二択判定だったので、もっと種類の多い分類をやるとおもしろいかもしれない。


“Unity” and Unity logos are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere, and are used under license.


免責事項

当サイトの広告バナー、リンクによって提供される情報、サービス内容について、当サイトは一切の責任を負いません。

また、当サイトの情報を元にユーザ様が不利益を被った場合にも、当サイトは一切の責任を負いません。

すべて自己責任でお願いします。