Оценка качества в задачах классификации и регрессии — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(SMAPE, Symmetric MAPE (симметричная MAPE))
м (rollbackEdits.php mass rollback)
 
(не показаны 134 промежуточные версии 4 участников)
Строка 3: Строка 3:
 
== Оценки качества классификации ==
 
== Оценки качества классификации ==
  
=== Сonfusion matrix (матрица ошибок) ===
+
=== Матрица ошибок (англ. Сonfusion matrix) ===
  
Перед переходом к самим метрикам необходимо ввести важную концепцию для описания этих метрик в терминах ошибок классификации — [[матрица ошибок|confusion matrix]] (матрица ошибок).
+
Перед переходом к самим метрикам необходимо ввести важную концепцию для описания этих метрик в терминах ошибок классификации — confusion matrix (матрица ошибок).
 
Допустим, что у нас есть два класса <math>y = \{ 0, 1 \}</math> и алгоритм, предсказывающий принадлежность каждого объекта одному из классов.
 
Допустим, что у нас есть два класса <math>y = \{ 0, 1 \}</math> и алгоритм, предсказывающий принадлежность каждого объекта одному из классов.
 
Рассмотрим пример. Пусть банк использует систему классификации заёмщиков на кредитоспособных и некредитоспособных. При этом первым кредит выдаётся, а вторые получат отказ. Таким образом, обнаружение некредитоспособного заёмщика (<math>y = 1 </math>) можно рассматривать как "сигнал тревоги", сообщающий о возможных рисках.
 
Рассмотрим пример. Пусть банк использует систему классификации заёмщиков на кредитоспособных и некредитоспособных. При этом первым кредит выдаётся, а вторые получат отказ. Таким образом, обнаружение некредитоспособного заёмщика (<math>y = 1 </math>) можно рассматривать как "сигнал тревоги", сообщающий о возможных рисках.
Строка 18: Строка 18:
 
Поскольку с точки зрения логики задачи нам важнее правильно распознать некредитоспособного заёмщика с меткой <math>y = 1 </math>, чем ошибиться в распознавании кредитоспособного, будем называть соответствующий исход классификации положительным (заёмщик некредитоспособен), а противоположный - отрицательным (заемщик кредитоспособен <math>y = 0 </math>). Тогда возможны следующие исходы классификации:
 
Поскольку с точки зрения логики задачи нам важнее правильно распознать некредитоспособного заёмщика с меткой <math>y = 1 </math>, чем ошибиться в распознавании кредитоспособного, будем называть соответствующий исход классификации положительным (заёмщик некредитоспособен), а противоположный - отрицательным (заемщик кредитоспособен <math>y = 0 </math>). Тогда возможны следующие исходы классификации:
  
* Некредитоспособный заёмщик классифицирован как некредитоспособный, т.е. положительный класс распознан как положительный. Наблюдения, для которых это имеет место называются истинно-положительными ([[true positive]] - TP).
+
* Некредитоспособный заёмщик классифицирован как некредитоспособный, т.е. положительный класс распознан как положительный. Наблюдения, для которых это имеет место называются '''истинно-положительными''' ('''True Positive''' {{---}} '''TP''').
* Кредитоспособный заёмщик классифицирован как кредитоспособный, т.е. отрицательный класс распознан как отрицательный. Наблюдения, которых это имеет место, называются истинно отрицательными ([[true negative]] - TN).
+
* Кредитоспособный заёмщик классифицирован как кредитоспособный, т.е. отрицательный класс распознан как отрицательный. Наблюдения, которых это имеет место, называются '''истинно отрицательными''' ('''True Negative''' {{---}} '''TN''').
* Кредитоспособный заёмщик классифицирован как некредитоспособный, т.е. имела место ошибка, в результате которой отрицательный класс был распознан как положительный. Наблюдения, для которых был получен такой исход классификации, называются ложно-положительными ([[false positive]] - FP), а ошибка классификации называется ошибкой I рода.
+
* Кредитоспособный заёмщик классифицирован как некредитоспособный, т.е. имела место ошибка, в результате которой отрицательный класс был распознан как положительный. Наблюдения, для которых был получен такой исход классификации, называются '''ложно-положительными''' ('''False Positive''' {{---}} '''FP'''), а ошибка классификации называется '''ошибкой I рода'''.
* Некредитоспособный заёмщик распознан как кредитоспособный, т.е. имела место ошибка, в результате которой положительный класс был распознан как отрицательный. Наблюдения, для которых был получен такой исход классификации, называются ложно-отрицательными ([[false negative]] - FN), а ошибка классификации называется ошибкой II рода.
+
* Некредитоспособный заёмщик распознан как кредитоспособный, т.е. имела место ошибка, в результате которой положительный класс был распознан как отрицательный. Наблюдения, для которых был получен такой исход классификации, называются '''ложно-отрицательными''' ('''False Negative''' {{---}} '''FN'''), а ошибка классификации называется '''ошибкой II рода'''.
  
 
Таким образом, ошибка I рода, или ложно-положительный исход классификации, имеет место, когда отрицательное наблюдение распознано моделью как положительное. Ошибкой 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> — истинная метка класса на этом объекте.
 
Здесь <math>a ( x )</math> — это ответ алгоритма на объекте, а <math>y </math> — истинная метка класса на этом объекте.
Таким образом, ошибки классификации бывают двух видов: False Negative (FN) и False Positive (FP).
+
Таким образом, ошибки классификации бывают двух видов: '''False Negative''' ('''FN''') и '''False Positive''' ('''FP''').  
Каждая строка в матрице ошибок представляет фактический класс, а каждый столбец - спрогнозированный класс.
+
'''P''' означает что классификатор определяет класс объекта как положительный ('''N''' {{---}} отрицательный). '''T''' значит что класс предсказан правильно (соответственно '''F''' {{---}} неправильно). Каждая строка в матрице ошибок представляет спрогнозированный класс, а каждый столбец {{---}} фактический класс.
  
 
   <font color="green"># код для матрицы ошибок</font>
 
   <font color="green"># код для матрицы ошибок</font>
 +
  <font color="green">'''# Пример классификатора, способного проводить различие между всего лишь двумя</font>
 +
  <font color="green">'''# классами, "пятерка" и "не пятерка" из набора рукописных цифр MNIST</font>
 +
  '''import''' numpy '''as''' np
 +
  '''from''' sklearn.datasets '''import''' fetch_openml
 +
  '''from''' sklearn.model_selection '''import''' cross_val_predict
 
   '''from''' sklearn.metrics '''import''' confusion_matrix
 
   '''from''' sklearn.metrics '''import''' confusion_matrix
   '''import''' pandas '''as''' pd
+
   '''from''' sklearn.linear_model '''import''' SGDClassifier
   '''n = confusion_matrix(y, a) # 1-й способ
+
   mnist = fetch_openml('mnist_784', version=1)
   '''n = pd.crosstab(y, a) # 2-й способ
+
  X, y = mnist["data"], mnist["target"]
   '''# Вычисление TN, FP, FN, TP
+
  y = y.astype(np.uint8)
   '''TN, FP, FN, TP = confusion_matrix(y, a).ravel()
+
  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>
  
 +
Безупречный классификатор имел бы только истинно-поло­жительные и истинно отрицательные классификации, так что его матрица ошибок содержала бы ненулевые значения только на своей главной диа­гонали (от левого верхнего до правого нижнего угла):
  
=== Accuracy ===
+
  '''import''' numpy '''as''' np
 +
  '''from''' sklearn.datasets '''import''' fetch_openml
 +
  '''from''' sklearn.metrics '''import''' confusion_matrix
 +
  mnist = fetch_openml('mnist_784', version=1)
 +
  X, y = mnist["data"], mnist["target"]
 +
  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]] — доля правильных ответов алгоритма:
+
=== Аккуратность (англ. Accuracy) ===
  
[[Файл:acc.png|300px]]
+
Интуитивно понятной, очевидной и почти неиспользуемой метрикой является ''accuracy'' — доля правильных ответов алгоритма:
  
Эта метрика бесполезна в задачах с неравными классами, и это легко показать на примере.
+
: <math>
 +
accuracy = \dfrac{TP+TN}{TP+TN+FP+FN}
 +
</math>
 +
 
 +
Эта метрика бесполезна в задачах с неравными классами, что как вариант можно исправить с помощью [[алгоритмы сэмплирования|алгоритмов сэмплирования]] и это легко показать на примере.
  
 
Допустим, мы хотим оценить работу спам-фильтра почты. У нас есть 100 не-спам писем, 90 из которых наш классификатор определил верно (True Negative = 90, False Positive = 10), и 10 спам-писем, 5 из которых классификатор также определил верно (True Positive = 5, False Negative = 5).
 
Допустим, мы хотим оценить работу спам-фильтра почты. У нас есть 100 не-спам писем, 90 из которых наш классификатор определил верно (True Negative = 90, False Positive = 10), и 10 спам-писем, 5 из которых классификатор также определил верно (True Positive = 5, False Negative = 5).
 
Тогда accuracy:
 
Тогда accuracy:
  
[[Файл:acc1.png|300px]]
+
: <math>
 +
accuracy = \dfrac{5+90}{5+90+10+5} = 86,4
 +
</math>
  
Однако если мы просто будем предсказывать все письма как не-спам, то получим более высокую accuracy:
+
Однако если мы просто будем предсказывать все письма как не-спам, то получим более высокую ''аккуратность'':
  
[[Файл:acc2.png|300px]]
+
: <math>
 +
accuracy = \dfrac{0+100}{0+100+0+10} = 90,9
 +
</math>
  
 
При этом, наша модель совершенно не обладает никакой предсказательной силой, так как изначально мы хотели определять письма со спамом. Преодолеть это нам поможет переход с общей для всех классов метрики к отдельным показателям качества классов.
 
При этом, наша модель совершенно не обладает никакой предсказательной силой, так как изначально мы хотели определять письма со спамом. Преодолеть это нам поможет переход с общей для всех классов метрики к отдельным показателям качества классов.
  
=== Precision ===
+
  <font color="green"># код для для подсчета аккуратности:</font>
 
+
   <font color="green">'''# Пример классификатора, способного проводить различие между всего лишь двумя
Precision (точностью) называется доля правильных ответов модели в пределах класса – это доля объектов действительно принадлежащих данному классу относительно всех объектов которые система отнесла к этому классу.
+
  '''# классами, "пятерка" и "не пятерка" из набора рукописных цифр MNIST</font>
 
+
   '''import''' numpy '''as''' np
[[Файл:prec.png|250px]]
+
   '''from''' sklearn.datasets '''import''' fetch_openml
 
+
   '''from''' sklearn.model_selection '''import''' cross_val_predict
Именно введение precision не позволяет нам записывать все объекты в один класс, так как в этом случае мы получаем рост уровня False Positive.
+
   '''from''' sklearn.metrics '''import''' accuracy_score
 
+
   '''from''' sklearn.linear_model '''import''' SGDClassifier
=== Recall ===
+
  mnist = fetch_openml('mnist_784', version=1)
 
+
  X, y = mnist["data"], mnist["target"]
Recall (Полнота системы) – это доля найденных классфикатором объектов принадлежащих классу относительно всех документов этого класса в тестовой выборке.
+
  y = y.astype(np.uint8)
 
+
  X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000], y[60000:]
[[Файл:rec.png|250px]]
+
  y_train_5 = (y_train == 5)<font color="green"> # True для всех пятерок, False для в сех остальных цифр. Задача опознать пятерки</font>
 
+
  y_test_5 = (y_test == 5)
Recall демонстрирует способность алгоритма обнаруживать данный класс вообще.
+
  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>
Имея матрицу ошибок точность и полнота для каждого класса рассчитывается очень просто. Precision (точность) равняется отношению соответствующего диагонального элемента матрицы и суммы всей строки класса. Recall (полнота) – отношению диагонального элемента матрицы и суммы всего столбца класса. Формально:
+
  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))
