Машинное обучение. Что делают методы fit() и predict()
Знакомлюсь с машинным обучением с помощью Python и библиотеки sklearn. Там есть 2 метода fit() и predict() Честно после некоторых сайтов понимаю,что они делают очень размыто.
lin_reg.fit(x_train[num_features], y_train)
fit(x,y) обучение (тренировка) модели на обучающей выборке X, y-цитата с форума А что это значит? 1)модель смотрит на x_train, выдает рандомное число и сранивает его с y_train? 2)модель смотрит на x_train и y_train и пытается найти какие-то взаимосвязи или настроить коэффициенты? Тут у меня и ступор. predict(X) предсказание на данных X -тоже цитата. То есть модель настроена и мы можем подавать ей входные данные?
y_pred=lin_reg.predict(x_train[num_features])
но меня тут смущает,почему для тренировки и предсказания мы испульзуем одни и те же данные? Разве не будет сбоя или модель не запомнит все ответы и выдаст 100% результат?
Отслеживать
149k 12 12 золотых знаков 59 59 серебряных знаков 132 132 бронзовых знака
задан 30 июн 2020 в 14:45
123 1 1 золотой знак 1 1 серебряный знак 9 9 бронзовых знаков
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
fit(x,y) обучение (тренировка) модели на обучающей выборке X, y-цитата с форума
А что это значит?
2)модель смотрит на x_train и y_train и пытается найти какие-то взаимосвязи или настроить коэффициенты?
Именно так. Модель пытается найти такие коэффициенты (ну, если примитивно говорить, реальные модели могут быть сильно сложнее, чем простой набор коэффициентов), чтобы минимизировать различие между предсказанием модели по данным x_train и реальным значением y_train.
predict(X) предсказание на данных X -тоже цитата.
То есть модель настроена и мы можем подавать ей входные данные?
y_pred=lin_reg.predict(x_train[num_features]) но меня тут смущает,почему для тренировки и предсказания мы испульзуем одни и те же данные? Разве не будет сбоя или модель не запомнит все ответы и выдаст 100% результат?
Достаточно сложная модель может запомнить все данные и давать на данных для обучения 100% точность, но цель же машинного обучения не в этом, а в том, чтобы модель хорошо предсказывала на тех данных, которых она ещё не видела. В данном случае просто проверяют, выучилась ли чему-то вообще модель, а то случаи бывают разные. Бывает, учишь модель, а она ничему не научилась вообще. Так что это просто примитивный «sanity check», а не реальная «боевая» ситуация. В реальной жизни, конечно, предсказывают уже на тестовых данных x_test.
А вообще тема машинного обучения довольно сложна, изучать её можно много лет. У вас вопросы совсем начинающего, постарайтесь почитать ещё какие-то статьи и литературу, там на все эти вопросы есть ответы. Лучше начать «от печки» — с теории, а не сразу применять библиотеки, не понимая, что они вообще делают.
1)модель смотрит на x_train, выдает рандомное число и сранивает его с y_train?
В некоторых моделях машинного обучения внутри действительно происходит что-то подобное, но далеко не во всех. Модель может искать нужные коэффициенты довольно разными способами. Важно понимать, что тренировка модели — это обычно сложный итеративный процесс. Модель подбирает каким-то образом коэффициенты (бывает, что и случайным), смотрит расхождение с целью, если оно большое — «думает» куда двигаться, пробует немного другие коэффициенты и т.д., пока не достигнет подходящего результата, либо не выйдет за отведённое ей на обучение число итераций.
Обзор методов классификации в машинном обучении с помощью Scikit-Learn
Для машинного обучения на Python написано очень много библиотек. Сегодня мы рассмотрим одну из самых популярных — Scikit-Learn.
Scikit-Learn упрощает процесс создания классификатора и помогает более чётко выделить концепции машинного обучения, реализуя их с помощью понятной, хорошо документированной и надёжной библиотекой.
Что такое Scikit-Learn?
Scikit-Learn — это Python-библиотека, впервые разработанная David Cournapeau в 2007 году. В этой библиотеке находится большое количество алгоритмов для задач, связанных с классификацией и машинным обучением в целом.
Scikit-Learn базируется на библиотеке SciPy, которую нужно установить перед началом работы.
Основные термины
В системах машинного обучения или же системах нейросетей существуют входы и выходы. То, что подаётся на входы, принято называть признаками (англ. features).
Признаки по существу являются тем же, что и переменные в научном эксперименте — они характеризуют какой-либо наблюдаемый феномен и их можно как-то количественно измерить.
Когда признаки подаются на входы системы машинного обучения, эта система пытается найти совпадения, заметить закономерность между признаками. На выходе генерируется результат этой работы.
Этот результат принято называть меткой (англ. label), поскольку у выходов есть некая пометка, выданная им системой, т. е. предположение (прогноз) о том, в какую категорию попадает выход после классификации.
В контексте машинного обучения классификация относится к обучению с учителем. Такой тип обучения подразумевает, что данные, подаваемые на входы системы, уже помечены, а важная часть признаков уже разделена на отдельные категории или классы. Поэтому сеть уже знает, какая часть входов важна, а какую часть можно самостоятельно проверить. Пример классификации — сортировка различных растений на группы, например «папоротники» и «покрытосеменные». Подобная задача может быть выполнена с помощью Дерева Решений — одного из типов классификатора в Scikit-Learn.
При обучении без учителя в систему подаются непомеченные данные, и она должна попытаться сама разделить эти данные на категории. Так как классификация относится к типу обучения с учителем, способ обучения без учителя в этой статье рассматриваться не будет.
Процесс обучения модели — это подача данных для нейросети, которая в результате должна вывести определённые шаблоны для данных. В процессе обучения модели с учителем на вход подаются признаки и метки, а при прогнозировании на вход классификатора подаются только признаки.
Принимаемые сетью данные делятся на две группы: набор данных для обучения и набор для тестирования. Не стоит проверять сеть на том же наборе данных, на которых она обучалась, т. к. модель уже будет «заточена» под этот набор.
Типы классификаторов
Scikit-Learn даёт доступ ко множеству различных алгоритмов классификации. Вот основные из них:
- Метод k-ближайших соседей (K-Nearest Neighbors);
- Метод опорных векторов (Support Vector Machines);
- Классификатор дерева решений (Decision Tree Classifier) / Случайный лес (Random Forests);
- Наивный байесовский метод (Naive Bayes);
- Линейный дискриминантный анализ (Linear Discriminant Analysis);
- Логистическая регрессия (Logistic Regression);
На сайте Scikit-Learn есть много литературы на тему этих алгоритмов с кратким пояснением работы каждого из них.
Обзор самых популярных алгоритмов машинного обучения
Метод k-ближайших соседей (K-Nearest Neighbors)
Этот метод работает с помощью поиска кратчайшей дистанции между тестируемым объектом и ближайшими к нему классифицированным объектами из обучающего набора. Классифицируемый объект будет относится к тому классу, к которому принадлежит ближайший объект набора.
Классификатор дерева решений (Decision Tree Classifier)
Этот классификатор разбивает данные на всё меньшие и меньшие подмножества на основе разных критериев, т. е. у каждого подмножества своя сортирующая категория. С каждым разделением количество объектов определённого критерия уменьшается.
Классификация подойдёт к концу, когда сеть дойдёт до подмножества только с одним объектом. Если объединить несколько подобных деревьев решений, то получится так называемый Случайный Лес (англ. Random Forest).
Наивный байесовский классификатор (Naive Bayes)
Такой классификатор вычисляет вероятность принадлежности объекта к какому-то классу. Эта вероятность вычисляется из шанса, что какое-то событие произойдёт, с опорой на уже на произошедшие события.
Каждый параметр классифицируемого объекта считается независимым от других параметров.
Линейный дискриминантный анализ (Linear Discriminant Analysis)
Этот метод работает путём уменьшения размерности набора данных, проецируя все точки данных на линию. Потом он комбинирует эти точки в классы, базируясь на их расстоянии от центральной точки.
Этот метод, как можно уже догадаться, относится к линейным алгоритмам классификации, т. е. он хорошо подходит для данных с линейной зависимостью.
Метод опорных векторов (Support Vector Machines)
Работа метода опорных векторов заключается в рисовании линии между разными кластерами точек, которые нужно сгруппировать в классы. С одной стороны линии будут точки, принадлежащие одному классу, с другой стороны — к другому классу.
Классификатор будет пытаться увеличить расстояние между рисуемыми линиями и точками на разных сторонах, чтобы увеличить свою «уверенность» определения класса. Когда все точки построены, сторона, на которую они падают — это класс, которому эти точки принадлежат.
Логистическая регрессия (Logistic Regression)
Логистическая регрессия выводит прогнозы о точках в бинарном масштабе — нулевом или единичном. Если значение чего-либо равно либо больше 0.5 , то объект классифицируется в большую сторону (к единице). Если значение меньше 0.5 — в меньшую (к нулю).
У каждого признака есть своя метка, равная только 0 или только 1. Логистическая регрессия является линейным классификатором и поэтому используется, когда в данных прослеживается какая-то линейная зависимость.
Примеры задач классификации
Задача классификации — эта любая задача, где нужно определить тип объекта из двух и более существующих классов. Такие задачи могут быть разными: определение, кошка на изображении или собака, или определение качества вина на основе его кислотности и содержания алкоголя.
В зависимости от задачи классификации вы будете использовать разные типы классификаторов. Например, если классификация содержит какую-то бинарную логику, то к ней лучше всего подойдёт логистическая регрессия.
По мере накопления опыта вам будет проще выбирать подходящий тип классификатора. Однако хорошей практикой является реализация нескольких подходящих классификаторов и выбор наиболее оптимального и производительного.
Реализация классификатора
Первый шаг в реализации классификатора — его импорт в Python. Вот как это выглядит для логистической регрессии:
from sklearn.linear_model import LogisticRegression
Вот импорты остальных классификаторов, рассмотренных выше:
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis from sklearn.neighbors import KNeighborsClassifier from sklearn.naive_bayes import GaussianNB from sklearn.tree import DecisionTreeClassifier from sklearn.svm import SVC
Однако, это не все классификаторы, которые есть в Scikit-Learn. Про остальные можно прочитать на соответствующей странице в документации.
После этого нужно создать экземпляр классификатора. Сделать это можно создав переменную и вызвав функцию, связанную с классификатором.
logreg_clf = LogisticRegression()
Теперь классификатор нужно обучить. Перед этим нужно «подогнать» его под тренировочные данные.
Обучающие признаки и метки помещаются в классификатор через функцию fit :
logreg_clf.fit(features, labels)
После обучения модели данные уже можно подавать в классификатор. Это можно сделать через функцию классификатора predict , передав ей параметр (признак) для прогнозирования:
logreg_clf.predict(test_features)
Эти этапы (создание экземпляра, обучение и классификация) являются основными при работе с классификаторами в Scikit-Learn. Но эта библиотека может управлять не только классификаторами, но и самими данными. Чтобы разобраться в том, как данные и классификатор работают вместе над задачей классификации, нужно разобраться в процессах машинного обучения в целом.
Процесс машинного обучения
Процесс содержит в себе следующие этапы: подготовка данных, создание обучающих наборов, создание классификатора, обучение классификатора, составление прогнозов, оценка производительности классификатора и настройка параметров.
Во-первых, нужно подготовить набор данных для классификатора — преобразовать данные в корректную для классификации форму и обработать любые аномалии в этих данных. Отсутствие значений в данных либо любые другие отклонения — все их нужно обработать, иначе они могут негативно влиять на производительность классификатора. Этот этап называется предварительной обработкой данных (англ. data preprocessing).
Следующим шагом будет разделение данных на обучающие и тестовые наборы. Для этого в Scikit-Learn существует отличная функция traintestsplit.
Как уже было сказано выше, классификатор должен быть создан и обучен на тренировочном наборе данных. После этих шагов модель уже может делать прогнозы. Сравнивая показания классификатора с фактически известными данными, можно делать вывод о точности классификатора.
Вероятнее всего, вам нужно будет «корректировать» параметры классификатора, пока вы не достигните желаемой точности (т. к. маловероятно, что классификатор будет соответствовать всем вашим требованиям с первого же запуска).
Ниже будет представлен пример работы машинного обучения от обработки данных и до оценки.
Реализация образца классификации
# Импорт всех нужных библиотек import pandas as pd from sklearn.metrics import classification_report from sklearn.metrics import confusion_matrix from sklearn.metrics import accuracy_score from sklearn.neighbors import KNeighborsClassifier from sklearn.svm import SVC
Поскольку набор данных iris достаточно распространён, в Scikit-Learn он уже присутствует, достаточно лишь заложить эту команду:
sklearn.datasets.load_iris
Тем не менее, тут ещё нужно подгрузить CSV-файл, который можно скачать здесь.
Этот файл нужно поместить в ту же папку, что и Python-файл. В библиотеке Pandas есть функция read_csv() , которая отлично работает с загрузкой данных.
data = pd.read_csv('iris.csv') # Проверяем, всё ли правильно загрузилось print(data.head(5))
Благодаря тому, что данные уже были подготовлены, долгой предварительной обработки они не требуют. Единственное, что может понадобиться — убрать ненужные столбцы (например ID ) таким образом:
data.drop('Id', axis=1, inplace=True)
Теперь нужно определить признаки и метки. С библиотекой Pandas можно легко «нарезать» таблицу и выбрать определённые строки/столбцы с помощью функции iloc() :
# ".iloc" принимает row_indexer, column_indexer X = data.iloc[. -1].values # Теперь выделим нужный столбец y = data['Species']
Код выше выбирает каждую строку и столбец, обрезав при этом последний столбец.
Выбрать признаки интересующего вас набора данных можно также передав в скобках заголовки столбцов:
# Альтернативный способ выбора нужных столбцов: X = data.iloc['SepalLengthCm', 'SepalWidthCm', 'PetalLengthCm']
После того, как вы выбрали нужные признаки и метки, их можно разделить на тренировочные и тестовые наборы, используя функцию train_test_split() :
# test_size показывает, какой объем данных нужно выделить для тестового набора # Random_state — просто сид для случайной генерации # Этот параметр можно использовать для воссоздания определённого результата: X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=27)
Чтобы убедиться в правильности обработки данных, используйте:
print(X_train) print(y_train)
Теперь можно создавать экземпляр классификатора, например метод опорных векторов и метод k-ближайших соседей:
SVC_model = svm.SVC() # В KNN-модели нужно указать параметр n_neighbors # Это число точек, на которое будет смотреть # классификатор, чтобы определить, к какому классу принадлежит новая точка KNN_model = KNeighborsClassifier(n_neighbors=5)
Теперь нужно обучить эти два классификатора:
SVC_model.fit(X_train, y_train) KNN_model.fit(X_train, y_train)
Эти команды обучили модели и теперь классификаторы могут делать прогнозы и сохранять результат в какую-либо переменную.
SVC_prediction = SVC_model.predict(X_test) KNN_prediction = KNN_model.predict(X_test)
Теперь пришло время оценить точности классификатора. Существует несколько способов это сделать.
Нужно передать показания прогноза относительно фактически верных меток, значения которых были сохранены ранее.
# Оценка точности — простейший вариант оценки работы классификатора print(accuracy_score(SVC_prediction, y_test)) print(accuracy_score(KNN_prediction, y_test)) # Но матрица неточности и отчёт о классификации дадут больше информации о производительности print(confusion_matrix(SVC_prediction, y_test)) print(classification_report(KNN_prediction, y_test))
Вот, к примеру, результат полученных метрик:
SVC accuracy: 0.9333333333333333 KNN accuracy: 0.9666666666666667
Поначалу кажется, что KNN работает точнее. Вот матрица неточностей для SVC:
[[ 7 0 0] [ 0 10 1] [ 0 1 11]]
Количество правильных прогнозов идёт с верхнего левого угла в нижний правый. Вот для сравнения метрики классификации для KNN:
precision recall f1-score support Iris-setosa 1.00 1.00 1.00 7 Iris-versicolor 0.91 0.91 0.91 11 Iris-virginica 0.92 0.92 0.92 12 micro avg 0.93 0.93 0.93 30 macro avg 0.94 0.94 0.94 30 weighted avg 0.93 0.93 0.93 30
Оценка классификатора
Когда дело доходит до оценки точности классификатора, есть несколько вариантов.
Точность классификации
Точность классификации измерять проще всего, и поэтому этот параметр чаще всего используется. Значение точности — это число правильных прогнозов, делённое на число всех прогнозов или, проще говоря, отношение правильных прогнозов ко всем.
Хоть этот показатель и может быстро дать вам явное представление о производительности классификатора, его лучше использовать, когда каждый класс имеет хотя бы примерно одинаковое количество примеров. Так как такое будет случаться редко, рекомендуется использовать другие показатели классификации.
Логарифмические потери
Значение Логарифмических Потерь (англ. Logarithmic Loss) — или просто логлосс — показывает, насколько классификатор «уверен» в своём прогнозе. Логлосс возвращает вероятность принадлежности объекта к тому или иному классу, суммируя их, чтобы дать общее представление об «уверенности» классификатора.
Этот показатель лежит в промежутке от 0 до 1 — «совсем не уверен» и «полностью уверен» соответственно. Логлосс сильно падает, когда классификатор сильно «уверен» в неправильном ответе.
Площадь ROC-кривой (AUC)
Такой показатель используется только при бинарной классификации. Площадь под ROC-кривой представляет способность классификатора различать подходящие и не подходящие какому-либо классу объекты.
Значение 1.0 : вся область, попадающая под кривую, представляет собой идеальный классификатор. Следовательно, 0.5 означает, что точность классификатора соответствует случайности. Кривая рассчитывается с учётом точности и специфичности модели. Подробнее о расчётах можно прочитать здесь.
Матрица неточностей
Матрица неточностей (англ. Confusion Matrix) — это таблица или диаграмма, показывающая точность прогнозирования классификатора в отношении двух и более классов. Прогнозы классификатора находятся на оси X, а результат (точность) — на оси Y.
Ячейки таблицы заполняются количеством прогнозов классификатора. Правильные прогнозы идут по диагонали от верхнего левого угла в нижний правый. Про это можно почитать в данной статье.
Отчёт о классификации
В библиотеке Scikit-Learn уже встроена возможность создавать отчёты о производительности классификатора. Эти отчёты дают интуитивно понятное представление о работе модели.
Заключение
Чтобы лучше вникнуть в работу с Scikit-Learn, неплохо было бы узнать больше о работе различных методов классификации. После этого стоит лучше узнать о замере производительности классификаторов. Однако понимание многих нюансов в классификации приходит только со временем.
Метрики в задачах машинного обучения
В задачах машинного обучения для оценки качества моделей и сравнения различных алгоритмов используются метрики, а их выбор и анализ — непременная часть работы датасатаниста.
В этой статье мы рассмотрим некоторые критерии качества в задачах классификации, обсудим, что является важным при выборе метрики и что может пойти не так.
Метрики в задачах классификации
Для демонстрации полезных функций sklearn и наглядного представления метрик мы будем использовать датасет по оттоку клиентов телеком-оператора.
Загрузим необходимые библиотеки и посмотрим на данные
import pandas as pd import matplotlib.pyplot as plt from matplotlib.pylab import rc, plot import seaborn as sns from sklearn.preprocessing import LabelEncoder, OneHotEncoder from sklearn.model_selection import cross_val_score from sklearn.linear_model import LogisticRegression from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier from sklearn.metrics import precision_recall_curve, classification_report from sklearn.model_selection import train_test_split df = pd.read_csv('../../data/telecom_churn.csv')
df.head(5)
Предобработка данных
# Сделаем маппинг бинарных колонок # и закодируем dummy-кодированием штат (для простоты, лучше не делать так для деревянных моделей) d = df['International plan'] = df['International plan'].map(d) df['Voice mail plan'] = df['Voice mail plan'].map(d) df['Churn'] = df['Churn'].astype('int64') le = LabelEncoder() df['State'] = le.fit_transform(df['State']) ohe = OneHotEncoder(sparse=False) encoded_state = ohe.fit_transform(df['State'].values.reshape(-1, 1)) tmp = pd.DataFrame(encoded_state, columns=['state ' + str(i) for i in range(encoded_state.shape[1])]) df = pd.concat([df, tmp], axis=1)
Accuracy, precision и recall
Перед переходом к самим метрикам необходимо ввести важную концепцию для описания этих метрик в терминах ошибок классификации — confusion matrix (матрица ошибок).
Допустим, что у нас есть два класса и алгоритм, предсказывающий принадлежность каждого объекта одному из классов, тогда матрица ошибок классификации будет выглядеть следующим образом:
| True Positive (TP) | False Positive (FP) |
| False Negative (FN) | True Negative (TN) |
Здесь — это ответ алгоритма на объекте, а — истинная метка класса на этом объекте.
Таким образом, ошибки классификации бывают двух видов: False Negative (FN) и False Positive (FP).
Обучение алгоритма и построение матрицы ошибок
X = df.drop('Churn', axis=1) y = df['Churn'] # Делим выборку на train и test, все метрики будем оценивать на тестовом датасете X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, test_size=0.33, random_state=42) # Обучаем ставшую родной логистическую регрессию lr = LogisticRegression(random_state=42) lr.fit(X_train, y_train) # Воспользуемся функцией построения матрицы ошибок из документации sklearn def plot_confusion_matrix(cm, classes, normalize=False, title='Confusion matrix', cmap=plt.cm.Blues): """ This function prints and plots the confusion matrix. Normalization can be applied by setting `normalize=True`. """ plt.imshow(cm, interpolation='nearest', cmap=cmap) plt.title(title) plt.colorbar() tick_marks = np.arange(len(classes)) plt.xticks(tick_marks, classes, rotation=45) plt.yticks(tick_marks, classes) if normalize: cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis] print("Normalized confusion matrix") else: print('Confusion matrix, without normalization') print(cm) thresh = cm.max() / 2. for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])): plt.text(j, i, cm[i, j], horizontalalignment="center", color="white" if cm[i, j] > thresh else "black") plt.tight_layout() plt.ylabel('True label') plt.xlabel('Predicted label') font = plt.rc('font', **font) cnf_matrix = confusion_matrix(y_test, lr.predict(X_test)) plt.figure(figsize=(10, 8)) plot_confusion_matrix(cnf_matrix, classes=['Non-churned', 'Churned'], title='Confusion matrix') plt.savefig("conf_matrix.png") plt.show()

