現在の課題
現在の課題は、連用形の場合を考慮できないこと(「〜する人」などの場合「〜する」をHowとしてしまう)です。
つまり、修飾語を区別できていません。
この問題に対し、係り受け解析を行うことで解決できないかどうかを検討しました。
係り受け解析
係り受け解析器というのは文章を形態素に分けた後に、単語間の修飾関係を解析することです。 たとえば、以下のような文章があるとします。 僕のランチ代はおおよそ200円でした。 僕の → ランチ代は ランチ代は → 200円でした。 おおよそ → 200円でした。 と修飾されます。
https://sitest.jp/blog/?p=11912 より引用
係り受け解析を行えるフリーソフトとしてCaboCha(南瓜)があります。 こちらを参考にインストールして実際に係り受け解析を行うと、下記の通りになります。
検討方針
抽出前に形態素解析と係り受け解析を行い、係り受け解析による修飾関係をもとに分類が難しい要素(HowやWhat, Why)を正しく分類する方法を検討します。
CaboChaAnalyzerのセットアップ
pythonで係り受け解析器CaboChaを扱いやすくするラッパーライブラリがあったので導入します。
https://github.com/kenkov/cabocha/blob/master/README.rst
このライブラリでは、下記のようにCaboChaAnalyzerに文を入力するとトークンと呼ばれる言葉の最小単位に分けることができます。
ruby:python from cabocha.analyzer import CaboChaAnalyzer analyzer = CaboChaAnalyzer() tree = analyzer.parse("日本語の形態素解析はすごい")
実行結果: Token("日本語") Token("の") Token("形態素") Token("解析") Token("は") Token("すごい")
トークンよりも一つ大きい単位となるのがチャンクです(例,"日本語の")。 下記のようにすることで、あるチャンクの係り受け先かどうかがわかります。
ruby:python chunks = tree.chunks start_chunk = chunks[0] start_chunk.next_link
実行結果: Chunk("形態素解析は")
この場合、「日本語の」の係り受け先が「形態素解析は」であることを表しています。
また、下記のようにすることでチャンクの係り元がわかります。
ruby:python end_chunk = chunks[-1] end_chunk.prev_links
実行結果: [Chunk("形態素解析は")]
ここで、実際の音声認識による文章を入力した時に問題が生じました。
入力: "混雑が始まりましたjr各社によりますと"
このように、文で区切られていない入力をすると「始まりました」の係り受け先はないはずですが、
「jr各社に」が係り受け先として抽出されてしまいました。
これは結果的にHow要素の抽出の精度を下げることになってしまうので、この方法では連体形を正しく見分けることができない可能性が高いです。
ただし、一文一文を区切ることができれば有効だと思われます。
精度向上
前回 → 今回 ((回避How)するためにWhat) → (回避するためにWhat) 痩せ子(さんのことをWhat) → (痩せ子さんのことをWhat) つきたくないんで → (つきたくないWhy)んで
ruby:python #特徴的パターン #特徴的パターン d = ['病院', '大学'] #Whereのパターン dare = ['が','は'] #Whoの後に続く助詞 nani = ['を','に'] #Whatの後に続く助詞 naze =['だから', 'それで', 'そのため', 'このため', 'そこで', 'したがって', 'ゆえに', 'それゆえに','から','んで']#Whyの後に続く接続助詞 suji = ['0','1','2','3','4','5','6','7','8','9'] itu1 = ['今日','昨日','明日','午前','午後','明後日','本日','年末'] #Whenのパターン1 itu2 = ['年','月','日'] #Whenのパターン2 words2 = [] poss2 = [] itu3 = ''.join(itu1) num = len(words)-1 while num > -1: ##Where# if poss[num-1][2] == '地域' : #一つ先を探索 words.insert(num,'Where)') words.insert(num-1,', (') #### ##When## for c in itu1: if c in words[num-1]: #一つ先を探索 words.insert(num,'When)') words.insert(num-1,', (') num -= 1 for c in itu2: if (c in words[num-1]) and poss[num-1][1]=='固有名詞': for s in suji: if s in words[num-1] : words.insert(num,'When)') words.insert(num-1,', (') num -= 1 #### ##Why## for c in naze: if words[num] == c: #続く助詞がWhyの後に続くものの場合 words.insert(num,'Why)') while num > 0: if (poss[num][0] =='名詞' and poss[num][1] != '非自立' and poss[num][1] != '接尾') or (poss[num][1] == '自立' and poss[num][6] != 'する' and poss[num][6] != 'なる'): break num -= 1 words.insert(num,', (') #### ##Who## for c in dare: if poss[num][0] == '助詞' and words[num] == c: #続く助詞がWhoの後に続くものの場合 words.insert(num,'Who)') while num > 0: if (poss[num][0] =='名詞' and poss[num][1] != '非自立' and poss[num][1] != '接尾') or (poss[num][1] == '自立' and poss[num][6] != 'する' and poss[num][6] != 'なる'): break num -= 1 words.insert(num,', (') #### ##How## if poss[num][1] == '自立' and poss[num][5] == '基本形': words.insert(num+1,'How)') if poss[num][6] == 'する' or poss[num][6] == 'なる': num -= 1 words.insert(num,', (') elif poss[num][1] == '接尾' and poss[num][5] == '基本形': words.insert(num+1,'How)') num -= 2 words.insert(num,', (') #print('{0} , How'.format(sw)) elif poss[num][0] == '助動詞' and poss[num][5] == '基本形': sw =[] words.insert(num+1,'How)') num -= 1 while num > 0: if (poss[num][0] =='名詞' and poss[num][1] != '非自立') or (poss[num][1] == '自立' and poss[num][6] != 'する' and poss[num][6] != 'なる'): break num -= 1 if words[num] == 'ん': while num>0: num -=1 if (poss[num][0] =='名詞' and poss[num][1] != '非自立') or (poss[num][1] == '自立' and poss[num][6] != 'する' and poss[num][6] != 'なる'): break words.insert(num,', (') #### ##What## elif poss[num][2] == '引用': #続く助詞がWhatの後に続くものの場合2 words.insert(num+1,'What)') while num>0: num -=1 if (poss[num][0] =='名詞' and poss[num][1] != '非自立' and poss[num][1] != '接尾') or (poss[num][1] == '自立' and poss[num][6] != 'する' and poss[num][6] != 'なる'): break words.insert(num,'(') for c in nani: if poss[num][0] == '助詞' and words[num] == c: #続く助詞がWhatの後に続くものの場合1 words.insert(num+1,'What)') while num>0: num -= 1 if (poss[num][0] =='名詞' and poss[num][1] != '非自立' and poss[num][1] != '接尾') or (poss[num][1] == '自立' and poss[num][6] != 'する' and poss[num][6] != 'なる'): break words.insert(num,'(') # num += 1 else: num -= 1
次回の予定
係り受け解析は少し保留にし、助詞などを手がかりとして精度の向上を検討していきます。