[[Файл:macro-e.png|200px]]
+
  # array([[53892, 687]
 
+
  #        [ 1891, 3530]])</font>
Результирующая точность классификатора рассчитывается как арифметическое среднее его точности по всем классам. То же самое с полнотой. Технически этот подход называется macro-averaging.
+
  print(accuracy_score(y_train_5, y_train_pred))<font color="green"> # == (53892 + 3530) / (53892 + 3530  + 1891 +687)</font>
 
+
 
=== F-mera ===
+
  <font color="green"># 0.9570333333333333</font>
 
 
Precision и recall не зависят, в отличие от accuracy, от соотношения классов и потому применимы в условиях несбалансированных выборок.
 
Часто в реальной практике стоит задача найти оптимальный (для заказчика) баланс между этими двумя метриками. Понятно что чем выше точность и полнота, тем лучше. Но в реальной жизни максимальная точность и полнота не достижимы одновременно и приходится искать некий баланс. Поэтому, хотелось бы иметь некую метрику которая объединяла бы в себе информацию о точности и полноте нашего алгоритма. В этом случае нам будет проще принимать решение о том какую реализацию запускать в production (у кого больше тот и круче). Именно такой метрикой является F-мера.
 
 
 
F-мера представляет собой [[гармоническое среднее]] между точностью и полнотой. Она стремится к нулю, если точность или полнота стремится к нулю.
 
 
 
[[Файл:f1.png|250px]]
 
 
 
Данная формула придает одинаковый вес точности и полноте, поэтому F-мера будет падать одинаково при уменьшении и точности и полноты. Возможно рассчитать F-меру придав различный вес точности и полноте, если вы осознанно отдаете приоритет одной из этих метрик при разработке алгоритма.
 
 
 
[[Файл:f-mera.png|350px]]
 
 
 
где β принимает значения в диапазоне 0<β<1 если вы хотите отдать приоритет точности, а при β>1 приоритет отдается полноте. При β=1 формула сводится к предыдущей и вы получаете сбалансированную F-меру (также ее называют F1).
 
F-мера достигает максимума при максимальной полноте и точности, и близка к нулю, если один из аргументов близок к нулю.
 
 
 
[[Файл:fmb.png]]
 
 
 
F-мера является хорошим кандидатом на формальную метрику оценки качества классификатора. Она сводит к одному числу две других основополагающих метрики: точность и полноту. Имея в своем распоряжении подобный механизм оценки вам будет гораздо проще принять решение о том являются ли изменения в алгоритме в лучшую сторону или нет.
 
 
 
=== ROC-кривая ===
 
 
 
Receiver Operating Characteristics curve (кривая рабочих характеристик).
 
Используется для анализа поведения классификаторов при различных пороговых значениях.
 
Позволяет рассмотреть все пороговые значения для данного классификатора.
 
Показывает долю ложно положительных примеров ( FPR, false positive rate ) в сравнении с долей истинно положительных примеров ( TPR, true positive rate).
 
 
 
[[Файл:Roccurves.png|600px]]
 
[[Файл:2f.png|250px]]
 
 
 
   <font color="green"># Код отрисовки ROC-кривой</font>
 
   '''sns.set(font_scale=1.5)
 
  '''sns.set_color_codes("muted")
 
  '''plt.figure(figsize=(10, 8))
 
  '''fpr, tpr, thresholds = roc_curve(y_test, lr.predict_proba(X_test)[:,1], pos_label=1)
 
   '''lw = 2
 
  '''plt.plot(fpr, tpr, lw=lw, label='ROC curve ')
 
  '''plt.plot([0, 1], [0, 1])
 
   '''plt.xlim([0.0, 1.0])
 
  '''plt.ylim([0.0, 1.05])
 
  '''plt.xlabel('False Positive Rate')
 
   '''plt.ylabel('True Positive Rate')
 
  '''plt.title('ROC curve')
 
   '''plt.savefig("ROC.png")
 
  '''plt.show()
 
 
 
 
 
=== Precison-recall кривая ===
 
 
 
'''Чувствительность к соотношению классов.'''  
 
Рассмотрим задачу выделения математических статей из множества научных статей. Допустим, что всего имеется 1.000.100 статей, из которых лишь 100 относятся к математике. Если нам удастся построить алгоритм a(x), идеально решающий задачу, то его TPR будет равен единице, а FPR — нулю. Рассмотрим теперь плохой алгоритм, дающий положительный ответ на 95 математических и 50.000 нематематических статьях. Такой алгоритм совершенно бесполезен, но при этом имеет TPR = 0.95 и FPR = 0.05, что крайне близко к показателям идеального алгоритма.
 
Таким образом, если положительный класс существенно меньше по размеру, то AUC-ROC может давать неадекватную оценку качества работы алгоритма, поскольку измеряет долю неверно принятых объектов относительно общего числа отрицательных. Так, алгоритм b(x), помещающий 100 релевантных документов на позиции с 50.001-й по 50.101-ю, будет иметь AUC-ROC 0.95.
 
 
 
'''Precison-recall кривая.''' Избавиться от указанной проблемы с несбалансированными классами можно, перейдя от ROC-кривой к Precision-Recall кривой. Она определяется аналогично ROC-кривой, только по осям откладываются не FPR и TPR, а полнота (по оси абсцисс) и точность (по оси ординат). Критерием качества семейства алгоритмов выступает площадь под PR-кривой (AUC-PR)
 
 
 
[[Файл:pr-rec.png|600px]]
 
 
 
== Оценки качества регрессии ==
 
 
 
Наиболее типичными мерами качества в задачах регрессии являются
 
 
 
=== MSE, Mean Squared Error (средняя квадратичная ошибка) ===
 
 
 
[[Файл:mse1.png]] и
 
 
 
=== MAE, Mean Absolute Error (средняя абсолютная ошибка) ===
 
 
 
[[Файл:mae2.png]]
 
 
 
Среднеквадратичный функционал сильнее штрафует за большие отклонения по сравнению со среднеабсолютным, и поэтому более чувствителен к выбросам. При использовании любого из этих двух функционалов может быть полезно проанализировать, какие объекты вносят наибольший вклад в общую ошибку — не исключено, что на этих объектах была допущена ошибка при вычислении признаков или целевой величины.
 
 
 
Среднеквадратичная ошибка подходит для сравнения двух моделей или для контроля качества во время обучения, но не позволяет сделать выводов о том, на сколько хорошо данная модель решает задачу. Например, MSE = 10 является очень плохим показателем, если целевая переменная принимает значения от 0 до 1, и очень хорошим, если целевая переменная лежит в интервале (10000, 100000). В таких ситуациях вместо среднеквадратичной ошибки полезно использовать коэффициент детерминации, или коэффициент R 2
 
 
 
=== Коэффициент детерминации ===
 
 
 
[[Файл:determ.png]]
 
 
 
Коэффициент детерминации измеряет долю дисперсии, объясненную моделью, в общей дисперсии целевой переменной. Фактически, данная мера качества — это нормированная среднеквадратичная ошибка. Если она близка к единице, то модель хорошо объясняет данные, если же она близка к нулю, то прогнозы сопоставимы по качеству с константным предсказанием.
 
 
 
=== MAPE, Mean Absolute Percentage Error (средняя абсолютная процентная ошибка) ===
 
 
 
[[Файл:mape1.png]]
 
 
 
=== SMAPE, Symmetric MAPE (симметричная MAPE) ===
 
 
 
[[Файл:smape1.png|300px]]
 
 
 
 
 
  
 +
=== Точность (англ. Precision) ===
  
