k-Nearest-Neighbors (k-NN) - это модель машинного обучения с учителем. Контролируемое обучение - это когда модель учится на данных, которые уже помечены. Модель контролируемого обучения принимает набор входных объектов и выходных значений. Затем модель обучается на этих данных, чтобы узнать, как сопоставить входные данные с желаемыми выходными данными, чтобы она могла научиться делать прогнозы на основе невидимых данных.

Модели k-NN работают, беря точку данных и глядя на «k» ближайших помеченных точек данных. Затем точке данных присваивается метка большинства «k» ближайших точек.

Например, если k = 5 и 3 точки являются «зелеными», а 2 - «красными», то рассматриваемая точка данных будет помечена как «зеленая», поскольку «зеленые» составляют большинство (как показано на приведенном выше графике. ).

Scikit-learn - это библиотека машинного обучения для Python. В этом руководстве мы построим модель k-NN с помощью Scikit-learn, чтобы предсказать, есть ли у пациента диабет.

Чтение обучающих данных

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

import pandas as pd
#read in the data using pandas
df = pd.read_csv(‘data/diabetes_data.csv’)
#check data has been read in properly
df.head()

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

#check number of rows and columns in dataset
df.shape

Мы видим, что у нас есть 768 строк данных (потенциальные пациенты с диабетом) и 9 столбцов (8 входных функций и 1 целевой выход).

Разделите набор данных на входы и цели

Теперь давайте разделим наш набор данных на входные (X) и нашу цель (y). Мы будем вводить все столбцы, кроме «диабета», потому что «диабет» - это то, что мы будем пытаться предсказать. Следовательно, нашей целью будет «диабет».

Мы будем использовать функцию pandas «drop», чтобы удалить столбец «диабет» из нашего фрейма данных и сохранить его в переменной «X». Это будет наш вклад.

#create a dataframe with all training data except the target column
X = df.drop(columns=[‘diabetes’])
#check that the target variable has been removed
X.head()

Мы вставим столбец «диабет» нашего набора данных в нашу целевую переменную (y).

#separate target values
y = df[‘diabetes’].values
#view target values
y[0:5]

Разделите набор данных на обучающие и тестовые данные

Теперь мы разделим набор данных на данные обучения и данные тестирования. Обучающие данные - это данные, на которых модель будет учиться. Данные тестирования - это данные, которые мы будем использовать, чтобы увидеть, насколько хорошо модель работает с невидимыми данными.

В Scikit-learn есть функция, которую мы можем использовать под названием «train_test_split», которая позволяет нам легко разделить наш набор данных на данные для обучения и тестирования.

from sklearn.model_selection import train_test_split
#split dataset into train and test data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1, stratify=y)

Train_test_split принимает 5 параметров. Первые два параметра - это входные и целевые данные, которые мы разделили ранее. Затем мы установим test_size на 0,2. Это означает, что 20% всех данных будет использоваться для тестирования, в результате чего 80% данных останется в качестве обучающих данных для модели, на которой можно будет учиться. Установка ‘random_state’ на 1 гарантирует, что мы получим одно и то же разбиение каждый раз, чтобы мы могли воспроизвести наши результаты.

Установка параметра «stratify» на y заставляет нашу тренировочную группу представлять долю каждого значения в переменной y. Например, в нашем наборе данных, если 25% пациентов страдают диабетом, а 75% не страдают диабетом, установка для параметра «стратификация» значения y гарантирует, что в случайное разделение будут включены 25% пациентов с диабетом и 75% пациентов без диабета.

Построение и обучение модели

Далее нам нужно построить модель. Вот код:

from sklearn.neighbors import KNeighborsClassifier
# Create KNN classifier
knn = KNeighborsClassifier(n_neighbors = 3)
# Fit the classifier to the data
knn.fit(X_train,y_train)

Сначала мы создадим новый классификатор k-NN и установим для n_neighbors значение 3. Напомним, это означает, что если по крайней мере 2 из 3 ближайших точек к новой точке данных являются пациентами без диабета, то новая точка данных будут помечены как «нет диабета», и наоборот. Другими словами, новая точка данных маркируется большинством из 3 ближайших точек.

Мы установили n_neighbors равным 3 в качестве отправной точки. Ниже мы более подробно рассмотрим, как лучше выбрать значение для «n_neighbors», чтобы модель могла улучшить свою производительность.

Далее нам нужно обучить модель. Чтобы обучить нашу новую модель, мы будем использовать функцию «fit» и передавать наши обучающие данные в качестве параметров, чтобы подогнать нашу модель к обучающим данным.

Тестирование модели

После обучения модели мы можем использовать функцию «прогнозирования» в нашей модели, чтобы делать прогнозы на основе наших тестовых данных. Как было видно при проверке «y» ранее, 0 указывает на то, что у пациента нет диабета, а 1 указывает на то, что у пациента действительно диабет. Для экономии места мы покажем print только первые 5 прогнозов нашего тестового набора.

#show first 5 model predictions on the test data
knn.predict(X_test)[0:5]

