はじめまして、ルーターのアズマインと申します。今日は漢文系言語 x 形態素解析についてご紹介したいと思います。

形態素解析とは

機械学習で文章を扱うとき形態素解析は欠かせない作業です。コンピューターは数字しか扱えないため、人間が読める言語を数字に変換しなければいけません。そしてこの文字列を数字に変換作業の過程で文章を「形態素」(言語で意味を持つ最小単位)の列に分割する必要があります。

例えば以下の文章があるとします。

私は台所で料理をします

この文章を

["私", "は", "台所", "で", "料理", "し", "ます"]

に直す作業を形態素解析といいます。

漢文系言語特有の問題

日本語は英語と違ってスペースなどを使って単語を区切らないため、単語の境界を定めることは難しいのです。 英文用の形態素解析ツールはスペースやカンマで文章を区切れるけど和文には応用できません。janomeやMeCabなどの既存のライブラリーを活用して形態素解析を自動化するのもいいですが、SNSからスクレイピングした文字列には絵文字、辞書に載っていない流行語、特殊文字も含まれます。これらを排除して辞書に載っている単語だけ使用してコンピューターに学習させても良いですが、排除した情報にも価値があるときもあります。少なくとも前述のライブラリーが使用しているアルゴリズムの中身を知って損はありません。

実装方法

開発環境 python 3.5.2

ソースコード:

#有効な文字の境目
combos = []
#1000文字以上の文字列の場合上限を上げても良い
leastcommacount = 1000
leastcommaindex = -1

#辞書(対応したい単語を記入)
word_dictionary = set(["あ", "い", "う", "え", "お", "私", "は", "台所", "で", "料理", "し", "ます"])

#word単語が辞書にあるのかを確認。ない場合はエラーを挙げる
def check_dictionary(word):
  if(not (word in word_dictionary)):
    raise Exception

#形態解析メソッド
def breakwords(word):
  #再帰メソッドでもグローバル変数をアクセスできるようにする
  global leastcommacount
  global leastcommaindex

  #有効な単語を発見するまでwordを一文字ずつ読み込む
  try:
    commaindex = word.rindex(",")
    word_copy = check_dictionary(word[commaindex+1:])
    already_transformed = word[:commaindex+1]
  except:
    word_copy = word[0:]
    already_transformed = ""

  #文章の最後までたどり着いた場合
  if(len(word_copy) == 0):
    combos.append(word)
    commacount = word.count(",")
    #最良単語の境目を更新
    if(commacount <= leastcommacount):
      leastcommacount = commacount
      leastcommaindex = len(combos) - 1

  else:
    #辿りつかなかった場合
    transformed_word = ""
    #単語を区切ったあと残りの文字列を次のスタックに委託
    for i,character in enumerate(word_copy):
      transformed_word+=character
      if(d.check(transformed_word)):
        send_word = already_transformed + word_copy[:i+1] + "," + word_copy[i+1:]
        breakwords(send_word)

#文章を入力
breakwords("私は台所で料理します")
#最良文字区切りを取り出す
bestwords = combos[leastcommaindex][:-1].split(",")
print(bestwords)

出力:

私,は,台所,で,料理,し,ます

最後に

いかがだったでしょうか。@memoizeをメソッドの冒頭に付けば動的計画法になり、もっと素早く計算できます。もちろんword_dictionaryに他の単語や絵文字などを入力したり外部の辞書からも単語を調べるメソッドをcheck_dictionaryに導入することで対応している単語数を増やすこともできます。

Pocket