'''Проблема оценки качества в [[Кластеризация|задаче кластеризации]]''' трудноразрешима, как минимум, по двум причинам:
+
Точностью (''precision'') называется доля правильных ответов модели в пределах класса {{---}} это доля объектов действительно принадлежащих данному классу относительно всех объектов которые система отнесла к этому классу.
* [[Кластеризация#Теорема невозможности Клейнберга|Теорема невозможности Клейнберга]] {{---}} не существует оптимального алгоритма кластеризации.
 
* Многие алгоритмы кластеризации не способны определить настоящее количество кластеров в данных. Чаще всего количество кластеров подается на вход алгоритма и подбирается несколькими запусками алгоритма.
 
  
== Методы оценки качества кластеризации ==
 
'''Метод оценки качества кластеризации''' {{---}} инструментарий для количественной оценки результатов кластеризации.
 
 
Принято выделять две группы методов оценки качества кластеризации:
 
* '''Внешние''' (англ. ''Internal'') меры основаны на сравнении результата кластеризации с априори известным разделением на классы.
 
* '''Внутренние''' (англ. ''External'') меры отображают качество кластеризации только по информации в данных.
 
 
== Внешние меры оценки качества ==
 
Данные меры используют дополнительные знания о кластеризуемом множестве: распределение по кластерам, количество кластеров и т.д.
 
 
=== Обозначения ===
 
Дано множество <math>S</math> из <math>n</math> элементов, разделение на классы <math>X = \{ X_1, X_2, \ldots , X_r \}</math>, и полученное разделение на кластеры <math>Y = \{ Y_1, Y_2, \ldots , Y_s \}</math>, совпадения между <math>X</math> и <math>Y</math> могут быть отражены в таблице сопряженности <math>\left[n_{ij}\right]</math>, где каждое <math>n_{ij}</math> обозначает число объектов, входящих как в <math>X_i</math>, так и в <math>Y_j</math> : <math>n_{ij}=|X_i \cap Y_j|</math>.
 
: <math>\begin{array}{c|cccc|c}
 
{{} \atop X}\!\diagdown\!^Y &
 
Y_1&
 
Y_2&
 
\ldots&
 
Y_s&
 
\text{Sums}
 
\\
 
\hline
 
X_1&
 
n_{11}&
 
n_{12}&
 
\ldots&
 
n_{1s}&
 
a_1
 
\\
 
X_2&
 
n_{21}&
 
n_{22}&
 
\ldots&
 
n_{2s}&
 
a_2
 
\\
 
\vdots&
 
\vdots&
 
\vdots&
 
\ddots&
 
\vdots&
 
\vdots
 
\\
 
X_r&
 
n_{r1}&
 
n_{r2}&
 
\ldots&
 
n_{rs}&
 
a_r
 
\\
 
\hline
 
\text{Sums}&
 
b_1&
 
b_2&
 
\ldots&
 
b_s&
 
n
 
\end{array}</math>
 
 
Пусть <math>p_{ij} = \dfrac{ n_{ij} }{ n }, p_{i} = \dfrac{ a_{i} }{ n }, p_{j} = \dfrac{ b_{j} }{ n } </math>.
 
 
Также рассмотрим пары <math>(x_i, x_j)</math> из элементов кластеризуемого множества <math>X</math>. Подсчитаем количество пар, в которых:
 
* Элементы принадлежат одному кластеру и одному классу {{---}} <math>TP</math>
 
* Элементы принадлежат одному кластеру, но разным классам {{---}} <math>TN</math>
 
* Элементы принадлежат разным кластерам, но одному классу {{---}} <math>FP</math>
 
* Элементы принадлежат разным кластерам и разным классам {{---}} <math>FN</math>
 
 
=== Индекс Rand ===
 
Индекс Rand оценивает, насколько много из тех пар элементов, которые находились в одном классе, и тех пар элементов, которые находились в разных классах, сохранили это состояние после кластеризации алгоритмом.
 
 
: <math>
 
: <math>
Rand = \dfrac{TP+FN}{TP+TN+FP+FN}
+
Precision = \dfrac{TP}{TP+FP}
 
</math>
 
</math>
Имеет область определения от 0 до 1, где 1 {{---}} полное совпадение кластеров с заданными классами, а 0 {{---}} отсутствие совпадений.
 
  
=== Индекс Adjusted Rand ===
+
Именно введение ''precision'' не позволяет нам записывать все объекты в один класс, так как в этом случае мы получаем рост уровня ''False Positive''.
:<math>\overbrace{ARI}^\text{Adjusted Index} = \frac{ \overbrace{\sum_{ij} \binom{n_{ij}}{2}}^\text{Index} - \overbrace{[\sum_i \binom{a_i}{2} \sum_j \binom{b_j}{2}] / \binom{n}{2}}^\text{Expected Index} }{ \underbrace{\frac{1}{2} [\sum_i \binom{a_i}{2} + \sum_j \binom{b_j}{2}]}_\text{Max Index} - \underbrace{[\sum_i \binom{a_i}{2} \sum_j \binom{b_j}{2}] / \binom{n}{2}}_\text{Expected Index} }</math>
 
где <math>n_{ij}, a_i, b_j</math> {{---}} значения из таблицы сопряженности.
 
  
В отличие от обычного [[{{NAMESPACE}}:{{PAGENAME}}#Индекс_Rand|индекса Rand]], индекс Adjusted Rand может принимать отрицательные значения, если <math>Index < Expected Index</math>.
+
=== Полнота (англ. Recall) ===
  
=== Индекс Жаккара (англ. Jaccard Index) ===
+
Полнота {{---}} это доля истинно положительных классификаций. Полнота показывает, какую долю объектов, реально относящихся к положительному классу, мы предсказали верно.
Индекс Жаккара похож на [[#Индекс_Rand|Индекс Rand]], только не учитывает пары элементов находящиеся в разные классах и разных кластерах (<math>FN</math>).
 
: <math>
 
Jaccard = \dfrac{TP}{TP+TN+FP}
 
</math>
 
Имеет область определения от 0 до 1, где 1 {{---}} полное совпадение кластеров с заданными классами, а 0 {{---}} отсутствие совпадений.
 
  
=== Индекс Фоулкса – Мэллова (англ. Fowlkes-Mallows Index) ===
 
Индекс Фоулкса – Мэллова используется для определения сходства между двумя кластерами.
 
 
: <math>
 
: <math>
FM = \sqrt{ \dfrac{TP}{TP+TN} \cdot \dfrac{TP}{TP+FP} }
+
Recall = \dfrac{TP}{TP+FN}
 
</math>
 
</math>
Более высокое значение индекса означает большее сходство между кластерами. Этот индекс также хорошо работает на зашумленных данных.
 
  
=== Hubert Г statistic ===
+
Полнота (''recall'') демонстрирует способность алгоритма обнаруживать данный класс вообще.
Данная мера отражает среднее расстояние между объектами разных кластеров:
 
: <math>
 
Г = \dfrac{1}{M} \sum \limits_{i=1}^{N-1} \sum \limits_{i=i+1}^{N} P(i, j) \cdot Q(i, j),
 
</math>
 
где <math>M = n*(n-1)/2</math>, <math>P(i, j)</math> {{---}} матрица близости, а
 
: <math>Q(i, j) = \begin{cases}
 
  0, & \mbox{если x(i) и x(j) лежат в одном кластере} \\
 
  1,  & \mbox{в другом случае } \\
 
\end{cases}
 
</math>
 
Можно заметить, что два объекта влияют на <math>Г</math>, только если они находятся в разных кластерах.
 
  
Чем больше значение меры {{---}} тем лучше.
+
Имея матрицу ошибок, очень просто можно вычислить точность и полноту для каждого класса. Точность (''precision'') равняется отношению соответствующего диагонального элемента матрицы и суммы всей строки класса. Полнота (''recall'') {{---}} отношению диагонального элемента матрицы и суммы всего столбца класса. Формально:
  
=== Индекс Phi ===
 
Классическая мера корреляции между двумя переменными:
 
 
: <math>
 
: <math>
\Phi = \dfrac{ TP \times FN - TN \times FP }{ (TP + TN)(TP + FP)(FN + FP)(FN + TN) }
+
Precision_c = \dfrac{A_{c,c}}{\sum \limits_{i=1}^{n} A_{c,i}}
 
</math>
 
</math>
  
=== Minkowski Score ===
 
 
: <math>
 
: <math>
MS = \dfrac{ \sqrt{ \sum_i \binom{a_i}{2} + \sum_j \binom{b_i}{2} - 2\sum_{ij} \binom{ n_{ij} }{ 2 } } }{ \sqrt{ \sum_j \binom{b_i}{2} } }
+
Recall_c = \dfrac{A_{c,c}}{\sum \limits_{i=1}^{n} A_{i,c}}
 
</math>
 
</math>
  
=== Индекс Гудмэна-Крускала (англ. Goodman-Kruskal Index) ===
+
Результирующая точность классификатора рассчитывается как арифметическое среднее его точности по всем классам. То же самое с полнотой. Технически этот подход называется '''macro-averaging'''.
: <math>
+
 
GK = \sum_i p_i(1 - \max_j \dfrac{ p_{ij} }{ p_i })
+
  <font color="green"># код для для подсчета точности и полноты:
</math>
+
  '''# Пример классификатора, способного проводить различие между всего лишь двумя
 +
  '''# классами, "пятерка" и "не пятерка" из набора рукописных цифр MNIST</font>
 +
  '''import''' numpy '''as''' np
 +
  '''from''' sklearn.datasets '''import''' fetch_openml
 +
  '''from''' sklearn.model_selection '''import''' cross_val_predict
 +
  '''from''' sklearn.metrics '''import''' precision_score, recall_score
 +
  '''from''' sklearn.linear_model '''import''' SGDClassifier
 +
  mnist = fetch_openml('mnist_784', version=1)
 +
  X, y = mnist["data"], mnist["target"]
 +
  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>
  
=== Entropy ===
+
=== F-мера (англ. F-score) ===
Энтропия измеряет "чистоту" меток классов:
 
: <math>
 
E = - \sum_i p_i ( \sum_j \dfrac{ p_{ij} }{ p_i } log( \dfrac{ p_{ij} }{ p_i } ) )
 
</math>
 
  
Стоит отметить, что если все кластера состоят из объектов одного класса, то энтропия равна 0.
+
''Precision'' и ''recall'' не зависят, в отличие от ''accuracy'', от соотношения классов и потому применимы в условиях несбалансированных выборок.
 +
Часто в реальной практике стоит задача найти оптимальный (для заказчика) баланс между этими двумя метриками. Понятно что чем выше точность и полнота, тем лучше. Но в реальной жизни максимальная точность и полнота не достижимы одновременно и приходится искать некий баланс. Поэтому, хотелось бы иметь некую метрику которая объединяла бы в себе информацию о точности и полноте нашего алгоритма. В этом случае нам будет проще принимать решение о том какую реализацию запускать в производство (у кого больше тот и круче). Именно такой метрикой является ''F-мера''.
  
=== Purity ===
+
F-мера представляет собой [https://ru.wikipedia.org/wiki/%D0%A1%D1%80%D0%B5%D0%B4%D0%BD%D0%B5%D0%B5_%D0%B3%D0%B0%D1%80%D0%BC%D0%BE%D0%BD%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B5 гармоническое среднее] между точностью и полнотой. Она стремится к нулю, если точность или полнота стремится к нулю.
Чистота ставит в соответствие кластеру самый многочисленный в этом кластере класс.  
 
: <math>
 
P = \sum_i p_i ( \max_j \dfrac{ p_{ij} }{ p_i } )
 
</math>
 
  
Чистота находится в интервале [0, 1], причём значение = 1 отвечает оптимальной кластеризации.
+
: <math> F = \dfrac{ 2 \times precision \times recall }{ precision + recall }</math>
  
=== F-мера ===
+
Данная формула придает одинаковый вес точности и полноте, поэтому F-мера будет падать одинаково при уменьшении и точности и полноты. Возможно рассчитать ''F-меру'' придав различный вес точности и полноте, если вы осознанно отдаете приоритет одной из этих метрик при разработке алгоритма:
F-мера представляет собой гармоническое среднее между точностью (precision) и полнотой (recall).
 
: <math>
 
F = \sum_j p_j \max_i \big\lbrack 2 \dfrac{ p_{ij} }{ p_i } \dfrac{ p_{ij} }{ p_j } \big/ (\dfrac{ p_{ij} }{ p_i } + \dfrac{ p_{ij} }{ p_j }) \big\rbrack
 
</math>
 
  
=== Variation of Information ===
 
Данная мера измеряет количество информации, потерянной и полученной при переходе из одного кластера в другой.
 
 
: <math>
 
: <math>
VI = - \sum_i p_i \log p_i - \sum_i p_j log p_j - 2 \sum_i \sum_j p_{ij} \log \dfrac{ p_{ij} }{ p_i p_j }
+
F_β = \dfrac{(1+β^2) \times precision \times recall }{ (β^2 \times precision) + recall }
 
</math>
 
</math>
  
== Внутренние меры оценки качества ==
+
где <math>β</math> принимает значения в диапазоне <math>0<β<1</math> если вы хотите отдать приоритет точности, а при <math>β>1</math> приоритет отдается полноте. При <math>β=1</math> формула сводится к предыдущей и вы получаете сбалансированную F-меру (также ее называют <math>F_1</math>).
Данные меры оценивают качество структуры кластеров опираясь только непосредственно на нее, не используя внешней информации.
 
  
=== Компактность кластеров (англ. Cluster Cohesion) ===
 
Идея данного метода в том, что чем ближе друг к другу находятся объекты внутри кластеров, тем лучше разделение.
 
  
Таким образом, необходимо минимизировать внутриклассовое расстояние, например, сумму квадратов отклонений:
+
<div><ul>
: <math>
+
<li style="display: inline-block;"> [[Файл:F_balanc.jpg|thumb|none|450px|Рис.1 Сбалансированная F-мера, <math>β=1</math>]] </li>
WSS = \sum \limits_{j=1}^{M} \sum \limits_{i = 1}^{|C_j|} (x_{ij} - \overline{x_j})^2
+
<li style="display: inline-block;"> [[Файл:F_prior_Prec.jpg|thumb|none|450px|Рис.2 F-мера c приоритетом точности, <math>β^2=\dfrac{ 1 }{ 4 }</math>]] </li>
</math>, где <math>M</math> {{---}} количество кластеров.
+
<li style="display: inline-block;"> [[Файл:F_prior_Recal.jpg|thumb|none|450px|Рис.3 F-мера c приоритетом полноты, <math>β^2=2</math>]] </li>
 +
</ul></div>
  
=== Отделимость кластеров (англ. Cluster Separation) ===
+
''F-мера'' достигает максимума при максимальной полноте и точности, и близка к нулю, если один из аргументов близок к нулю.
В данном случае идея противоположная {{---}} чем дальше друг от друга находятся объекты разных кластеров, тем лучше.  
 
  
Поэтому здесь стоит задача максимизации суммы квадратов отклонений:
+
''F-мера'' является хорошим кандидатом на формальную метрику оценки качества классификатора. Она сводит к одному числу две других основополагающих метрики: точность и полноту. Имея "F-меру" гораздо проще ответить на вопрос: "поменялся алгоритм в лучшую сторону или нет?"
: <math>
 
BSS = n \cdot \sum \limits_{j=1}^{M} (\overline{x_{j}} - \overline{x})^2
 
</math>, где <math>M</math> {{---}} количество кластеров.
 
  
=== Индекс Данна (англ. Dunn Index) ===
+
  <font color="green"># код для подсчета метрики F-mera:
Индекс Данна имеет множество вариаций, оригинальная версия выглядит следующим образом:
+
  '''# Пример классификатора, способного проводить различие между всего лишь двумя
: <math>
+
  '''# классами, "пятерка" и "не пятерка" из набора рукописных цифр MNIST</font>
D(C) = \dfrac{ min_{c_k \in C} \{ min_{c_l \in C \setminus c_k} \{ \delta(c_k, c_l) \} \} }{ max_{c_k \in C} \{ \Delta(c_k) \} }
+
  '''import''' numpy '''as''' np
</math>,
+
  '''from''' sklearn.datasets '''import''' fetch_openml
где:
+
  '''from''' sklearn.model_selection '''import''' cross_val_predict
: <math>\delta</math> {{---}} межкластерное расстояние (оценка разделения), <math>\delta(c_k, c_l) = min_{x_i \in c_k, x_j \in c_l} \|x_i - x_j\|</math>,
+
  '''from''' sklearn.linear_model '''import''' SGDClassifier
: <math>\Delta(c_k)</math> {{---}} диаметр кластера (оценка сплоченности), <math>\Delta(c_k) = max_{x_i,x_j \in c_k} \|x_i - x_j\|</math>.
+
  '''from''' sklearn.metrics '''import''' f1_score
 +
  mnist = fetch_openml('mnist_784', version=1)
 +
  X, y = mnist["data"], mnist["target"]
 +
  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>
  
=== Обобщенный Индекс Данна (gD31, gD41, gD51, gD33, gD43, gD53) ===
+
=== ROC-кривая ===
Все эти вариации являются комбинациями 3 вариантов вычисления оценки разделения <math>\delta</math> и оценки компактности <math>\Delta</math>
 
  
Оценки разделения:
+
'''Кривая рабочих характеристик''' (англ. '''Receiver Operating Characteristics curve''').
: <math>\delta^3(c_k, c_l) = \dfrac{1}{|c_k| * |c_l|} \sum_{x_i \in c_k} \sum_{x_j \in c_l} \|x_i - x_j\|  </math>,
+
Используется для анализа поведения классификаторов при различных пороговых значениях.
 +
Позволяет рассмотреть все пороговые значения для данного классификатора.
 +
Показывает долю ложно положительных примеров (англ. '''false positive rate, FPR''') в сравнении с долей истинно положительных примеров (англ. '''true positive rate, TPR''').
  
: <math>\delta^4(c_k, c_l) = \|\overline{c_k} - \overline{c_l}\|  </math>,
+
[[Файл:ROC_2.png]]
  
: <math>\delta^5(c_k, c_l) = \dfrac{1}{|c_k| + |c_l|} (\sum_{x_i \in c_k} \|x_i - \overline{c_k}\| +  \sum_{x_j \in c_l} \|x_j - \overline{c_l}\|)  </math>.
+
: <math> TPR = \dfrac{TP}{TP+FN} = Recall</math>
  
Оценки компактности:
+
: <math> FPR = \dfrac{FP}{FP+TN} </math>
: <math>\Delta^1(c_k) = \Delta(c_k) </math>,
 
  
: <math>\Delta^3(c_k) = \dfrac{2}{|c_k|} \sum_{x_i \in c_k} \|x_i - \overline{c_k}\| </math>.
+
Доля '''FPR''' {{---}} это пропорция отрицательных образцов, которые были некорректно классифицированы как положительные.
  
Обобщенный индекс Данна, как и обычный, должен возрастать вместе с улучшением качества кластеризации.
+
: <math> FPR = 1 - TNR</math>,  
  
=== Индекс S_Dbw ===
+
где '''TNR''' {{---}} доля истинно отрицательных классификаций (англ. '''Тrие Negative Rate'''), пред­ставляющая собой пропорцию отрицательных образцов, которые были кор­ректно классифицированы как отрицательные.
Основан на вычислении Евклидовой нормы
 
  
: <math>\ \|x\| = (x^Tx)^(1/2) </math>
+
Доля '''TNR''' также называется '''специфичностью''' (англ. '''specificity'''). Следовательно, ROC-кривая изображает '''чувствительность''' (англ. '''seпsitivity'''), т.е. полноту, в срав­нении с разностью '''1 - specificity'''.
  
и стандартных отклонений
+
Прямая линия по диагонали представляет ROC-кривую чисто случайного классификатора. Хороший классификатор держится от указанной линии настолько далеко, насколько это
 +
возможно (стремясь к левому верхнему углу).
  
: <math> \sigma(X) = \dfrac{1}{|X|} \sum_{x_i \in X} (x_i - \overline{x}) ^ 2 </math>,
+
Один из способов сравнения классификаторов предусматривает измере­ние '''площади под кривой''' (англ. '''Area Under the Curve {{---}} AUC'''). Безупречный клас­сификатор будет иметь площадь под  ROC-кривой ('''ROC-AUC'''), равную 1, тогда как чисто случайный классификатор - площадь 0.5.
  
: <math> stdev(C) = \dfrac{1}{K}\sqrt{\sum_{c_k \in C} \|\sigma(c_k)\|} </math>.
+
  <font color="green"># Код отрисовки ROC-кривой
 +
  '''# На примере классификатора, способного проводить различие между всего лишь двумя классами
 +
  '''# "пятерка" и "не пятерка" из набора рукописных цифр MNIST</font>
 +
  '''from''' sklearn.metrics '''import''' roc_curve
 +
  '''import''' matplotlib.pyplot '''as''' plt
 +
  '''import''' numpy '''as''' np
 +
  '''from''' sklearn.datasets '''import''' fetch_openml
 +
  '''from''' sklearn.model_selection '''import''' cross_val_predict
 +
  '''from''' sklearn.linear_model '''import''' SGDClassifier
 +
  mnist = fetch_openml('mnist_784', version=1)
 +
  X, y = mnist["data"], mnist["target"]
 +
  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")
 +
  fpr, tpr, thresholds = roc_curve(y_train_5, y_scores)
 +
  def plot_roc_curve(fpr, tpr, label=None):
 +
      plt.plot(fpr, tpr, linewidth=2, label=label)
 +
      plt.plot([0, 1], [0, 1], 'k--') # dashed diagonal
 +
      plt.xlabel('False Positive Rate, FPR (1 - specificity)')
 +
      plt.ylabel('True Positive Rate, TPR (Recall)')
 +
      plt.title('ROC curve')
 +
      plt.savefig("ROC.png")
 +
  plot_roc_curve(fpr, tpr)
 +
  plt.show()
  
Сам индекс определяется формулой:
+
=== Precison-recall кривая ===
  
: <math> SDbw(C) = \dfrac{1}{K} \sum_{c_k \in C} \dfrac{\|\sigma(c_k)\|}{\|\sigma(X)\|} + \dfrac{1}{K(K-1)} \sum_{c_k \in C} \sum_{c_l \in C \setminus c_k} \dfrac{den(c_k,c_l)}{max(den(c_k),den(c_l))} </math>.
+
'''Чувствительность к соотношению классов.'''
 +
Рассмотрим задачу выделения математических статей из множества научных статей. Допустим, что всего имеется 1.000.100 статей, из которых лишь 100 относятся к математике. Если нам удастся построить алгоритм <math>a(x)</math>, идеально решающий задачу, то его TPR будет равен единице, а FPR — нулю. Рассмотрим теперь плохой алгоритм, дающий положительный ответ на 95 математических и 50.000 нематематических статьях. Такой алгоритм совершенно бесполезен, но при этом имеет TPR = 0.95 и FPR = 0.05, что крайне близко к показателям идеального алгоритма.
 +
Таким образом, если положительный класс существенно меньше по размеру, то AUC-ROC может давать неадекватную оценку качества работы алгоритма, поскольку измеряет долю неверно принятых объектов относительно общего числа отрицательных. Так, алгоритм <math>b(x)</math>, помещающий 100 релевантных документов на позиции с 50.001-й по 50.101-ю, будет иметь AUC-ROC 0.95.
  
Здесь
+
'''Precison-recall (PR) кривая.''' Избавиться от указанной проблемы с несбалансированными классами можно, перейдя от ROC-кривой к PR-кривой. Она определяется аналогично ROC-кривой, только по осям откладываются не FPR и TPR, а полнота (по оси абсцисс) и точность (по оси ординат). Критерием качества семейства алгоритмов выступает '''площадь под PR-кривой''' (англ. '''Area Under the Curve — AUC-PR''')
  
: <math> den(c_k) = \sum_{x_i \in c_k} f(x_i, \overline{c_k}) </math>,
+
[[Файл:PR_curve.png]]
  
: <math> den(c_k, c_l) = \sum_{x_i \in c_k \cup c_l} f(x_i, \dfrac{\overline{c_k} + \overline{c_l}}{2}) </math>,
+
  <font color="green"># Код отрисовки Precison-recall кривой
 +
  '''# На примере классификатора, способного проводить различие между всего лишь двумя классами
 +
  '''# "пятерка" и "не пятерка" из набора рукописных цифр MNIST</font>
 +
  '''from''' sklearn.metrics '''import''' precision_recall_curve
 +
  '''import''' matplotlib.pyplot '''as''' plt
 +
  '''import''' numpy '''as''' np
 +
  '''from''' sklearn.datasets '''import''' fetch_openml
 +
  '''from''' sklearn.model_selection '''import''' cross_val_predict
 +
  '''from''' sklearn.linear_model '''import''' SGDClassifier
 +
  mnist = fetch_openml('mnist_784', version=1)
 +
  X, y = mnist["data"], mnist["target"]
 +
  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")
 +
  precisions, recalls, thresholds = precision_recall_curve(y_train_5, y_scores)
 +
  def plot_precision_recall_vs_threshold(precisions, recalls, thresholds):
 +
      plt.plot(recalls, precisions, linewidth=2)
 +
      plt.xlabel('Recall')
 +
      plt.ylabel('Precision')
 +
      plt.title('Precision-Recall curve')
 +
      plt.savefig("Precision_Recall_curve.png")
 +
  plot_precision_recall_vs_threshold(precisions, recalls, thresholds)
 +
  plt.show()
  
: <math> f(x_i, c_k) = 0 </math>, если <math> \|x_i - \overline{c_k}\| > stdev(C) </math> и <math>1</math> в ином случае.
+
== Оценки качества регрессии ==
  
Должен снижаться с улучшением кластеризации.
+
Наиболее типичными мерами качества в задачах регрессии являются
  
=== Силуэт (англ. Silhouette) ===  
+
=== Средняя квадратичная ошибка (англ. Mean Squared Error, MSE) ===
Значение силуэта показывает, насколько объект похож на свой кластер по сравнению с другими кластерами.
 
  
Оценка для всей кластерной структуры:
+
''MSE'' применяется в ситуациях, когда нам надо подчеркнуть большие ошибки и выбрать модель, которая дает меньше больших ошибок прогноза. Грубые ошибки становятся заметнее за счет того, что ошибку прогноза мы возводим в квадрат. И модель, которая дает нам меньшее значение среднеквадратической ошибки, можно сказать, что что у этой модели меньше грубых ошибок.
: <math>
 
Sil(С) = \dfrac{1}{N} \sum_{c_k \in C} \sum_{x_i \in c_k} \dfrac{ b(x_i, c_k) - a(x_i, c_k) }{ max \{ a(x_i, c_k), b(x_i, c_k) \}  }
 
</math>,
 
где:
 
: <math>
 
a(x_i, c_k) = \dfrac{1}{|c_k|} \sum_{x_j \in c_k} \|x_i - x_j\|
 
</math> {{---}} среднее расстояние от <math>x_i \in c_k</math> до других объектов из кластера <math>c_k</math> (компактность),
 
: <math>
 
b(x_i, c_k) = min_{c_l \in C \setminus c_k } \{ \dfrac{1}{|c_l|} \sum_{x_j \in c_l} \|x_i - x_j\| \}
 
</math> {{---}} среднее расстояние от <math>x_i \in c_k</math> до объектов из другого кластера <math>c_l: k \neq l</math> (отделимость).
 
Можно заметить, что  
 
: <math> -1 \le Sil(C) \le 1
 
</math>.
 
Чем ближе данная оценка к 1, тем лучше.
 
 
 
Есть также упрощенная вариация силуэта: <math>a(x_i, c_k)</math> и <math>b(x_i, c_k)</math> вычисляются через центры кластеров.
 
  
=== Индекс Calinski–Harabasz ===
 
 
: <math>
 
: <math>
CH(C) = \dfrac{ N-K }{ K-1 } \cdot \dfrac{ \sum_{c_k \in C} |c_k| \cdot \| \overline{c_k} - \overline{X} \| }{ \sum_{c_k \in C} \sum_{ x_i \in c_k } \| x_i - \overline{c_k} \| }
+
MSE = \dfrac{1}{n}\sum \limits_{i=1}^{n}(a(x_i) - y_i)^2
</math>
+
</math> и
Компактность основана на расстоянии от точек кластера до их центроидов, а разделимость - на расстоянии от центроид кластеров до глобального центроида. Должен возрастать.
 
  
=== Индекс C ===
+
=== Cредняя абсолютная ошибка (англ. Mean Absolute Error, MAE) ===
Индекс C представляет собой нормализованную оценку компактности:
 
: <math>
 
CI(C) = \dfrac{ S(C) - S_{min}(C) }{ S_{max}(C) - S_{min}(C)}
 
</math>,
 
где:
 
: <math>
 
S(C) = \sum \limits_{c_k \in C} \sum \limits_{x_i, x_j \in c_k} \| x_i - x_j \|
 
</math>,
 
: <math>S_{min}(C) (S_{max}(C))</math> - сумма <math>\dfrac{ |c_k|\cdot(|c_k| - 1) }{2}</math> минимальных (максимальных) расстояний между парами всех объектов во всем датасете.
 
  
=== Индекс Дэвиcа-Болдуина (англ. Davies–Bouldin Index) ===
 
Это, возможно, одна из самых используемых мер оценки качества кластеризации.<br/>
 
Она вычисляет компактность как расстояние от объектов кластера до их центроидов, а отделимость - как расстояние между центроидами.
 
 
: <math>
 
: <math>
DB(C) = \dfrac{1}{K} \sum \limits_{c_k \in C} \max \limits_{c_l \in C \setminus c_k} \Big\{ \dfrac{ S(c_k)+S(c_l) }{ \| \overline{c_k} - \overline{c_l} \| } \Big\}
+
MAE = \dfrac{1}{n}\sum \limits_{i=1}^{n}|a(x_i) - y_i|
</math>,
 
где:
 
: <math>
 
S(c_k) = \dfrac{ 1 }{ |c_k| } \sum \limits_{x_i \in c_k} \|x_i - \overline{c_k}\|
 
 
</math>
 
</math>
  
Существует еще одна вариация данной меры, которая была предложена автором вместе с основной версией:
+
Среднеквадратичный функционал сильнее штрафует за большие отклонения по сравнению со среднеабсолютным, и поэтому более чувствителен к выбросам. При использовании любого из этих двух функционалов может быть полезно проанализировать, какие объекты вносят наибольший вклад в общую ошибку — не исключено, что на этих объектах была допущена ошибка при вычислении признаков или целевой величины.
: <math>
 
DB^*(C) = \dfrac{1}{K} \sum \limits_{c_k \in C} \dfrac
 
{ \max \limits_{c_l \in C \setminus c_k} \{ S(c_k)+S(c_l) \} }
 
{ \min \limits_{c_l \in C \setminus c_k} \{ \| \overline{c_k} - \overline{c_l} \| \} }
 
</math>
 
  
C-индекс и индекс Дэвиcа-Болдуина должны минимизироваться для роста кластеризации.
+
Среднеквадратичная ошибка подходит для сравнения двух моделей или для контроля качества во время обучения, но не позволяет сделать выводов о том, на сколько хорошо данная модель решает задачу. Например, MSE = 10 является очень плохим показателем, если целевая переменная принимает значения от 0 до 1, и очень хорошим, если целевая переменная лежит в интервале (10000, 100000). В таких ситуациях вместо среднеквадратичной ошибки полезно использовать коэффициент детерминации {{---}} <math>R^2</math>
  
=== Score function ===
+
=== Коэффициент детерминации ===  
Индекс, основанный на суммировании. Здесь оценка компактности выражается в дистанции от точек кластера до его центроида, а оценка разделимости — в дистанции от центроидов кластеров до глобального центроида.
 
  
 
: <math>
 
: <math>
SF(C) = 1 - \dfrac{ 1 }{ e^{e^{bcd(C) + wcd(C)}} }
+
R^2 = 1 - \dfrac{\sum \limits_{i=1}^{n}(a(x_i) - y_i)^2}{\sum \limits_{i=1}^{n}(y_i - \overline{y})^2}
</math>,
 
где:
 
: <math>
 
bcd(C) = \dfrac{ \sum \limits_{c_k \in C} |c_k| \cdot \|\overline{c_k} - \overline{X}\| }{ N \times K }
 
</math>,
 
: <math>
 
wcd(C) = \sum \limits_{c_k \in C} \dfrac{ 1 }{ |c_k| } \sum \limits_{x_i \in c_k} \|x_i - \overline{c_k}\|
 
 
</math>
 
</math>
  
Чем больше данный индекс, тем выше качество.
+
Коэффициент детерминации измеряет долю дисперсии, объясненную моделью, в общей дисперсии целевой переменной. Фактически, данная мера качества — это нормированная среднеквадратичная ошибка. Если она близка к единице, то модель хорошо объясняет данные, если же она близка к нулю, то прогнозы сопоставимы по качеству с константным предсказанием.
 +
 
 +
=== Средняя абсолютная процентная ошибка (англ. Mean Absolute Percentage Error, MAPE) ===
  
=== Индекс Gamma ===
 
 
: <math>
 
: <math>
G(C) = \dfrac{ \sum_{c_k \in C} \sum_{x_i,x_j \in c_k} |c_k| \cdot dl(x_i, x_j) }{ n_w (\binom{N}{2} - n_w) }
+
MAPE = 100\% \times \dfrac{1}{n}\sum \limits_{i=1}^{n} \dfrac{|y_i - a(x_i)|}{|y_i|}
 
</math>
 
</math>
  
где:
+
Это коэффициент, не имеющий размерности, с очень простой интерпретацией. Его можно измерять в долях или процентах. Если у вас получилось, например, что MAPE=11.4%, то это говорит о том, что ошибка составила 11,4% от фактических значений.
: <math>dl(x_i,x_j)</math> {{---}} число пар <math>(x_k, x_l) \in X</math> таких, что (1) <math>x_k</math> и <math>x_l</math> принадлежат разным кластерам, и (2) <math>\|x_k - x_l\| < \|x_i - x_j\|</math>,
+
Основная проблема данной ошибки — нестабильность.
: <math>
 
n_w = \sum_{c_k \in C} \binom{|c_k|}{2}
 
</math>.
 
  
=== Индекс COP ===
+
=== Корень из средней квадратичной ошибки (англ. Root Mean Squared Error, RMSE) ===
В данной мере компактность вычисляется как расстояние от точек кластера до его центроиды, а разделимость основана на расстоянии до самого отдаленного соседа.
 
: <math>
 
COP(C) = \dfrac{1}{N} \sum \limits_{c_k \in C} |c_k| \dfrac{ 1/|c_k| \sum_{x_i \in c_k} \| x_i - \overline{c_k} \| }{ \min_{x_i \notin c_k} \max_{x_j \in c_k} \| x_i - x_j\| }
 
</math>.
 
 
 
=== Индекс CS ===
 
Был предложен в области сжатия изображений, но может быть успешно адаптирован для любого другого окружения. Он оценивает компактность по диаметру кластера, а отделимость — как дистанцию между ближайшими элементами двух кластеров.
 
  
 
: <math>
 
: <math>
CS(C) = \dfrac{\sum_{c_k \in C} \{ 1 / |c_k| \sum_{x_i \in c_k} \max_{x_j \in c_k}\{\|x_i - x_j\|\} \}}{\sum_{c_k \in C} \min_{c_l \in C \setminus c_k} \{\|\overline{c_k} - \overline{c_l}\| \}}
+
RMSE = \sqrt{\dfrac{1}{n}\sum \limits_{i=1}^{n}(a(x_i) - y_i)^2}
</math>.
+
</math>  
 
 
Чем меньше значение данного индекса, тем выше качество кластеризации.
 
 
 
=== Индекс Sym ===
 
: <math>
 
Sym(C) = \dfrac {\max_{c_k, c_l \in C} \{\|\overline{c_k} - \overline{c_l}\|\}}{K\sum_{c_k \in C}\sum_{x_i \in c_k} \overset{\ast}{d_{ps}}(x_i, c_k)}
 
</math>.
 
 
 
Здесь <math>\overset{\ast}{d_{ps}}(x_i, c_k)</math> — дистанция симметрии для точки <math>x_i</math> из кластера <math>c_k</math>.
 
 
 
Чем выше данное значение, тем лучше.
 
 
 
=== Индексы SymDB, SymD, Sym33 ===
 
Модифицируют оценку компактности для индексов Дэвиса-Боулдина, Данна и gD33 соответственно.
 
  
SymDB вычисляется аналогично DB с изменением вычисления <math>S</math> на:
+
Примерно такая же проблема, как и в MAPE: так как каждое отклонение возводится в квадрат, любое небольшое отклонение может значительно повлиять на показатель ошибки. Стоит отметить, что существует также ошибка MSE, из которой RMSE как раз и получается путем извлечения корня.
  
: <math> S(c_k) = \dfrac{1}{|c_k| \sum_{x_i \in c_k} \overset{\ast}{d_{ps}}(x_i, c_k)} </math>.
+
=== Cимметричная MAPE (англ. Symmetric MAPE, SMAPE) ===
 
 
Данная оценка должна уменьшаться для улучшения качества кластеризации.
 
 
 
В SymD переопределена функция <math>\Delta</math>:
 
 
 
: <math> \Delta(c_k) = \max_{x_i \in c_k} \{\overset{\ast}{d_{ps}}(x_i, c_k)\} </math>.
 
 
 
в Sym33 аналогично SymD переопределена <math>\Delta</math>:
 
 
 
: <math> \Delta(c_k) = \dfrac{2}{|c_k| \sum_{x_i \in c_k} \overset{\ast}{d_{ps}}(x_i, c_k)} </math>.
 
 
 
Последние две оценки должны расти для улучшения качества кластеризации.
 
 
 
=== Negentropy increment ===
 
В отличие от подавляющего большинства других оценок, не основывается на сравнении компактности и разделимости. Определяется следующим образом:
 
  
 
: <math>
 
: <math>
NI(C) = \dfrac{1}{2} \sum_{c_k \in C} p(c_k)log|cov_{c_k}| - \dfrac{1}{2}log|cov_X| - \sum_{c_k \in C} p(c_k)log p(c_k)
+
SMAPE = \dfrac{1}{n}\sum \limits_{i=1}^{n} \dfrac{2 \times |y_i - a(x_i)|}{|y_i| + |a(x_i)|}
</math>.
+
</math>
  
Здесь <math>p(c_k) = |c_k| / N</math>, <math>|cov_{c_k}|</math> - определитель ковариационной матрицы кластера <math>c_k</math>, <math>|cov_X|</math> - определитель ковариационной матрицы всего датасета.
+
=== Средняя абсолютная масштабированная ошибка (англ. Mean absolute scaled error, MASE) ===
  
Данная оценка должна уменьшаться пропорционально росту качества кластеризации.
+
: <math> MASE = \dfrac{\sum \limits_{i=1}^n |Y_i - e_i|}{\frac{n}{n-1}\sum \limits_{i=2}^n | Y_i-Y_{i-1}|} </math>
=== Индекс SV ===
 
Одна из самых новых из рассматриваемых в данном разделе оценок. Измеряет разделимость по дистанции между ближайшими точка кластеров, а компактность — по расстоянию от пограничных точек кластера до его центроида.
 
  
: <math>
+
''MASE'' является очень хорошим вариантом для расчета точности, так как сама ошибка не зависит от масштабов данных и является симметричной: то есть положительные и отрицательные отклонения от факта рассматриваются в равной степени.
SV(C) = \dfrac{\sum_{c_k \in C} \min_{c_l \in C \setminus c_k} \{\|\overline{c_k} - \overline{c_l}\|\}}{\sum_{c_k \in C} 10 / |c_k| \sum \max_{x_i \in c_k}(0.1 * |c_k|) * \|\overline{x_i} - \overline{c_k}\|}
+
Обратите внимание, что в ''MASE'' мы имеем дело с двумя суммами: та, что в числителе, соответствует тестовой выборке, та, что в знаменателе - обучающей. Вторая фактически представляет собой среднюю абсолютную ошибку прогноза. Она же соответствует среднему абсолютному отклонению ряда в первых разностях. Эта величина, по сути, показывает, насколько обучающая выборка предсказуема. Она может быть равна нулю только в том случае, когда все значения в обучающей выборке равны друг другу, что соответствует отсутствию каких-либо изменений в ряде данных, ситуации на практике почти невозможной. Кроме того, если ряд имеет тенденцию к росту либо снижению, его первые разности будут колебаться около некоторого фиксированного уровня. В результате этого по разным рядам с разной структурой, знаменатели будут более-менее сопоставимыми. Всё это, конечно же, является очевидными плюсами ''MASE'', так как позволяет складывать разные значения по разным рядам и получать несмещённые оценки.
</math>.
 
  
Данная оценка должна увеличиваться.
+
Недостаток ''MASE'' в том, что её тяжело интерпретировать. Например, ''MASE''=1.21 ни о чём, по сути, не говорит. Это просто означает, что ошибка прогноза оказалась в 1.21 раза выше среднего абсолютного отклонения ряда в первых разностях, и ничего более.
  
=== Индекс OS ===
+
== Кросс-валидация ==
Отличается от предыдущей оценки усложненным способом вычисления оценки разделимости.
 
  
: <math>
+
Хороший способ оценки модели предусматривает применение [[Кросс-валидация|кросс-валидации]] (cкользящего контроля или перекрестной проверки).
OS(C) = \dfrac{\sum_{c_k \in C} \sum_{x_i \in c_k} ov(x_i, c_k)}{\sum_{c_k \in C} 10 / |c_k| \sum \max_{x_i \in c_k}(0.1 * |c_k|) * \|\overline{x_i} - \overline{c_k}\|}
 
</math>.
 
  
Где
+
В этом случае фиксируется некоторое множество разбиений исходной выборки на две подвыборки: обучающую и контрольную. Для каждого разбиения выполняется настройка алгоритма по обучающей подвыборке, затем оценивается его средняя ошибка на объектах контрольной подвыборки. Оценкой скользящего контроля называется средняя по всем разбиениям величина ошибки на контрольных подвыборках.
  
: <math>
+
== Примечания ==
ov(x_i, c_k) = \dfrac{a(x_i, c_k)}{b(x_i, c_k)}
+
# [https://www.coursera.org/lecture/vvedenie-mashinnoe-obuchenie/otsienivaniie-kachiestva-xCdqN] Лекция "Оценивание качества" на www.coursera.org
</math>.
+
# [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
при <math> \dfrac{b(x_i, c_k) - a(x_i, c_k)}{b(x_i, c_k) + a(x_i, c_k)} < 0.4 </math>, и <math>0</math> в ином случае.
+
# [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 о метриках качества, примеры
Функции <math>a</math> и <math>b</math> определены следующим образом:
 
 
 
: <math>
 
a(x_i, c_k) = \dfrac{1}{|c_k|\sum_{x_j \in c_k}\|x_i - x_j\|}
 
</math>.
 
 
 
: <math>
 
b(x_i, c_k) = \dfrac{1}{|c_k|\sum_{x_j \notin c_k}\ \min(|c_k)\|x_i - x_j\|}
 
</math>.
 
 
 
Данная оценка, как и предыдущая, должна возрастать.
 
 
 
== Сравнение ==
 
Не существует лучшего метода оценки качества кластеризации. Однако, в рамках исследования<ref>[https://www.sciencedirect.com/science/article/abs/pii/S003132031200338X An extensive comparative study of cluster validity indices]</ref> была предпринята попытка сравнить существующие меры на различных данных. Полученные результаты показали, что на искусственных датасетах наилучшим образом себя проявили индексы <math>Silhouette</math>, <math>DB^*</math> и <math>Calinski-Harabasz</math>. На реальных датасетах лучше всех показал себя <math>Score-function</math>.
 
 
 
В Таблице 1 приведены оценки сложности мер качества кластеризации (<math>n</math> — число объектов в рассматриваемом наборе данных):
 
 
 
{|class="wikitable" style="margin:auto; clear:both;
 
|+ Таблица 1 — Оценка сложности для 19 мер качества кластеризации.
 
|<math>Davies-Bouldin</math>
 
|<math>O(n\log{n})</math>
 
|<math>CS</math>
 
|<math>O(n\log{n})</math>
 
|-
 
|<math>Dunn</math>
 
|<math>O(n^2)</math>
 
|<math>DB^*</math>
 
|<math>O(n\log{n})</math>
 
|-
 
|<math>Calinski-Harabasz</math>
 
|<math>O(n\log{n})</math>
 
|<math>SF</math>
 
|<math>O(n)</math>
 
|-
 
|<math>Sillhouette</math>
 
|<math>O(n^2)</math>
 
|<math>Sym</math>
 
|<math>O(n^2)</math>
 
|-
 
|<math>gD31</math>
 
|<math>O(n^2)</math>
 
|<math>COP</math>
 
|<math>O(n^2)</math>
 
|-
 
|<math>gD41</math>
 
|<math>O(n^2)</math>
 
|<math>SV</math>
 
|<math>O(n\log{n})</math>
 
|-
 
|<math>gD51</math>
 
|<math>O(n^2)</math>
 
|<math>OS</math>
 
|<math>O(n^2\log{n})</math>
 
|-
 
|<math>gD33</math>
 
|<math>O(n^2)</math>
 
|<math>SDbw</math>
 
|<math>O(n\log{n})</math>
 
|-
 
|<math>gD43</math>
 
|<math>O(n^2)</math>
 
|<math>C-index</math>
 
|<math>O(n^2\log{n})</math>
 
|-
 
|<math>gD53</math>
 
|<math>O(n\log{n})</math>
 
|
 
|
 
|}
 
 
 
Из всех рассмотренных мер, меры <math>Sym</math>, <math>gD41</math>, <math>OS</math> и <math>COP</math> наиболее полно соответствуют когнитивному представлению асессоров о качестве кластеризации<ref>[https://ieeexplore.ieee.org/abstract/document/7891855 Towards cluster validity index evaluation and selection]</ref>.
 
  
 
== См. также ==
 
== См. также ==
* [[Кластеризация]]
+
* [[Оценка качества в задаче кластеризации]]
* [[Оценка качества в задачах классификации и регрессии]]<sup>[на 28.01.19 не создан]</sup>
+
* [[Кросс-валидация]]
  
 
== Источники информации ==
 
== Источники информации ==
# [https://en.wikipedia.org/wiki/Category:Clustering_criteria Wikipedia {{---}} Category:Clustering criteria]
+
# [https://compscicenter.ru/media/courses/2018-autumn/spb-recommendation/materials/lecture02-linregr_1.pdf] Соколов Е.А. Лекция линейная регрессия
# [http://synthesis.ipi.ac.ru/sigmod/seminar/sivogolovko20111124.pdf Сивоголовко Е. В. Методы оценки качества четкой кластеризации]
+
# [http://www.machinelearning.ru/wiki/images/5/59/PZAD2016_04_errors.pdf] - Дьяконов А. Функции ошибки / функционалы качества
# [http://www.cs.kent.edu/~jin/DM08/ClusterValidation.pdf Cluster Validation]
+
# [https://forecasting.svetunkov.ru/etextbook/forecasting_toolbox/models_quality/] - Оценка качества прогнозных моделей
# [https://link.springer.com/article/10.1023/A:1012801612483 Halkidi, M., Batistakis, Y., Vazirgiannis, M., 2001. On clustering validation techniques. Journal of intelligent information systems, 17(2-3), pp.107-145.]
+
# [https://shtem.ru/%D0%BE%D1%88%D0%B8%D0%B1%D0%BA%D0%B0-%D0%BF%D1%80%D0%BE%D0%B3%D0%BD%D0%BE%D0%B7%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F-%D1%84%D0%BE%D1%80%D0%BC%D1%83%D0%BB%D0%B0/] - HeinzBr Ошибка прогнозирования: виды, формулы, примеры
# [https://eurekamag.com/pdf/008/008337083.pdf Pal, N.R., Biswas, J., 1997. Cluster validation using graph theoretic concepts. Pattern Recognition, 30(6), pp.847-857.]
+
# [https://habr.com/ru/company/ods/blog/328372/] - egor_labintcev Метрики в задачах машинного обучения
 
+
# [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] - К.В.Воронцов, Скользящий контроль
  
 
[[Категория:Машинное обучение]]
 
[[Категория:Машинное обучение]]
[[Категория:Кластеризация]]
+
[[Категория:Классификация]]
 +
[[Категория:Регрессия]]

Текущая версия на 19:06, 4 сентября 2022

В машинном обучении различают оценки качества для задачи классификации и регрессии. Причем оценка задачи классификации часто значительно сложнее, чем оценка регрессии.

Оценки качества классификации

Матрица ошибок (англ. Сonfusion matrix)

Перед переходом к самим метрикам необходимо ввести важную концепцию для описания этих метрик в терминах ошибок классификации — confusion matrix (матрица ошибок). Допустим, что у нас есть два класса [math]y = \{ 0, 1 \}[/math] и алгоритм, предсказывающий принадлежность каждого объекта одному из классов. Рассмотрим пример. Пусть банк использует систему классификации заёмщиков на кредитоспособных и некредитоспособных. При этом первым кредит выдаётся, а вторые получат отказ. Таким образом, обнаружение некредитоспособного заёмщика ([math]y = 1 [/math]) можно рассматривать как "сигнал тревоги", сообщающий о возможных рисках.

Любой реальный классификатор совершает ошибки. В нашем случае таких ошибок может быть две:

  • Кредитоспособный заёмщик распознается моделью как некредитоспособный и ему отказывается в кредите. Данный случай можно трактовать как "ложную тревогу".
  • Некредитоспособный заёмщик распознаётся как кредитоспособный и ему ошибочно выдаётся кредит. Данный случай можно рассматривать как "пропуск цели".

Несложно увидеть, что эти ошибки неравноценны по связанным с ними проблемам. В случае "ложной тревоги" потери банка составят только проценты по невыданному кредиту (только упущенная выгода). В случае "пропуска цели" можно потерять всю сумму выданного кредита. Поэтому системе важнее не допустить "пропуск цели", чем "ложную тревогу".

Поскольку с точки зрения логики задачи нам важнее правильно распознать некредитоспособного заёмщика с меткой [math]y = 1 [/math], чем ошибиться в распознавании кредитоспособного, будем называть соответствующий исход классификации положительным (заёмщик некредитоспособен), а противоположный - отрицательным (заемщик кредитоспособен [math]y = 0 [/math]). Тогда возможны следующие исходы классификации:

  • Некредитоспособный заёмщик классифицирован как некредитоспособный, т.е. положительный класс распознан как положительный. Наблюдения, для которых это имеет место называются истинно-положительными (True PositiveTP).
  • Кредитоспособный заёмщик классифицирован как кредитоспособный, т.е. отрицательный класс распознан как отрицательный. Наблюдения, которых это имеет место, называются истинно отрицательными (True NegativeTN).
  • Кредитоспособный заёмщик классифицирован как некредитоспособный, т.е. имела место ошибка, в результате которой отрицательный класс был распознан как положительный. Наблюдения, для которых был получен такой исход классификации, называются ложно-положительными (False PositiveFP), а ошибка классификации называется ошибкой I рода.
  • Некредитоспособный заёмщик распознан как кредитоспособный, т.е. имела место ошибка, в результате которой положительный класс был распознан как отрицательный. Наблюдения, для которых был получен такой исход классификации, называются ложно-отрицательными (False NegativeFN), а ошибка классификации называется ошибкой II рода.

Таким образом, ошибка I рода, или ложно-положительный исход классификации, имеет место, когда отрицательное наблюдение распознано моделью как положительное. Ошибкой II рода, или ложно-отрицательным исходом классификации, называют случай, когда положительное наблюдение распознано как отрицательное. Поясним это с помощью матрицы ошибок классификации:

[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] — истинная метка класса на этом объекте. Таким образом, ошибки классификации бывают двух видов: False Negative (FN) и False Positive (FP). P означает что классификатор определяет класс объекта как положительный (N — отрицательный). T значит что класс предсказан правильно (соответственно F — неправильно). Каждая строка в матрице ошибок представляет спрогнозированный класс, а каждый столбец — фактический класс.

 # код для матрицы ошибок
 # Пример классификатора, способного проводить различие между всего лишь двумя
 # классами, "пятерка" и "не пятерка" из набора рукописных цифр MNIST
 import numpy as np
 from sklearn.datasets import fetch_openml
 from sklearn.model_selection import cross_val_predict
 from sklearn.metrics import confusion_matrix
 from sklearn.linear_model import SGDClassifier
 mnist = fetch_openml('mnist_784', version=1)
 X, y = mnist["data"], mnist["target"]
 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) # True для всех пятерок, False для в сех остальных цифр. Задача опознать пятерки
 y_test_5 = (y_test == 5)
 sgd_clf = SGDClassifier(random_state=42) # классификатор на основе метода стохастического градиентного спуска (англ. Stochastic Gradient Descent SGD)
 sgd_clf.fit(X_train, y_train_5) # обучаем классификатор распозновать пятерки на целом обучающем наборе
 # Для расчета матрицы ошибок сначала понадобится иметь набор прогнозов, чтобы их можно было сравнивать с фактическими целями
 y_train_pred = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3)
 print(confusion_matrix(y_train_5, y_train_pred))
 # array([[53892, 687],
 #        [ 1891, 3530]])

Безупречный классификатор имел бы только истинно-поло­жительные и истинно отрицательные классификации, так что его матрица ошибок содержала бы ненулевые значения только на своей главной диа­гонали (от левого верхнего до правого нижнего угла):

 import numpy as np
 from sklearn.datasets import fetch_openml
 from sklearn.metrics import confusion_matrix
 mnist = fetch_openml('mnist_784', version=1)
 X, y = mnist["data"], mnist["target"]
 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) # True для всех пятерок, False для в сех остальных цифр. Задача опознать пятерки
 y_test_5 = (y_test == 5)
 y_train_perfect_predictions = y_train_5 # притворись, что мы достигли совершенства
 print(confusion_matrix(y_train_5, y_train_perfect_predictions))
 # array([[54579, 0],
 #        [ 0, 5421]])

Аккуратность (англ. Accuracy)

Интуитивно понятной, очевидной и почти неиспользуемой метрикой является accuracy — доля правильных ответов алгоритма:

[math] accuracy = \dfrac{TP+TN}{TP+TN+FP+FN} [/math]

Эта метрика бесполезна в задачах с неравными классами, что как вариант можно исправить с помощью алгоритмов сэмплирования и это легко показать на примере.

Допустим, мы хотим оценить работу спам-фильтра почты. У нас есть 100 не-спам писем, 90 из которых наш классификатор определил верно (True Negative = 90, False Positive = 10), и 10 спам-писем, 5 из которых классификатор также определил верно (True Positive = 5, False Negative = 5). Тогда accuracy:

[math] accuracy = \dfrac{5+90}{5+90+10+5} = 86,4 [/math]

Однако если мы просто будем предсказывать все письма как не-спам, то получим более высокую аккуратность:

[math] accuracy = \dfrac{0+100}{0+100+0+10} = 90,9 [/math]

При этом, наша модель совершенно не обладает никакой предсказательной силой, так как изначально мы хотели определять письма со спамом. Преодолеть это нам поможет переход с общей для всех классов метрики к отдельным показателям качества классов.

 # код для для подсчета аккуратности:
 # Пример классификатора, способного проводить различие между всего лишь двумя
 # классами, "пятерка" и "не пятерка" из набора рукописных цифр MNIST
 import numpy as np
 from sklearn.datasets import fetch_openml
 from sklearn.model_selection import cross_val_predict
 from sklearn.metrics import accuracy_score
 from sklearn.linear_model import SGDClassifier
 mnist = fetch_openml('mnist_784', version=1)
 X, y = mnist["data"], mnist["target"]
 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) # True для всех пятерок, False для в сех остальных цифр. Задача опознать пятерки
 y_test_5 = (y_test == 5)
 sgd_clf = SGDClassifier(random_state=42) # классификатор на основе метода стохастического градиентного спуска (Stochastic Gradient Descent SGD)
 sgd_clf.fit(X_train, y_train_5) # обучаем классификатор распозновать пятерки на целом обучающем наборе
 y_train_pred = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3)
 # print(confusion_matrix(y_train_5, y_train_pred))
 # array([[53892, 687]
 #        [ 1891, 3530]])
 print(accuracy_score(y_train_5, y_train_pred)) # == (53892 + 3530) / (53892 + 3530  + 1891 +687)
 
 # 0.9570333333333333

Точность (англ. Precision)

Точностью (precision) называется доля правильных ответов модели в пределах класса — это доля объектов действительно принадлежащих данному классу относительно всех объектов которые система отнесла к этому классу.

[math] Precision = \dfrac{TP}{TP+FP} [/math]

Именно введение precision не позволяет нам записывать все объекты в один класс, так как в этом случае мы получаем рост уровня False Positive.

Полнота (англ. Recall)

Полнота — это доля истинно положительных классификаций. Полнота показывает, какую долю объектов, реально относящихся к положительному классу, мы предсказали верно.

[math] Recall = \dfrac{TP}{TP+FN} [/math]

Полнота (recall) демонстрирует способность алгоритма обнаруживать данный класс вообще.

Имея матрицу ошибок, очень просто можно вычислить точность и полноту для каждого класса. Точность (precision) равняется отношению соответствующего диагонального элемента матрицы и суммы всей строки класса. Полнота (recall) — отношению диагонального элемента матрицы и суммы всего столбца класса. Формально:

[math] Precision_c = \dfrac{A_{c,c}}{\sum \limits_{i=1}^{n} A_{c,i}} [/math]
[math] Recall_c = \dfrac{A_{c,c}}{\sum \limits_{i=1}^{n} A_{i,c}} [/math]

Результирующая точность классификатора рассчитывается как арифметическое среднее его точности по всем классам. То же самое с полнотой. Технически этот подход называется macro-averaging.

 # код для для подсчета точности и полноты:
 # Пример классификатора, способного проводить различие между всего лишь двумя
 # классами, "пятерка" и "не пятерка" из набора рукописных цифр MNIST
 import numpy as np
 from sklearn.datasets import fetch_openml
 from sklearn.model_selection import cross_val_predict
 from sklearn.metrics import precision_score, recall_score
 from sklearn.linear_model import SGDClassifier
 mnist = fetch_openml('mnist_784', version=1)
 X, y = mnist["data"], mnist["target"]
 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) # True для всех пятерок, False для в сех остальных цифр. Задача опознать пятерки
 y_test_5 = (y_test == 5)
 sgd_clf = SGDClassifier(random_state=42) # классификатор на основе метода стохастического градиентного спуска (Stochastic Gradient Descent SGD)
 sgd_clf.fit(X_train, y_train_5) # обучаем классификатор распозновать пятерки на целом обучающем наборе
 y_train_pred = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3)
 # print(confusion_matrix(y_train_5, y_train_pred))
 # array([[53892, 687]
 #        [ 1891, 3530]])
 print(precision_score(y_train_5, y_train_pred)) # == 3530 / (3530 + 687)
 print(recall_score(y_train_5, y_train_pred)) # == 3530 / (3530 + 1891)
   
 # 0.8370879772350012
 # 0.6511713705958311

F-мера (англ. F-score)

Precision и recall не зависят, в отличие от accuracy, от соотношения классов и потому применимы в условиях несбалансированных выборок. Часто в реальной практике стоит задача найти оптимальный (для заказчика) баланс между этими двумя метриками. Понятно что чем выше точность и полнота, тем лучше. Но в реальной жизни максимальная точность и полнота не достижимы одновременно и приходится искать некий баланс. Поэтому, хотелось бы иметь некую метрику которая объединяла бы в себе информацию о точности и полноте нашего алгоритма. В этом случае нам будет проще принимать решение о том какую реализацию запускать в производство (у кого больше тот и круче). Именно такой метрикой является F-мера.

F-мера представляет собой гармоническое среднее между точностью и полнотой. Она стремится к нулю, если точность или полнота стремится к нулю.

[math] F = \dfrac{ 2 \times precision \times recall }{ precision + recall }[/math]

Данная формула придает одинаковый вес точности и полноте, поэтому F-мера будет падать одинаково при уменьшении и точности и полноты. Возможно рассчитать F-меру придав различный вес точности и полноте, если вы осознанно отдаете приоритет одной из этих метрик при разработке алгоритма:

[math] F_β = \dfrac{(1+β^2) \times precision \times recall }{ (β^2 \times precision) + recall } [/math]

где [math]β[/math] принимает значения в диапазоне [math]0\lt β\lt 1[/math] если вы хотите отдать приоритет точности, а при [math]β\gt 1[/math] приоритет отдается полноте. При [math]β=1[/math] формула сводится к предыдущей и вы получаете сбалансированную F-меру (также ее называют [math]F_1[/math]).


  • Рис.1 Сбалансированная F-мера, [math]β=1[/math]
  • Рис.2 F-мера c приоритетом точности, [math]β^2=\dfrac{ 1 }{ 4 }[/math]
  • Рис.3 F-мера c приоритетом полноты, [math]β^2=2[/math]

F-мера достигает максимума при максимальной полноте и точности, и близка к нулю, если один из аргументов близок к нулю.

F-мера является хорошим кандидатом на формальную метрику оценки качества классификатора. Она сводит к одному числу две других основополагающих метрики: точность и полноту. Имея "F-меру" гораздо проще ответить на вопрос: "поменялся алгоритм в лучшую сторону или нет?"

 # код для подсчета метрики F-mera:
 # Пример классификатора, способного проводить различие между всего лишь двумя
 # классами, "пятерка" и "не пятерка" из набора рукописных цифр MNIST
 import numpy as np
 from sklearn.datasets import fetch_openml
 from sklearn.model_selection import cross_val_predict
 from sklearn.linear_model import SGDClassifier
 from sklearn.metrics import f1_score
 mnist = fetch_openml('mnist_784', version=1)
 X, y = mnist["data"], mnist["target"]
 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) # True для всех пятерок, False для в сех остальных цифр. Задача опознать пятерки
 y_test_5 = (y_test == 5)
 sgd_clf = SGDClassifier(random_state=42) # классификатор на основе метода стохастического градиентного спуска (Stochastic Gradient Descent SGD)
 sgd_clf.fit(X_train, y_train_5) # обучаем классификатор распознавать пятерки на целом обучающем наборе
 y_train_pred = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3)
 print(f1_score(y_train_5, y_train_pred))
 
 # 0.7325171197343846

