回归的K-最近邻算法实用介绍(使用Python代码)

Introduction

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

甚至更好? 它可以用于分类和回归问题! 然而,它更常用于分类问题。 我很少看到KNN在任何回归任务上实现。 我的目的是说明并强调当目标变量本质上是连续的时,KNN如何同等有效。
在这里插入图片描述
在本文中,我们将首先了解KNN算法背后的直觉,研究计算点之间距离的不同方法,然后最终在Big Mart Sales数据集上用Python实现该算法。 我们走吧!

目录

一个简单的例子来理解KNN背后的直觉
KNN算法如何工作?
计算点之间距离的方法
如何选择k因子?
处理数据集
其他资源

1. A simple example to understand the intuition behind 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 首先,计算新点与每个训练点之间的距离。

在这里插入图片描述

2. 选择最接近的k个数据点(基于距离)。 在此示例中,如果k的值为3,则将选择点1,5,6。我们将在本文后面进一步探索选择正确的k值的方法。在这里插入图片描述
3. 这些数据点的平均值是新点的最终预测。 在这里,我们的重量为ID11 =(77 + 72 + 60)/ 3 = 69.66千克。

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

3.计算点之间距离的方法

第一步是计算新点和每个训练点之间的距离。 计算该距离有多种方法,其中最常见的方法是 - 欧几里德,曼哈顿(连续)和汉明距离(分类)。

欧几里德距离:欧几里德距离计算为新点(x)和现有点(y)之间的平方差之和的平方根。
曼哈顿距离:这是实际向量之间的距离,使用它们的绝对差值之和。
在这里插入图片描述
汉明距离:用于分类变量。 如果值(x)和值(y)相同,则距离D将等于0。 否则D = 1。

在这里插入图片描述

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

4.如何选择k因子?

第二步是选择k值。 这决定了我们在为任何新观察值分配值时看到的邻居数。

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

在这里插入图片描述

ID11的重量预测将是:

ID11 = (77+72+60)/3 

ID11 = 69.66 kg

对于k = 5的值,最近的点将是ID1,ID4,ID5,ID6,ID10。
在这里插入图片描述

在这里插入图片描述

ID11的预测将是:

ID 11 =  (77+59+72+60+58)/5 

ID 11 = 65.2 kg

我们注意到,基于k值,最终结果趋于改变。 那我们怎样才能找出k的最佳值? 让我们根据我们的列车和验证集的误差计算来决定它(毕竟,最小化误差是我们的最终目标!)。

请看下面的图表,了解不同k值的训练误差和验证误差。

在这里插入图片描述
在这里插入图片描述

对于非常低的k值(假设k = 1),模型过度拟合训练数据,这导致验证集上的高错误率。另一方面,对于k的高值,该模型在列车和验证集上都表现不佳。如果仔细观察,验证误差曲线在k = 9的值处达到最小值。该k值是模型的最佳值(对于不同的数据集,它将有所不同)。该曲线称为“肘形曲线”(因为它具有类似肘部的形状),通常用于确定k值。

您还可以使用网格搜索技术来查找最佳k值。我们将在下一节中实现这一点。

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

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

1. Read the file
import pandas as pd
df = pd.read_csv('train.csv')
df.head()
2. Impute missing values
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. Deal with categorical variables and drop the id columns
df.drop(['Item_Identifier', 'Outlet_Identifier'], axis=1, inplace=True)
df = pd.get_dummies(df)
4. Create train and test set
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. Preprocessing – Scaling the features
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. Let us have a look at the error rate for different k values
#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
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)

Output :

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
#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.测试数据集的预测

#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)
On submitting this file, I get an RMSE of 1279.5159651297.

8. Implementing GridsearchCV

为了确定k的值,每次绘制肘曲线是一个繁琐且繁琐的过程。 您只需使用gridsearch即可找到最佳值。

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_

Output :

{'n_neighbors': 7}

6.结束注释和其他资源

在本文中,我们介绍了KNN算法的工作原理及其在Python中的实现。 它是最基本但最有效的机器学习技术之一。 对于R中的KNN实现,您可以阅读本文:使用R的kNN算法

在本文中,我们直接从sklearn库中使用了KNN模型。 您还可以从头开始实施KNN(我推荐这个!),本文将对此进行介绍:KNN简化

如果你认为你很了解KNN并且对这项技术有扎实的把握,那就在MCQ测验中测试你的技能:关于kNN算法的30个问题。 祝好运!

猜你喜欢

转载自blog.csdn.net/weixin_41697507/article/details/89508169