実践型AIプログラミング特講#20

実践型AIプログラミング特講#20

前回までは言語に対して分類的なアプローチをしてきましたが今回は言語を逆に自動生成するアルゴリズムの構築をしてみましょう。言語生成は人間が作成したリストから適宜条件に合わせて適した意味の言語を機械が選定するプロセスのことで、そのようなアルゴリズムもパッケージを用いることで簡単に実装することができます。ぜひ皆様も本記事を学んで機械に文章作成をさせてみましょう。

前回の記事をご覧になっていない方々はこちらをご覧ください。

自然言語処理自動作文に挑戦しよう

これまでの節では、入力された文章を理解(形態素解析)することに焦点が置かれてきました。そこで本節では、文章を作成することに挑戦してみましょう。具体的には、マルコフ連鎖という手法を用いて行います。

マルコフ連鎖について

マルコフ連鎖とは、未来の状態が現在の状態のみで決まる(過去の状態とは無関係である)という性質を持つ確率過程のことです。つまり、n個の状態({s1, s2, s3, ,, .. S(n)})が存在し、現在の状態 s()に対し、次の状態 s() に遷移する確率は、P(s()\s())で決定します(未来の状態が現在の状態のみで決まるということです)このマルコフ連鎖を利用すると、既存の文章を利用し、自動で文章を生成することができます。そこで、マルコフ連鎖を利用した作文の仕組みについて見ていきましょう。マルコフ連鎖による作文の仕組みについてマルコフ連鎖を使った自動作文は、大きく分けて3つのステップで行います。

(1) 入力された文章を単語に分解する(形態素解析を行う)

(2) 辞書を作成する

(3) 始点となる単語と辞書を使って、作文する

(1)ついては、前回において説明済みですので、ここでは (2) (3) について詳しく見てみましょう。

マルコフ連鎖の辞書は、文章を構成する各単語について前後の結びつきを登録します。わかりやすくするために具体例で考えましょう。

たとえば、「天気について教えて。」という文章が入力されたとしましょう。形態素解析した結果は以下の通りとなります。

天気 について 教え て 。

マルコフ連鎖の辞書は、各単語に関して、前後の結びつきに注目して、3単語ずつ登録していきます。

そして、この辞書が作文をするための知識となります。始点となる単語と辞書を使って作文するでは次に、作文する方法について見てみましょう。方法は比較的シンプルで、辞書に登録されている同じ組み合わせを持つ単語をランダムに選択してつなげていきます。こちらも、わかりやすくするために具体例で考えましょう。たとえば、以下の文章を登録した場合について、考えてみましょう。

魚 を 買う 。

魚 は 好き 。

魚 は 綺麗 。

真珠 は 綺麗 で 高い 。

この形態素解析の結果をマルコフ連鎖の辞書に登録すると、以下のような辞書となります。

そして、始点となる単語を「魚」とするとしましょう。そうすると「魚」につながる単語は、「魚」は」になります。次に、「魚」は」につながる単語は「好き」と「縞麗」になります。ここでは、ランダムに「椅麗」を選んだとしましょう。さらに、「は|椅麗」につながる単語は「で」となり、この作業を繰り返すと、結果として「魚は締麗で高い。」という文章を生成することができます。

マルコフ連鎖を利用して自動作文に挑戦してみよう

それではさっそく、マルコフ連鎖を利用して自動作文に挑戦してみましょう。まずは、Jupyter Notebook で新規ノートブックを作りましょう。画面右上の[New> Python 3] で新規ノートブックを作成します。そして、以下のプログラムを記述しましょう。

import MeCab

import os,json,random

dict_file =”markov_dict.json”

dic ={}

# 辞書への登録(*1)

def regist_dic(wordlist):

global dic

w1 =””

w2 =””

# 要素が3未満の場合は、何もしない

if len (wordlist) < 3 : return

for w in wordlist :

word = w[0]

if word == “” or word == “\r\n” or word == “\n” : continue

 

 

# 辞書に単語を設定

if w1 and w2 :

set_dic(dic,w1, w2, word)

# 文末を表す語の場合、連鎖をクリアする