ROC-кривая

Кривая рабочих характеристик (англ. Receiver Operating Characteristics curve). Используется для анализа поведения классификаторов при различных пороговых значениях. Позволяет рассмотреть все пороговые значения для данного классификатора. Показывает долю ложно положительных примеров (англ. false positive rate, FPR) в сравнении с долей истинно положительных примеров (англ. true positive rate, TPR).

ROC 2.png

[math] TPR = \dfrac{TP}{TP+FN} = Recall[/math]
[math] FPR = \dfrac{FP}{FP+TN} [/math]

Доля FPR — это пропорция отрицательных образцов, которые были некорректно классифицированы как положительные.

[math] FPR = 1 - TNR[/math],

где TNR — доля истинно отрицательных классификаций (англ. Тrие Negative Rate), пред­ставляющая собой пропорцию отрицательных образцов, которые были кор­ректно классифицированы как отрицательные.

Доля TNR также называется специфичностью (англ. specificity). Следовательно, ROC-кривая изображает чувствительность (англ. seпsitivity), т.е. полноту, в срав­нении с разностью 1 - specificity.

Прямая линия по диагонали представляет ROC-кривую чисто случайного классификатора. Хороший классификатор держится от указанной линии настолько далеко, насколько это возможно (стремясь к левому верхнему углу).

