ナイーブベイズについて勉強したのでざっくりまとめ

2017.12.06

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

概要

 こんにちは、データインテグレーション部のyoshimです。この記事は機械学習アドベントカレンダー6日目のものとなります。  今回は「ナイーブベイズ」という手法を説明してみようと思います。
 ナイーブベイズは「学習が高速、かつ実装が容易」といった実用性の観点から利用されることの多いアルゴリズムです。
 (より精度が高いアルゴリズムやナイーブベイズを元にした発展系も存在します)
 なお、今回のエントリーではナイーブベイズの「理論」の部分だけで、実際にやってみた例については後日公開しようと思います。

目次  

文書を単語単位に分割する

早速、「ナイーブベイズ」について説明していきたいのですが、その前に「自然言語を機械学習で扱う際によくやる前処理」について説明します。 今回の記事では、ナイーブベイズを使って「文書分類」をする例で説明しようと考えておりますので、「ナイーブベイズで扱うデータがどのような状態のデータか」ということを把握しておく必要があります。

自然言語を扱う際のデータの前処理において、文書を「n文字単位」、「単語単位」で分割するといった前処理をすることがよくあります。これらの処理が具体的にどのようなものか、というイメージは下記の通りです。

参考文: 公園まで散歩した
n文字(3文字):公園ま、園まで、まで散、で散歩、散歩し、歩した
単語単位:公園、まで、散歩、し、た

このように、特定のルールで文を分割して、処理できる状態にします。 今回の記事では、「単語単位」で文を分割した、という仮定で話を進めます。

ベイズの定理とは

続いて、「ベイズの定理」というものについて説明します。なぜかというと、今回ご紹介する「ナイーブベイズ」というアルゴリズムにはこの「ベイズの定理」というものが利用されているからです。「ベイズの定理」は一言で言うと「確率の求め方の定義」です。ここからは、一般的な確率の求め方とベイズの定理を比較することで説明していこうと思います。

事象A、事象Bが発生する確率をそれぞれP(A)、P(B)とします。
この仮定のもと、同時に起きる確率は一般的に下記の計算で求めることができます。 左辺を事象A、Bが同時に発生する確率なので、「同時確率」と呼びます。
[latex] (事象A、Bが同時に起きる確率) = (事象Aが起きる確率) * (事象Bが起きる確率) [/latex] [latex] P(A,B) = P(A) * P(B) [/latex]

これに対して、「ベイズの定理」の定義は下記の通りです。
[latex] (事象A、Bが同時に起きる確率) = (事象Aが起き、かつ事象Bが起きる確率) = (事象Bが起き、かつ事象Aが起きる確率) [/latex] [latex] P(A,B) = P(B|A) * P(A) = P(A|B) * P(B) [/latex]

「ベイズの定理」では、P(A),P(B)を事前確率、P(A|B)、P(B|A)を事後確率と呼んでいます。 「ベイズの定理」では「事前確率をどう設定するか」、という点が計算結果に大きく影響を及ぼす上に、複雑で難しいのですが、今回は「ふーん、そうなんだ。」くらいに思っていただければ大丈夫です。

ナイーブベイズとは

やっと本題の「ナイーブベイズ」のご説明です。
 ナイーブベイズは 「単純ベイズ」とも呼びます。何が単純なのか、というと「仮定を立てることで問題を単純化する」、ということです。
この「仮定」がどのような仮定なのか、ということが大事なのですがこの仮定の内容について直感的に理解することを目的として、できるだけ数式を入れないで説明しようと思います。

「文書分類」を元にして「ナイーブベイズ」を説明します。 一般的に文書中の単語間には「何らかの関係性」があるものです。
(「iphone」、「apple」、「Mac」という単語はそれぞれ同じ文書に登場する可能性が高いでしょう)
文書分類を正確にやりたいのであれば、この関係性についてもしっかり考慮する必要があるのですが、ナイーブベイズでは「単語間の関係性を考慮しない」と仮定しています。
(単語がそれぞれ独立であると仮定,とも表現します)
ナイーブベイズでは、このように仮定を単純なものに設定しているからこそ、処理内容がわかりやすく実装も容易で処理も早い、という特徴があるのです。   (ベイズ的手法を使うのならば、本来ならばもっと考えないといけないことがあるのに!(ex.事前確率等))

もう少し数学的な要素も説明すると、「単語間の関係性を考慮しない」ということは、「各クラスにおける各単語の出現確率に基づく同時確率から、文書が各クラスに所属する確率を求める」といったものになります。
例えば、ある文書を単語単位に分割した結果、単語x,y,zからなっていたとわかったとしましょう。
この時、スパムメールと判別するクラスでは単語x,y,zの出現確率がP(x),P(y),P(z)だったとします。
この条件の時、この文書がスパムメールである確率は、
[latex] P(x) * P(y) * P(z) [/latex]
で求めます。
(このように同時に発生する確率の場合、全ての確率を乗算して求めることを「確率の乗法定理に基づき」と言ったりします)

このような計算をするために、k個のクラス確率(上記のスパムメールの場合だと2個のクラス確率)と、nk個のクラスごとの単語確率をあらかじめ用意する必要があります。
(nは文書分類をする際の判別指標とする単語数。文書中の単語数とは異なります。)
(ナイーブベイズで必要なパラメータは、クラス確率とクラスごとの単語確率、と言った方がわかりやすいかもしれません...。)

この2つのパラメータの求め方は簡単です。
クラスAのクラス確率は下記の式で求まります。
[latex] (クラスAの確率)=\frac{(クラスAの文書数)}{(全クラスの文書数)} [/latex]

クラスAにおける単語Bの出現確率は下記の式で求まります。
[latex] (クラスAにおける単語Bの出現確率)=\frac{(クラスAにおいて、単語Bの出現する文書数)}{(クラスAの文書数)} [/latex]

ここまでの内容をまとめると、ナイーブベイズ法の大まかな流れは下記の通りです。
1.2つのパラメータ(クラス確率、クラスごとの単語出現確率)を計算
2.文書を「各単語の同時確率」からクラス判別する
(本来なら、データの前準備や次元削減等の処理が必要ですが、今回はナイーブベイズ法のみの説明に限定しております)

まとめ

今回は文書を多クラス分類する手法の一つである、ナイーブベイズ法についてご説明しました。
ナイーブベイズはアルゴリズムがシンプルで処理が高速なため、利用される機会が多いようです。
ただ、文書中の「単語間の関係」についての仮定があまりにもシンプルすぎるが故に、「精度が低い」と指摘されているのも事実です。
いざ、文書分類をするためのアルゴリズムは多々あるので、いざ実務で使う際は色々なアルゴリズムの特徴を把握する必要がありますが、「とりあえず文書分類をしてみて雰囲気を感じ取りたい」、という場合はナイーブベイズを試してみるのも有効だと思います。

明日は、今回ご説明した「ナイーブベイズ」について、実際にPythonで実装してみようと思います。