Изменения

Перейти к: навигация, поиск
Precison-recall кривая
Поскольку с точки зрения логики задачи нам важнее правильно распознать некредитоспособного заёмщика с меткой <math>y = 1 </math>, чем ошибиться в распознавании кредитоспособного, будем называть соответствующий исход классификации положительным (заёмщик некредитоспособен), а противоположный - отрицательным (заемщик кредитоспособен <math>y = 0 </math>). Тогда возможны следующие исходы классификации:
* Некредитоспособный заёмщик классифицирован как некредитоспособный, т.е. положительный класс распознан как положительный. Наблюдения, для которых это имеет место называются '''истинно-положительными''' ('''true positiveTrue Positive''' {{---}} '''TP''').* Кредитоспособный заёмщик классифицирован как кредитоспособный, т.е. отрицательный класс распознан как отрицательный. Наблюдения, которых это имеет место, называются '''истинно отрицательными''' ('''true negativeTrue Negative''' {{---}} '''TN''').* Кредитоспособный заёмщик классифицирован как некредитоспособный, т.е. имела место ошибка, в результате которой отрицательный класс был распознан как положительный. Наблюдения, для которых был получен такой исход классификации, называются '''ложно-положительными''' ('''false positiveFalse Positive''' {{---}} '''FP'''), а ошибка классификации называется '''ошибкой I рода'''.* Некредитоспособный заёмщик распознан как кредитоспособный, т.е. имела место ошибка, в результате которой положительный класс был распознан как отрицательный. Наблюдения, для которых был получен такой исход классификации, называются '''ложно-отрицательными''' ('''false negativeFalse Negative''' {{---}} '''FN'''), а ошибка классификации называется '''ошибкой II рода'''.
Таким образом, ошибка I рода, или ложно-положительный исход классификации, имеет место, когда отрицательное наблюдение распознано моделью как положительное. Ошибкой II рода, или ложно-отрицательным исходом классификации, называют случай, когда положительное наблюдение распознано как отрицательное. Поясним это с помощью матрицы ошибок классификации:
[[Файл:Confusion_matrix.png{|500px]]class="wikitable" style="text-align: center"||<math>y = 1</math>|<math>y = 0</math>|-|<math>a ( x ) = 1</math>|Истинно-положительный ('''True Positive — TP''')|Ложно-положительный ('''False Positive — FP''')|-|<math>a ( x ) = 0</math>|Ложно-отрицательный ('''False Negative — FN''')|Истинно-отрицательный ('''True Negative — TN''')|}
Здесь <math>a ( x )</math> — это ответ алгоритма на объекте, а <math>y </math> — истинная метка класса на этом объекте.
<font color="green"># код для матрицы ошибок</font>
<font color="green">'''# Пример классификатора, способного проводить различие между всего лишь двумя</font> <font color="green">'''# классами, "пятерка" и "не пятерка" из набор данных набора рукописных цифр MNIST</font>
'''import''' numpy '''as''' np
'''from''' sklearn.datasets '''import''' fetch_openml
y = y.astype(np.uint8)
X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000], y[60000:]
y_train_5 = (y_train == 5) <font color="green"># True для всех пятерок, False для в сех остальных цифр. Задача опознать пятерки</font>
y_test_5 = (y_test == 5)
sgd_clf = SGDClassifier(random_state=42) <font color="green"> #классификатор на основе метода стохастического градиентного спуска (англ. Stochastic Gradient Descent SGD)</font> sgd_clf.fit(X_train, y_train_5) <font color="green">#обучаем классификатор распозновать пятерки на целом обучающем наборе</font> <font color="green"># Для расчета матрицы ошибок сначала понадобится иметь набор прогнозов, чтобы их можно было сравнивать с фактическими целями # Можно получить прогнозы и на тестовом наборе. Но мы пока тестовый набор не трогаем. Тестовый набор используем только в самом конце проекта # после того, как будет готов классификатор, готовый кзапуску</font>
y_train_pred = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3)
print(confusion_matrix(y_train_5, y_train_pred))
<font color="green"># array([[53892, 687], # [ 1891, 3530]])</font>
Безупречный классификатор имел бы только истинно-поло­жительные и истинно отрицательные классификации, так что его матрица ошибок содержала бы ненулевые значения только на своей главной диа­гонали (от левого верхнего до правого нижнего угла):
y = y.astype(np.uint8)
X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000], y[60000:]
y_train_5 = (y_train == 5) <font color="green"># True для всех пятерок, False для в сех остальных цифр. Задача опознать пятерки</font>
y_test_5 = (y_test == 5)
y_train_perfect_predictions = y_train_5 <font color="green"># притворись, что мы достигли совершенства</font>
print(confusion_matrix(y_train_5, y_train_perfect_predictions))
<font color="green"># array([[54579, 0], # [ 0, 5421]])</font>
=== Аккуратность (англ. Accuracy) ===
<font color="green"># код для для подсчета аккуратности:</font>
<font color="green">'''# Пример классификатора, способного проводить различие между всего лишь двумя '''# классами, "пятерка" и "не пятерка" из набор данных набора рукописных цифр MNIST</font>
'''import''' numpy '''as''' np
'''from''' sklearn.datasets '''import''' fetch_openml
y = y.astype(np.uint8)
X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000], y[60000:]
y_train_5 = (y_train == 5) <font color="green"> # True для всех пятерок, False для в сех остальных цифр. Задача опознать пятерки</font>
y_test_5 = (y_test == 5)
sgd_clf = SGDClassifier(random_state=42) <font color="green">#классификатор на основе метода стохастического градиентного спуска (Stochastic Gradient Descent SGD)</font> sgd_clf.fit(X_train, y_train_5) <font color="green">#обучаем классификатор распозновать пятерки на целом обучающем наборе</font>
y_train_pred = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3)
<font color="green"># print(confusion_matrix(y_train_5, y_train_pred))
# array([[53892, 687]
# [ 1891, 3530]])</font> print(accuracy_score(y_train_5, y_train_pred)) <font color="green"> # == (53892 + 3530) / (53892 + 3530 + 1891 +687)</font>
<font color="green"># 0.9570333333333333</font>
=== Точность (англ. Precision) ===
Результирующая точность классификатора рассчитывается как арифметическое среднее его точности по всем классам. То же самое с полнотой. Технически этот подход называется '''macro-averaging'''.
<font color="green"># код для для подсчета точности и полноты:</font>
'''# Пример классификатора, способного проводить различие между всего лишь двумя
'''# классами, "пятерка" и "не пятерка" из набор данных набора рукописных цифр MNIST</font>
'''import''' numpy '''as''' np
'''from''' sklearn.datasets '''import''' fetch_openml
y = y.astype(np.uint8)
X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000], y[60000:]
y_train_5 = (y_train == 5) <font color="green"># True для всех пятерок, False для в сех остальных цифр. Задача опознать пятерки</font>
y_test_5 = (y_test == 5)
sgd_clf = SGDClassifier(random_state=42) <font color="green"> #классификатор на основе метода стохастического градиентного спуска (Stochastic Gradient Descent SGD)</font> sgd_clf.fit(X_train, y_train_5) <font color="green">#обучаем классификатор распозновать пятерки на целом обучающем наборе</font>
y_train_pred = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3)
<font color="green"># print(confusion_matrix(y_train_5, y_train_pred))
# array([[53892, 687]
# [ 1891, 3530]])</font> print(precision_score(y_train_5, y_train_pred)) <font color="green"># == 3530 / (3530 + 687)</font> print(recall_score(y_train_5, y_train_pred)) <font color="green"># == 3530 / (3530 + 1891)</font>
<font color="green"># 0.8370879772350012 # 0.6511713705958311</font>
=== F-мера (англ. F-score) ===
''F-мера'' является хорошим кандидатом на формальную метрику оценки качества классификатора. Она сводит к одному числу две других основополагающих метрики: точность и полноту. Имея "F-меру" гораздо проще ответить на вопрос: "поменялся алгоритм в лучшую сторону или нет?"
<font color="green"># код для подсчета метрики F-mera:</font>
'''# Пример классификатора, способного проводить различие между всего лишь двумя
'''# классами, "пятерка" и "не пятерка" из набор данных набора рукописных цифр MNIST</font>
'''import''' numpy '''as''' np
'''from''' sklearn.datasets '''import''' fetch_openml
y = y.astype(np.uint8)
X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000], y[60000:]
y_train_5 = (y_train == 5) <font color="green"> # True для всех пятерок, False для в сех остальных цифр. Задача опознать пятерки</font>
y_test_5 = (y_test == 5)
sgd_clf = SGDClassifier(random_state=42) <font color="green"> #классификатор на основе метода стохастического градиентного спуска (Stochastic Gradient Descent SGD)</font> sgd_clf.fit(X_train, y_train_5) <font color="green">#обучаем классификатор распознавать пятерки на целом обучающем наборе</font>
y_train_pred = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3)
print(f1_score(y_train_5, y_train_pred))
<font color="green"># 0.7325171197343846</font>
=== ROC-кривая ===
Один из способов сравнения классификаторов предусматривает измере­ние '''площади под кривой''' (англ. '''Area Under the Curve {{---}} AUC'''). Безупречный клас­сификатор будет иметь площадь под ROC-кривой ('''ROC-AUC'''), равную 1, тогда как чисто случайный классификатор - площадь 0.5.
<font color="green"># Код отрисовки ROC-кривой</font>
'''# На примере классификатора, способного проводить различие между всего лишь двумя классами
'''# "пятерка" и "не пятерка" из набор данных набора рукописных цифр MNIST</font>
'''from''' sklearn.metrics '''import''' roc_curve
'''import''' matplotlib.pyplot '''as''' plt
y = y.astype(np.uint8)
X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000], y[60000:]
y_train_5 = (y_train == 5) <font color="green"># True для всех пятерок, False для в сех остальных цифр. Задача опознать пятерки</font>
y_test_5 = (y_test == 5)
sgd_clf = SGDClassifier(random_state=42) <font color="green">#классификатор на основе метода стохастического градиентного спуска (Stochastic Gradient Descent SGD)</font> sgd_clf.fit(X_train, y_train_5) <font color="green">#обучаем классификатор распозновать пятерки на целом обучающем наборе</font>
y_train_pred = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3)
y_scores = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3, method="decision_function")
[[Файл:PR_curve.png]]
<font color="green"># Код отрисовки Precison-recall кривой</font>
'''# На примере классификатора, способного проводить различие между всего лишь двумя классами
'''# "пятерка" и "не пятерка" из набор данных набора рукописных цифр MNIST</font>
'''from''' sklearn.metrics '''import''' precision_recall_curve
'''import''' matplotlib.pyplot '''as''' plt
y = y.astype(np.uint8)
X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000], y[60000:]
y_train_5 = (y_train == 5) <font color="green"># True для всех пятерок, False для в сех остальных цифр. Задача опознать пятерки</font>
y_test_5 = (y_test == 5)
sgd_clf = SGDClassifier(random_state=42) <font color="green"> #классификатор на основе метода стохастического градиентного спуска (Stochastic Gradient Descent SGD)</font> sgd_clf.fit(X_train, y_train_5) <font color="green">#обучаем классификатор распозновать пятерки на целом обучающем наборе</font>
y_train_pred = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3)
y_scores = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3, method="decision_function")
</math>
Примерно такая же проблема, как и в MAPE: так как каждое отклонение возводится в квадрат, любое небольшое отклонение может значительно повлиять на показатель ошибки. Стоит отметить, что существует также ошибка MSE, из которой RMSE как раз и получается путем извлечения корня. Но так как MSE дает расчетные единицы измерения в квадрате, то использовать данную ошибку будет немного неправильно.
=== Cимметричная MAPE (англ. Symmetric MAPE, SMAPE) ===
''MASE'' является очень хорошим вариантом для расчета точности, так как сама ошибка не зависит от масштабов данных и является симметричной: то есть положительные и отрицательные отклонения от факта рассматриваются в равной степени.
Обратите внимание, что в ''MASE'' мы имеем дело с двумя суммами: та, что в числителе, соответствует тестовой выборке, та, что в знаменателе - обучающей. Вторая фактически представляет собой среднюю абсолютную ошибку прогноза по методу Naive. Она же соответствует среднему абсолютному отклонению ряда в первых разностях. Эта величина, по сути, показывает, насколько обучающая выборка предсказуема. Она может быть равна нулю только в том случае, когда все значения в обучающей выборке равны друг другу, что соответствует отсутствию каких-либо изменений в ряде данных, ситуации на практике почти невозможной. Кроме того, если ряд имеет тендецию тенденцию к росту либо снижению, его первые разности будут колебаться около некоторого фиксированного уровня. В результате этого по разным рядам с разной структурой, знаменатели будут более-менее сопоставимыми. Всё это, конечно же, является очевидными плюсами ''MASE'', так как позволяет складывать разные значения по разным рядам и получать несмещённые оценки.
Но, конечно же, без минусов нельзя. Проблема Недостаток ''MASE'' в том, что её тяжело интерпретировать. Например, ''MASE''=1.21 ни о чём, по сути, не говорит. Это просто означает, что ошибка прогноза оказалась в 1.21 раза выше среднего абсолютного отклонения ряда в первых разностях, и ничего более.
== Кросс-валидация ==
Хороший способ оценки модели предусматривает применение [[Кросс-валидация|кросс-валидации]](cкользящего контроля или перекрестной проверки). В этом случае фиксируется некоторое множество разбиений исходной выборки на две подвыборки: обучающую и контрольную. Для каждого разбиения выполняется настройка алгоритма по обучающей подвыборке, затем оценивается его средняя ошибка на объектах контрольной подвыборки. Оценкой скользящего контроля называется средняя по всем разбиениям величина ошибки на контрольных подвыборках.
== Примечания ==
# [https://www.coursera.org/lecture/vvedenie-mashinnoe-obuchenie/otsienivaniie-kachiestva-xCdqN] Лекция "Оценивание качества" на www.coursera.org
# [https://stepik.org/lesson/209691/step/8?unit=183195] Лекция на www.stepik.org о кросвалидации# [https://stepik.org/lesson/209692/step/5?unit=183196] Лекция на www.stepik.org о метриках качества, Precison и Recall# [https://stepik.org/lesson/209692/step/7?unit=183196] Лекция на www.stepik.org о метриках качества, F-мера# [https://stepik.org/lesson/209692/step/8?unit=183196] Лекция на www.stepik.org о метриках качества, примеры
== См. также ==
== Источники информации ==
# [https://compscicenter.ru/media/courses/2018-autumn/spb-recommendation/materials/lecture02-linregr_1.pdf] Соколов Е. Семинар по выбору моделейА. Лекция линейная регрессия
# [http://www.machinelearning.ru/wiki/images/5/59/PZAD2016_04_errors.pdf] - Дьяконов А. Функции ошибки / функционалы качества
# [https://forecasting.svetunkov.ru/etextbook/forecasting_toolbox/models_quality/] - Оценка качества прогнозных моделей
# [https://habr.com/ru/post/19657/] - grossu Методы оценки качества прогноза
# [http://www.machinelearning.ru/wiki/index.php?title=%D0%9A%D0%BB%D0%B0%D1%81%D1%81%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F] - К.В.Воронцов, Классификация
# [http://www.machinelearning.ru/wiki/index.php?title=CV] - К.В.Воронцов, Скользящий контроль
187
правок

Навигация