cedro-blog

Keras LSTM の文章生成を単語単位でやってみる

今回は、Keras LSTM の文章生成のプログラムを改造して、単語単位の文章生成をやってみます。

こんちは cedro です。

以前、Keras LSTM のサンプルプログラムで文字単位の文章生成をしてみました。これはこれで、結構雰囲気が出て面白いのですが、やっぱり本格的にやるには、単語単位じゃないとねーと思っていました。

最近、文章カテゴリー分類マルコフ連鎖による文章生成をやってみる中で、Python による辞書の取り扱いにも慣れて来たので、そろそろ単語単位の文章生成をやってみたくなりました。

ということで、今回は、Keras LSTM の文章生成のプログラムを改造して、単語単位の文章生成をやってみます。

 

テキストを準備します。

今回も、元となるテキストは推理小説にしてみます。青空文庫にあるエドガー・アラン・ポー「モルグ街の殺人」605_ruby_20933.zip)をダウンロードします。

 

ダウンロードしたテキストファイルをプログラムに適切に読ませるために、前処理を行うプログラムです。実行すると、テキストファイルの形式(Shift-JIS)で読み込み、改行ルビ入力者注などを削除してから、 UTF-8に変換して、data.txt という名前で保存します。

あとはエディターを使い、文章の前後にある余分な部分や、文中に出て来る注の(1)〜(19)や、空白等を手動で削除します。容量は101KBでした。

 

プログラムを改造します

今回、改造するプログラムは、lstm_text_generation.py  です。

プログラムの冒頭〜データセット作成までの部分です。8行目に、形態素解析ライブラリー janome を追加します。19〜22行目コメントアウトし、24〜36行目追加します。まず、24行目でテキストを分かち書きをして下記の様に text をリスト形式にしています。

text = [ ‘分析’, ‘的’, ‘な’, ‘もの’, ‘として’, ‘論じ’, ‘られ’, ‘て’, ‘いる’,  … ]

30行目から分かち書きされた単語を順次辞書(char_indices)に登録して行きます。登録が完了したら、36行目で、逆引き辞書(indices_char)を辞書から作成します。それそれの辞書は、下記の様なイメージになります。

char_indices = { ‘分析’: 0, ‘的’: 1, ‘な’: 2, ‘もの’: 3, ‘として’: 4, ‘論じ’: 5, ‘られ’: 6, ‘て’: 7, ‘いる’: 8,   …  }

indices_char = { 0: ‘分析’, 1: ‘的’, 2: ‘な’, 3: ‘もの’, 4: ‘として’, 5: ‘論じ’, 6: ‘られ’, 7: ‘て’, 8: ‘いる’,   …  }

39−40行目は、データセット作成の設定で、5つの連続した単語(maxlen = 5)から次の単語を予測し、1つづつ(step = 1 )スライドしながらデータセットを作成する設定にします。43−45行目で、5つの連続した単語sentences に、次の単語next_char に順次格納して行きます。その結果以下の様なイメージになります、

sentences = [ [‘分析’, ‘的’, ‘な’, ‘もの’, ‘として’],  [‘的’, ‘な’, ‘もの’, ‘として’, ‘論じ’],  [‘な’, ‘もの’, ‘として’, ‘論じ’, ‘られ’], … ]

next_char = [  ‘論じ’, ‘られ’, ‘て’, ‘いる’,  …  ]

後は、文字単位の場合と一緒で、辞書を使ってワンホットベクトルに変換する部分に渡せばOKです。

 

プログラムの中盤から最後までの部分です。8行目の start_index = 0 は、毎回テキストの最初の5単語から( ‘ 分析的なものとして’ から)、文章生成をさせる設定です。9行目diversity0.2 のみ使用することにしています。

15、19行目は、” ” . join(sentence)  でリストを文字列に変換しています。元は、1文字単位の文章生成プログラムなので、 sentence 文字列だったわけですが、分かち書きをした影響で sentence がリストになったため、リストから文字列に戻す必要があるわけです。

35行目sentenceリストなので、next_char の結合は append を使います。

 

プログラム全体を載せておきます。

 

プログラムを動かします

コーパス101KB程度なので、普通のノートパソコンでも動きます。私のMacbookAirでは、220sec / epoch60epoch 動かすのに約3.7時間掛かりました。プログラムを実行すると、スクリーン表示が以下の様に自動的に進んで行きます。

まず、コーパスの文字数(corpus length)は 33539文字と表示されます。その後、分かち書きした単語に数字を振って辞書に登録し、登録した内容を逐次表示します。

 

登録した単語数は2671個でした。5つの連続した単語から次の単語を予測するデータセット(nb_sequences)は、20971個作成されました。

 

1 epoch 終了する毎に、’ 分析的なものとして’ に続く文章を400字自動生成します。これは、学習を始めたばかりの段階で、「その人の声」ばかり言っていますね(笑)。

 

学習がかなり進んだ状態です。まだ文章としての意味は良く分からないものが多いですが、なんとなく論理立てて推理を展開しようとするイメージは伝わって来ます。文体は、確かにエドガー・アラン・ポーですね。

いやー、それにしても、自然言語処理(NLP)は面白いですね。

では、また。