一、K最近邻算法的原理
原理部分直接看我另一篇《KNN是什么东东?》,本文主要针对如何应用。
K这个字母的含义就是最近邻的个数。在scikit-learn中,K最近邻算法的K值是通过 n_neighbors 参数来调节的,默认值是 5。
K最近邻算法也可以用于回归。当使用K最近邻回归计算某个数据点的预测值时,模型会选择离该数据点最近的若干个训练数据集中的点,并且将他们的 y 值取平均值,并把该平均值作为新数据点的预测值。
二、K最近邻算法在二分类任务中的应用
首先,使用 scikit-learn 的 make_blobs 函数来生成一个样本数量为 200,分类数为 2 的数据集,并赋值给 X 和 y,并使用 matplotlib 绘制出数据集图形。
from sklearn.datasets import make_blobs
from sklearn.neighbors import KNeighborsClassifier #导入 KNN 分类器
import matplotlib.pyplot as plt # 导入画图工具
from sklearn.model_selection import train_test_split # 导入数据集拆分工具
#生成样本数为 200,分类为 2 的数据集;n_features默认为2,即2个特征
data = make_blobs(n_samples=200, centers=2, random_state=8)
data = make_blobs(n_samples=200, centers=2, random_state=8)
X, y= data
#将生成的数据可视化
plt.scatter(X[:,0],X[:,1], c=y,cmap=plt.cm.spring, edgecolors='k')
plt.show()
执行结果为:
使用 make_blobs 生成的数据集.png
注释1:
sklearn.datasets.make_blobs
函数原型:sklearn.datasets.make_blobs(n_samples=100, n_features=2, centers=None, cluster_std=1.0, center_box=(-10.0, 10.0), shuffle=True, random_state=None)
参数解释:
n_samples(int/array): 如果参数为int,代表总样本数;如果参数为array-like,数组中的每个数代表每一簇的样本数。
n_features(int): 样本点的维度。
centers(int): 样本中心数。如果样本数为int且centers=None,生成三个样本中心;如果样本数(n_samples)为数组,则centers 要么为None,要么为数组的长度。
cluster_std(float/sequence of floats): 样本中,簇的标准差。
center_box(pair of floats (min, max)): 每个簇的上下限。
shuffle(boolean): 是否将样本打乱。
random_state(int/RandomState instance /None): 指定随机数种子,每个种子生成的序列相同,与minecraft地图种子同理。
返回类型:X : 样本数组 [n_samples, n_features]
产生的样本
y : array of shape [n_samples]
每个簇的标签
注释2:
matplotlib.pyplot.scatter
接下来,用 K最近邻算法来拟合数据
import numpy as np
clf = KNeighborsClassifier() #KNN
clf.fit(X, y) #训练
#画图
#分别确定两个属性值的最大和最小值,用于绘图边界
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
#返回坐标矩阵
xx, yy = np.meshgrid(np.arange(x_min, x_max, .02),
np.arange(y_min, y_max, .02))
#预测
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
Z= Z.reshape(xx.shape)
#分类图绘制
plt.pcolormesh(xx, yy, Z, cmap=plt.cm.Pastel1)
#将生成的样本数据可视化
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.spring, edgecolors='k')
#坐标轴范围限定
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
#绘图标题
plt.title("Claccifier:KNN")
plt.show()
执行结果为:
预测结果为:
==========================
新数据的分类是: [1]
knn_two_classify.png
注释1:
meshgrid()
meshgrid函数用两个坐标轴上的点在平面上画网格,即从坐标向量中返回坐标矩阵
可以参考以下两篇文章:《3分钟理解np.meshgrid()》和《Numpy中Meshgrid函数介绍及2种应用场景》
注释2:
注释3:
pcolormesh()
绘制分类图
函数原型: matplotlib.pyplot.pcolormesh(*args, alpha=None, norm=None, cmap=None, vmin=None, vmax=None, shading='flat', antialiased=False, data=None, **kwargs) 创建一个带有不规则矩形网格的伪彩色图
最后,附上二分类任务的完整代码
import numpy as np
from sklearn.datasets import make_blobs
from sklearn.neighbors import KNeighborsClassifier #导入 KNN 分类器
import matplotlib.pyplot as plt # 导入画图工具
from sklearn.model_selection import train_test_split # 导入数据集拆分工具
#生成样本数为 200,分类为 2 的数据集,n_features默认为2,即2个特征
data = make_blobs(n_samples=200, centers=2, random_state=8)
X, y= data
clf = KNeighborsClassifier() #KNN
clf.fit(X, y) #训练
#画图
#分别确定两个属性值的最大和最小值,用于绘图边界
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
#返回坐标矩阵
xx, yy = np.meshgrid(np.arange(x_min, x_max, .02),
np.arange(y_min, y_max, .02))
#预测
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
Z= Z.reshape(xx.shape)
#分类图绘制
plt.pcolormesh(xx, yy, Z, cmap=plt.cm.Pastel1)
#将生成的样本数据可视化
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.spring, edgecolors='k')
#坐标轴范围限定
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
#绘图标题
plt.title("Claccifier:KNN")
#对特征值为 6.75 和4.82 的新数据点分类进行预测
print('预测结果为:')
print('==========================')
print('新数据的分类是:', clf.predict([[6.75, 4.82]]))
#可视化的数据分类
plt.scatter(6.75, 4.82, marker='*', c='red',s=200)
plt.show()
三、K最近邻算法在多元分类任务中的应用
首先,使用 scikit-learn 的 make_blobs 函数来生成一个样本数量为 500,分类数为 5 的数据集,并赋值给 X 和 y,与二分类构造数类似,不再赘述样本绘图部分
import numpy as np
from sklearn.datasets import make_blobs
from sklearn.neighbors import KNeighborsClassifier #导入 KNN 分类器
import matplotlib.pyplot as plt # 导入画图工具
#生成样本数为 500,分类为 5 的数据集,n_features默认为2,即2个特征
data = make_blobs(n_samples=500, centers=5, random_state=8)
X, y= data
clf = KNeighborsClassifier() #KNN
clf.fit(X, y) #训练
#画图
#分别确定两个属性值的最大和最小值,用于绘图边界
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
#返回坐标矩阵
xx, yy = np.meshgrid(np.arange(x_min, x_max, .02),
np.arange(y_min, y_max, .02))
#预测
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
Z= Z.reshape(xx.shape)
#分类图绘制
plt.pcolormesh(xx, yy, Z, cmap=plt.cm.Pastel1)
#将生成的样本数据可视化
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.spring, edgecolors='k')
#坐标轴范围限定
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
#绘图标题
plt.title("Claccifier:KNN")
#模型评分
print('==========================')
print('模型评分:{:.2f}'.format(clf.score(X, y)))
plt.show()
执行结果为:
==========================
模型评分:0.96
knn_multi_classify.png
四、K最近邻算法用于回归分析
首先,使用 scikit-learn 的 make_regression 函数来生成一个特征数量为 1,标准差为 50 的noise 的数据集,并赋值给 X 和 y,并使用 matplotlib 绘制出数据集图形。
from sklearn.datasets import make_regression #回归分析数据生成器
import matplotlib.pyplot as plt # 导入画图工具
X, y = make_regression(n_features=1, n_informative=1, noise=50, random_state=8)
#用散点图将数据可视化
plt.scatter(X, y, c='orange',edgecolors='k')
plt.show()
执行结果如下,横轴代表样本特征的数值,纵轴代表样本的测定值:
knn_regression_data.png
注释:
sklearn.datasets.make_regression
函数原型:sklearn.datasets.make_regression(_samples=100, n_features=100, n_informative=10,
n_targets=1, bias=0.0, effective_rank=None,
tail_strength=0.5, noise=0.0, shuffle=True, coef=False,
random_state=None)
关键参数解释:
n_samples(生成样本数)
n_features(样本特征数)
noise(样本随机噪音)
coef(是否返回回归系数)
返回类型:
X为样本特征
y为样本输出
coef为回归系数
然后,使用K最近邻算法来进行回归分析,并输出模型评分
import numpy as np
from sklearn.datasets import make_blobs
from sklearn.neighbors import KNeighborsClassifier #导入 KNN 分类器
import matplotlib.pyplot as plt # 导入画图工具
#生成样本数为 500,分类为 5 的数据集,n_features默认为2,即2个特征
data = make_blobs(n_samples=500, centers=5, random_state=8)
X, y= data
clf = KNeighborsClassifier() #KNN
clf.fit(X, y) #训练
#画图
#分别确定两个属性值的最大和最小值,用于绘图边界
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
#返回坐标矩阵
xx, yy = np.meshgrid(np.arange(x_min, x_max, .02),
np.arange(y_min, y_max, .02))
#预测
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
Z= Z.reshape(xx.shape)
#分类图绘制
plt.pcolormesh(xx, yy, Z, cmap=plt.cm.Pastel1)
#将生成的样本数据可视化
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.spring, edgecolors='k')
#坐标轴范围限定
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
#绘图标题
plt.title("Claccifier:KNN")
#模型评分
print('==========================')
print('模型评分:{:.2f}'.format(clf.score(X, y)))
plt.show()
执行结果如下图所示,拟合效果不是很好
knn_regression_5neighbors.png
========
==================
模型评分:0.77
n_neighbors 参数默认值是 5,调节该参数,这是为2 ,再执行
reg = KNeighborsRegressor(n_neighbors=2)
执行结果如下图所示,拟合效果有改善,评分也有提高
knn_regression_2neighbors.png
======
====================
模型评分:0.86
最后,附上完整代码
import numpy as np
from sklearn.datasets import make_regression #回归分析数据生成器
from sklearn.neighbors import KNeighborsRegressor #用于回归分析的KNN模型
import matplotlib.pyplot as plt # 导入画图工具
X, y = make_regression(n_features=1, n_informative=1, noise=50, random_state=8)
#n_neighbors 默认是5
#reg = KNeighborsRegressor()
#调节n_neighbors为 2
reg = KNeighborsRegressor(n_neighbors=2) #KNN
reg.fit(X, y) #拟合数据
#预测结果可视化
z = np.linspace(-3, 3, 200).reshape(-1, 1) #范围由生成的回顾分析数据确定
#用散点图将数据可视化
plt.scatter(X, y, c='orange',edgecolors='k')
plt.plot(z, reg.predict(z), c='k', linewidth=3)
#添加标题
plt.title('KNN Regression')
#模型评分
print('==========================')
print('模型评分:{:.2f}'.format(reg.score(X, y)))
plt.show()