HOME >> Pythonをさわってみよう > 機械学習の実感 文章の自動生成
機械学習の実感 文章の自動生成
今、機械学習の実感をつかむため、教本のChapter4 「日本語の文章を生成しよう」に挑戦しています。今回はその後半であるマルコフ連鎖用の辞書データを使って文章を自動生成する方法について、まとめておきます。
■ 文章の自動生成方法
今回も、自分なりに理解したロジックをイラストにまとめてみました。

文章の作成は、単語をつなげた文字列を作ればよいのです。 この時、単語をつなげていく指針は単語の状態遷移図を使います。そして、分岐点では先回の報告にて作成したマルコフ連鎖用の辞書のデータにもとずいた選択確率に従って、ランダムに単語を選択しながら文字列をつなげていけば良いのです。文章の分解作業の逆を実施していくのである。
■ 実際のプログラムの内容
ここでは、Pythonの学習のために、教本に示された内容を追って行こう。 内容は、「Lesson 32 マルコフ連鎖で文章自動生成しましょう」を実施していきます。この本では、各ステップでのプログラムの記述の後に、その結果としての出力をプリントアウトしているので、プログラムの実行内容を理解することが出来ます。わかりやすいですね。
●ステップ4:
文章の自動生成の前に、最初の単語をランダムに選択するため、単語の出現回数のデータを作成する。

- 使用する元データは、先回実施した three_words_count のリストを使います。
- 使用するライブラリーは、collection モジュールの defaultdict クラスをインポートする。このクラスを使用するとキーが存在しない場合の初期値を指定でき、よりシンプルなプログラムが書けるとのことである。int を指定すると初期値にゼロが入るのだ。
- 3単語組のうち、BEGIN で始まる組のだけを選び、その中の2番目の単語 three_words[1] の出現回数をカウントします。
●ステップ5:
最初の単語の出現回数のデータをランダムチョイスで処理できるようにデータを変換する。

- ステップ4で作成した単語の出現回数のデータをもとに、最初の単語のリストとその重みのリストを作成する。
- 1行目から10行目によって get_first_word_weights 関数を作成する。
- 3行目、 three_words_count を使って関数 get_first_word_and_count (ステップ4)により、辞書データ first_word_count を作ります。
- 4、5行目、単語と重みを書き込むリストを作る。
- 6〜8行目、作成された辞書データ first_word_count の中のキーと値のセットを取り出し、単語リストと重みリストに追加していきます。
- 12行目、関数を実行して作られたリストを、最初の単語のリストとその重みのリストとする。
- 即ち、{'おいしい':2, 'ビール':1} という辞書データから、['おいしい', 'ビール']と [2, 1] という2種類のリストが得られたことになります。
●ステップ6:
最後に文章の生成関数を作成し、文章の生成を実行します。

- 1行目、ランダムに要素を取り出すため、random をインポートする。
- 3行目〜、generate_text 関数を作成する。
- 5行目、最初の単語( first_word )を、ランダム(ただし、重みあり)に取り出すため random.choices() 関数を使用する。最初の単語のリスト first_words 即ち、リスト['おいしい', 'ビール']の中の単語を、重みとして first_weghts 即ち、リスト[2, 1] の重みデータの従って、ランダムに選択する。
- 6行目、文字列生成用の単語を格納するリストを作る。最初の単語は、BEGIN で、次の単語は first_word として文字列を作る。
- 7〜14行目、break されるまで繰り返し実行する。
- 8行目、作成された文字列( 最初は6行目で作られたもの)の最後の2つの単語を pair とする。 でも、なぜタプルにするの?
- 9、10行目、この2つの単語を元に、marov_dict から、次の単語のリストとその重みを取得する。 ここで辞書が出てきたのだ。
- 11行目、次の単語のリストとその重みにより、重みありランダムにて、次の単語 next_word を選択する。
- 12、13行目、ここで END が選択されると処理は完了なので、繰り返しループがら離脱する。
- 14行目、 次の単語 next_word を文字列に追加して、繰り返しループに戻る。
- 16行目、最初の単語 BEGIN は役目が終わったので、2番目以降のリストを文字の無いデータ(半角スペースなども無い)を使って結合する。すると一つの文字列文章として完成させることができた
- 「7」の1行目、range() で指定した回数だけループを回す。即ち、ここでは5個の文章を作れという命令となる。
- 2、3行目、generate_text 関数を使って文章を生成し、プリントアウトする。
■ まとめ
目的とする「文章の自動生成」のプログラムを理解することが出来ました。そのロジックも、なるほどと感心する内容であった。
また、最初のイラストに示した出力例では、20個の文章を出力させましたが、元となる文章が、ほぼ同じ割合で生成されていることが分かります。さらに、元となる文章とは異なるようなものが一つも出現していないことにも注目をしたい。
突然 ”生ビールは一番搾りだ!” との文章は出てこないのである。
これは、機械学習、即ち AI の限界のような気がします。 発想の転換を図るようなことは起こらないのである。ロジックを振り返っても、そのようなことが起こりえないことが理解できますが、最近のディープラーニングの世界ではどうなんでしょうか?
いろいろな元データを数多く覚え込ませれば、ガチャガチャ・ポン!で意外な組み合わせができるかも知れません。その組み合わせの意外さに気が付き、新しい発想のもとになれば効果的ですが、そこにはやはり人間の判断力が必要となりますね。
***********************************************************
そして、次なるステップとして、機械学習の元となる文章を増やしたりして、マルコフ連鎖用の辞書のデータがどのように変化するのか、生成される文章はどのように変わるかを簡単な実験を実施して理解を深めたいと思います。実験屋の悪いクセ(?)ですが・・・・・・・・。