If word== “。” or word == “?” or  word == “ ? ”:

w1=””

w2=””

continue

# 次の前後関係を登録するために、単語をスライド

w1, w2 =w2, word

# 辞書を保存

json.dump(dic, open(dict_file, “w”, encoding=”utf-8″))

# 応答文の作成(* 2)

def set_dic(dic, w1, w2, w3):

# 新しい単語の場合は、新しい辞書オブジェクトを作成

if w1 not in dic : dic[w1] = {}

if w2 not in dic [w1] : dic [w1] [w2] ={}

if w3 not in dic [w1] [w2]: dic[w1] [w2] [w3] = 0

# 単語の出現数をインクリメントする

dic [w1] [w2] [w3] += 1

# メイン処理(* 3)

def make_response (word):

res =[]

#「名詞」/「形容詞」/「動詞」は、文章の意図を示していることが多いと想定し、始点の単語とする

w1 = word

res.append (w1)

word_choice (dic [w1])

res.append (w2)

while True:

# w1,w2 の組み合わせから予想される単語を選択

if wi in dic and w2 in dic[w1] : w3 = word_choice (dic [w1] [w2])

else : w3 =””

res.append (w3)

# 文末を表す語の場合、作文を終了

if w3 == “。”or w3 == “?” or w3 ==”” : break

# 次の単語を選択するために、単語をスライド

w1, w2 = w2, w3

return “”.join(res)

def word_choice(candidate):

keys = candidate.keys ()

return random.choice(list(keys))

 

# 辞書がすでに存在する場合は、最初に読み込む

if os.path.exists (dict_file):

dic = json.load (open(dict_file,”r”))

# 標準入力から入力を受け付け、「さようなら」が入力されるまで続ける

while True:

text =input (“You -> “)

if text == “”or text ==”さようなら”:

print (“Bot -> “さようなら “)

break

文章整形

if text [-1] !== “. ” and text[-1] != “?” and text[-1] != ” ?” : text +=”。”

# 形態素解析

Tagger = MeCab.Tagger (“-d /var/lib/mecab/dic/mecab-ipadic-neologd”)

tagger.parse (“”)

node =tagger.parseToNode(text)

# 形態素解析の結果から、単語と品詞情報を抽出

wordlist=[]

while node is not None:

hinshi =node.feature.split(“,”) [0]

if hinnsi not in [“BOS/EOS”]:

wordlist.append ([node.surface,hinshi])

node = node.next

# マルコフ連鎖の辞書に登録

regist_dic(wordlist)

# 応答文の作成

for w in wordlist:

word = w [0]

hinnsi= w[1]

# 品詞が「感動詞」の場合は、単語をそのまま返す

if hinshi in [ “感動詞 “] :

print (“Bot -> ” + word)

break

# 品詞が「名詞」「形容詞」「動詞」の場合で、かつ、辞書に単語が存在する場合は、作文して返す

elif (hinshi in [ “感動詞,“”形容詞”,”動詞”]) and (word in dic):

print (“Bot -> ” + make_response (word))

break

では、Jupyter Notebook からプログラムを実行してみましょう。Run ボタンを押すと、結果が表示されます。

最初は、会話が噛み合わないことも多々ありますが、しばらく続けていると少しずつそれらしい会話ができるようになってくるのではないでしょうか。それでは、プログラムを確認してみましょう(※1)の部分では、形態素解析した結果の単語リストの内容をマルコフ連鎖の辞書へ登録し、外部ファイルとして保存しています。外部ファイルに保存することで、辞書の内容を蓄積して、自動作文器を育てることができるようにしています。辞書への登録の部分を少し詳しく見てみましょう。たとえば、先ほどと同様、「天気について教えて。」という文章が入力された場合、形態素解析した結果は以下の通りでした

天気 について 教え て 。

そのためこのとき、for 文は5回ループすることになりますが、その際の w1,w2,word 変数の変化は以下の通りです。

(※2)の部分では、作成した辞書と始点となる単語から、応答文を作成しています。応答文の作成についても詳しく見てみましょう。たとえば、上記の辞書を利用し、「天気」というキ語を始点とした応答文を作るとしましょう。このとき、while 文における w1,w2,w3,res 変数の変化は以下の通りです。