Один из способов сравнения классификаторов предусматривает измере­ние площади под кривой (англ. Area Under the Curve — AUC). Безупречный клас­сификатор будет иметь площадь под ROC-кривой (ROC-AUC), равную 1, тогда как чисто случайный классификатор - площадь 0.5.

 # Код отрисовки ROC-кривой
 # На примере классификатора, способного проводить различие между всего лишь двумя классами
 # "пятерка" и "не пятерка" из набора рукописных цифр MNIST
 from sklearn.metrics import roc_curve
 import matplotlib.pyplot as plt
 import numpy as np
 from sklearn.datasets import fetch_openml
 from sklearn.model_selection import cross_val_predict
 from sklearn.linear_model import SGDClassifier
 mnist = fetch_openml('mnist_784', version=1)
 X, y = mnist["data"], mnist["target"]
 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)  # True для всех пятерок, False для в сех остальных цифр. Задача опознать пятерки
 y_test_5 = (y_test == 5)
 sgd_clf = SGDClassifier(random_state=42) # классификатор на основе метода стохастического градиентного спуска (Stochastic Gradient Descent SGD)
 sgd_clf.fit(X_train, y_train_5) # обучаем классификатор распозновать пятерки на целом обучающем наборе
 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")
 fpr, tpr, thresholds = roc_curve(y_train_5, y_scores)
 def plot_roc_curve(fpr, tpr, label=None):
     plt.plot(fpr, tpr, linewidth=2, label=label)
     plt.plot([0, 1], [0, 1], 'k--') # dashed diagonal
     plt.xlabel('False Positive Rate, FPR (1 - specificity)')
     plt.ylabel('True Positive Rate, TPR (Recall)')
     plt.title('ROC curve')
     plt.savefig("ROC.png")
 plot_roc_curve(fpr, tpr)
 plt.show()

