前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >机器学习-K邻近算法(KNN)简介

机器学习-K邻近算法(KNN)简介

作者头像
XXXX-user
发布2019-10-14 17:36:10
1.5K0
发布2019-10-14 17:36:10
举报
文章被收录于专栏:不仅仅是python不仅仅是python

微信公众号:yale记 关注可了解更多的教程问题或建议,请公众号留言。

背景介绍

在我们遇到的所有机器学习算法中,KNN很容易成为最简单的学习方法。 尽管它很简单,但是事实证明它在某些任务上非常有效(正如您将在本文中看到的那样)。

甚至更好? 它可以用于分类和回归问题! 但是,它广泛用于分类问题。 我很少看到在任何回归任务上实施KNN。我的目的是说明和强调当目标变量本质上是连续的时,KNN如何同样有效。

本文中,我们将首先了解KNN算法背后的直觉,探讨计算点之间距离的不同方法,然后最后在Big Mart Sales数据集上以Python实现该算法。 我们开始吧!

目录

  1. 一个简单的例子,了解KNN背后的直觉
  2. KNN算法如何工作?
  3. 点之间距离的计算方法
  4. 如何选择k因子?
  5. 处理数据集
  6. 额外资源

1.一个简单的例子,了解KNN背后的直觉

让我们从一个简单的例子开始。 考虑下表-它由10人的身高,年龄和体重(目标)值组成。 如您所见,ID11的权重值缺失。 我们需要根据其身高和年龄来预测其体重。

注意:此表中的数据不代表实际值。 它仅用作说明此概念的示例。

为了更清楚地了解这一点,以下是上表中身高与年龄的关系图:

上图中,y轴代表一个人的身高(以英尺为单位),x轴代表年龄(以年为单位)。 这些点根据ID值编号。 黄点(ID 11)是我们的测试点。

如果我要求您根据图表确定ID11的重量,您的答案是什么? 您可能会说,由于ID11 更接近点5和1,因此它的重量必须类似于这些ID,大约在72-77千克之间(表中ID1和ID5的重量)。 这实际上是有道理的,但是您认为该算法如何预测这些值? 我们将在本文中找到答案。

2. KNN算法如何工作?

如上所述,KNN可用于分类和回归问题。 该算法使用“ 特征相似度 ”来预测任何新数据点的值。 这意味着,根据新点与训练集中的点的相似程度为其分配一个值。 从我们的示例中,我们知道ID11的身高和年龄类似于ID1和ID5,因此重量也将大致相同。

如果是分类问题,我们将采用该模式作为最终预测。 在这种情况下,我们有两个权重值– 72和77。您猜怎么计算最终值? 值的平均值被认为是最终预测。

以下是该算法的逐步说明:

  1. 首先,计算新点与每个训练点之间的距离。

选择最接近的k个数据点(基于距离)。 在此示例中,如果k的值为3,则将选择点1、5、6。我们将在本文后面进一步探讨选择正确的k值的方法。

这些数据点的平均值是对新点的最终预测。 在这里,我们的重量为ID11 =(77 + 72 + 60)/ 3 = 69.66 kg。

在接下来的几节中,我们将详细讨论这三个步骤。

3.点间距离的计算方法

第一步是计算新点与每个训练点之间的距离。 有多种计算此距离的方法,其中最常用的方法是– Euclidian,Manhattan(连续)和Hamming距离(绝对)。

  1. 欧几里德距离:欧几里德距离被计算为新点(x)与现有点(y)之间平方差之和的平方根。
  2. 曼哈顿距离(Manhattan Distance) :这是实向量之间的距离,使用它们的绝对差之和。

3.汉明距离 :用于分类变量。 如果值(x)和值(y)相同,则距离D等于0。 否则,D = 1。

一旦测量了新观测值与训练集中各点的距离,下一步便是选择最接近的点。 要考虑的点数由k的值定义。

4.如何选择k因子?

第二步是选择k值。 这决定了当我们给任何新观测值赋值时,我们观察的邻居数量。

在我们的示例中,对于值k = 3,最接近的点是ID1,ID5和ID6。

ID11的权重预测将是:

代码语言:javascript
复制
  ID11 =(77 + 72 + 60)/ 3 

 ID11 = 69.66 kg

对于k = 5的值,最接近的点将是ID1,ID4,ID5,ID6,ID10。

ID11的预测为:

