クラス分類器の不確実性推定
Overview
あるテストポイントに対して、クラス分類器が出力する予測クラスだけでなく、その予測がどのくらい確かなのかを知りたいことがよくあります。scikit-learnでは、クラス分類器の予測に対する不確実性推定機能があります。
Coding(Classification)
scikit-learnには、クラス分類器の不確実性推定に利用できる関数が2つあります。decision_functionとpredict_proba関数です。scikit-learnのクラス分類器のほとんどは少なくともどちらかを実装しています。
合成2次元データセットを勾配ブースティングで分類した際の決定関数(Decision Function)の動作を確認する
2クラス分類の場合、decision_functionの結果の配列は(n_samples,)の形になり、サンプルごとに1つの浮動小数点が返されます。陽性であるとモデルが信じている度合いがエンコードされています。
code: Python
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.datasets import make_circles
X, y = make_circles(noise=0.25, factor=0.5, random_state=1)
# わかりやすいようにクラスを'blue'と'red'にする
# train_test_splitは任意の数の配列に適用できる
X_train, X_test, y_train_named, y_test_named, y_train, y_test = train_test_split(X, y_named, y, random_state=0)
# 勾配ブースティングモデルを構築
gbrt = GradientBoostingClassifier(random_state=0)
gbrt.fit(X_train, y_train_named)
print('X_test.shape: {}'.format(X_test.shape))
print('Decision function shape: {}\n'.format(gbrt.decision_function(X_test).shape))
# 正の値であれば陽性クラス、負の値であれば陰性クラスを返す
# 陽性であるとモデルが信じている度合いがエンコードされている
print('Decision function:\n{}\n'.format(gbrt.decision_function(X_test):6)) # 決定関数の返り値の符号だけみれば、予測クラスがわかる
print('Thresholded decision function:\n', gbrt.decision_function(X_test) > 0)
print('Predictions:\n', gbrt.predict(X_test), '\n')
# 2クラス分類では、「陰性」クラスがclasses_属性の第一エントリに、「陽性」クラスが第2エントリになる
# True/Falseを0/1に変換
greater_zero = (gbrt.decision_function(X_test) > 0).astype(int)
# 0/1をクラスのインデックスに使う
# predはgbrt.predictの出力と同じになる
print('pred is equal to predictions:', np.all(pred == gbrt.predict(X_test)))
--------------------------------------------------------------------------
X_test.shape: (25, 2)
Decision function shape: (25,)
Decision function:
Thresholded decision function:
[ True False False False True True False True True True False True
True False True False False False True True True True True False
False]
Predictions:
['red' 'blue' 'blue' 'blue' 'red' 'red' 'blue' 'red' 'red' 'red' 'blue'
'red' 'red' 'blue' 'red' 'blue' 'blue' 'blue' 'red' 'red' 'red' 'red'
'red' 'blue' 'blue']
pred is equal to predictions: True
--------------------------------------------------------------------------
decision_function関数の結果は、どのようなスケールで表示されるかわからないので、解釈が難しいです。
合成2次元データセットを勾配ブースティングで分類した際の確率の予測(Predict Probabilities)をする
predict_probaの出力は、それぞれのクラスに属する確率で、decision_functionの出力よりも理解しやすいです。出力配列の形は、2クラス分類では、常に(n_samples, 2)になります。
code: Python
print('Shape of probabilities: {}'.format(gbrt.predict_proba(X_test).shape))
# 各行の第1エントリは第1クラスの予測確率で、第2エントリは第2クラスの予測確率
# 確率なので、predict_probaの出力は常に0から1であり、双方の和は常に1になっている
print('Predicted probabilities:\n{}'.format(gbrt.predict_proba(X_test:6))) --------------------------------------------------------------------------
Shape of probabilities: (25, 2)
Predicted probabilities:
--------------------------------------------------------------------------
このクラス分類器は多くの点について比較的確信度が高いことがわかります。過剰適合したモデルは、間違っている場合でさえ、高い確率で予測する傾向にあり、複雑さが低いモデルの予測は、確信度が低いです。あるモデルが報告する確信度が、実際の正答率と一致している場合、較正されているといいます。
Advanced
多クラス分類の不確実性
decision_function関数とpredict_proba関数は、多クラス分類に対しても利用できます。3クラス分類問題である、irisデータセットに適用してみます。
code: Python
from sklearn.datasets import load_iris
iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=42)
gbrt = GradientBoostingClassifier(learning_rate=0.01, random_state=0)
gbrt.fit(X_train, y_train)
print('Decision function shape: {}'.format(gbrt.decision_function(X_test).shape))
print('Decision function:\n{}'.format(gbrt.decision_function(X_test):6, :)) --------------------------------------------------------------------------
Decision function shape: (38, 3)
Decision function:
--------------------------------------------------------------------------
多クラス分類では、decision_functionの結果は、(n_samples, n_classes)の形の配列になります。大きいとそのクラスである確率が高くなります。各データポイントに対して、各進度スコアが最大になるクラスを選ぶことで予測クラスが得られます。
code: python
print('Argmax of decision function: {}'.format(np.argmax(gbrt.decision_function(X_test), axis=1)))
print('Predictions: {}'.format(gbrt.predict(X_test)))
--------------------------------------------------------------------------
Argmax of decision function: [1 0 2 1 1 0 1 2 1 1 2 0 0 0 0 1 2 1 1 2 0 2 0 2 2 2 2 2 0 0 0 0 1 0 0 2 1
0]
Predictions: [1 0 2 1 1 0 1 2 1 1 2 0 0 0 0 1 2 1 1 2 0 2 0 2 2 2 2 2 0 0 0 0 1 0 0 2 1
0]
--------------------------------------------------------------------------
predict_probaの出力も、同じ(n_samples, n_classes)の形の配列となります。各クラスになる確率の和は1となります。
code: Python
print('Predicted probabilities: {}'.format(gbrt.predict_proba(X_test):6)) print('Sums: {}'.format(gbrt.predict_proba(X_test):6.sum(axis=1))) --------------------------------------------------------------------------
--------------------------------------------------------------------------
predict_probaのargmaxを取ることで、予測クラスを再現します。
code: Python
print('Argmax of predicted probabilities: {}'.format(np.argmax(gbrt.predict_proba(X_test), axis=1)))
print('Predictions: {}'.format(gbrt.predict(X_test)))
--------------------------------------------------------------------------
Argmax of predicted probabilities: [1 0 2 1 1 0 1 2 1 1 2 0 0 0 0 1 2 1 1 2 0 2 0 2 2 2 2 2 0 0 0 0 1 0 0 2 1
0]
Predictions: [1 0 2 1 1 0 1 2 1 1 2 0 0 0 0 1 2 1 1 2 0 2 0 2 2 2 2 2 0 0 0 0 1 0 0 2 1
0]
--------------------------------------------------------------------------
Summary
まとめると、decision_functionとpredict_probaの結果は(n_samples, n_classes)の形の配列になりますが、2クラス分類の場合のdecision_functionだけが例外です。2クラス分類の場合のdecision_functionには「陽性」クラスであるclasses_[1]に対応する1列しかありません。