Accuracy
Интуитивно понятной, очевидной и почти неиспользуемой метрикой является accuracy — доля правильных ответов алгоритма:
Эта метрика бесполезна в задачах с неравными классами, и это легко показать на примере.
Допустим, мы хотим оценить работу спам-фильтра почты. У нас есть 100 не-спам писем, 90 из которых наш классификатор определил верно (True Negative = 90, False Positive = 10), и 10 спам-писем, 5 из которых классификатор также определил верно (True Positive = 5, False Negative = 5).
Тогда accuracy:
Однако если мы просто будем предсказывать все письма как не-спам, то получим более высокую accuracy:
При этом, наша модель совершенно не обладает никакой предсказательной силой, так как изначально мы хотели определять письма со спамом. Преодолеть это нам поможет переход с общей для всех классов метрики к отдельным показателям качества классов.
Precision, recall и F-мера
Для оценки качества работы алгоритма на каждом из классов по отдельности введем метрики precision (точность) и recall (полнота).
Precision можно интерпретировать как долю объектов, названных классификатором положительными и при этом действительно являющимися положительными, а recall показывает, какую долю объектов положительного класса из всех объектов положительного класса нашел алгоритм.

Именно введение precision не позволяет нам записывать все объекты в один класс, так как в этом случае мы получаем рост уровня False Positive. Recall демонстрирует способность алгоритма обнаруживать данный класс вообще, а precision — способность отличать этот класс от других классов.
Как мы отмечали ранее, ошибки классификации бывают двух видов: False Positive и False Negative. В статистике первый вид ошибок называют ошибкой I-го рода, а второй — ошибкой II-го рода. В нашей задаче по определению оттока абонентов, ошибкой первого рода будет принятие лояльного абонента за уходящего, так как наша нулевая гипотеза состоит в том, что никто из абонентов не уходит, а мы эту гипотезу отвергаем. Соответственно, ошибкой второго рода будет являться «пропуск» уходящего абонента и ошибочное принятие нулевой гипотезы.
Precision и recall не зависят, в отличие от accuracy, от соотношения классов и потому применимы в условиях несбалансированных выборок.
Часто в реальной практике стоит задача найти оптимальный (для заказчика) баланс между этими двумя метриками. Классическим примером является задача определения оттока клиентов.
Очевидно, что мы не можем находить всех уходящих в отток клиентов и только их. Но, определив стратегию и ресурс для удержания клиентов, мы можем подобрать нужные пороги по precision и recall. Например, можно сосредоточиться на удержании только высокодоходных клиентов или тех, кто уйдет с большей вероятностью, так как мы ограничены в ресурсах колл-центра.
Обычно при оптимизации гиперпараметров алгоритма (например, в случае перебора по сетке GridSearchCV ) используется одна метрика, улучшение которой мы и ожидаем увидеть на тестовой выборке.
Существует несколько различных способов объединить precision и recall в агрегированный критерий качества. F-мера (в общем случае ) — среднее гармоническое precision и recall :
в данном случае определяет вес точности в метрике, и при это среднее гармоническое (с множителем 2, чтобы в случае precision = 1 и recall = 1 иметь )
F-мера достигает максимума при полноте и точности, равными единице, и близка к нулю, если один из аргументов близок к нулю.
В sklearn есть удобная функция _metrics.classificationreport, возвращающая recall, precision и F-меру для каждого из классов, а также количество экземпляров каждого класса.
report = classification_report(y_test, lr.predict(X_test), target_names=['Non-churned', 'Churned']) print(report)
| class | precision | recall | f1-score | support |
|---|---|---|---|---|
| Non-churned | 0.88 | 0.97 | 0.93 | 941 |
| Churned | 0.60 | 0.25 | 0.35 | 159 |
| avg / total | 0.84 | 0.87 | 0.84 | 1100 |
Здесь необходимо отметить, что в случае задач с несбалансированными классами, которые превалируют в реальной практике, часто приходится прибегать к техникам искусственной модификации датасета для выравнивания соотношения классов. Их существует много, и мы не будем их касаться, здесь можно посмотреть некоторые методы и выбрать подходящий для вашей задачи.
AUC-ROC и AUC-PR
При конвертации вещественного ответа алгоритма (как правило, вероятности принадлежности к классу, отдельно см. SVM) в бинарную метку, мы должны выбрать какой-либо порог, при котором 0 становится 1. Естественным и близким кажется порог, равный 0.5, но он не всегда оказывается оптимальным, например, при вышеупомянутом отсутствии баланса классов.
Одним из способов оценить модель в целом, не привязываясь к конкретному порогу, является AUC-ROC (или ROC AUC) — площадь (Area Under Curve) под кривой ошибок (Receiver Operating Characteristic curve ). Данная кривая представляет из себя линию от (0,0) до (1,1) в координатах True Positive Rate (TPR) и False Positive Rate (FPR):
TPR нам уже известна, это полнота, а FPR показывает, какую долю из объектов negative класса алгоритм предсказал неверно. В идеальном случае, когда классификатор не делает ошибок (FPR = 0, TPR = 1) мы получим площадь под кривой, равную единице; в противном случае, когда классификатор случайно выдает вероятности классов, AUC-ROC будет стремиться к 0.5, так как классификатор будет выдавать одинаковое количество TP и FP.
Каждая точка на графике соответствует выбору некоторого порога. Площадь под кривой в данном случае показывает качество алгоритма (больше — лучше), кроме этого, важной является крутизна самой кривой — мы хотим максимизировать TPR, минимизируя FPR, а значит, наша кривая в идеале должна стремиться к точке (0,1).
Код отрисовки ROC-кривой
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()

