前回作成したプログラムの課題
[前回の記事(https://www.itd-blog.jp/entry/5W1H-AI-2)の実行結果3では、2つの誤検知が発生していました。
一つ目は固有名詞である"北多摩病院"を一語として捉えられず誤判定を起こしていて、二つ目は "診てもらいに"のようなWhy要素を分類できていませんでした。
課題の解決策
この課題の解決策として、病院や学校などの前に地名のつく可能性のある語は、抽出する前に統合するようにします。
Why要素となる語の後につく語のパターンを洗いだすと、下記の通りです。
* 接続助詞のパターン: ~ので、~から
* 助詞のパターン: ~に(目的)
接続助詞: ~て( 確定の順接)の場合は前後の動詞と連結します。
抽出器の改良
以下のように固有名詞と接続助詞"~て"によって接続される動詞を連結してから抽出することで精度が向上しました。
以下は、単語を接続するプログラムです。
python import MeCab mecab = MeCab.Tagger ('-d /usr/local/lib/mecab/dic/mecab-ipadic-neologd') #特徴的パターン d = ['病院', '大学'] #Whereのパターン i = ['日','時','今日','昨日'] #Whenのパターン dare = ['が','は'] #Whoの後に続く助詞 nani = ['を','に'] #Whatの後に続く助詞 words = [] poss = [] text = '私は医者に診てもらいに北多摩病院に明日行く' mecab.parse('')#文字列がGCされるのを防ぐ node = mecab.parseToNode(text) while node: #単語を取得 word = node.surface words.append(word) #文字をスタック #品詞を取得 pos = node.feature.split(",") poss.append(pos) #品詞をスタック node = node.next words2 = [] poss2 = [] num = 0 for w in words: if poss[num][2] == '地域': for c in d: if (c in words[num+1]) and (num != len(words)): sw = [w,words[num+1]]; words2.append(sw) poss2.append(poss[num]) words.pop(num+1) poss.pop(num+1) break elif num != 0 and poss[num][1] == '接続助詞' and poss[num-1][0] == '動詞' and poss[num+1][0] == '動詞' : sw = [words[num-1],words[num], words[num+1]]; words2.pop(num-1) words2.append(sw) poss2.pop(num-1) poss2.append(poss[num-1]) words.pop(num+1) poss.pop(num+1) else: words2.append(w) poss2.append(poss[num]) num += 1
実行結果
(入力: '私は医者に診てもらいに北多摩病院に明日行く')
単語
品詞
下記プログラムで5W1Hを抽出します。
python #特徴的パターン d = ['病院', '大学'] #Whereのパターン i = ['日','時','今日','昨日'] #Whenのパターン dare = ['が','は'] #Whoの後に続く助詞 nani = ['を','に'] #Whatの後に続く助詞 naze =['ので','から']#Whyの後に続く接続助詞 num = 0 for w in words2: for c in dare: if poss2[num][0] == '助詞' and w == c and poss2[num-1][0] == '名詞': #続く助詞がWhoの後に続くものの場合 print('{0} , Who'.format(words2[num-1])) for c in nani: if poss2[num][0] == '助詞' and w == 'に' and poss2[num-1][0] == '名詞' and poss2[num-1][1] == '一般': #続く助詞がWhatの後に続くものの場合 sw = [words2[num-1], w] print('{0} , What'.format(sw)) for c in i: if (c in w): print('{0} , When'.format(w)) if poss2[num][0] == '助詞' and w == 'に' and poss2[num-1][0] == '動詞': #続く助詞がWhyの後に続くものの場合 sw = [words2[num-1], w] print('{0} , Why'.format(sw)) for c in naze: if poss2[num][1] == '接続助詞' and w == c and poss2[num-1][0] == '動詞': #続く助詞がWhyの後に続くものの場合 sw = [words2[num-1], w] print('{0} , Why'.format(sw)) if poss2[num][2] == '地域': print('{0} , Where'.format(words2[num])) num += 1
実行結果:
連結し、まとめて出力することができました。
おわりに
考慮できていないパターン("~したい"など)やHowについては次回以降検討していきます。