問題
エントロピーはラベル集合の不確かさを測ります:H(S) = -Σ pₖ × log₂(pₖ)。pₖ はクラス k のラベルの割合です。情報利得は、集合を特徴量で分割したときにエントロピーがどれだけ下がるかです。
IG = H(labels) - Σ (|Sᵥ| / |S|) × H(Sᵥ)
ここで Sᵥ は、特徴量が v であるサンプルのラベルです。決定木は情報利得が最も高い特徴量を選びます。
information_gain(feature, labels) を実装してください。
入力
feature: 各サンプルの特徴量の値。
labels: 各サンプルのクラスラベル(同じ長さ)。
出力
情報利得をビット単位の小数で返してください。
制約
1 ≤ 長さ ≤ 10,000
各値とラベルは 1 〜 20 文字
例
入力:
labels = ["no", "no", "yes", "yes"]
feature = ["sunny", "sunny", "rain", "rain"]
期待される出力:
expected = 1.0
入力:
std::vector<std::string> labels = {"no", "no", "yes", "yes"};
std::vector<std::string> feature = {"sunny", "sunny", "rain", "rain"};
期待される出力:
double expected = 1.0;
入力:
string[] labels = new string[] {"no", "no", "yes", "yes"};
string[] feature = new string[] {"sunny", "sunny", "rain", "rain"};
期待される出力:
double expected = 1.0;
解説
ラベルは半分が yes、半分が no なので H = 1 ビット。天気で分割すると純粋な2グループ(それぞれ H = 0)になるので、利得は 1 - 0 = 1 です。この特徴量ですべてがわかります。
入力:
labels = ["yes", "yes", "no", "no"]
feature = ["a", "b", "a", "b"]
期待される出力:
expected = 0.0
入力:
std::vector<std::string> labels = {"yes", "yes", "no", "no"};
std::vector<std::string> feature = {"a", "b", "a", "b"};
期待される出力:
double expected = 0.0;
入力:
string[] labels = new string[] {"yes", "yes", "no", "no"};
string[] feature = new string[] {"a", "b", "a", "b"};
期待される出力:
double expected = 0.0;
解説
グループ a と b はどちらも yes と no を1つずつ含む(H = 1)ので、残りは 0.5 × 1 + 0.5 × 1 = 1、利得は 1 - 1 = 0 です。この特徴量は役に立ちません。
参考資料
この課題はCodeUtility用に調整されています。上記の説明と制約に従ってください。