Критерий AUC-ROC устойчив к несбалансированным классам (спойлер: увы, не всё так однозначно) и может быть интерпретирован как вероятность того, что случайно выбранный positive объект будет проранжирован классификатором выше (будет иметь более высокую вероятность быть positive), чем случайно выбранный negative объект.
Рассмотрим следующую задачу: нам необходимо выбрать 100 релевантных документов из 1 миллиона документов. Мы намашинлернили два алгоритма:
- Алгоритм 1 возвращает 100 документов, 90 из которых релевантны. Таким образом,
- Алгоритм 2 возвращает 2000 документов, 90 из которых релевантны. Таким образом,
Скорее всего, мы бы выбрали первый алгоритм, который выдает очень мало False Positive на фоне своего конкурента. Но разница в False Positive Rate между этими двумя алгоритмами крайне мала — всего 0.0019. Это является следствием того, что AUC-ROC измеряет долю False Positive относительно True Negative и в задачах, где нам не так важен второй (больший) класс, может давать не совсем адекватную картину при сравнении алгоритмов.
Для того чтобы поправить положение, вернемся к полноте и точности :
Здесь уже заметна существенная разница между двумя алгоритмами — 0.855 в точности!
Precision и recall также используют для построения кривой и, аналогично AUC-ROC, находят площадь под ней.

