K-近邻算法分类和回归

K近邻算法的主要思想是用离测试集数据点最近的训练集点(称为其邻居)的输出来估计测试集数据点的输出,参数K代表用多少个邻居来估计。超参数K通常设置为奇数来防止平局现象。

其中对邻居的判定:我们可以用欧几里得距离来衡量距离来确定其K个邻居。

K近邻算法是一种惰性学习和非参数模型。当训练数据数量庞大,同时你对响应变量和解释变量之间的关系所知甚少时,非参数模型会非常有用。KNN 模型只基于一个假设:互相接近的实例拥有类似的响应变量值。非参数模型提供的灵活性并不总是可取的,当训练数据很缺乏或者你对响应变量和解释变量之间的关系有所了解时,对响应变量和解释变量之间关系做假设的模型就很有用。

KNN模型分类:

下面我们看一个分类的例子和代码实现来了解一下K近邻算法:

 上表是我们的训练集,下面先对数据进行可视化

import numpy as np
from matplotlib import pyplot as plt
import sklearn

X_train = np.array([ # 身高体重
    [158, 64],
    [170, 86],
    [183, 84],
    [191, 80],
    [155, 49],
    [163, 59],
    [180, 67],
    [158, 54],
    [170, 67]])
y_train = ['male']*4 + ['female']*5 # 性别

#绘制图像
plt.figure()
plt.title('Human Height and Weights by Sex')
plt.xlabel('Height in cm')
plt.ylabel('Weight in kg')
for i, x in enumerate(X_train):
    plt.scatter(x[0],x[1],c='k',marker='x' if y_train[i] == 'male' else 'D')
plt.grid()
plt.show()

结果: 

 我们使用欧几里得距离公式来衡量距离:

 我们设置参数K=3,来寻找3个距离最近的训练实例

下面代码实现K近邻算法进行分类:

x = np.array([[155, 70]])
distances = np.sqrt(np.sum((X_train - x)**2, axis=1)) # 计算距离

nearest_neighbor_indices = distances.argsort()[:3] # 找出前三个距离最小的下标
nearest_neighbor_genders = np.take(y_train, nearest_neighbor_indices) # 得到下标对应的标签

from collections import Counter
b = Counter(np.take(y_train, distances.argsort()[:3])) #得到三个结果标签中最频繁的标签得到结果female

print(b.most_common(1)[0][0]) # female

因此,从上述代码可以得到K近邻算法进行分类就是找到离样本点最近的K个实例,再取K个实例的标签中出现次数最多的那个作为我们的结果。

上述K近邻算法在scikit-learn中也有对应的函数:

from sklearn.preprocessing import LabelBinarizer
from sklearn.neighbors import KNeighborsClassifier

lb = LabelBinarizer() # 创建将标签二值数值化的类实例
y_train_binarized = lb.fit_transform(y_train) # 将标签二值数值化
print(y_train_binarized) 

K = 3
clf = KNeighborsClassifier(n_neighbors=K) # 创建K近邻分类器实例
clf.fit(X_train, y_train_binarized.reshape(-1, 1)) # 对训练集进行训练
prediction_binarized = clf.predict(np.array([155, 70]).reshape(1,-1))[0] # 对测试样本点进行预测
prediction_label = lb.inverse_transform(prediction_binarized) # 将预测结果从数字转换为标签
print(prediction_label) # array(['female'], dtype='<U6')

KNN回归:

K近邻算法进行回归和K近邻思想一致,只不过在得到了K个邻居后,分类是取邻居中出现次数最多的那个,而回归是取其他的操作来预测输出值(比如取平均)

对应的代码在scikit-learn中其实也很简单

from sklearn.neighbors import KNeighborsRegressor
K = 3
clf = KNeighborsRegressor(n_neighbors=K)
clf.fit(X_train, y_train)
predictions = clf.predict(X_test)

特征缩放

下面我们谈谈一个提升算法精确度的小细节。假设还是上面的数据,我们现在要做回归,给定身高和性别标签来预测体重。如果我们的训练数据集包含一个身高170cm的男性和身高160cm的女性。如果我们的测试集数据为身高为164cm的男性,你觉得其预测结果会接近170cm的男性还是身高160cm的女性呢?我们可能相信测试实例更接近男性实例,因为对预测体重来说,性别差异可能会比 6cm 的身高差距更重要。但是如果我们以毫米为单位表示身高,测试实例更接近于身高1600mm 的女性。如果我们以米为单位表示身高,测试实例更接近于身高 1.7m 的男性。(记住我们以欧几里得距离来衡量)

因此,我们的特征缩放的作用就出来了(其实就相当于深度学习对数据集预处理中的Normalize)

将所有实例特征值减去均值来将其居中。其次将每个实例特征值除以特征的标准差对其进行缩放。均值为 0,方差为 1 的数据称为标准化数据

而在sklearn中的preprocessing包中有一个scale函数能够实现这一功能:

​​​​​​​


 

参考资料:

scikit-learn机器学习第2版

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值