Мы видим, что модель предсказала «отсутствие диабета» для первых 4 пациентов в тестовой выборке и «диабет» для 5-го пациента.

Теперь давайте посмотрим, насколько точна наша модель на всем тестовом наборе. Для этого мы воспользуемся функцией «score» и передадим тестовые входные и целевые данные, чтобы увидеть, насколько хорошо наши прогнозы модели соответствуют фактическим результатам.

#check accuracy of our model on the test data
knn.score(X_test, y_test)

Наша модель имеет точность примерно 66,88%. Это хорошее начало, но ниже мы увидим, как повысить производительность модели.

Поздравляю! Вы построили потрясающую модель k-NN!

k-кратная перекрестная проверка

Перекрестная проверка - это случайное разбиение набора данных на «k» групп. Одна из групп используется в качестве тестового набора, а остальные используются в качестве обучающего набора. Модель обучается на обучающем наборе и оценивается на тестовом наборе. Затем процесс повторяется до тех пор, пока каждая уникальная группа не будет использоваться в качестве тестового набора.

Например, для 5-кратной перекрестной проверки набор данных будет разделен на 5 групп, а модель будет обучена и протестирована 5 раз, так что каждая группа получит шанс стать тестовым набором. Это можно увидеть на графике ниже.

Метод «поезд-тест-разделение», который мы использовали ранее, называется «задержка». Перекрестная проверка лучше, чем использование метода удержания, потому что оценка метода удержания зависит от того, как данные разделяются на наборы для обучения и тестирования. Перекрестная проверка дает модели возможность протестировать на нескольких разделениях, чтобы мы могли лучше понять, как модель будет работать с невидимыми данными.

Чтобы обучить и протестировать нашу модель с помощью перекрестной проверки, мы будем использовать функцию cross_val_score со значением перекрестной проверки 5. cross_val_score принимает нашу модель k-NN и наши данные в качестве параметров. Затем он разбивает наши данные на 5 групп и сравнивает и оценивает наши данные 5 раз, каждый раз записывая оценку точности в массив. Мы сохраним оценки точности в переменной «cv_scores».

Чтобы найти среднее из 5 оценок, мы будем использовать функцию numpy mean, передавая "cv_score". Numpy - полезная математическая библиотека на Python.

from sklearn.model_selection import cross_val_score
import numpy as np
#create a new KNN model
knn_cv = KNeighborsClassifier(n_neighbors=3)
#train model with cv of 5 
cv_scores = cross_val_score(knn_cv, X, y, cv=5)
#print each cv score (accuracy) and average them
print(cv_scores)
print(‘cv_scores mean:{}’.format(np.mean(cv_scores)))

Используя перекрестную проверку, наш средний балл составляет около 71,36%. Это более точное представление того, как наша модель будет работать с невидимыми данными, чем наше предыдущее тестирование с использованием метода удержания.

Параметры модели гипертюнинга с использованием GridSearchCV

При построении нашей исходной модели k-NN мы устанавливаем параметр «n_neighbors» равным 3 в качестве отправной точки без какой-либо реальной логики, стоящей за этим выбором.

Параметры гипертюнинга - это когда вы выполняете процесс поиска оптимальных параметров для вашей модели с целью повышения точности. В нашем случае мы будем использовать GridSearchCV, чтобы найти оптимальное значение для «n_neighbors».

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

Для нашей модели мы укажем диапазон значений для «n_neighbors», чтобы увидеть, какое значение лучше всего подходит для нашей модели. Для этого мы создадим словарь, установив «n_neighbors» в качестве ключа и используя numpy для создания массива значений от 1 до 24.

Наша новая модель, использующая поиск по сетке, примет новый классификатор k-NN, наш param_grid и значение перекрестной проверки 5, чтобы найти оптимальное значение для «n_neighbors».

from sklearn.model_selection import GridSearchCV
#create new a knn model
knn2 = KNeighborsClassifier()
#create a dictionary of all values we want to test for n_neighbors
param_grid = {‘n_neighbors’: np.arange(1, 25)}
#use gridsearch to test all values for n_neighbors
knn_gscv = GridSearchCV(knn2, param_grid, cv=5)
#fit model to data
knn_gscv.fit(X, y)

После обучения мы можем проверить, какие из наших тестируемых нами значений параметра «n_neighbors» оказались наиболее эффективными. Для этого мы вызовем в нашей модели "best_params_".

#check top performing n_neighbors value
knn_gscv.best_params_

Мы видим, что 14 - оптимальное значение для «n_neighbors». Мы можем использовать функцию «best_score_» для проверки точности нашей модели, когда «n_neighbors» равно 14. «best_score_» выводит среднюю точность оценок, полученных посредством перекрестной проверки.

#check mean score for the top performing value of n_neighbors
knn_gscv.best_score_

Используя поиск по сетке для поиска оптимального параметра для нашей модели, мы повысили точность нашей модели более чем на 4%!

Спасибо за прочтение! Репозиторий GitHub для этого руководства (блокнот jupyter и набор данных) можно найти здесь.

Если вы хотите быть в курсе моих материалов по машинному обучению, подписывайтесь на меня :)