Здесь можно отметить, что на маленьких датасетах площадь под PR-кривой может быть чересчур оптимистична, потому как вычисляется по методу трапеций, но обычно в таких задачах данных достаточно. За подробностями о взаимоотношениях AUC-ROC и AUC-PR можно обратиться сюда.
Logistic Loss
Особняком стоит логистическая функция потерь, определяемая как:
здесь — это ответ алгоритма на -ом объекте, — истинная метка класса на -ом объекте, а размер выборки.
Подробно про математическую интерпретацию логистической функции потерь уже написано в рамках поста про линейные модели.
Данная метрика нечасто выступает в бизнес-требованиях, но часто — в задачах на kaggle.
Интуитивно можно представить минимизацию logloss как задачу максимизации accuracy путем штрафа за неверные предсказания. Однако необходимо отметить, что logloss крайне сильно штрафует за уверенность классификатора в неверном ответе.
def logloss_crutch(y_true, y_pred, eps=1e-15): return - (y_true * np.log(y_pred) + (1 - y_true) * np.log(1 - y_pred)) print('Logloss при неуверенной классификации %f' % logloss_crutch(1, 0.5)) >> Logloss при неуверенной классификации 0.693147 print('Logloss при уверенной классификации и верном ответе %f' % logloss_crutch(1, 0.9)) >> Logloss при уверенной классификации и верном ответе 0.105361 print('Logloss при уверенной классификации и НЕверном ответе %f' % logloss_crutch(1, 0.1)) >> Logloss при уверенной классификации и НЕверном ответе 2.302585
Отметим, как драматически выросла logloss при неверном ответе и уверенной классификации!
Следовательно, ошибка на одном объекте может дать существенное ухудшение общей ошибки на выборке. Такие объекты часто бывают выбросами, которые нужно не забывать фильтровать или рассматривать отдельно.
Всё становится на свои места, если нарисовать график logloss:

