ブログ名

【第3回】5W1H抽出AI 抽出器の検討2

前回作成したプログラムの課題

[前回の記事(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

実行結果
(入力: '私は医者に診てもらいに北多摩病院に明日行く')
単語
f:id:shizuuuka0202:20200616221247p:plain

品詞
f:id:shizuuuka0202:20200616221154p:plain

下記プログラムで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

実行結果:
f:id:shizuuuka0202:20200616221107p:plain

連結し、まとめて出力することができました。

おわりに

考慮できていないパターン("~したい"など)やHowについては次回以降検討していきます。


次の記事へ

前の記事へ 戻る