KNN: K Nearest Neighbor - один из фундаментальных алгоритмов машинного обучения. Модели машинного обучения используют набор входных значений для прогнозирования выходных значений. KNN - одна из простейших форм алгоритмов машинного обучения, которые в основном используются для классификации. Он классифицирует точку данных по тому, как классифицируется ее сосед.
KNN классифицирует новые точки данных на основе меры сходства ранее сохраненных точек данных. Например, если у нас есть набор данных о помидорах и бананах. KNN будет хранить аналогичные меры, такие как форма и цвет. Когда приходит новый объект, он проверяет его сходство по цвету (красный или желтый) и форме.
K в KNN представляет собой количество ближайших соседей, которые мы использовали для классификации новых точек данных.
Как выбрать K?
В реальных задачах, когда у нас много точек, возникает вопрос: как выбрать значение K?
Выбор правильного значения K называется настройкой параметров и необходим для получения лучших результатов. Выбирая значение K, мы извлекаем квадратный корень из общего числа точек данных, доступных в наборе данных.
а. K = sqrt (общее количество точек данных).
б. Всегда выбирается нечетное значение K, чтобы избежать путаницы между двумя классами.
Когда KNN?
а. У нас есть данные с должной маркировкой. Например, если мы прогнозируем, что у кого-то диабет или нет, окончательная метка может быть 1 или 0. Это не может быть NaN или -1.
б. Данные без шума. Для набора данных о диабете мы не можем иметь уровень глюкозы как 0 или 10000. Это практически невозможно.
c. Небольшой набор данных.
Как работает KNN?
Обычно мы используем евклидово расстояние для вычисления ближайшего соседа. Если у нас есть две точки (x, y) и (a, b). Формула для евклидова расстояния (d) будет
d = sqrt ((x-a) ² + (y-b) ²)
Мы пытаемся получить наименьшее евклидово расстояние и, основываясь на количестве меньших расстояний, выполняем наш расчет.
Давайте попробуем KNN в одной базе данных, чтобы увидеть, как это работает. Данные можно извлечь из https://github.com/adityakumar529/Coursera_Capstone/blob/master/diabetes.csv.
import pandas as pd import numpy as np from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.neighbors import KNeighborsClassifier from sklearn.metrics import confusion_matrix from sklearn.metrics import accuracy_score from sklearn.metrics import f1_score
pd и np предназначены для pandas и библиотеки NumPy. Последние 3 строки (confusion_matrix, precision_score и f1_score) предназначены для проверки точности модели. train_test_split предназначен для разделения и обучения данных. KNeighborsClassifier предназначен для K ближайшего соседа. Стандартизация наборов данных является общим требованием для многих оценщиков машинного обучения: они могут плохо себя вести, если отдельные функции не более или менее выглядят как стандартные нормально распределенные данные.
data = pd.read_csv("../input/diabetes.csv") data.head()
Мы прочитали CSV-файл через pd.read_csv. А через головку () мы видим верхние 5 рядов. Есть некоторые факторы, значения которых не могут быть нулевыми. Например, уровень глюкозы для человека не может быть 0. Точно так же кровяное давление, толщина кожи, инсулин и ИМТ не могут быть нулевыми для человека.
non_zero = ['Glucose','BloodPressure','SkinThickness','Insulin','BMI'] for coloumn in non_zero: data[coloumn] = data[coloumn].replace(0,np.NaN) mean = int(data[coloumn].mean(skipna = True)) data[coloumn] = data[coloumn].replace(np.NaN, mean) print(data[coloumn]) 0 148.0 1 85.0 2 183.0 3 89.0 4 137.0 ... 763 101.0 764 122.0 765 121.0 766 126.0 767 93.0 Name: Glucose, Length: 768, dtype: float64 0 72.0 1 66.0 2 64.0 3 66.0 4 40.0 ... 763 76.0 764 70.0 765 72.0 766 60.0 767 70.0 Name: BloodPressure, Length: 768, dtype: float64 0 35.0 1 29.0 2 29.0 3 23.0 4 35.0 ... 763 48.0 764 27.0 765 23.0 766 29.0 767 31.0 Name: SkinThickness, Length: 768, dtype: float64 0 155.0 1 155.0 2 155.0 3 94.0 4 168.0 ... 763 180.0 764 155.0 765 112.0 766 155.0 767 155.0 Name: Insulin, Length: 768, dtype: float64 0 33.6 1 26.6 2 23.3 3 28.1 4 43.1 ... 763 32.9 764 36.8 765 26.2 766 30.1 767 30.4 Name: BMI, Length: 768, dtype: float64
Мы создали non_zero, в котором есть все столбцы, необходимые для прогнозирования конечного значения. Нам нужно убедиться, что эти столбцы не имеют никакого значения, связанного с нулем или значением NaN. Если у нас 0, мы заменим его на NaN. А затем заменив NaN на среднее значение столбца. Давайте нанесем на график подробные данные о диабете.
import seaborn as sns p=sns.pairplot(data, hue = 'Outcome')
Мы определили non_zero со столбцом, значения которого не могут быть нулевыми. В каждом столбце мы сначала проверим, есть ли у нас 0 значений. Затем мы заменяем его на NaN. Позже мы создаем значение столбца и заменяем предыдущее на среднее.
Поскольку данные у нас готовы. Пришло время обучить и проверить данные.
X =data.iloc[:,0:8] y =data.iloc[:,8] X_train,X_test,y_train, y_test = train_test_split(X, y, test_size=0.2,random_state=0, stratify=y)
Для данных X мы берем все строки столбцов в диапазоне от 0 до 7. Аналогично, для y мы берем все строки для 8-го столбца.
У нас есть train_test_split, который мы импортировали во время запуска программы, и мы определили размер теста как 0,2, что означает, что из всех данных 20% будут отложены для тестирования данных на более позднем этапе.
#feature Scaling sc_X = StandardScaler() X_train = sc_X.fit_transform(X_train) X_test = sc_X.transform(X_test)
StandardScaler выполняет задачу стандартизации. Обычно набор данных содержит переменные, различающиеся по масштабу. Например, набор данных будет содержать столбец инсулина со значениями по шкале 20–70 и столбец глюкозы со значениями по шкале 80–200. Поскольку эти два столбца различаются по масштабу, они стандартизированы, чтобы иметь общий масштаб при построении модели машинного обучения.
import math math.sqrt(len(y_test))
Вне:
12.409673645990857
Мы взяли это значение, чтобы получить значение K. Нам нужно нечетное значение K, поэтому мы сделаем его 12–1 или 12 + 1.
classifier = KNeighborsClassifier(n_neighbors=13,p=2,metric='euclidean') classifier.fit(X_train,y_train)
Вне:
KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='euclidean', metric_params=None, n_jobs=None, n_neighbors=13, p=2, weights='uniform')
Давайте спрогнозируем наши данные, используя предсказание классификатора.
y_pred = classifier.predict(X_test) y_pred
Вне:
array([0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0])
У нас есть массив данных, но нам нужно оценить нашу модель, чтобы проверить точность. Начнем с матрицы путаницы.
cm= confusion_matrix(y_test,y_pred) cm
Вне:
array([[86, 14], [24, 30]])
У нас есть матрица неточностей, где диагональ с 86 и 30 показывает правильное значение, а 14, 24 показывает прогноз, который мы пропустили.
Мы проверим счет f1.
print(f1_score(y_test,y_pred))
Вне
0.6122448979591836 print(accuracy_score(y_test,y_pred))
Вне:
0.7532467532467533
У нас есть оценка f1 как 0,61 и оценка точности 0,75.
Давайте построим график для фактических данных и нашего прогнозируемого значения.
import matplotlib.pyplot as plt plt.figure(figsize=(5, 7)) ax = sns.distplot(data['Outcome'], hist=False, color="r", label="Actual Value") sns.distplot(y_pred, hist=False, color="b", label="Predicted Values", ax=ax) plt.title('Actual vs Precited value for outcome') plt.show() plt.close()
Фактический код можно проверить на:
Https://github.com/adityakumar529/Coursera_Capstone/blob/master/KNN.ipynb.