代码语言:javascript
复制
  ID 11 =(77 + 59 + 72 + 60 + 58)/ 5 

 ID 11 = 65.2kg

我们注意到,基于k值,最终结果趋于变化。 那么我们如何找出k的最优值呢? 让我们根据训练和验证集的错误计算来决定(毕竟,将错误最小化是我们的最终目标!)。请查看以下图表,了解不同k值的训练误差和验证误差。

于非常低的k值(假设k = 1),模型对训练数据过度拟合,从而导致验证集的错误率很高。 另一方面,对于较高的k值,模型在训练集和验证集上的表现均较差。 如果仔细观察,验证误差曲线将在k = 9时达到最小值。该k值是模型的最佳值(对于不同的数据集,它会有所不同)。 该曲线称为“ 肘曲线 ”(因为它具有类似肘的形状),通常用于确定k值。您也可以使用网格搜索技术找到最佳的k值。 我们将在下一部分中实现它。

5.处理数据集(Python代码)

到目前为止,您必须对算法有清楚的了解。 如果您对此有任何疑问,请使用下面的评论部分,我们很乐意回答。现在,我们将继续在数据集上实现该算法。 我已经使用Big Mart销售数据集显示了实现,您可以从此链接下载它。

完整的Python代码在下面,但是我们在这里有一个非常酷的编码窗口,您可以在其中用Python编写自己的k最近邻居模型:

代码语言:javascript
复制
'''
The following code is for the K-Nearest Neighbors
Created by - ANALYTICS VIDHYA
'''
# importing required libraries
import pandas as pd
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score

# read the train and test dataset
train_data = pd.read_csv('train-data.csv')
test_data = pd.read_csv('test-data.csv')

# shape of the dataset
print('Shape of training data :',train_data.shape)
print('Shape of testing data :',test_data.shape)

# Now, we need to predict the missing target variable in the test data
# target variable - Survived

# seperate the independent and target variable on training data
train_x = train_data.drop(columns=['Survived'],axis=1)
train_y = train_data['Survived']

# seperate the independent and target variable on testing data
test_x = test_data.drop(columns=['Survived'],axis=1)
test_y = test_data['Survived']

'''
Create the object of the K-Nearest Neighbor model
You can also add other parameters and test your code here
Some parameters are : n_neighbors, leaf_size
Documentation of sklearn K-Neighbors Classifier:

https://scikit-learn.org/stable/modules/
generated/sklearn.neighbors.KNeighborsClassifier.html

 '''
model = KNeighborsClassifier()

# fit the model with the training data
model.fit(train_x,train_y)

# Number of Neighbors used to predict the target
print('\nThe number of neighbors used to predict the target : ',\
model.n_neighbors)

# predict the target on the train dataset
predict_train = model.predict(train_x)
print('\nTarget on train data',predict_train)

# Accuray Score on train dataset
accuracy_train = accuracy_score(train_y,predict_train)
print('accuracy_score on train dataset : ', accuracy_train)

# predict the target on the test dataset
predict_test = model.predict(test_x)
print('Target on test data',predict_test)

# Accuracy Score on test dataset
accuracy_test = accuracy_score(test_y,predict_test)
print('accuracy_score on test dataset : ', accuracy_test)

1. 读取文件

代码语言:javascript
复制
import pandas as pd
df = pd.read_csv('train.csv')
df.head()

2. 估算缺失值

代码语言:javascript
复制
df.isnull().sum()
#missing values in Item_weight and Outlet_size needs to be imputed
mean = df['Item_Weight'].mean() #imputing item_weight with mean
df['Item_Weight'].fillna(mean, inplace =True)

mode = df['Outlet_Size'].mode() #imputing outlet size with mode
df['Outlet_Size'].fillna(mode[0], inplace =True)

3. 处理分类变量并删除id列

代码语言:javascript
复制
df.drop(['Item_Identifier', 'Outlet_Identifier'], axis=1, inplace=True)
df = pd.get_dummies(df)

4. 创建训练和测试数据集

代码语言:javascript
复制
from sklearn.model_selection import train_test_split
train , test = train_test_split(df, test_size = 0.3)

x_train = train.drop('Item_Outlet_Sales', axis=1)
y_train = train['Item_Outlet_Sales']

x_test = test.drop('Item_Outlet_Sales', axis = 1)
y_test = test['Item_Outlet_Sales']

5. 预处理–特征

