Давайте подумаем о данных как о непрерывных, категориальных или порядковых (категориальных, но с порядком). Матрицы неточностей – это средство оценки эффективности категориальной модели. Чтобы понять, как это работает, мы сначала освежим знания о непрерывных данных. Благодаря этому мы можем увидеть, что матрицы путаницы являются просто расширением уже известных нам гистограмм.

Непрерывное распределение данных

Когда мы хотим понять непрерывные данные, первым шагом часто является изучение того, как они распределяются. Рассмотрим следующую гистограмму.

Мы видим, что метка в среднем равна нулю, а большинство точек данных находятся в диапазоне от -1 до 1. Она выглядит симметричной; существует примерно четное количество чисел, меньших и больших, чем среднее. Если бы мы захотели, мы могли бы использовать таблицу, а не гистограмму, но это могло бы быть громоздко.

Категориальные распределения данных

В некоторых отношениях категориальные данные не так уж отличаются от непрерывных данных. Мы по-прежнему можем создавать гистограммы, чтобы оценить, насколько часто значения появляются для каждой метки. Например, двоичная метка (true/false) может появляться с такой частотой:

Это говорит нам о том, что имеется 750 образцов с меткой false и 250 с меткой true.

Ярлыки для трех категорий аналогичны:

Это говорит нам о том, что существует 200 образцов, которые являются человеком, 400 — животными и 100 — деревом.

Поскольку категориальные метки проще, мы часто можем отображать их в виде простых таблиц. Два предыдущих графика будут выглядеть так:

Label       False       True
Count        750         250

И

Label       Person       Animal       Tree
Count        200          400          100

Глядя на прогнозы

Мы можем смотреть на прогнозы, которые делает модель, так же, как мы смотрим на метки истинности в наших данных. Например, мы можем увидеть, что в тестовом наборе наша модель предсказала false 700 раз и true 300 раз.

Prediction       Count
False             700
True              300

Это дает прямую информацию о прогнозах, которые делает наша модель, но не говорит нам, какие из них верны. Хотя мы можем использовать функцию стоимости, чтобы понять, как часто даются правильные ответы, функция стоимости не скажет нам, какие ошибки совершаются.
Например, модель может правильно угадать все значения true, а также угадать true, когда она должна была угадать false.

Матрица путаницы

Ключом к пониманию эффективности модели является объединение таблицы прогнозирования модели с таблицей меток достоверных данных:

Квадрат, который мы не заполнили, называется Матрица путаницы.

Каждая ячейка в матрице путаницы говорит нам одну вещь о производительности модели. Это Истинно отрицательные результаты (TN), Ложноотрицательные результаты (FN),
Ложноположительные результаты (FP) и Истинно положительные результаты. (ТП).

Давайте объясним это одно за другим, заменив эти аббревиатуры фактическими значениями. Сине-зеленые квадраты означают, что модель сделала правильный прогноз, а оранжевые квадраты означают, что модель сделала неправильный прогноз.

Истинно отрицательные результаты (ТН)

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

Ложноотрицательные результаты (FN)

Значение в правом верхнем углу показывает, сколько раз модель предсказывала ложь, но фактическая метка была верной. Теперь мы знаем, что это 200. Как? Потому что модель предсказала ложь 700 раз, и 500 из них она сделала это правильно. Таким образом, 200 раз он должен был предсказать ложь, хотя этого не следовало делать.

Ложные срабатывания (FP)

Значение в левом нижнем углу содержит ложные срабатывания. Это говорит нам о том, сколько раз модель предсказывала правду, но фактическая метка была ложной. Теперь мы знаем, что это 250, потому что 750 раз правильный ответ был неверным. 500 из этих значений времени отображаются в верхней левой ячейке (TN):

Истинные позитивы (TP)

Наконец, у нас есть настоящий позитив. Это количество раз, когда модель правильно предсказала истину. Мы знаем, что это 50 по двум причинам. Во-первых, модель предсказала правду 300 раз, но 250 раз она оказалась неверной (нижняя левая ячейка). Во-вторых, в 250 случаях правильный ответ был «истина», но в 200 раз модель предсказала ложь.

Окончательная матрица путаницы

Обычно мы немного упрощаем нашу матрицу путаницы, например:

Мы раскрасили ячейки здесь, чтобы подчеркнуть, когда модель сделала правильные прогнозы. Благодаря этому мы знаем не только то, как часто модель делала определенные типы прогнозов, но и то, как часто эти прогнозы были правильными или неправильными.

