のどあめ

ググってもなかなか出てこなかった情報を垂れ流すブログ。

Tensorflow 2.0でなんJスレタイ生成器を構築する(2回目)

前回なんJスレタイ生成器を作る記事を書きましたが、 これには以下の問題がありました。

  • 当時は train_on_batch の存在を知らずにゴリ押しでモデル学習をしていた
  • 生成されるサンプルに多様性がなかった

今回Tensorflow 2.0を勉強するついでになんJスレタイ生成器を作り直してみました。

github.com

注意

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を使ってハマることも多かったですが、 最終的にまあまあの精度の生成器ができたので満足です。

参考にしたサイト