Python机器学习之K最近邻算法

一、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

用来绘制散点图
参考:《Python中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:

numpy.ravel()

将多维数组将为一维数组
参考:《numpy 辨异 (五)—— numpy.ravel() vs numpy.flatten()》

注释3:

pcolormesh()

绘制分类图
函数原型: matplotlib.pyplot.pcolormesh(*args, alpha=None, norm=None, cmap=None, vmin=None, vmax=None, shading='flat', antialiased=False, data=None, **kwargs) 创建一个带有不规则矩形网格的伪彩色图

具体的参数解释参见 :pcolormesh参数

具体使用方法参考:利用plt.pcolormesh绘制分类图

 最后,附上二分类任务的完整代码

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()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,589评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,615评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,933评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,976评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,999评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,775评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,474评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,359评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,854评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,007评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,146评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,826评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,484评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,029评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,153评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,420评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,107评论 2 356