Матрицы путаницы также можно построить, если меток больше. Например, для нашего примера человек/животное/дерево мы могли бы получить такую ​​матрицу:

Когда есть три категории, такие метрики, как True Positives, больше не применяются, но мы все равно можем точно видеть, как часто модель допускала определенные виды ошибок. Например, мы видим, что модель предсказала этого человека 200 раз, хотя на самом деле правильным результатом было животное.

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

Визуализация данных

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

import pandas
!wget https://raw.githubusercontent.com/MicrosoftDocs/mslearn-introduction-to-machine-learning/main/graphing.py
!wget https://raw.githubusercontent.com/MicrosoftDocs/mslearn-introduction-to-machine-learning/main/Data/snow_objects.csv

#Import the data from the .csv file
dataset = pandas.read_csv('snow_objects.csv', delimiter="\t")

#Let's have a look at the data
dataset
           size     roughness     color     motion     label
0       50.959361    1.318226     green    0.054290    tree
1       60.008521    0.554291     brown    0.000000    tree
2       20.530772    1.097752     white    1.380464    tree
3       28.092138    0.966482     grey     0.650528    tree
4       48.344211    0.799093     grey     0.000000    tree
 ...       ...          ...        ...        ...       ...
2195    1.918175     1.182234     white    0.000000    animal
2196    1.000694     1.332152     black    4.041097    animal
2197    2.331485     0.734561     brown    0.961486    animal
2198    1.786560     0.707935     black    0.000000    animal
2199    1.518813     1.447957     brown    0.000000    animal

2200 rows × 5 columns

Исследование данных

Мы видим, что набор данных содержит как непрерывные (размер, шероховатость, движение), так и категориальные данные (цвет и метка). Давайте проведем небольшое исследование данных и посмотрим, какие у нас есть разные классы меток и их количество:

import graphing # custom graphing code. See our GitHub repo for details

# Plot a histogram with counts for each label
graphing.multiple_histogram(dataset, label_x="label", label_group="label", title="Label distribution")

Предыдущая гистограмма позволяет легко понять как метки, которые есть в наборе данных, так и их распределение.

Следует обратить внимание на одну важную информацию: это
несбалансированный набор данных: классы представлены в разных пропорциях (у нас в 4 раза больше камней и деревья, чем животные, например).

Это актуально, поскольку несбалансированные наборы очень распространены «в дикой природе».
В будущем мы научимся решать эту проблему, чтобы создавать более качественные модели.

Мы можем провести тот же анализ для функции color:

# Plot a histogram with counts for each label
graphing.multiple_histogram(dataset, label_x="color", label_group="color", title="Color distribution")

Мы можем заметить, что:

  • У нас есть 8 различных цветовых категорий.
  • Функция color также сильно несбалансирована.
  • Наш алгоритм построения графиков недостаточно умен, чтобы назначить правильные цвета их соответствующим именам.

Давайте посмотрим, что мы можем найти о других функциях:

graphing.box_and_whisker(dataset, label_y="size", title='Boxplot of "size" feature')

На предыдущей диаграмме мы заметили, что большинство наших выборок относительно небольшие, с размерами от 0 до 70, но у нас есть несколько гораздо более крупных выбросов.

Давайте построим график функции шероховатости:

graphing.box_and_whisker(dataset, label_y="roughness", title='Boxplot of "roughness" feature')

Здесь не так уж много различий: значения шероховатости варьируются от 0 до чуть более 2, причем большинство образцов имеют значения, близкие к среднему значению.

Давайте построим функцию движения:

graphing.box_and_whisker(dataset, label_y="motion", title='Boxplot of "motion" feature')

Большинство объектов кажутся либо статичными, либо движущимися очень медленно. Меньшее количество объектов движется быстрее, с парой выбросов более 10.

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

Постройте модель классификации

Давайте построим и обучим модель классификации, используя случайный лес, чтобы предсказать класс объекта на основе функций в нашем наборе данных:

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split

# Split the dataset in an 70/30 train/test ratio. 
train, test = train_test_split(dataset, test_size=0.3, random_state=2)
print(train.shape)
print(test.shape)
(1540, 5)
(660, 5)

Теперь мы можем обучить нашу модель, используя только что созданный набор данных train:

# Create the model
model = RandomForestClassifier(n_estimators=1, random_state=1, verbose=False)

