完成した太宰治風文章生成モデルで遊んでみた―RNNで文章生成〈11〉

はじめに

前回の記事↓

RNNが太宰治風の文章を自動生成してくれた―RNNで文章生成〈10〉

前回に引き続きいろいろな文章生成を試してみた後に、結果の考察や反省、今後の予定などについて書いていきます。

作成した文章生成モデルはJupyter Notebook形式でGithubにまとめてあります。↓

mitaka1962/dazai-text-generation (Github)

自動文章生成で遊んでみる

前回と同様の学習済みモデルを使って文章生成を行います。入力単語であるstart_wordsを変更したり、その他の引数を変更したりしてどんな文章ができるか試行します。ただし各学習ごとに、あるいはGPUとCPUのいずれを使うかによって引数の設定が同じでも生成結果は変わってきます。

人生について

まず入力単語を「人生とは」にしてfor文で0から99までシード値を変えて文章生成を実行し、その中から面白いものを取り出してみます。

start_words = ['人生', 'と', 'は']

# 中略

skip_ids = [word_to_id['<unk>']]

for i in range(100):
  word_ids = text_generate(model, start_ids, length=50,
                          skip_ids=skip_ids, top=None, seed=i)
  text = ''.join([id_to_word[w_id] for w_id in word_ids])
  text = text.replace('。', '。\n').replace('。\n」', '。」\n')
  print(f'seed:{i} ' + text + '\n')

生成された文の中で面白いものを選んで、それぞれについて長さlengthを調整して出力させてみました。

word_ids = text_generate(model, start_ids, length=10,
                         skip_ids=skip_ids, top=None, seed=21)

人生とは、たいへん明確なものだ。

だそうです。

word_ids = text_generate(model, start_ids, length=12,
                         skip_ids=skip_ids, top=None, seed=25)

人生とは、酒飲みの争いの事である。

なかなかペシミスティックなご意見。

word_ids = text_generate(model, start_ids, length=16,
                         skip_ids=skip_ids, top=None, seed=51)

人生とは、既にその孤島の山々よりも全く真実である。

何かの比喩だろうか。。。

word_ids = text_generate(model, start_ids, length=8,
                         skip_ids=skip_ids, top=None, seed=57)

人生とは、単純の自信。

体言止めはかなり珍しかったです。

word_ids = text_generate(model, start_ids, length=10,
                         skip_ids=skip_ids, top=None, seed=67)

人生とは、療養の憂鬱に過ぎない。

「療養の憂鬱」という言葉選びがお気に入り。

word_ids = text_generate(model, start_ids, length=12,
                         skip_ids=skip_ids, top=None, seed=97)

人生とは、ほんとうに同じ芝居かも知れない。

シェイクスピアみたいな言葉です。

太宰っぽい答えかどうかはわかりませんが、一応何らかの答えを返してくれました。とは言っても、これは数ある結果の中から比較的意味の通っている文章を選び出しただけであって、よくわからない文章もたくさん生成されています。また、これらの一文に続く文章は残念ながら「人生」をテーマとしたものにはなりませんでした。

セリフの入力

『「どうしましたか。」』というセリフを入力してみてどんな文章が続くのか先ほどと同じ方法で検証してみます。

word_ids = text_generate(model, start_ids, length=17,
                         skip_ids=skip_ids, top=None, seed=2)

「どうしましたか。」

と、クスクス笑いながら言いました。

笑っているそうです。

word_ids = text_generate(model, start_ids, length=24,
                         skip_ids=skip_ids, top=None, seed=11)

「どうしましたか。」

「古い市バスを買いたいのだ。

百日も、ごめんなさいね。」

古い市バスって何円くらいするんでしょうか。

word_ids = text_generate(model, start_ids, length=46,
                         skip_ids=skip_ids, top=None, seed=12)

「どうしましたか。」

「そりゃ、何の事も無い。

誰も相談が出来ない。」

周さんは、笑い出し、「ええ、そうかも知れん」「そうです。」

周さんは「惜別」という作品に出てくる人物だそうです(まだ読んでない。。。)。作品中の人名が生成結果に登場することは多く、他にも「斜陽」の上原さんや「人間失格」の佐竹がよく出てきました。

word_ids = text_generate(model, start_ids, length=23,
                         skip_ids=skip_ids, top=None, seed=15)

「どうしましたか。」

と傍の人たちは内心、不安な事を言った。

不安な様子です。