Видно, что чем ближе к нулю ответ алгоритма при ground truth = 1, тем выше значение ошибки и круче растёт кривая.
Подытожим:
- В случае многоклассовой классификации нужно внимательно следить за метриками каждого из классов и следовать логике решения задачи, а не оптимизации метрики
- В случае неравных классов нужно подбирать баланс классов для обучения и метрику, которая будет корректно отражать качество классификации
- Выбор метрики нужно делать с фокусом на предметную область, предварительно обрабатывая данные и, возможно, сегментируя (как в случае с делением на богатых и бедных клиентов)
Полезные ссылки
- Курс Евгения Соколова: Семинар по выбору моделей (там есть информация по метрикам задач регрессии)
- Задачки на AUC-ROC от А.Г. Дьяконова
- Дополнительно о других метриках можно почитать на kaggle. К описанию каждой метрики добавлена ссылка на соревнования, где она использовалась
- Презентация Богдана Мельника aka ld86 про обучение на несбалансированных выборках
Благодарности
Спасибо mephistopheies и madrugado за помощь в подготовке статьи.
Введение в машинное обучение в Python: Полное руководство с примерами

Вы хотите сделать машинное обучение с помощью Python, но у вас возникли вопросы с чего начать? В этом уроке вы сделаете свой первый проект по машинному обучению с помощью Python. В уроке мы разберем шаг за шагом как:
- Скачать и установить Python SciPy и какие самые полезные пакеты для машинного обучения в Python.
- Загрузить датасет, поймем его структуру с помощью статистических методов и визуализируем данные
- Создадим 6 моделей машинного обучения, выберем лучшую и убедимся что точность модели является приемлемой
Если вы новичок в машинном обучении и хотите начать использовать Python, этот урок был разработан для вас.
Как начать использовать машинное обучение в Python?
Лучший способ научиться машинному обучению — проектировать и завершать небольшие проекты.
Python может быть пугающим при начале работы
Python является популярным и мощным интерпретируемым языком. В отличие от R, Python является и полным языком и платформой, которые можно использовать как для исследований, численных расчетов, так и для разработки производственных систем.
В Python есть также много модулей и библиотек на выбор, обеспечивая несколько способов выполнения каждой задачи.
Лучший способ начать использовать Python для машинного обучения — это разобрать готовый проект по машинному обучению и затем его сделать самому с нуля:
- Это заставит вас установить и запустить Python интерпретатор.
- Это даст вам понимание с высоты птичьего полета о том, как выглядит небольшой проект.
- Это даст вам уверенность, чтобы перейти к собственным задача и проектам.
Новичкам нужен небольшой сквозной проект
Книги и курсы порой часто расстраивают. Они дают вам много теоретических конструкций и фрагментов, но вы никогда не увидите, как все они сочетаются друг с другом.
Когда вы применяете машинное обучение к собственному датасету, вы работаете над проектом. Проект по машинному обучению может быть не всегда последовательным, но обычно он имеет несколько выраженных этапов:
- Постановка задачи
- Подготовка данных
- Оценка качества алгоритмов
- Оптимизация результата
- Презентация результата.
Лучший способ по-настоящему примириться с новой платформой или инструментом – это работать над проектом машинного обучения и покрыть эти ключевые этапы.
Если вы можете сделать это, у вас будет шаблон, который можно будет использовать в будущем на другой выборке данных или задаче. Вы сможете заполнить пробелы, такие как дальнейшая подготовка данных и улучшение алгоритмов.
«Hello World!» машинного обучения
Отличным примером небольшого проекта чтобы начать является задача классификация цветов (на примере цветов ириса).
Это хороший проект, потому что он легко интерпретируется.
- Атрибуты данных являются числовыми, так что вы должны разобраться, как загрузить и обрабатывать данные
- Это проблема классификации, позволяющая практиковаться с, возможно, более простым типом контролируемого алгоритма обучения
- Задача является многоклассовой классификацией и может потребовать некоторой специализированной обработки
- Выборка имеет только 4 атрибута и 150 строк, что означает, что она достаточно мала, легко будет обработана в операционном памяти локальном компьютера (и легко визуализировать на экране)
- Все числовые атрибуты находятся в одном и том же масштабе и одинаковой шкале, не требуя специальной нормализации или масштабирования для начала работы
Давайте начнем проект «hello world» машинного обучения в Python.
Машинное обучение в Python (начало проекта)
Вот краткий обзор того, что мы собираемся охватить:
- Установка платформы Python и SciPy
- Загрузка датасета
- Анализ датасета
- Визуализация данных
- Оценка алгоритмов машинного обучения
- Прогнозирование данных
Не торопитесь, проработайте и поймете, что происходит на каждом шагу. Мы рекомендуем самостоятельно вводить команды.
Если у вас есть какие-либо вопросы, пожалуйста, задавайте их в чат.
1. Загрузка, установка и запуск Python и SciPy
Раздел для тех, у кого ее не установлен Python и SciPy. Мы не будем подробно останавливаться на том как устанавливать Python, есть много пошаговых руководств в интернете как это сделать или рекомендуем посетить раздел «Введение в Python».
1.1 Установка библиотек SciPy
Есть 5 ключевых библиотек, которые необходимо установить. Ниже приведен список библиотек Python SciPy, необходимых для этого руководства:
На сайте SciPy есть отличная инструкция по установке вышеуказанных библиотек на ключевых платформах: Windows, Linux, OS X mac. Если у вас есть какие-либо сомнения или вопросы, обратитесь к этому руководству, через него прошли миллионы людей.
Существует множество способов установить библиотеки. В качестве совета мы рекомендуем выбрать один метод и быть последовательным в установке каждой библиотеки. Если вы пользуетесь Windows или вы не уверены как это сделать, мы рекомендую установить бесплатную версию Anaconda, которая включает в себя все, что вам нужно (windows, macOS, Linux).
1.2 Запуск Python и проверка версий
Рекомендуется убедиться, что среда Python была успешно установлена и работает в штатном состоянии. Сценарий ниже поможет вам проверить вашу среду. Он импортирует каждую библиотеку, требуемую в этом учебнике, и печатает версию.
Откройте командную строку и запустите Python:
python
Мы рекомендуем работать непосредственно в интерпретаторе или писать скрипты и запускать их в командной строке, нежели редакторах и IDEs. Это позволит сосредоточиться на машинном обучении, а не инструментарии программиста.
Введите или скопируйте и вставьте следующий скрипт в интерпретатор:
# Проерка версий библиотек # Версия Python import sys print('Python: <>'.format(sys.version)) # Загрузка scipy import scipy print('scipy: <>'.format(scipy.__version__)) # Загрузка numpy import numpy print('numpy: <>'.format(numpy.__version__)) # Загрузка matplotlib import matplotlib print('matplotlib: <>'.format(matplotlib.__version__)) # Загрузка pandas import pandas print('pandas: <>'.format(pandas.__version__)) # Загрукзка scikit-learn import sklearn print('sklearn: <>'.format(sklearn.__version__))
Вот пример вывода:
Python: 3.7.0 (default, Jun 28 2018, 08:04:48) [MSC v.1912 64 bit (AMD64)] scipy: 1.1.0 numpy: 1.15.1 matplotlib: 2.2.3 pandas: 0.23.4 sklearn: 0.19.2
В идеале, ваши версии должны соответствовать или быть более поздними. API библиотек не меняются быстро, так что не не стоит переживать, если ваша версии другие. Все в этом урове, скорее всего, все еще будет работать для вас.
Если же выдает ошибку, рекомендуем обновить версионность системы. Если вы не можете запустить скрипт выше, вы не сможете пройти урок.
2. Загрузите данные
Мы будем использовать датасет цветов ирисов Фишера. Этот датасет известен тем, что он используется практически всеми в качестве «hello world» примера в машинном обучении и статистике.
Набор данных содержит 150 наблюдений за цветами ириса. В датасете есть четыре колонки измерений цветов в сантиметрах. Пятая колонна является видом наблюдаемого цветка.
Все наблюдаемые цветы принадлежат к одному из трех видов. Узнать больше об этом датасете можно в Википедия.
На этом этапе мы загрузим данные из URL-адреса в CSV файл.
2.1 Импорт библиотек
Во-первых, давайте импортировать все модули, функции и объекты, которые мы планируем использовать в этом уроке.
# Загрузка библиотек from pandas import read_csv from pandas.plotting import scatter_matrix from matplotlib import pyplot from sklearn.model_selection import train_test_split from sklearn.model_selection import cross_val_score from sklearn.model_selection import StratifiedKFold from sklearn.metrics import classification_report from sklearn.metrics import confusion_matrix from sklearn.metrics import accuracy_score from sklearn.linear_model import LogisticRegression from sklearn.tree import DecisionTreeClassifier from sklearn.neighbors import KNeighborsClassifier from sklearn.discriminant_analysis import LinearDiscriminantAnalysis from sklearn.naive_bayes import GaussianNB from sklearn.svm import SVC
Все должно загружаться без ошибок. Если у вас есть ошибка, остановитесь. Перед продолжением необходима рабочая среда SciPy. Посмотрите совет выше о настройке вашей среды.
2.2 Загрузка датасета
Мы можем загрузить данные непосредственно из репозитория машинного обучения UCI.
Мы используем модуль pandas для загрузки данных. Мы также будем использовать pandas чтобы исследовать данные как целей описательной статистики, так для визуализации данных.
Обратите внимание, что при загрузке данных мы указываем имена каждого столбца. Это поможет позже, когда мы будем исследовать данные.
# Загрузка датасета url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/iris.csv" names = ['sepal-length', 'sepal-width', 'petal-length', 'petal-width', 'class'] dataset = read_csv(url, names=names)
Датасет должен загрузиться без происшествий.
Если у вас есть проблемы с сетью, вы можете скачать файл iris.csv в рабочую директорию и загрузить его с помощью того же метода, изменив URL на локальное имя файла.
3. Анализ датасета
Теперь пришло время взглянуть на данные более детально. На этом этапе мы погрузимся в анализ данные несколькими способами:
- Размерность датасета
- Просмотр среза данных
- Статистическая сводка атрибутов
- Разбивка данных по атрибуту класса.
Не волнуйтесь, каждый взгляд на данные является одной командой. Это полезные команды, которые можно использовать снова и снова в будущих проектах.
3.1 Размерность датасета
Мы можем получить быстрое представление о том, сколько экземпляров (строк) и сколько атрибутов (столбцов) содержится в датасете с помощью метода shape.
# shape print(dataset.shape)
Вы должны увидеть 150 экземпляров и 5 атрибутов:
(150, 5)
3.2 Просмотр среза данных
Исследовании данных, стоит сразу в них заглянуть, для этого есть метод head()
# Срез данных head print(dataset.head(20))
Это должно вывести первые 20 строк датасета.
sepal-length sepal-width petal-length petal-width class 0 5.1 3.5 1.4 0.2 Iris-setosa 1 4.9 3.0 1.4 0.2 Iris-setosa 2 4.7 3.2 1.3 0.2 Iris-setosa 3 4.6 3.1 1.5 0.2 Iris-setosa 4 5.0 3.6 1.4 0.2 Iris-setosa 5 5.4 3.9 1.7 0.4 Iris-setosa 6 4.6 3.4 1.4 0.3 Iris-setosa 7 5.0 3.4 1.5 0.2 Iris-setosa 8 4.4 2.9 1.4 0.2 Iris-setosa 9 4.9 3.1 1.5 0.1 Iris-setosa 10 5.4 3.7 1.5 0.2 Iris-setosa 11 4.8 3.4 1.6 0.2 Iris-setosa 12 4.8 3.0 1.4 0.1 Iris-setosa 13 4.3 3.0 1.1 0.1 Iris-setosa 14 5.8 4.0 1.2 0.2 Iris-setosa 15 5.7 4.4 1.5 0.4 Iris-setosa 16 5.4 3.9 1.3 0.4 Iris-setosa 17 5.1 3.5 1.4 0.3 Iris-setosa 18 5.7 3.8 1.7 0.3 Iris-setosa 19 5.1 3.8 1.5 0.3 Iris-setosa
3.3 Статистическая сводка
Давайте взглянем теперь на статистическое резюме каждого атрибута. Статистическая сводка включает в себя количество экземпляров, их среднее, мин и макс значения, а также некоторые процентили.
# Стастические сводка методом describe print(dataset.describe())
Мы видим, что все численные значения имеют одинаковую шкалу (сантиметры) и аналогичные диапазоны от 0 до 8 сантиметров.
sepal-length sepal-width petal-length petal-width count 150.000000 150.000000 150.000000 150.000000 mean 5.843333 3.054000 3.758667 1.198667 std 0.828066 0.433594 1.764420 0.763161 min 4.300000 2.000000 1.000000 0.100000 25% 5.100000 2.800000 1.600000 0.300000 50% 5.800000 3.000000 4.350000 1.300000 75% 6.400000 3.300000 5.100000 1.800000 max 7.900000 4.400000 6.900000 2.500000
3.4 Распределение классов
Давайте теперь рассмотрим количество экземпляров (строк), которые принадлежат к каждому классу. Мы можем рассматривать это как абсолютный счет.
# Распределение по атрибуту class print(dataset.groupby('class').size())
Мы видим, что каждый класс имеет одинаковое количество экземпляров (50 или 33% от датасета).
class Iris-setosa 50 Iris-versicolor 50 Iris-virginica 50 dtype: int64
3.5 Резюме загрузки датасета
На будущее мы можем объединить все предыдущие элементы вместе в один скрипт..
# Загрузка библиотек from pandas import read_csv # Загрузка датасета url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/iris.csv" names = ['sepal-length', 'sepal-width', 'petal-length', 'petal-width', 'class'] dataset = read_csv(url, names=names) # shape print(dataset.shape) # Срез данных head print(dataset.head(20)) # Стастические сводка методом describe print(dataset.describe()) # Распределение по атрибуту class print(dataset.groupby('class').size())
4. Визуализация данных
Теперь когда у нас есть базовое представление о данных, давайте расширим его с помощью визуализаций.
Мы рассмотрим два типа графиков:
- Одномерные (Univariate) графики, чтобы лучше понять каждый атрибут.
- Многомерные (Multivariate) графики, чтобы лучше понять взаимосвязь между атрибутами.
4.1 Одномерные графики
Начнем с некоторых одномерных графиков, то есть графики каждой отдельной переменной. Учитывая, что входные переменные являются числовыми, мы можем создавать диаграмма размаха (или «ящик с усами», по-английски «box and whiskers diagram») каждого из них.
# Диаграмма размаха dataset.plot(kind='box', subplots=True, layout=(2,2), sharex=False, sharey=False) pyplot.show()
Это дает нам более четкое представление о распределении атрибутов на входе.