# Define which features are to be used (leave color out for now)
features = ["size", "roughness", "motion"]

# Train the model
model.fit(train[features], train.label)

print("Model trained!")
Model trained!

Оцените модель

Теперь мы можем использовать нашу недавно обученную модель для прогнозирования с использованием тестового набора. Сравнивая прогнозируемые значения с фактическими метками (также называемыми истинными значениями), мы можем измерить эффективность модели, используя различные показатели.

Точность, например, – это количество правильно предсказанных ярлыков из всех выполненных прогнозов:

Accuracy = Correct Predictions / Total Predictions

Давайте посмотрим, как это можно сделать в коде:

# Import a function that measures a models accuracy
from sklearn.metrics import accuracy_score

# Calculate the model's accuracy on the TEST set
actual = test.label
predictions = model.predict(test[features])

# Return accuracy as a fraction
acc = accuracy_score(actual, predictions)

# Return accuracy as a number of correct predictions
acc_norm = accuracy_score(actual, predictions, normalize=False)

print(f"The random forest model's accuracy on the test set is {acc:.4f}.")
print(f"It correctly predicted {acc_norm} labels in {len(test.label)} predictions.")
The random forest model's accuracy on the test set is 0.8924.
It correctly predicted 589 labels in 660 predictions.

Наша модель, кажется, чувствует себя неплохо!

Однако эта интуиция может ввести в заблуждение:

  • Точность не учитывает неправильные прогнозы, сделанные моделью.
  • Также не очень хорошо получается нарисовать четкую картину в несбалансированных по классам наборах данных, таких как наш, где количество возможных классов распределено неравномерно (напомним, что у нас есть 800 деревьев, 800 камнейs, но только 200 животных).

Постройте матрицу путаницы

Матрица путаницы — это таблица, в которой мы сравниваем фактические метки с тем, что предсказала модель. Это дает нам более детальное понимание того, как работает модель и где она делает все правильно, а где нет.

Это один из способов сделать это в коде:

# sklearn has a very convenient utility to build confusion matrices
from sklearn.metrics import confusion_matrix

# Build and print our confusion matrix, using the actual values and predictions 
# from the test set, calculated in previous cells
cm = confusion_matrix(actual, predictions, normalize=None)

print("Confusion matrix for the test set:")
print(cm)
Confusion matrix for the test set:
[[ 28  38   0   0]
 [ 30 103   1   0]
 [  0   1 217   1]
 [  0   0   0 241]]

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

# We use plotly to create plots and charts
import plotly.figure_factory as ff

# Create the list of unique labels in the test set, to use in our plot
# I.e., ['animal', 'hiker', 'rock', 'tree']
x = y = sorted(list(test["label"].unique()))

# Plot the matrix above as a heatmap with annotations (values) in its cells
fig = ff.create_annotated_heatmap(cm, x, y)

# Set titles and ordering
fig.update_layout(  title_text="<b>Confusion matrix</b>", 
                    yaxis = dict(categoryorder = "category descending"))

fig.add_annotation(dict(font=dict(color="black",size=14),
                        x=0.5,
                        y=-0.15,
                        showarrow=False,
                        text="Predicted label",
                        xref="paper",
                        yref="paper"))

fig.add_annotation(dict(font=dict(color="black",size=14),
                        x=-0.15,
                        y=0.5,
                        showarrow=False,
                        text="Actual label",
                        textangle=-90,
                        xref="paper",
                        yref="paper"))

# We need margins so the titles fit
fig.update_layout(margin=dict(t=80, r=20, l=100, b=50))
fig['data'][0]['showscale'] = True
fig.show()

Обратите внимание, что на графике есть Фактические метки на оси y и Прогнозированные метки на ось X, как определено вызовом функции confusion_matrix.

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

Когда дело доходит до путешественников и животных, модель запутывается (она показывает большое количество FP и FN), но поскольку эти классы менее представлены в наборе данных, показатель точности остается высоким.

Краткое содержание

В этом упражнении мы говорили о следующих понятиях:

  • Несбалансированные наборы данных, в которых объекты или классы могут быть представлены непропорциональным количеством образцов.
  • Точность как показатель оценки эффективности модели и ее недостатков.
  • Как генерировать, отображать и интерпретировать матрицы путаницы, чтобы лучше понять, как работает модель классификации.

Приятного обучения!
Далее ›› Матрица путаницы и дисбаланс данных (2/3)