言語モデルにおける未知語の扱いとスムージング

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、小澤です。

当エントリは「Machine Learning Advent Calendar 2017」の8日目のエントリです。

yoshimさんが自然言語処理系な内容を書いてくれているので、その流れに乗ってみます。 最近だと自然言語処理も機械翻訳などを中心にだいぶDeep Learningが主流になっていますが、統計的言語モデル側の話を書かせていただきます。

自然言語処理における語の並びと未知語

本アドベントカレンダーのtf-idfナイーブベイズの会で取り上げられていますが、文章に対して機械学習のアリゴズムを適用させる場合、単語などの単位に分割してそれを特徴として扱います。

 元の文章 単語
もう何も怖くない [もう, 何も, 怖く, ない]
あたしってほんとバカ [あたし, って, ほんと, バカ]
ひとりぼっちはさびしいもんな [ひとりぼっち, は, さびしい, もん, な]
わけがわからないよ [わけが, わから, ない, よ]

この単語1つ1つを列としたテーブルをつくります(本来であれば不要な品詞や頻出後を除去したり、活用形を直したりしますが、今回は割愛します)

 元の文章 もう 何も こわく ない あたし って ほんと バカ ひとりぼっち さびしい もん な  わけが わから
もう何も怖くない 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0
あたしってほんとバカ 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0
ひとりぼっちはさびしいもんな 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0
わけがわからないよ 0 0 0 1 0 0 0 0 0 0 0 0 0 1 1 1

さて、この形式の問題点としては以下の2つが挙げられます。

  • 元の文章での単語の並びの情報が失われている
  • このデータに含まれない単語を扱うことができない

これらを解決方法を考えていきます。

N-gramを単語単位で利用

さて、文章を単語に分割する際に、形態素解析の他にN-gramという方法がありました。 これは、例えばbi-gram(2-gram)であれば、

  • もう何も怖くない : もう/う何/何も/も怖/怖く/くな/ない

のように2文字ずつ分けていくような方法になります。 これを分割された単語にも適用してみます。

ナイーブベイズの回では各単語の確率P(w)に対して、

[latex] \prod P(w_i) [/latex]

を計算していました。 これを単語のbi-gramで計算すると

[latex] \prod P(w_i | w_{i-1}) [/latex]

のように、直前の単語が何であったかを含む条件付き確率となります。 これによって1つ前の単語を含めた確率の計算を行います。

N-gramであればN個前の単語まで見ることができるようになります。 これによって文章全体をみているわけではありませんが、直前の状態を加味した確率モデルを作成することが可能になります。

未知語への対応

さて、続いて未知語への対応を考えてみます。

例えば、スパムメール分類の問題なんかを考えた際には "学習に利用したデータに含まれてなかった単語"が予測対象のデータには含まれている可能性があります。 そのため、このままでは未知の単語wにたいするP(w)を計算する必要があります。

そういった未知語に対する確率をどのように扱うかがスムージングとなります。

スムージングにはいくつかの方法がありますが、今回はもっとも簡単な加算スムージングを紹介します。 その他の方法については、参考文献を記載しておきますのでそちらをご覧ください。

加算スムージング

さて、まずはすご簡単な方法である加算スムージングです。 これは、「常にちょっとだけ足してあげれば、存在しないものなんてない」方式ですw

単語wの確率P(w)を以下のように計算してやります。

[latex] P(w) = \frac{n(w) + \alpha}{C + \alpha V} [/latex]

それぞれ以下のような感じになっています。

  • n(w) : 特定の文章中の単語の出現回数
  • C : データ全体での単語の出現回数
  • V : データ全体での単語数
  • α : 加算する定数

いい感じの性能になるようにαの値を適切に設定してやります。

おわりに

今回は、単語n-gramモデルとスムージングの紹介をしました。

明日は、マルコフ連鎖について書かせていただきます。 お楽しみに!

参考文献