Мы также можем создать гистограмму входных данных каждой переменной, чтобы получить представление о распределении.
# Гистограмма распределения атрибутов датасета dataset.hist() pyplot.show()
Из графиков видно, что две из входных переменных имеют около гауссово (нормальное) распределение. Это полезно отметить, поскольку мы можем использовать алгоритмы, которые могут использовать это предположение.

4.2 Многомерные графики
Теперь мы можем посмотреть на взаимодействия между переменными.
Во-первых, давайте посмотрим на диаграммы рассеяния всех пар атрибутов. Это может быть полезно для выявления структурированных взаимосвязей между входными переменными.
#Матрица диаграмм рассеяния scatter_matrix(dataset) pyplot.show()
Обратите внимание на диагональ некоторых пар атрибутов. Это говорит о высокой корреляции и предсказуемой взаимосвязи.

4.3 Резюме визуализации данных
Для справки мы можем связать все предыдущие элементы вместе в один скрипт. Полный пример приведен ниже.
# Загрузка библиотек from pandas import read_csv # Загрузка датасета url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/iris.csv" names = ['sepal-length', 'sepal-width', 'petal-length', 'petal-width', 'class'] dataset = read_csv(url, names=names) # Диаграмма размаха dataset.plot(kind='box', subplots=True, layout=(2,2), sharex=False, sharey=False) pyplot.show() # Гистограмма распределения атрибутов датасета dataset.hist() pyplot.show() #Матрица диаграмм рассеяния scatter_matrix(dataset) pyplot.show()
5. Оценка алгоритмов
Теперь пришло время создать некоторые модели данных и оценить их точность на контрольных данных.
Вот что мы собираемся охватить в этом шаге:
- Отделим обучающая выборка от контрольной (тестовой) выборке.
- Настройка 10-кратной кросс-валидации
- Построим несколько различных моделей для прогнозирования класса цветка из измерений цветов
- Выберем лучшую модель.
5.1 Создание контрольной выборки
Мы должны знать, что модель, которую мы создали, хороша.
Позже мы будем использовать статистические методы для оценки точности моделей. Мы также хотим получить более конкретную оценку точности наилучшей модели на контрольных данных, оценив ее по фактических контрольным данным.
То есть, мы собираемся удержать некоторые данные, на которых алгоритмы не будут обучаться, и мы будем использовать эти данные, чтобы получить второе и независимое представление о том, насколько точной может быть лучшая модель на самом деле.
Разделим загруженный датасет на два:
- 80% данных мы будем использовать для обучения, оценки и выбора лучшей среди наших моделей
- 20% данных, что мы будем использовать в качестве контрольного теста качества полученных моделей
# Разделение датасета на обучающую и контрольную выборки array = dataset.values # Выбор первых 4-х столбцов X = array[:,0:4] # Выбор 5-го столбца y = array[:,4] # Разделение X и y на обучающую и контрольную выборки X_train, X_validation, Y_train, Y_validation = train_test_split(X, y, test_size=0.20, random_state=1)
Теперь у вас есть обучающиеся данные в X_train и Y_train для подготовки моделей и контрольная выборка X_validation и Y_validation, которые мы можем использовать позже.
Обратите внимание, что мы использовали срез в Python для выбора столбцов в массиве NumPy.
5.2 Тестирование проверки
Для оценки точности модели мы будем использовать стратифицированную 10-кратную кросс-валидацию.
Это разделит наш датасет на 10 частей, обучающийся на 9 частях и 1 тестовой проверке и будет повторять обучение на всех комбинаций из выборок train-test.
Стратифицированная означает, что каждый прогон по выборке данных будет стремиться иметь такое же распределение примера по классу, как это существует во всем наборе обучаемых данных.
Для получения дополнительной информации о том как работает метод k-fold кросс-валидации можно посмотреть по ссылке.
Мы устанавливаем случайное затравку через random_state аргумент на фиксированное число, чтобы гарантировать, что каждый алгоритм оценивается на тех же выборках обучающихся данных. Конкретные случайные затравки не имеет значения.
Мы используем метрику «acccuracy» для оценки моделей.
Это соотношение числа правильно предсказанных экземпляров, разделенных на общее количество экземпляров в наборе данных, умноженном на 100, чтобы дать процент (например, точность 95%). Мы будем использовать оценочную переменную, когда мы будем запускать сборку и оценивать каждую модель.
5.3 Строим модели машинного обучения
Мы не знаем, какие алгоритмы будет хороши для этой задачи или какие конфигурации их использовать.
Все что увидела выше, что некоторые классы частично линейно зависят в некоторых измерениях, поэтому в целом ожидаем хорошие результаты.
Давайте протестируем 6 различных алгоритмов:
- Логистическая регрессия или логит-модель (LR)
- Линейный дискриминантный анализ (LDA)
- Метод k-ближайших соседей (KNN)
- Классификация и регрессия с помощью деревьев (CART)
- Наивный байесовский классификатор (NB)
- Метод опорных векторов (SVM)
Здесь приведена смесь простых линейных (LR и LDA), нелинейных (KNN, CART, NB и SVM) алгоритмов.
Давайте построим и оценим наши модели:
# Загружаем алгоритмы модели models = [] models.append(('LR', LogisticRegression(solver='liblinear', multi_class='ovr'))) models.append(('LDA', LinearDiscriminantAnalysis())) models.append(('KNN', KNeighborsClassifier())) models.append(('CART', DecisionTreeClassifier())) models.append(('NB', GaussianNB())) models.append(('SVM', SVC(gamma='auto'))) # оцениваем модель на каждой итерации results = [] names = [] for name, model in models: kfold = StratifiedKFold(n_splits=10, random_state=1, shuffle=True) cv_results = cross_val_score(model, X_train, Y_train, cv=kfold, scoring='accuracy') results.append(cv_results) names.append(name) print('%s: %f (%f)' % (name, cv_results.mean(), cv_results.std()))
5.4 Выбираем модель
Теперь у нас есть 6 моделей и оценки точности каждой из них. Мы должны сравнить модели друг с другом и выбрать наиболее точные.
Запустив приведенный выше пример, мы получим следующие необработанные результаты:
LR: 0.955909 (0.044337) LDA: 0.975641 (0.037246) KNN: 0.950524 (0.040563) CART: 0.951166 (0.052812) NB: 0.951166 (0.052812) SVM: 0.983333 (0.033333)
Обратите внимание, что ваши результаты могут немного варьироваться, учитывая стохастический характер алгоритмов обучения.
Как интерпретировать полученные значения качества моделей?
В этом случае, мы видим, что это выглядит как метод опорных векторов (SVM) имеет самый большой расчет точности около 0,98 или 98%.
Мы также можем создать график результатов оценки модели и сравнить расхождение средней точность каждой модели. Существует разбор показателей точности для каждого алгоритма, потому что каждый алгоритм был оценен 10 раз (в рамках 10-кратной кросс-валидации).
Хороший способ сравнить результаты для каждого алгоритма заключается в создании диаграмме размаха атрибутов выходных данных и их усов для каждого распределения и сравнения распределений.
# Сравниванием алгоритмы pyplot.boxplot(results, labels=names) pyplot.title('Algorithm Comparison') pyplot.show()
Мы видим, что ящики и усы участков в верхней части диапазона достигают 100% точности, а некоторые находятся в районе 85% точности.