代码语言:javascript
复制
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler(feature_range=(0, 1))

x_train_scaled = scaler.fit_transform(x_train)
x_train = pd.DataFrame(x_train_scaled)

x_test_scaled = scaler.fit_transform(x_test)
x_test = pd.DataFrame(x_test_scaled)

6. 让我们看一下不同k值的错误率

代码语言:javascript
复制
#import required packages
from sklearn import neighbors
from sklearn.metrics import mean_squared_error
from math import sqrt
import matplotlib.pyplot as plt
%matplotlib inline
代码语言:javascript
复制
rmse_val = [] #to store rmse values for different k
for K in range(20):
    K = K+1
    model = neighbors.KNeighborsRegressor(n_neighbors = K)

    model.fit(x_train, y_train)  #fit the model
    pred=model.predict(x_test) #make prediction on test set
    error = sqrt(mean_squared_error(y_test,pred)) #calculate rmse
    rmse_val.append(error) #store rmse values
    print('RMSE value for k= ' , K , 'is:', error)

输出 :

代码语言:javascript
复制
RMSE value for k = 1 is: 1579.8352322344945
RMSE value for k = 2 is: 1362.7748806138618
RMSE value for k = 3 is: 1278.868577489459
RMSE value for k = 4 is: 1249.338516122638
RMSE value for k = 5 is: 1235.4514224035129
RMSE value for k = 6 is: 1233.2711649472913
RMSE value for k = 7 is: 1219.0633086651026
RMSE value for k = 8 is: 1222.244674933665
RMSE value for k = 9 is: 1219.5895059285074
RMSE value for k = 10 is: 1225.106137547365
RMSE value for k = 11 is: 1229.540283771085
RMSE value for k = 12 is: 1239.1504407152086
RMSE value for k = 13 is: 1242.3726040709887
RMSE value for k = 14 is: 1251.505810196545
RMSE value for k = 15 is: 1253.190119191363
RMSE value for k = 16 is: 1258.802262564038
RMSE value for k = 17 is: 1260.884931441893
RMSE value for k = 18 is: 1265.5133661294733
RMSE value for k = 19 is: 1269.619416217394
RMSE value for k = 20 is: 1272.10881411344
代码语言:javascript
复制
#plotting the rmse values against k values
curve = pd.DataFrame(rmse_val) #elbow curve
curve.plot()

如我们所讨论的,当我们使k = 1时,我们得到非常高的RMSE值。 随着我们增加k值,RMSE值减小。 在k = 7时,RMSE约为1219.06,并且随着k值的进一步增加而增加。 我们可以肯定地说,在这种情况下,k = 7将为我们提供最佳结果。

这些是我们训练数据集的预测。 现在让我们预测测试数据集的值并进行提交。

7.对测试数据集的预测

代码语言:javascript
复制
#reading test and submission files
test = pd.read_csv('test.csv')
submission = pd.read_csv('SampleSubmission.csv')
submission['Item_Identifier'] = test['Item_Identifier']
submission['Outlet_Identifier'] = test['Outlet_Identifier']

#preprocessing test dataset
test.drop(['Item_Identifier', 'Outlet_Identifier'], axis=1, inplace=True)
test['Item_Weight'].fillna(mean, inplace =True)
test = pd.get_dummies(test)
test_scaled = scaler.fit_transform(test)
test = pd.DataFrame(test_scaled)

#predicting on the test set and creating submission file
predict = model.predict(test)
submission['Item_Outlet_Sales'] = predict
submission.to_csv('submit_file.csv',index=False)

提交此文件后,我得到的RMSE为1279.5159651297。

8.实施GridsearchCV

为了确定k的值,每次绘制肘曲线是一个繁琐而繁琐的过程。 您可以简单地使用gridsearch来找到最佳价值。

代码语言:javascript
复制
from sklearn.model_selection import GridSearchCV
params = {'n_neighbors':[2,3,4,5,6,7,8,9]}

knn = neighbors.KNeighborsRegressor()

model = GridSearchCV(knn, params, cv=5)
model.fit(x_train,y_train)
model.best_params_

输出:

代码语言:javascript
复制
{'n_neighbors': 7}
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-10-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 yale记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景介绍
  • 目录
  • 1.一个简单的例子,了解KNN背后的直觉
  • 2. KNN算法如何工作?
  • 3.点间距离的计算方法
  • 4.如何选择k因子?
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档