Precison-recall кривая

Чувствительность к соотношению классов. Рассмотрим задачу выделения математических статей из множества научных статей. Допустим, что всего имеется 1.000.100 статей, из которых лишь 100 относятся к математике. Если нам удастся построить алгоритм [math]a(x)[/math], идеально решающий задачу, то его TPR будет равен единице, а FPR — нулю. Рассмотрим теперь плохой алгоритм, дающий положительный ответ на 95 математических и 50.000 нематематических статьях. Такой алгоритм совершенно бесполезен, но при этом имеет TPR = 0.95 и FPR = 0.05, что крайне близко к показателям идеального алгоритма. Таким образом, если положительный класс существенно меньше по размеру, то AUC-ROC может давать неадекватную оценку качества работы алгоритма, поскольку измеряет долю неверно принятых объектов относительно общего числа отрицательных. Так, алгоритм [math]b(x)[/math], помещающий 100 релевантных документов на позиции с 50.001-й по 50.101-ю, будет иметь AUC-ROC 0.95.

Precison-recall (PR) кривая. Избавиться от указанной проблемы с несбалансированными классами можно, перейдя от ROC-кривой к PR-кривой. Она определяется аналогично ROC-кривой, только по осям откладываются не FPR и TPR, а полнота (по оси абсцисс) и точность (по оси ординат). Критерием качества семейства алгоритмов выступает площадь под PR-кривой (англ. Area Under the Curve — AUC-PR)