(※3)の部分が、メイン処理となっています。標準入力から文章を受け取ったのち、形態素解析を行います。次に、これまで見てきたメソッドを使って、辞書への登録、応答文の作成を行なっています。応答文については、品詞が「感動詞」の場合にはそのまま返し、品詞が「名詞」「形容詞」「動詞」で辞書に登録されている場合には、その単語を始点に応答文を作成するようにしています。このように、マルコフ連鎖を利用して、自動作文ができました。ただし、マルコフ連鎖では単語の選択に関して、意味や構文を考えて選択するわけではないので、作文の質を高めるにはさまざまな改善を行う必要があるでしょう。

応用のヒント

紙面の都合上、複雑なロジックを作ることはできませんでしたが、応用箇所はたくさんあることでしょう。たとえば、応答文を作成する場合、ここでは単語の品詞に注目し、始点となる単語を決めていますが、機械学習により文章の意図を判定し、その結果を始点に応答文を作成するなら、今回のようなおうむ返しのような返答ではなく、もう少し実際の会話に近い応答を返すことが可能でしょう。さらに、辞書を充実させたり、会話の規則を作ったりすることもできます。マルコフ連鎖以外に目を向けると、ディープラーニングを用いた LSTM (Long Short Term-Memory) や RNN(Recurrent NeuralNetwork) も文章を自動生成する手法として有名なため、それらの手法を利用して自動作文に挑戦してみることもできるでしょう。

column

・オープンなテキストリソース

自然言語処理を実践する際には、ある程度の規模を持ったテキストリソースが必須となります。しかし、自分でテキストデータを用意するのはたいヘんな労力が必要です。インターネット上には、多くの有益なテキストリソースがオープンな形で公開されているので、それを利用すると良いでしょう。ここでは、そうした有益なリソースを提供している Web サイトを紹介します。

Wikipedia (ウィキペディア)

Wikipedia は世界最大のフリーの百科事典です。ゆえに膨大なテキストデータが存在します。ただし、ライセンスはクリエイティブ·コモンズ表示·継承ライセンス「CC-BY-SA 3.0」なので、完全な著作権フリーではありません。

[URL] https://ja.wikipedia.org/

著作権の消滅した作品、あるいはクリエイティブ·コモンズの元で多くの作品が公開されています。著作権の消滅した作品であれば、パブリックドメイン(public domain)となっており、知的財産権が発生しないので、かなり自由に利用できます。問題は、作者の死後50年/70年経過した作品なので、文章自体が古いことです。

[URL] http://www.aozora.gr.jp/

livedoor ニュースコーパス

クリエイティブ·コモンズライセンスが適用される livedoor のニュース記事を収集したものです。残念ながら、2012年で契約が切れてしまったそうで、2012年までのデータとなっていますが、提供媒体ごとにニュース記事がしっかりと分類されています。文字コードが UTF-8 で統一されたテキストファイルで提供されているので、プログラムから扱いやすいデータとなっています。

[URL] http://www.rondhuit.com/download.html#1dc

基本語ドメイン辞書 (KNBC)

京都大学と NTTの共同研究の成果が公開されたもので、4テーマ(京都観光、携帯電話、スポーツ、グルメ)、249記事、4,186文の解析済みブログコーパスがあります。テキストデータだけでなく、形態素解析済みのデータや、係り受けの対応データなど、アノテーション済みのデータが公開されています。

[URL] http://nlp.ist.i.kyoto-u.ac.jp/kuntt/

  • 京都大学ウェブ文書リードコーパス

Web 文書のリード(冒頭)3文に対して、各種言語情報を人手で付与したテキストコーパスです。多様なジャンル、文体の文書、約5,000 文書からリード文を集めたものです。

(URL] http://nlp.ist.i.kyoto-u.ac.jp/index.php?KWDLC

この節のまとめ

マルコフ連鎖を利用すると自動作文を行える

マルコフ連鎖では既存の文章を知識として蓄え、起点となる単語からランダムに語句をつなげて文章を作成する

 

プログラミングカテゴリの最新記事