На этом шаге мы рассмотрим особенности вычисления и анализа такой неопределенности.
До сих пор мы говорили только об оценках неопределенности в бинарной классификации. Однако методы decision_function и predict_proba также можно применять в мультиклассовой классификации. Давайте применим их к набору данных Iris, который представляет собой пример 3-классовой классификации: =
[In 12]: 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)
[In 13]: print("Форма решающей функции: {}".format(gbrt.decision_function(X_test).shape)) # выведем первые несколько элементов решающей функции print("Решающая функция:\n{}".format(gbrt.decision_function(X_test)[:6, :])) Форма решающей функции: (38, 3) Решающая функция: [[-1.995715 0.04758267 -1.92720695] [ 0.06146394 -1.90755736 -1.92793758] [-1.99058203 -1.87637861 0.09686725] [-1.995715 0.04758267 -1.92720695] [-1.99730159 -0.13469108 -1.20341483] [ 0.06146394 -1.90755736 -1.92793758]]
В мультиклассовой классификации decision_function имеет форму (n_samples, n_classes) и каждый столбец показывает "оценку определенности" для каждого класса, где высокая оценка означает большую вероятность данного класса, а низкая оценка означает меньшую вероятность этого класса. Вы можете получить прогнозы, исходя из этих оценок, с помощью функции np.argmax. Она возвращает индекс максимального элемента массива для каждой точки данных:
[In 14]: print("Argmax решающей функции:\n{}".format( np.argmax(gbrt.decision_function(X_test), axis=1))) print("Прогнозы:\n{}".format(gbrt.predict(X_test))) Argmax решающей функции: [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] Прогнозы: [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:
[In 15]: # выведем первые несколько элементов predict_proba print("Спрогнозированные вероятности:\n{}".format(gbrt.predict_proba(X_test)[:6])) # покажем, что сумма значений в каждой строке равна 1 print("Суммы: {}".format(gbrt.predict_proba(X_test)[:6].sum(axis=1))) Спрогнозированные вероятности: [[0.10217718 0.78840034 0.10942248] [0.78347147 0.10936745 0.10716108] [0.09818072 0.11005864 0.79176065] [0.10217718 0.78840034 0.10942248] [0.10360005 0.66723901 0.22916094] [0.78347147 0.10936745 0.10716108]] Суммы: [1. 1. 1. 1. 1. 1.]
Мы вновь можем получить прогнозы, вычислив argmax для predict_proba:
[In 16]: print("Argmax спрогнозированных вероятностей:\n{}".format( np.argmax(gbrt.predict_proba(X_test), axis=1))) print("Прогнозы:\n{}".format(gbrt.predict(X_test))) Argmax спрогнозированных вероятностей: [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] Прогнозы: [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 и decision_function всегда имеют форму (n_samples, n_classes), за исключением decision_function в случае бинарной классификации. В бинарной классификации decision_function имеет только один столбец, соответствующий "положительному" классу classes_[1].
Для количества столбцов, равного n_classes, вы можете получить прогноз, вычислив argmax по столбцам. Однако будьте осторожны, если ваши классы - строки или вы используете целые числа, которые не являются последовательными и начинаются не с 0. Если вы хотите сравнить результаты, полученные с помощью predict, с результатами decision_function или predict_proba, убедитесь, что используете атрибут classes_ для получения фактических названий классов:
[In 17]: from sklearn.linear_model import LogisticRegression logreg = LogisticRegression() # представим каждое целевое значение названием класса в наборе iris named_target = iris.target_names[y_train] logreg.fit(X_train, named_target) print("уникальные классы в обучающем наборе: {}".format(logreg.classes_)) print("прогнозы: {}".format(logreg.predict(X_test)[:10])) argmax_dec_func = np.argmax(logreg.decision_function(X_test), axis=1) print("argmax решающей функции: {}".format(argmax_dec_func[:10])) print("argmax объединенный с классами_: {}".format( logreg.classes_[argmax_dec_func][:10])) уникальные классы в обучающем наборе: ['setosa' 'versicolor' 'virginica'] прогнозы: ['versicolor' 'setosa' 'virginica' 'versicolor' 'versicolor' 'setosa' 'versicolor' 'virginica' 'versicolor' 'versicolor'] argmax решающей функции: [1 0 2 1 1 0 1 2 1 1] argmax объединенный с классами_: ['versicolor' 'setosa' 'virginica' 'versicolor' 'versicolor' 'setosa' 'versicolor' 'virginica' 'versicolor' 'versicolor']
Архив блокнота со всеми вычислениями, выполненными на 74-77 шагах, можно взять здесь.
На следующем шаге мы рассмотрим выводы и перспективы.