Kneighbors 算法分类和回归
k近邻算法属于有监督学习算法,是一种基本的分类和回归算法。
算法的原理:对一个未分类的数据,通过与它相邻且距离最近的k个已分类的实例来投票,从而确定其所属的类别,即与它距离最近的k个实例多数归属的类别就是此分类实例的类别。
简单理解为近朱者赤近墨者黑。
一般k值选择的不同,会导致不同的结果,选择合适的k值对该算法非常重要。
k值太小,意味着模型太复杂,容易导致过拟合:容易收到噪声的影响。
k值太大,意味着模型太简单,容易导致欠拟合:此时与待分类问题距离较远的样本点也会对分类起作用,使得预测发生错误。
距离的度量
k近邻算法每次都要计算未分类数据与所有知分类的样本数据的距离,然后排序取出距离最近的k个数据来投票得到最终的分类结果,因此距离的计算也是非常重要的一环,距离的计算一般有三种方式:
- 欧式距离:
L ( x i , x j ) = ( ∑ l = 1 n ( x i ( l ) − x j ( l ) ) 2 ) 1 2 ) L(x_i, x_j)=\left ( \sum_{l=1}^{n}(x_i^{(l)}-x_j^{(l)})^2 \right )^{\frac{1}{2}} ) L(xi,xj)=(l=1∑n(xi(l)−xj(l))2)21)
- 曼哈顿距离:
L ( x i , x j ) = ∑ l = 1 n ∣ x i ( l ) − x j ( l ) ∣ L(x_i, x_j)=\sum_{l=1}^{n}|x_i^{(l)}-x_j^{(l)}| L(xi,xj)=l=1∑n∣xi(l)−xj(l)∣
- 各个坐标距离的最大值:
KaTeX parse error: Undefined control sequence: \sideset at position 13: L(x_i,x_j)=\̲s̲i̲d̲e̲s̲e̲t̲{}{}{max}_l|x_i…
算法的优缺点
算法的优点:
- 可以通过不断地实验来找到合适的k值;
- 算法的准确度较高;
- 对异常值和噪声有较高的容忍度。
算法的缺点:
- 每次对一个未标记的样本进行分类时,都需要对与其全部近邻的已标记的样本计算距离和排序
- k值的选择难以确定;
- 计算对内存的需求较大。
算法案例
分类任务
在这里使用Jupyter notebook环境:
导包:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.neighbors import KNeighborsClassifier
生成数据:
X, y = make_blobs(n_samples=400, centers=4, cluster_std=1.3, random_state=6)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap='rainbow')
引入封装好的分类函数:
def KneighborsClassifier(X, y, ax=None, n_neighbors=5, weights='uniform', algorithm='auto', cmap='rainbow'):
"""
采用K近邻算法进行分类
:param X:待处理的二维矩阵,其中(X[:, 0], X[:, 1])表示二维平面内的一个点
:param y:监督学习标签
:param ax:传入提前好的axis对象或默认为None
:param n_neighbors: 最重要的超参数k值
:param weights: 'uniform '表示每个点的权重都一样
:param algorithm: 采用分类的算法 默认为自动
:param cmap: 采用的颜色映射
:return:
"""
# 生成非None的ax对象
ax = ax or plt.gca()
# 画出训练数据以及ax对象的设置
ax.scatter(X[:, 0], X[:, 1], c=y, s=30, cmap='rainbow')
ax.axis('tight')
ax.set_xlabel('x', fontsize=16)
ax.set_ylabel('y', fontsize=16)
ax.set_title('KNeighborsClassifier', fontsize=19)
# 获取坐标轴的范围
xlim = ax.get_xlim()
ylim = ax.get_ylim()
# 建立模型并配置超参数
# p=2表示采用欧式距离
model = KNeighborsClassifier(n_neighbors=n_neighbors, weights=weights,
algorithm=algorithm, leaf_size=30, p=2)
# 用评估器拟合数据
model.fit(X, y)
# 画出预测的二维网络
xx, yy = np.meshgrid(np.linspace(*xlim, num=200),
np.linspace(*ylim, num=200))
Z = model.predict(np.c_[xx.ravel(), yy.ravel()]).reshape(xx.shape)
# 为结果生成彩色图
n_classes = len(np.unique(y))
contours = ax.contourf(xx, yy, Z, alpha=0.3, cmap=cmap, zorder=1,
levels=np.arange(n_classes + 1) - 0.5)
# 设置图像边界
ax.set(xlim=xlim, ylim=ylim)
return model
查看分类结果:
KneighborsClassifier(X, y)
回归任务
导包:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.neighbors import KNeighborsRegressor
生成数据:
rng = np.random.RandomState(42)
x = rng.rand(100) * 10
y = np.sin(x) + 0.2 * rng.randn(100)
plt.scatter(x, y)
导入封装好的函数:
def plusNewAxis(x):
"""
给数组x增加一个维度的函数
:param x: 待处理的数组
:return: np.ndarray
"""
return x[:, np.newaxis]
def KneighborsRegression(x, y, k=5, ax=None):
"""
使用k近邻算法做回归分析
:param x: 回归数据的x坐标
:param y: 回归数据的y坐标
:param k: 近邻值的超参数
:param ax: 传入的ax对象
:return: model
"""
# 调整绘制的ax对象
ax = plt.gca() or ax
# 转化为机器学习可以利用的维度
if x.ndim == 1:
X = plusNewAxis(x)
else:
X = x
# 建立模型并完成拟合
model = KNeighborsRegressor(k)
model.fit(X, y)
# 评估模型得分
print('模型得分:', model.score(X, y))
# 生成测试数据
Min, Max = X.min() - 0.5, X.max() + 0.5
xfit = np.linspace(Min, Max, 1000)
Xfit = xfit[:, np.newaxis]
yfit = model.predict(Xfit)
# 绘制原始数据
ax.scatter(x, y, color='b')
# 绘制回归曲线
ax.plot(xfit, yfit, color='r')
# 设置标题与轴信息
ax.set_title('KNeighbors Regression', fontsize=19)
ax.set_xlabel('x', fontsize=16)
ax.set_ylabel('y', fontsize=16)
# 添加图例
ax.legend(['row data', 'Regression'], loc='best')
# 返回模型
return model
完成回归拟合并计算得分:
KneighborsRegression(x, y)
16)
# 添加图例
ax.legend(['row data', 'Regression'], loc='best')
# 返回模型
return model
完成回归拟合并计算得分:
~~~python
KneighborsRegression(x, y)