PR curve.png

 # Код отрисовки Precison-recall кривой
 # На примере классификатора, способного проводить различие между всего лишь двумя классами
 # "пятерка" и "не пятерка" из набора рукописных цифр MNIST
 from sklearn.metrics import precision_recall_curve
 import matplotlib.pyplot as plt
 import numpy as np
 from sklearn.datasets import fetch_openml
 from sklearn.model_selection import cross_val_predict
 from sklearn.linear_model import SGDClassifier
 mnist = fetch_openml('mnist_784', version=1)
 X, y = mnist["data"], mnist["target"]
 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) # True для всех пятерок, False для в сех остальных цифр. Задача опознать пятерки
 y_test_5 = (y_test == 5)
 sgd_clf = SGDClassifier(random_state=42) # классификатор на основе метода стохастического градиентного спуска (Stochastic Gradient Descent SGD)
 sgd_clf.fit(X_train, y_train_5) # обучаем классификатор распозновать пятерки на целом обучающем наборе
 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")
 precisions, recalls, thresholds = precision_recall_curve(y_train_5, y_scores)
 def plot_precision_recall_vs_threshold(precisions, recalls, thresholds):
     plt.plot(recalls, precisions, linewidth=2)
     plt.xlabel('Recall')
     plt.ylabel('Precision')
     plt.title('Precision-Recall curve')
     plt.savefig("Precision_Recall_curve.png")
 plot_precision_recall_vs_threshold(precisions, recalls, thresholds)
 plt.show()

