"Машинное обучение"
Алгоритм KNN для классификации и регрессии: практические занятия с Scikit-Learn
Google Colab и Python
Table of Contents: A — KNN for classification 1. Import Libraries 2. Build a dataset 3. Explore Dataset 4. Setting variables for ML 5. Split data into train and test 6. Building the model 7. Finding best k value 8. Model Complexity 9. Plotting decision boundaries B — KNN for regression 1. Import Libraries ... 6. Building the model 7. Finding best k value 8. Model Complexity C — Advantages and Disadvantages of KNN Advantages Disadvantages
K-ближайший сосед — один из самых простых алгоритмов в машинном обучении. Это алгоритм кластеризации, который назначает точку кластеру ближайшего соседа во входном наборе данных. Этот алгоритм можно использовать для аппроксимации задачи k ближайших соседей как задачи классификации, где k — количество ближайших соседей. Его также можно использовать для задач регрессии, находя среднюю разницу с соответствующими соседями.
А — КНН для классификации:
При использовании KNN для задач классификации и k = 1 наша модель просто ищет точку данных из набора данных, которая ближе к значению, которое мы хотим классифицировать. Если мы выберем k=3, k=5 или K=n, модель будет искать значения 3, 5 или n, которые ближе к нужному значению. классифицировать. Затем наше значение присваивается классу, у которого больше значений.
Пример 1.Для k=7 модель обнаруживает, что из 7 точек, которые ближе к нашему значению, 3 относятся к классу 0, а 4 относятся к классу 1. В этом случае наше значение будет присвоено классу 1.
Пример 2. Для k=6 модель обнаруживает, что из 6 точек, которые ближе к нашему значению, 3 относятся к классу 0 и 3 относятся к классу 1. В этом В этом случае модель рассчитает среднее евклидово расстояние по нашему значению и трем точкам каждого класса. Наше значение будет отнесено к классу с меньшим евклидовым расстоянием.
Практика:
1. Импорт библиотек:
Как и в любом другом проекте по машинному обучению, первым делом нужно импортировать необходимые библиотеки:
#Import Libraries: from random import random from random import randint import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns from sklearn.model_selection import train_test_split from sklearn.neighbors import KNeighborsClassifier from mlxtend.plotting import plot_decision_regions
2. Создайте набор данных:
Далее я создам поддельный набор данных для использования в этой задаче. Вы можете сделать то же самое в учебных целях или использовать свои данные, если работаете над реальной проблемой.
#Fabricating variables: #Creating values for FeNO with 3 classes: FeNO_0 = np.random.randint(1,20, 100) FeNO_1 = np.random.randint(25,55, 100) FeNO_2 = np.random.randint(45, 100, 100) #Creating values for FEV1 with 3 classes: FEV1_0 = [np.random.uniform(3.12,4.50) for _ in range(100)] FEV1_1 = [np.random.uniform(2.98,4.25) for _ in range(100)] FEV1_2 = [np.random.uniform(2.55,3.99) for _ in range(100)] #Creating values for Bronco Dilation with 3 classes: BD_0 = [np.random.uniform(0,0.180) for _ in range(100)] BD_1 = [np.random.uniform(0.160,0.250) for _ in range(100)] BD_2 = [np.random.uniform(0.200,0.700) for _ in range(100)] #Creating labels variable with two classes (1)Disease (0)No disease: not_asma = np.zeros((150,), dtype=int) asma = np.ones((150,), dtype=int)
Обратите внимание, что я создал три переменные с тремя классами и переменную label только с двумя классами. Это было сделано специально, чтобы создать некоторую сложность в наборе данных, добавив некоторые записи с характеристиками обоих классов.
Теперь пришло время объединить три класса переменных в одну переменную:
#Concatenate classes into one variable: FeNO = np.concatenate([FeNO_0, FeNO_1, FeNO_2]) FEV1 = np.concatenate([FEV1_0, FEV1_1, FEV1_2]) BD = np.concatenate([BD_0, BD_1, BD_2]) dx = np.concatenate([not_asma, asma])
А теперь создайте DataFrame и добавьте переменные в DataFrame:
#Create DataFrame: df = pd.DataFrame() #Add variables to DataFrame: df['FeNO'] = FeNO.tolist() df['FEV1'] = FEV1.tolist() df['BD'] = BD.tolist() df['dx'] = dx.tolist()
Чтобы проверить DataFrame, просто введите:
df
и вы увидите DataFrame с именем df с 300 строками и 4 столбцами:
3. Исследуйте набор данных:
Чтобы изучить наш набор данных и взаимосвязь между переменными:
#Exploring dataset: # left sns.pairplot(df, kind="scatter", hue="dx") plt.show() # right: you can give other arguments with plot_kws. sns.pairplot(df, kind="scatter", hue="dx") plt.show()
4. Установка переменных:
В проектах машинного обучения мы обычно вызываем X для набора данных, содержащего функции, и y для массива меток. Чтобы создать переменные X и y:
X = df.drop('dx', axis=1) y = df['dx']
Мы можем проверить, все ли в порядке, набрав X:
И y:
5. Разделить данные на обучение и тестирование:
Теперь мы разделим наши данные на обучение и тестирование. Это важно, потому что мы будем обучать нашу модель с помощью обучающего подмножества и проверять точность модели с помощью тестового подмножества. В Scikit-Lear есть функция train_test_split, которую мы будем использовать. Мы будем использовать 80% наших данных для обучения и 20% для теста (обозначается test_size=0.20):
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20)
6. Построение модели:
Теперь пришло время построить модель и передать данные в модель. Начнем с k=1.
clf = KNeighborsClassifier(n_neighbors=1) clf.fit(X_train, y_train)
Мы можем увидеть некоторые прогнозы модели:
clf.predict(X_test)
Чтобы оценить модель:
clf.score(X_test, y_test)
7. Поиск лучшего k:
И мы видим, что точность нашей модели составляет 0,80. Неплохо, но мы можем попробовать другое число k. Чтобы найти наилучшее число k, мы пробуем разные случайные k или можем построить график, отображающий различные значения k и точность модели. В этом случае я попробую значения k от 1 до 30.
training_accuracy = [] test_accuracy = [] # try n_neighbors from 1 to 30. neighbors_settings = range(1, 31) for n_neighbors in neighbors_settings: # build the model clf = KNeighborsClassifier(n_neighbors=n_neighbors) clf.fit(X_train, y_train) # record training set accuracy training_accuracy.append(clf.score(X_train, y_train)) # record generalization accuracy test_accuracy.append(clf.score(X_test, y_test)) plt.plot(neighbors_settings, training_accuracy, label="training accuracy") plt.plot(neighbors_settings, test_accuracy, label="test accuracy") plt.legend()
При графическом осмотре k=20 показал наилучшую точность теста. Итак, мы построили нашу модель с k=20:
clf = KNeighborsClassifier(n_neighbors=20) clf.fit(X_train, y_train) clf.predict(X_test) clf.score(X_test, y_test)
Теперь у нас есть оценка 0,82, что немного выше, чем 0,8.
8. Сложность модели:
Использование k=20 вместо k=1 повысило точность нашей модели. Еще один важный аспект KNN заключается в том, что модели с более высоким k являются моделями с меньшей сложностью. Таким образом, используя более высокое значение k, мы не только повышаем точность модели, но и уменьшаем ее сложность.
9. Нанесение границ решений:
График границ решений лучше всего работает для данных только с двумя функциями. Наши данные имеют три функции, но мы все еще можем построить границы решений, выбрав, какие функции использовать.
Первый шаг — сохранить наш набор данных в формате CSV и снова импортировать его с помощью pandas:
df.to_csv('data.csv', index = False) data = pd.read_csv('data.csv')
Теперь мы построим функцию для создания другой модели и построения границ решений. С нашими тремя переменными мы можем построить 3 разных графика. Для этого примера я буду FEV1 и BD в качестве функций:
def knn_comparison(data,k): x = data[['FEV1','BD',]].values y = data['dx'].astype(int).values clf = KNeighborsClassifier(n_neighbors=k) clf.fit(x,y) print(clf.score(x,y)) #Plot decision region: plot_decision_regions(x,y,clf=clf, legend=2) #Adding axes annotations: plt.xlabel('X_train') plt.ylabel('y_train') plt.title('KNN with k='+str(k)) plt.show()
Чтобы построить модель и график, просто вызовите функцию:
knn_comparison(data,20)
B — KNN для регрессии:
Алгоритм KNN также можно использовать для регрессии. Если K=1, значением регрессии будет значение ближайшей точки в наборе данных. Если k=n и n>1, значением регрессии будет среднее евклидово расстояние между нашим значением и n точками в наборе данных.
1. Импорт библиотек:
Нам понадобится еще один:
from sklearn.neighbors import KNeighborsRegressor
Поскольку мы будем использовать тот же набор данных, мы можем сразу перейти к шагу номер 6.
6. Построение модели:
Чтобы построить модель, мы выполним шаги, очень похожие на классификацию, начиная с k = 1:
reg = KNeighborsRegressor(n_neighbors=1) reg.fit(X_train, y_train) reg.predict(X_test) reg.score(X_test, y_test)
Оценка нашей модели составляет около 0,40, что довольно плохо. Мы постараемся найти наилучшее значение k и улучшить прогнозы нашей модели.
7. Поиск лучшего значения k:
training_accuracy = [] test_accuracy = [] # try n_neighbors from 1 to 30. neighbors_settings = range(1, 31) for n_neighbors in neighbors_settings: # build the model reg = KNeighborsRegressor(n_neighbors=n_neighbors) reg.fit(X_train, y_train) # record training set accuracy training_accuracy.append(reg.score(X_train, y_train)) # record generalization accuracy test_accuracy.append(reg.score(X_test, y_test)) plt.plot(neighbors_settings, training_accuracy, label="training accuracy") plt.plot(neighbors_settings, test_accuracy, label="test accuracy") plt.legend()
Анализируя график, k=22 кажется оптимальным значением.
reg = KNeighborsRegressor(n_neighbors=22) reg.fit(X_train, y_train) reg.predict(X_test) reg.score(X_test, y_test)
Как и ожидалось, увеличение значений k увеличило оценку модели, которая теперь составляет около 0,63, что намного лучше, чем 0,39.
8. Сложность модели:
Как и в случае с классификацией, увеличение числа k в регрессионных моделях снижает сложность модели. Подумайте о большем количестве соседей, чтобы получить более точный прогноз.
C — Преимущества и недостатки KNN
Как и все другие алгоритмы, KNN имеет преимущества и недостатки. Некоторые из них:
Преимущества:
-Простая модель машинного обучения;
-Легко понять и объяснить нетехническим специалистам;
-Простота проектирования (только скорректировать на k);
-Хорошо подумать, прежде чем пробовать более сложные модели.
Недостатки:
- Медленная работа с очень большими наборами данных;
- Невозможность обработки и представления многих функций.
Заключение
KNN — это простой и легкий алгоритм для запуска в проектах машинного обучения, особенно если у нас есть небольшой набор функций для анализа и если наши данные стратифицированы на фиксированное количество классов. В этой статье вы найдете все, что вам нужно для завершения вашего проекта, включая код Python для создания, оценки и разработки модели и, при необходимости, создания графической визуализации.
Спасибо за чтение!
Если: вам понравилась эта статья, не забудьте подписаться на меня и, таким образом, получать все обновления о новых публикациях.
Иначе Если: вы хотите узнать больше, вы можете подписаться на членство в Medium с помощью моей реферальной ссылки. Это не будет стоить вам больше, но заплатит мне за кофе.
Еще: Спасибо, что прочитали!