word_ids = text_generate(model, start_ids, length=24,
                         skip_ids=skip_ids, top=None, seed=17)

「どうしましたか。」

「いいえ。」

ひとりで七人の恋をしていた。

ハーレムなのか?

word_ids = text_generate(model, start_ids, length=13,
                         skip_ids=skip_ids, top=None, seed=80)

「どうしましたか。」

と二人で言う。

ふたりで言ってくれました。

セリフの後に「言う」、「呟く」などの動詞が入ったり、あるいはかぎ括弧のセリフが続いたりと、会話の状況の文章を学習してくれているようです。ただ続く内容はやはり支離滅裂でした。

小説内に登場しない単語の入力

「インターネットは」という文を入力して文章を生成させてみます。太宰治の作品内には「インターネット」という単語は登場しませんが、今回のモデル作成においては小説内の語彙からではなく、日本語単語ベクトルchiVeから辞書を作成したので「インターネット」のような現代の単語についても入力することができます。こちらもシード値を変えていろいろ試した中から面白いものを選択しています。

word_ids = text_generate(model, start_ids, length=10,
                         skip_ids=skip_ids, top=None, seed=4)

インターネットは、私には、わからぬ。

まあそうでしょうね。

word_ids = text_generate(model, start_ids, length=10,
                         skip_ids=skip_ids, top=None, seed=12)

インターネットはありやしないのですね。

まだなかったそうです。

word_ids = text_generate(model, start_ids, length=29,
                         skip_ids=skip_ids, top=None, seed=40)

インターネットはある。

「知ってるわね。

演劇は、どうですね。」

私は、眼を杯ほど清書した。

やっぱりあるそうです。

word_ids = text_generate(model, start_ids, length=9,
                         skip_ids=skip_ids, top=None, seed=42)

インターネットは大丈夫のように思われる。

セキュリティがしっかりしているんでしょうか。

word_ids = text_generate(model, start_ids, length=4,
                         skip_ids=skip_ids, top=None, seed=70)

インターネットはもろい。

やっぱりしっかりしていないようです。

word_ids = text_generate(model, start_ids, length=11,
                         skip_ids=skip_ids, top=None, seed=80)

インターネットは、詩と一軒の平和である。

謎の比喩。

インターネットという単語を理解しているかは別としても、一応名詞として認識はしているようです。「ある」、「ない」といった単語が続くことが比較的多かったのが特徴的でした。

その他

これら以外にも、太宰治自身の小説の最初の一文を入力したり、他の作家の小説の最初の一文(「吾輩は猫である。」等)を入力したりと試してみたのですが、特に関係のない文章が出力されるのみであまり面白い結果にはなりませんでした。

結果の考察

結果としては、文法面での学習はそれなりにうまくいっているが全体的な文章の整合性を考えるとまだまだといったところでしょうか。今回の結果からわかったことは日本語としての自然さを学習することと、文章の全体像であるストーリーやテーマを学習することは別だということです。このままより学習を続けてパープレキシティがより良い結果になったとしても、文法間違いの頻度は減少するでしょうが全体的に筋の通った文章の生成にはたどり着けない気がします。

RNNが時系列的に離れた入力の影響をうまく伝えられないこと、後ろの単語の影響を考慮していないこと、文章全体のテーマやストーリーを別に入力する必要があること、が課題かなと。

今後の予定

とりあえずここで文章生成モデルの作成はひとまず完成とします。Transformerなどの新しい手法を使ってモデルを改善していきたいのですが、如何せん知識が不足しているので学習の必要があり、すぐにはできないと思うので。他にも別の作家の小説で学習させたり、変分Dropoutを導入したり、LSTMの層を増やしたりと改善はいくつも考えられるのですが、そのあたりはそのうちやっていこうかと思います。

作っている途中で少し思いついたのですが、文章を太宰治風に変換するモデルも面白いんじゃないかと思いました。今回は文章を一から生成させるスタイルだったので結果は微妙でしたが、与えられた文章を太宰風に「翻訳」するモデルならうまくいくんじゃないでしょうか。そういうプログラムをネットで公開したら面白そうだなと。

おわりに

文章生成モデルを作り終えての感想です。

11回も記事を使ったわりには結果の微妙さが否めない。。。もうちょっと全体的に文章として完成して欲しかったです。学習済みの単語ベクトルの導入に結構時間を使ったので、その効果がほとんどなかったのはちょっとショックでした。しかし、WebスクレイピングやPython、PyTorchのいい勉強にはなったと思います。