テーブル:
イントロ
Naive Bayes は、ベイズの定理に基づいた分類機械学習アルゴリズムです。特に感情分析、スパム検出、テキスト分類などのテキスト データを処理する場合に非常に効率的です。
このアルゴリズムは、すべてのデータセット変数が独立していると仮定しているため、「ナイーブ」と呼ばれますが、常にそうであるとは限りません。
Naive Bayes がどのように機能するかをさらに説明する前に、次のことを必ず理解してください。
## 条件付き確率
ナイーブ ベイズ アルゴリズムは、条件付き確率に基づくベイズの定理に基づいています。条件付き確率とは、イベント B がすでに発生していると仮定した場合に、イベント A が発生する確率です。
例:
カラーボールが入った瓶を 2 つ用意しましょう。
-
ジャー 1 には、青いボール 3 つ、赤いボール 2 つ、緑のボール 4 つがあります。
-
ジャー 2 には、青いボール 1 つ、赤いボール 4 つ、緑のボール 3 つがあります。
瓶の 1 つから青いボールがランダムに選択される確率を計算したいとします。
これは、Jar1 または Jar2 から青いボールが選択される確率の合計に他なりません。
ここで、Jar1 を選択したとして、青いボールを選択する確率を計算したいと思います。
最後に、青いボールを引いたとして、Jar1 が選択される確率を計算します。ここでは、次のように述べられているベイズの定理を使用します。
単純ベイズ分類
単純ベイズ分類器では、入力ベクトル X が与えられた条件付き確率を最大化するクラスを見つけたいと考えています。したがって、単純ベイズは次のように定式化できます。
ベイズの定理を使用すると、関数は次のようになります。
この公式では、クラス Ci の確率である P(Ci) を計算することは簡単であり、イベント x が発生する確率である P(x) を計算することも簡単です。
計算が難しいのは P(x|Ci) です。クラス Ci が与えられた場合のイベント x の確率。これをさらに単純化するには、すべての入力変数が独立していると仮定する必要があります。したがって、次のように書くことができます。
そして、実際には、入力変数の独立性を常に保証できるわけではないため、この分類器を「ナイーブ」と呼ぶのはこの仮定のためです。単純ベイズ分類器は次のようになります。
実際、P(x) はすべてのクラスで同じであるため、P(x) を削除することでこの定式化をさらに簡素化できます。
では、例を見てみましょう:
|天気 |時間 |曜日 |ディナー |
| ------- | -------- | --------------- | ------ |
|クリア |夕方 |週末 |料理人 |
|曇り |夜 |平日 |注文 |
|雨 |夜 |平日 |注文 |
|雨 |正午 |平日 |注文 |
|曇り |正午 |週末 |料理人 |
|クリア |夜 |週末 |料理人 |
|雪 |夕方 |週末 |注文 |
|クリア |夜 |平日 |料理人 |
|クリア |ミッドナイト |週末 |注文 |
ここには、天気、時刻、曜日という 3 つの入力変数と、人が夕食を作るか注文するかを示す 1 つのターゲット変数「夕食」を含む小さなデータセットがあります。入力 x={Clear, Evening, Weekend} のクラスを見つけたいと思います。
入力 x={Clear, Evening, Weekend} を指定して、クラス「Cooks」とクラス「Orders」の条件付き確率を計算する必要があります。予測されたクラスは、条件付き確率が最も高いクラスです。
まず、クラス「Cooks」の条件付き確率を計算します。
ここで、それぞれの条件付き確率を独自に計算します。
クラスが「Cooks」である場合の天気=「Clear」の確率は、クラスが「Cooks」の行の総数に対する、天気が「Clear」でクラスが「Cooks」の行の数です。
他の条件付き確率についても同様です。
ここで確率 P(Cooks) については、総行数に対するクラス「Cooks」の行数です。
次に、これらの確率の積を計算します。
これはクラス「Cooks」に対するものでしたが、今度はクラス「Orders」に対しても同じことを行う必要があります。
個々の確率を計算します。
そして最後に確率の積を計算します。
最後に、最も高い確率でクラス「Cooks」を選択します。
このアルゴリズムの利点と制限事項
利点:
-
非常に高速な分類器です。
-
実装は簡単です。
-
トレーニングフェーズはなく、推論のみです。
-
推論を行うために多くのデータは必要ありません。
制限事項:
- Naive Bayes は入力変数が独立していると仮定しますが、これは常に真実であるとは限りません。
- Naive Bayes はゼロ周波数問題に悩まされます。それは、入力変数にゼロ確率を割り当てる場合です。これにより、すべての条件付き確率 P(C|x) がゼロになります。これを回避するための 1 つのトリックは、すべての変数に対して最小頻度 1 ( 0 ではなく) を使用することです。
練習する
これは、例で見たのと同じデータセットのデータフレームです。
あなたのタスクは、Python を使用して Naive Bayes を自分で実装することです。
import pandas as pd
dataset = pd.DataFrame()
dataset['Weather'] = ['Clear', 'Cloudy', 'Rainy', 'Rainy', 'Cloudy', 'Clear', 'Snowy', 'Clear', 'Clear']
dataset['Time'] = ['Evening', 'Night', 'Night', 'Midday', 'Midday', 'Night', 'Evening', 'Night', 'Midnight']
dataset['Day'] = ['Weekend', 'Weekday', 'Weekday', 'Weekday', 'Weekend', 'Weekend', 'Weekend', 'Weekday', 'Weekend']
dataset['Class'] = ['Cooks', 'Orders', 'Orders', 'Orders', 'Cooks', 'Cooks', 'Orders', 'Cooks', 'Orders']
def naive_bayes(weather, time, day):
# res_dict = {class1: probability of class 1, class1: probability of class 1
return res_dict
## 解決
def naive_bayes(x_weather, x_time, x_day):
TARGET = 'Dinner' # The name of the target variable
CLASSES = list(dataset['Dinner'].unique()) # The classes of the target variable
len_dataset = len(dataset) # The length of the dataset
res_dict = {} # res_dict = {class1:probability1, ..., class_n:probability_n}
# for each class of the target classes, we calculate the it's conditional probability
for class_name in CLASSES:
# the number of lines that belong to the class "class_name"
len_c = len(dataset[ (dataset[TARGET] == class_name) ])
# the number of lines that belong to the class "class_name" and have weather="x_weather"
n_weather = len(dataset[ (dataset[TARGET] == class_name) & (dataset['Weather'] == x_weather) ])
# the number of lines that belong to the class "class_name" and have time="x_time"
n_time = len(dataset[ (dataset[TARGET] == class_name) & (dataset['Time'] == x_time) ])
# the number of lines that belong to the class "class_name" and have day="x_day"
n_day = len(dataset[ (dataset[TARGET] == class_name) & (dataset['Day'] == x_day) ])
# We calculate the conditional probability:
# P(class|x) = P(weather|class) x P(time|class) x P(day|class) x P(class)
p = (n_weather / len_c) * (n_time / len_c) * (n_day / len_c) * (len_c / len_dataset) res_dict[class_name] = p
return res_dict