すべてのチャレンジ
中級 0件解決済み 正答率0%

ナイーブベイズ分類器

ベイズの定理とラプラス平滑化で、カテゴリ型の特徴量からクラスを予測します。

このチャレンジで学べること

  • クラスの事前確率と尤度を計算する
  • 未知の特徴量の値を平滑化する
  • 最も確率の高いクラスを選ぶ

問題

原文(英語)を表示

ナイーブベイズは、クラスが与えられたとき特徴量どうしは独立だと仮定し、スコアが最も高いクラスを選びます。

score(c) = P(c) × P(x₁ | c) × P(x₂ | c) × … × P(xₙ | c)

特徴量は整数で符号化されたカテゴリです。確率は学習データから推定します。

  • P(c) = (クラス c のサンプル数) / (サンプル数)
  • P(xⱼ = v | c) = (クラス c のうち特徴量 j が v のサンプル数 + 1) / (クラス c のサンプル数 + Kⱼ)

ここで Kⱼ は、学習サンプルとクエリに現れる特徴量 j の異なる値の数です。+1(ラプラス平滑化)により、見たことのない値でスコアが 0 になるのを防ぎます。

スコアが最も高いクラスを返してください。同点なら小さいほうのクラスを返します。小さな確率をたくさん掛けるとアンダーフローするので、代わりに対数を足してください。

naive_bayes_predict(features, labels, query) を実装してください。

入力

features: 学習サンプルごとに n 個のカテゴリ型特徴量の行。

labels: 各学習サンプルのクラス。

query: 分類するサンプルの n 個の特徴量。

出力

予測したクラスを返してください。

制約

1 ≤ サンプル数 ≤ 1,000、1 ≤ n ≤ 20

0 ≤ 各特徴量の値とラベル ≤ 100

例

例 1
入力:
query = [0, 1]
labels = [1, 1, 0, 0, 1]
features = [
    [0, 1],
    [0, 0],
    [1, 1],
    [1, 0],
    [0, 1]
]

期待される出力:
expected = 1
入力:
std::vector<long long> query = {0, 1};
std::vector<long long> labels = {1, 1, 0, 0, 1};
std::vector<std::vector<long long>> features = {
    {0, 1},
    {0, 0},
    {1, 1},
    {1, 0},
    {0, 1}
};

期待される出力:
long long expected = 1;
入力:
long[] query = new long[] {0, 1};
long[] labels = new long[] {1, 1, 0, 0, 1};
long[][] features = new long[][] {
    new long[] {0, 1},
    new long[] {0, 0},
    new long[] {1, 1},
    new long[] {1, 0},
    new long[] {0, 1}
};

期待される出力:
long expected = 1;

解説

クラス 1 は 3 サンプル、クラス 0 は 2 サンプルです。特徴量1の値は {0, 1}(K = 2)、特徴量2は {0, 1}(K = 2)。score(1) = 3/5 × (3+1)/(3+2) × (2+1)/(3+2) = 0.6 × 0.8 × 0.6 = 0.288。score(0) = 2/5 × (0+1)/(2+2) × (1+1)/(2+2) = 0.4 × 0.25 × 0.5 = 0.05。クラス 1 の勝ちです。

例 2
入力:
query = [2]
labels = [0, 0, 1]
features = [
    [0],
    [0],
    [1]
]

期待される出力:
expected = 0
入力:
std::vector<long long> query = {2};
std::vector<long long> labels = {0, 0, 1};
std::vector<std::vector<long long>> features = {
    {0},
    {0},
    {1}
};

期待される出力:
long long expected = 0;
入力:
long[] query = new long[] {2};
long[] labels = new long[] {0, 0, 1};
long[][] features = new long[][] {
    new long[] {0},
    new long[] {0},
    new long[] {1}
};

期待される出力:
long expected = 0;

解説

値 2 は一度も現れないので、K = 3(値 0、1、2)。score(0) = 2/3 × (0+1)/(2+3) ≈ 0.133、score(1) = 1/3 × (0+1)/(1+3) ≈ 0.083。平滑化のおかげでどちらも 0 にならず、より多いクラス 0 が勝ちます。

参考資料

この課題はCodeUtility用に調整されています。上記の説明と制約に従ってください。

他の人の解答から学ぶ

コミュニティの解答

まだ公開された解答がありません。この課題を解いて最初の解答を共有しましょう。