Оценки качества регрессии

Наиболее типичными мерами качества в задачах регрессии являются

Средняя квадратичная ошибка (англ. Mean Squared Error, MSE)

MSE применяется в ситуациях, когда нам надо подчеркнуть большие ошибки и выбрать модель, которая дает меньше больших ошибок прогноза. Грубые ошибки становятся заметнее за счет того, что ошибку прогноза мы возводим в квадрат. И модель, которая дает нам меньшее значение среднеквадратической ошибки, можно сказать, что что у этой модели меньше грубых ошибок.

[math] MSE = \dfrac{1}{n}\sum \limits_{i=1}^{n}(a(x_i) - y_i)^2 [/math] и

Cредняя абсолютная ошибка (англ. Mean Absolute Error, MAE)

[math] MAE = \dfrac{1}{n}\sum \limits_{i=1}^{n}|a(x_i) - y_i| [/math]

Среднеквадратичный функционал сильнее штрафует за большие отклонения по сравнению со среднеабсолютным, и поэтому более чувствителен к выбросам. При использовании любого из этих двух функционалов может быть полезно проанализировать, какие объекты вносят наибольший вклад в общую ошибку — не исключено, что на этих объектах была допущена ошибка при вычислении признаков или целевой величины.

Среднеквадратичная ошибка подходит для сравнения двух моделей или для контроля качества во время обучения, но не позволяет сделать выводов о том, на сколько хорошо данная модель решает задачу. Например, MSE = 10 является очень плохим показателем, если целевая переменная принимает значения от 0 до 1, и очень хорошим, если целевая переменная лежит в интервале (10000, 100000). В таких ситуациях вместо среднеквадратичной ошибки полезно использовать коэффициент детерминации — [math]R^2[/math]

Коэффициент детерминации

[math] R^2 = 1 - \dfrac{\sum \limits_{i=1}^{n}(a(x_i) - y_i)^2}{\sum \limits_{i=1}^{n}(y_i - \overline{y})^2} [/math]

Коэффициент детерминации измеряет долю дисперсии, объясненную моделью, в общей дисперсии целевой переменной. Фактически, данная мера качества — это нормированная среднеквадратичная ошибка. Если она близка к единице, то модель хорошо объясняет данные, если же она близка к нулю, то прогнозы сопоставимы по качеству с константным предсказанием.

Средняя абсолютная процентная ошибка (англ. Mean Absolute Percentage Error, MAPE)

[math] MAPE = 100\% \times \dfrac{1}{n}\sum \limits_{i=1}^{n} \dfrac{|y_i - a(x_i)|}{|y_i|} [/math]

Это коэффициент, не имеющий размерности, с очень простой интерпретацией. Его можно измерять в долях или процентах. Если у вас получилось, например, что MAPE=11.4%, то это говорит о том, что ошибка составила 11,4% от фактических значений. Основная проблема данной ошибки — нестабильность.

Корень из средней квадратичной ошибки (англ. Root Mean Squared Error, RMSE)

[math] RMSE = \sqrt{\dfrac{1}{n}\sum \limits_{i=1}^{n}(a(x_i) - y_i)^2} [/math]

Примерно такая же проблема, как и в MAPE: так как каждое отклонение возводится в квадрат, любое небольшое отклонение может значительно повлиять на показатель ошибки. Стоит отметить, что существует также ошибка MSE, из которой RMSE как раз и получается путем извлечения корня.

Cимметричная MAPE (англ. Symmetric MAPE, SMAPE)

[math] SMAPE = \dfrac{1}{n}\sum \limits_{i=1}^{n} \dfrac{2 \times |y_i - a(x_i)|}{|y_i| + |a(x_i)|} [/math]

Средняя абсолютная масштабированная ошибка (англ. Mean absolute scaled error, MASE)

[math] MASE = \dfrac{\sum \limits_{i=1}^n |Y_i - e_i|}{\frac{n}{n-1}\sum \limits_{i=2}^n | Y_i-Y_{i-1}|} [/math]

MASE является очень хорошим вариантом для расчета точности, так как сама ошибка не зависит от масштабов данных и является симметричной: то есть положительные и отрицательные отклонения от факта рассматриваются в равной степени. Обратите внимание, что в MASE мы имеем дело с двумя суммами: та, что в числителе, соответствует тестовой выборке, та, что в знаменателе - обучающей. Вторая фактически представляет собой среднюю абсолютную ошибку прогноза. Она же соответствует среднему абсолютному отклонению ряда в первых разностях. Эта величина, по сути, показывает, насколько обучающая выборка предсказуема. Она может быть равна нулю только в том случае, когда все значения в обучающей выборке равны друг другу, что соответствует отсутствию каких-либо изменений в ряде данных, ситуации на практике почти невозможной. Кроме того, если ряд имеет тенденцию к росту либо снижению, его первые разности будут колебаться около некоторого фиксированного уровня. В результате этого по разным рядам с разной структурой, знаменатели будут более-менее сопоставимыми. Всё это, конечно же, является очевидными плюсами MASE, так как позволяет складывать разные значения по разным рядам и получать несмещённые оценки.

Недостаток MASE в том, что её тяжело интерпретировать. Например, MASE=1.21 ни о чём, по сути, не говорит. Это просто означает, что ошибка прогноза оказалась в 1.21 раза выше среднего абсолютного отклонения ряда в первых разностях, и ничего более.

Кросс-валидация

Хороший способ оценки модели предусматривает применение кросс-валидации (cкользящего контроля или перекрестной проверки).

В этом случае фиксируется некоторое множество разбиений исходной выборки на две подвыборки: обучающую и контрольную. Для каждого разбиения выполняется настройка алгоритма по обучающей подвыборке, затем оценивается его средняя ошибка на объектах контрольной подвыборки. Оценкой скользящего контроля называется средняя по всем разбиениям величина ошибки на контрольных подвыборках.

Примечания

  1. [1] Лекция "Оценивание качества" на www.coursera.org
  2. [2] Лекция на www.stepik.org о кросвалидации
  3. [3] Лекция на www.stepik.org о метриках качества, Precison и Recall
  4. [4] Лекция на www.stepik.org о метриках качества, F-мера
  5. [5] Лекция на www.stepik.org о метриках качества, примеры

См. также

Источники информации

  1. [6] Соколов Е.А. Лекция линейная регрессия
  2. [7] - Дьяконов А. Функции ошибки / функционалы качества
  3. [8] - Оценка качества прогнозных моделей
  4. [9] - HeinzBr Ошибка прогнозирования: виды, формулы, примеры
  5. [10] - egor_labintcev Метрики в задачах машинного обучения
  6. [11] - grossu Методы оценки качества прогноза
  7. [12] - К.В.Воронцов, Классификация
  8. [13] - К.В.Воронцов, Скользящий контроль