5.5 Резюме оценки алгоритмов
Для справки мы можем связать все предыдущие элементы вместе в один скрипт. Полный пример приведен ниже.
# Загрузка библиотек from pandas import read_csv from pandas.plotting import scatter_matrix from matplotlib import pyplot from sklearn.model_selection import train_test_split from sklearn.model_selection import cross_val_score from sklearn.model_selection import StratifiedKFold from sklearn.metrics import classification_report from sklearn.metrics import confusion_matrix from sklearn.metrics import accuracy_score from sklearn.linear_model import LogisticRegression from sklearn.tree import DecisionTreeClassifier from sklearn.neighbors import KNeighborsClassifier from sklearn.discriminant_analysis import LinearDiscriminantAnalysis from sklearn.naive_bayes import GaussianNB from sklearn.svm import SVC # Загрузка датасета url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/iris.csv" names = ['sepal-length', 'sepal-width', 'petal-length', 'petal-width', 'class'] dataset = read_csv(url, names=names) # Разделение датасета на обучающую и контрольную выборки array = dataset.values # Выбор первых 4-х столбцов X = array[:,0:4] # Выбор 5-го столбца y = array[:,4] # Разделение X и y на обучающую и контрольную выборки X_train, X_validation, Y_train, Y_validation = train_test_split(X, y, test_size=0.20, random_state=1) # Загружаем алгоритмы моделей models = [] models.append(('LR', LogisticRegression(solver='liblinear', multi_class='ovr'))) models.append(('LDA', LinearDiscriminantAnalysis())) models.append(('KNN', KNeighborsClassifier())) models.append(('CART', DecisionTreeClassifier())) models.append(('NB', GaussianNB())) models.append(('SVM', SVC(gamma='auto'))) # оцениваем модель на каждой итерации results = [] names = [] for name, model in models: kfold = StratifiedKFold(n_splits=10, random_state=1, shuffle=True) cv_results = cross_val_score(model, X_train, Y_train, cv=kfold, scoring='accuracy') results.append(cv_results) names.append(name) print('%s: %f (%f)' % (name, cv_results.mean(), cv_results.std())) # Сравниванием алгоритмы pyplot.boxplot(results, labels=names) pyplot.title('Algorithm Comparison') pyplot.show()
6. Прогнозирование данных
Прежде чем что-либо прогнозировать необходимо выбрать алгоритм для прогнозирования. По результатам оценки моделей предыдущего раздела мы выбрали модель SVM как наиболее точную. Мы будем использовать эту модель в качестве нашей конечной модели.
Теперь мы хотим получить представление о точности модели на нашей контрольной выборке данных.
Это даст нам независимую окончательную проверку точности лучшей модели. Полезно сохранить контрольную выборку для случаев когда была допущена ошибки в процессе обучения, такая как переобучение или утечка данных. Обе эти проблемы могут привести к чрезмерно оптимистичному результату.
6.1 Создаем прогноз
Мы можем протестировать модель на всей выборке обучаемых данных и сделать прогноз на контрольной выборке.
# Создаем прогноз на контрольной выборке model = SVC(gamma='auto') model.fit(X_train, Y_train) predictions = model.predict(X_validation)
6.2 Оцениваем прогноз
Мы можем оценить прогноз, сравнив его с ожидаемым результатом контрольной выборки, а затем вычислить точность классификации, а также матрицу ошибок и отчет о классификации.
# Оцениваем прогноз print(accuracy_score(Y_validation, predictions)) print(confusion_matrix(Y_validation, predictions)) print(classification_report(Y_validation, predictions))
Мы видим, что точность 0,966 или около 96% на контрольной выборке.
Матрица ошибок дает представление об одной допущенной ошибке (сумма недиагональных значений).
Наконец, отчет о классификации предусматривает разбивку каждого класса по точности (precision), полнота (recall), f1-оценка, показывающим отличные результаты (при этом контрольная выборка была небольшая, всего 30 значений).
0.9666666666666667 [[11 0 0] [ 0 12 1] [ 0 0 6]] precision recall f1-score support Iris-setosa 1.00 1.00 1.00 11 Iris-versicolor 1.00 0.92 0.96 13 Iris-virginica 0.86 1.00 0.92 6 avg / total 0.97 0.97 0.97 30
6.3 Резюме прогнозирование данных
Для справки мы можем связать все предыдущие элементы вместе в один скрипт. Полный пример приведен ниже.
# Загрузка библиотек from pandas import read_csv from sklearn.model_selection import train_test_split from sklearn.metrics import classification_report from sklearn.metrics import confusion_matrix from sklearn.metrics import accuracy_score # Загрузка датасета url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/iris.csv" names = ['sepal-length', 'sepal-width', 'petal-length', 'petal-width', 'class'] dataset = read_csv(url, names=names) # Разделение датасета на обучающую и контрольную выборки array = dataset.values # Выбор первых 4-х столбцов X = array[:,0:4] # Выбор 5-го столбца y = array[:,4] # Разделение X и y на обучающую и контрольную выборки X_train, X_validation, Y_train, Y_validation = train_test_split(X, y, test_size=0.20, random_state=1) # Создаем прогноз на контрольной выборке model = SVC(gamma='auto') model.fit(X_train, Y_train) predictions = model.predict(X_validation) # Оцениваем прогноз print(accuracy_score(Y_validation, predictions)) print(confusion_matrix(Y_validation, predictions)) print(classification_report(Y_validation, predictions))
Машинное обучение в Python это не сложно
Проработайте примеры из урока, это не займет дольше 10-15 минут.
Вам не обязательно сразу все понимать. Ваша цель состоит в том, чтобы запустить ряд скриптов описанных в уроке и получить конечный результат. Вам не нужно понимать все при первом проходе. Записывайте свои вопросы параллельно с тем как пишите код. Рекомендуем использовать справку («FunctionName») в Python чтобы разобраться глубже во всех функциях, которые вы используете.
Вам не нужно знать, как работают алгоритмы. Важно знать об ограничениях и о том, как настроить алгоритмы машинного обучения. Более подробное узнать о конкретных алгоритмах можно и позже. Вы должны постепенно накапливать знания о работе алгоритмы. Сегодня, начните с того что поймете как его использовать в Python.
Вам не нужно быть программистом Python. Синтаксис языка Python может быть интуитивно понятным, даже если вы новичок в нем. Как и на других языках, сосредоточьтесь на вызовах функций (например,function()) и назначениях (например, a = «b»). Если вы являетесь разработчиком, вы итак уже знаете, как подобрать основы языка очень быстро.
Вам не нужно быть экспертом по машинного обучению. Вы можете узнать о преимуществах и ограничениях различных алгоритмов гораздо позже, и есть много информации в интернете, о более глубинных тонкостях алгоритмов и этапах проекта машинного обучения и важности оценки точности с помощью перекрестной валидации.
Итого
Вы сделали свой первый мини-проект по машинному обучению в Python.
Вы наверняка обнаружили, что после завершения даже небольшого проекта от загрузки данных до прогнозирования — вы уже намного сильнее продвинулись.
Какие могут быть следующие шаги по изучению машинного обучения?
Мы не освещали все этапы проекта машинного обучения, потому что это ваш первый проект, и нам нужно сосредоточиться на ключевых этапах. А именно, загрузке данных, анализе данных, оценка некоторых алгоритмов и прогнозировании данных. В других уроках мы рассмотрим другие аспекты машинного обучения по подготовке данных и улучшению результатов.