Tensorflow 2.0でなんJスレタイ生成器を構築する(2回目)
前回なんJスレタイ生成器を作る記事を書きましたが、 これには以下の問題がありました。
- 当時は
train_on_batch
の存在を知らずにゴリ押しでモデル学習をしていた - 生成されるサンプルに多様性がなかった
今回Tensorflow 2.0を勉強するついでになんJスレタイ生成器を作り直してみました。
注意
NLPもニューラルネットもよくわかってない人が書いているので間違っている部分があると思います。
生成例
※ 一部ブログに書くにはアレな文書も生成されていたので選抜しています。
選抜していないものを見たい方はこちら
※ SOS
はスタートトークン、EOS
はエンドトークン、PAD
はパディングトークン、UNK
は未知語トークンを表します
制限なし
かなりバリエーションのある文書を生成できるようになりました。
また、今回は割と長めの文書も生成できるようになっています。
※ スレタイの後ろにあるスコアはEvaluator(後述)の出力値です。
SOS 名前 に 「 デス 」 が 付く 曲 NUM つ しか ない EOS PAD PAD PAD PAD PAD PAD PAD PAD PAD PAD score: 4.6163287 SOS 敵 「 ワイ の こと 好き な ん ? 」 トッモ 「 は ? 僕 は ? 」 EOS PAD PAD PAD PAD score: 3.3199003 SOS なんj 民 が 知っ て いる 一番 の UNK は ? EOS PAD PAD PAD PAD PAD PAD PAD PAD PAD PAD PAD score: 3.029164 SOS ワイ NUM 歳 大学生 結婚 し たい のに 仕事 が ない EOS PAD PAD PAD PAD PAD PAD PAD PAD PAD PAD PAD score: 2.7726371 SOS (*^◯^*) ← 今年 ? 行か なけれ ば なら ない EOS PAD PAD PAD PAD PAD PAD PAD PAD PAD PAD PAD PAD PAD score: 2.641209
prefix「三大」
前回の例でも出した「三大」から始まるスレタイです。
今回も「三大〜「A」「B」あと一つは?」のような構造を学習できています。 (一部怪しいのもありますが)
SOS 三大 やらかし た UNK の 根本 の 中 で の 会話 「 ドア 机 」 「 杉浦 」 EOS PAD PAD PAD PAD score: 3.601511 SOS 三大 う けど 勢い 揃っ てる 気 が つい た 欠陥 UNK 馬 EOS PAD PAD PAD PAD PAD PAD PAD PAD PAD score: 3.2168586 SOS 三大 UNK が UNK に 必要 な もの 「 早稲田 」 「 ポテチ 」 あと 一 人 は ? EOS PAD PAD PAD score: 3.192483 SOS 三大 値段 高い と 思う な カッコイイ モビルスーツ ランキング ( NUM 番 最初 数字 ) EOS PAD PAD PAD PAD PAD PAD PAD score: 3.0752976 SOS 三大 当たり 出し が 激しい チーム 助っ人 采配 イチロー EOS PAD PAD PAD PAD PAD PAD PAD PAD PAD PAD PAD PAD PAD score: 3.0569434
prefix「【なぞなぞ】」
【なぞなぞ】から始まるスレタイはたいてい最後が問いかけになるのですが、 その構造がうまく取れています。ちゃんとなぞなぞっぽくなっていますね。
SOS 【 なぞなぞ 】 誰 でも 作る べき UNK の 曲 なー ん だ ? EOS PAD PAD PAD PAD PAD PAD PAD PAD score: 4.264069 SOS 【 なぞなぞ 】 ゴム つけ て そのまま ケーキ 誘う もの ってな ー ん だ ? EOS PAD PAD PAD PAD PAD PAD PAD score: 3.9145274 SOS 【 なぞなぞ 】 口 に 入れる と 美味しい 食べ物 ってな ~ ん だ ? EOS PAD PAD PAD PAD PAD PAD PAD PAD score: 3.8251681 SOS 【 なぞなぞ 】 UNK で 海 ワン が かける 言葉 ってな ー ん だ ? EOS PAD PAD PAD PAD PAD PAD PAD score: 3.6090522 SOS 【 なぞなぞ 】 バイク が 食わ れ て の sa お トラブル みたい な 名前 の メンバー は なん でしょ う ? EOS score: 3.5852108
モデルの詳細
今回のなんJスレタイ生成器は、スレタイっぽい文章を生成するGeneratorと、 Generatorの生成した文書を評価するEvaluaterの2つで構成されます。
Generatorでたくさんスレタイを生成し、Evaluaterで高スコアのスレタイのみを出力します。
Generator
Generatorは4層GRUによるテキスト生成器です。モデル構造はnotebookで見たほうが早いと思います。
Evaluater
EvaluatorはBidirectional GRUで構成された「Generatorの生成したスレタイ」と「本物のスレタイ」を区別する識別器です。 こちらもモデル構造はnotebookを見てください。
工夫した点・苦労した点
Generator / Evaluator構成
最初はVAEでスレタイを潜在ベクトルzで表現し、zをGANで生成する、というアイデアで文書生成を試みました。
ところが、このアイデアはVAEまではうまくいったのですがGANの学習がうまく行かず断念し、 最終的にGenerator・Evaluator構成に落ち着きました。
ちなみに、Evaluatorがないと以下のように構造を捉えられていないスレタイが生成されてしまうので、Evaluatorには一定の効果はありそうです。
SOS 【 なぞなぞ 】 女児 に 笑わ れ た 男 EOS PAD PAD PAD PAD PAD PAD PAD PAD PAD PAD PAD PAD PAD SOS 【 なぞなぞ 】 bbq に いる 女の子 と は なん だ ? EOS PAD PAD PAD PAD PAD PAD PAD PAD PAD PAD SOS 【 なぞなぞ 】 なんj を UNK て も 訪れ なかっ た もの EOS PAD PAD PAD PAD PAD PAD PAD PAD PAD PAD SOS 【 なぞなぞ 】 ミサイル が 嫌 に なら なかっ た 球場 に ビビっ てる スレ で は ない チーム は ? 日本 だけ SOS 【 なぞなぞ 】 精神的 に しか いる ん だ う なー ンゴ ? EOS PAD PAD PAD PAD PAD PAD PAD PAD PAD
Functional APIの利用
Tensorflow 2.0のチュートリアルの一部では
tf.keras.Model
を継承したクラスを作ってモデルを作っている例が出ていますが、
この場合、そのままだとsave_weights
などでモデルを保存することができません。
KerasのFunctional APIを使えば回避できるので、 よっぽどでなければFunctional APIを使うのが良いと思います。
tf.functionを使うときはなるべくtf.functionで完結させる
Better performance with tf.function | TensorFlow Core によると、tf.function
を使うと色々と性能UPするようです。
今回の検証でもtf.functionを使うと学習時間が早くなり、大きいバッチサイズでもOOMしないなどメモリ効率も良くなりました。
一方で、副作用が出ないように注意したのに@tf.function
だとエラーが出る、という挙動になることがままありました。
いろいろ試した結論としては「tf.function
を使うときはなるべくtf.function
内ですべてを完結させる」ということです。
例えば一部の前処理を tf.function
外で行ってその結果をtf.function
の引数で渡すのではなく、
前処理も含めてtf.function
内で動かすと良いです。
tf.function
の引数はdatasetから取得したデータだけにする、ぐらいの心持ちで実装するのが良いと思います。
まとめ
Tensorflow 2.0を触るついでに、なんJスレタイ生成器を作り直しました。
はじめてTensorflow 2.0を使ってハマることも多かったですが、 最終的にまあまあの精度の生成器ができたので満足です。