В этом посте мы рассмотрим наиболее важные параметры классификатора Sklearn KNeighbors и то, как они влияют на нашу модель с точки зрения переобучения или недостаточного подбора.
Этот классификатор реализует голосование k-ближайших соседей.
Мы будем использовать Titanic Data from kaggle. Ради этого поста мы будем выполнять как можно меньше функций, поскольку это не является целью этого поста.
import numpy as np import pandas as pd import matplotlib.pyplot as plt
Загрузить данные поезда
# get titanic & test csv files as a DataFrame train = pd.read_csv(“input/train.csv”) print train.shape > (891, 12)
Проверить отсутствующие значения
#Checking for missing data NAs = pd.concat([train.isnull().sum()], axis=1, keys=[‘Train’]) NAs[NAs.sum(axis=1) > 0] > Age 177 Cabin 687 Embarked 2
Мы удалим столбцы «Кабина», «Имя» и «Билет», так как они требуют некоторой обработки для извлечения полезных функций.
# At this point we will drop the Cabin feature since it is missing a lot of the data train.pop(‘Cabin’) train.pop(‘Name’) train.pop(‘Ticket’) train.shape > (891, 9)
Заполните отсутствующие значения возраста средним значением
# Filling missing Age values with mean train[‘Age’] = train[‘Age’].fillna(train[‘Age’].mean())
Заполните отсутствующие значения "Embarked" наиболее частым значением.
# Filling missing Embarked values with most common value train[‘Embarked’] = train[‘Embarked’].fillna(train[‘Embarked’].mode()[0])
«Pclass» - это категориальная функция, поэтому мы преобразуем его значения в строки.
train[‘Pclass’] = train[‘Pclass’].apply(str)
Давайте выполним простое горячее кодирование категориальных функций.
# Getting Dummies from all other categorical vars for col in train.dtypes[train.dtypes == ‘object’].index: for_dummy = train.pop(col) train = pd.concat([train, pd.get_dummies(for_dummy, prefix=col)], axis=1)
labels = train.pop(‘Survived’)
Для тестирования мы решили разделить наши данные на 75% для обучения и 25% для тестирования.
from sklearn.model_selection import train_test_split x_train, x_test, y_train, y_test = train_test_split(train, labels, test_size=0.25)
Давайте сначала подберем дерево решений с параметрами по умолчанию, чтобы получить базовое представление о производительности.
from sklearn.neighbors import KNeighborsClassifier model = KNeighborsClassifier() model.fit(x_train, y_train) > KNeighborsClassifier(algorithm=’auto’, leaf_size=30, metric=’minkowski’, metric_params=None, n_jobs=1, n_neighbors=5, p=2, weights=’uniform’) y_pred = model.predict(x_test)
Мы будем использовать AUC (Площадь под кривой) в качестве метрики оценки. Наше целевое значение является двоичным, поэтому это проблема двоичной классификации. AUC - хороший способ оценки для этого типа проблем.
from sklearn.metrics import roc_curve, auc false_positive_rate, true_positive_rate, thresholds = roc_curve(y_test, y_pred) roc_auc = auc(false_positive_rate, true_positive_rate) roc_auc > 0.51680529621456472
n_neighbors
n_neighbors представляет количество соседей, которые будут использоваться для запросов коленей.
neighbors = list(xrange(1,30)) train_results = [] test_results = [] for n in neighbors: model = KNeighborsClassifier(n_neighbors=n) model.fit(x_train, y_train) train_pred = model.predict(x_train) false_positive_rate, true_positive_rate, thresholds = roc_curve(y_train, train_pred) roc_auc = auc(false_positive_rate, true_positive_rate) train_results.append(roc_auc) y_pred = model.predict(x_test) false_positive_rate, true_positive_rate, thresholds = roc_curve(y_test, y_pred) roc_auc = auc(false_positive_rate, true_positive_rate) test_results.append(roc_auc) from matplotlib.legend_handler import HandlerLine2D line1, = plt.plot(neighbors, train_results, ‘b’, label=”Train AUC”) line2, = plt.plot(neighbors, test_results, ‘r’, label=”Test AUC”) plt.legend(handler_map={line1: HandlerLine2D(numpoints=2)}) plt.ylabel(‘AUC score’) plt.xlabel(‘n_neighbors’) plt.show()
Использование n_neighbors = 1 означает, что каждый образец использует себя в качестве эталона, что является случаем переобучения. По нашим данным, увеличение количества соседей улучшает результаты тестов.
p на расстоянии L_p
Это степенной параметр для метрики Минковского. Когда p = 1, это эквивалентно использованию manhattan_distance (l1) и euliddean_distance (l2) для p = 2. Для произвольного p используется расстояние Минковского (l_p).
distances = [1, 2, 3, 4, 5] train_results = [] test_results = [] for p in distances: model = KNeighborsClassifier(p=p) model.fit(x_train, y_train) train_pred = model.predict(x_train) false_positive_rate, true_positive_rate, thresholds = roc_curve(y_train, train_pred) roc_auc = auc(false_positive_rate, true_positive_rate) train_results.append(roc_auc) y_pred = model.predict(x_test) false_positive_rate, true_positive_rate, thresholds = roc_curve(y_test, y_pred) roc_auc = auc(false_positive_rate, true_positive_rate) test_results.append(roc_auc) from matplotlib.legend_handler import HandlerLine2D line1, = plt.plot(distances, train_results, ‘b’, label=”Train AUC”) line2, = plt.plot(distances, test_results, ‘r’, label=”Test AUC”) plt.legend(handler_map={line1: HandlerLine2D(numpoints=2)}) plt.ylabel(‘AUC score’) plt.xlabel(‘p’) plt.show()
В большинстве случаев выбор всегда между l1 и l2, но интересно увидеть результаты более высоких расстояний Минковского. Для наших данных использование l1 кажется лучше, чем l2 и другие расстояния l_p.
Серия inDepth исследует, как параметры модели влияют на производительность с точки зрения переобучения и недостаточного подгонки. Вы можете проверить настройку параметров для моделей на основе дерева, таких как Дерево решений, Случайный лес и Повышение градиента.