快速了解KNN算法和代码实现

一.算法介绍

1.定义

KNN算法全称是K-Nearest Neighbor,翻译过来是K邻近算法,也可以称为找邻居算法,是机器学习中常用的基础分类算法。

KNN是在对测试集进行分类时,首先扫描整个训练集,找到与测试集最相近的K个样本,根据这些样本的类别进行投票,以确定测试集的类别。

我们以下图为例:

KNN算法要解决的问题就是判断紫色圆圈是绿色三角形类别还是红色正方形类别,并把它归入这两类中的一类。若k=1,则找到离图中紫圆最近的1个样本,这个样本为红色正方形,故紫圆属于红色正方形类别;若k=7,则找到离紫圆最近的7个样本,这7个样本中有5个绿色三角形和两个红色正方形,其中类数三角形数量比红色正方形多,故紫圆属于绿色三角形。由以上例子可知k近邻算法对样本的分类及其依赖于k的取值。

 当然k近邻算法对距离的计算方式有多种,其中以Manhattan 距离与Euclidean 距离为主。

我们一般采用Euclidean距离进行计算。

2.K的取值

我们不难看出KNN算法非常依赖K的取值。对于K的取值,不宜过大也不易过小。

  • K值过大,模型的偏差越大,对噪声数据与不敏感,学习到的特征就越粗糙,容易造成欠拟合。
  • K值越小,模型的方差越大,学习到的特征就越细致,容易造成过拟合。

K的取值应该满足:

  • 邻近点要有相同或相近的类别。
  • 特征维度(个数)的尺度(范围)要具有一致性。

3.数据归一化处理

数据的归一化处理事用来解决数据相差太大的问题,将数据转换至0到1之间,使其更容易收敛。

通常的归一化处理方法有:0-1标准化、Z-score标准化、SIGMOD标准化。我们这里使用0-1标准化的方法。

                         newValue=(oldValue-min)/(max-min)

4.KNN算法的优缺点及应用场合

优点:1.简单有效。

           2.重新训练的代价低

           3.适合大样本自动分类

           4.适合域类交叉样本

缺点:1.惰性学习

            2.计算量较大

            3.类别评论不是规格化

            4.输出可解释性不强

            5.对不均衡的样本不擅长

应用场景:KNN算法的应用场景包括图像识别、语音识别、文本分类、推荐系统等。例如,KNN算法可以用于图像分类问题,其中每个图像可以看作是一个输入样本,它的特征可以表示为图像的像素值。通过计算每个图像与已知的训练集中的图像之间的距离,可以找到与其最相似的K个图像,然后通过这K个图像的分类信息来预测该图像的分类。
 

二、代码实现

1.算法描述

要自己实现KNN算法主要有以下三个步骤:

           算距离:给定待分类样本,计算它与已分类样本中的每个样本的距离;

           找邻居:圈定与待分类样本距离最近的K个已分类样本,作为待分类样本的近邻;

           做分类:根据这K个近邻中的大部分样本所属的类别来决定待分类样本该属于哪个分类;

2.实现过程中需要注意的问题

1.sklearn库在pycharm中叫做scikit-learn库,安装完这个库就可以使用sklearn的功能。

2.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,n_features]的X数组和形状为[n_samples]的y数组。

参数:
n_samples:int或数组类,可选参数(默认值= 100)如果为int,则为在簇之间平均分配的点总数。 如果是数组,则序列中的每个元素表示每个簇的样本数。
n_features:int,可选(默认值= 2)每个样本的特征数量。
centers:int或形状数组[n_centers,n_features],可选默认= None)要生成的中心数或固定的中心位置。 如果n_samples是一个int且center为None,则将生成3个中心。 如果n_samples是数组类,则中心必须为None或长度等于n_samples长度的数组。
cluster_std: 浮点数或浮点数序列,可选(默认值为1.0)聚类的标准偏差。
center_box: 一对浮点数(最小,最大),可选(默认=(-10.0,10.0))随机生成中心时每个聚类中心的边界框。
shuffle:布尔值,可选(默认= True)样本洗牌
random_state:int,RandomState实例或无(默认)确定用于创建数据集的随机数生成。 为多个函数调用传递可重复输出的int值。

3.sklearn.neighbors.KNeighborsClassifier()函数用于实现k近邻投票算法的分类器。class sklearn.neighbors.KNeighborsClassifier(n_neighbors=5, weights=’uniform',algorithm=’auto’, leaf_size=30, p=2, metric=’minkowski',metric_params=None, n_jobs=None, **kwargs)

参数:

n_neighbors : int,optional(default = 5)默认情况下kneighbors查询使用的邻居数。就是k-NN的k的值,选取最近的k个点。

weights : str或callable,可选(默认=‘uniform’)默认是uniform,参数可以是uniform、distance,也可以是用户自己定义的函数。uniform是均等的权重,就说所有的邻近点的权重都是相等的。distance是不均等的权重,距离近的点比距离远的点的影响大。用户自定义的函数,接收距离的数组,返回一组维数相同的权重。

algorithm : {‘auto’,‘ball_tree’,‘kd_tree’,‘brute’},可选快速k近邻搜索算法,默认参数为auto,可以理解为算法自己决定合适的搜索算法。除此之外,用户也可以自己指定搜索算法ball_tree、kd_tree、brute方法进行搜索,brute是蛮力搜索,也就是线性扫描,当训练集很大时,计算非常耗时。kd_tree,构造kd树存储数据以便对其进行快速检索的树形数据结构,kd树也就是数据结构中的二叉树。以中值切分构造的树,每个结点是一个超矩形,在维数小于20时效率高。ball tree是为了克服kd树高纬失效而发明的,其构造过程是以质心C和半径r分割样本空间,每个节点是一个超球体。

leaf_size : int,optional(默认值= 30)默认是30,这个是构造的kd树和ball树的大小。这个值的设置会影响树构建的速度和搜索速度,同样也影响着存储树所需的内存大小。需要根据问题的性质选择最优的大小。

p : 整数,可选(默认= 2)距离度量公式。在上小结,我们使用欧氏距离公式进行距离度量。除此之外,还有其他的度量方法,例如曼哈顿距离。这个参数默认为2,也就是默认使用欧式距离公式进行距离度量。也可以设置为1,使用曼哈顿距离公式进行距离度量。

metric : 字符串或可调用,默认为’minkowski’用于距离度量,默认度量是minkowski,也就是p=2的欧氏距离(欧几里德度量)。

metric_params : dict,optional(默认=None)距离公式的其他关键参数,这个可以不管,使用默认的None即可。

n_jobs : int或None,可选(默认=None)并行处理设置。默认为1,临近点搜索并行工作数。如果为-1,那么CPU的所有cores都用于并行工作。

4.clf. fit(X_train, y_train) 用于训练分类器模型。clf代表分类器, fit是训练方法, y_train是样本标签,x_train是样本特征。具体来说, 该函数的作用是用y_train标签训练模型, 使得模型能够根据x_train特征对未知数据进行分类预测。clf是一个分类器(classifier) 的实例, fit方法用于将模型与训练数据进行拟合, 即通过输入的特征数据x_train和对应的目标标签y_train, 调整模型的参数以使其能够对新的未见过的数据进行准确的预测。在该步骤中, 模型会根据训练数据进行学习, 调整自身的参数以最大程度地减小预测结果与真实标签之间的差异。通过这个过程, 模型能够提取出输入特征与目标标签之间的关联规律, 从而实现对未知数据的预测。

5.clf. predict(np. c_[xx. ravel(), yy. ravel()])这是一个机器学习中的分类算法, 使用clf对数据进行分类, np. c_[]是用来将两个数组按行合并的numpy函数, xx. ravel()和yy. travel()是将二维数组降为一维的函数。最终结果被存储在Z中。

6.np.meshgrid函数用于生成一个二维坐标矩阵。具体来说,它会根据给定的x_min、x_max、0.02三个参数生成一个以0.02为步长的一维数组x,然后再根据x的长度,生成两个数组xx和yy,它们的长度都为x的长度,且xx是以x为行向量、以x长度为列的矩阵,而yy是以x为列向量、以x长度为行的矩阵。也就是说,xx和yy是一对坐标矩阵,每个坐标都对应了一个点的横坐标和纵坐标。

7.plt.scatter()函数用于生成一个scatter散点图matplotlib.pyplot.scatter(x, y,  s=20,  c='b',  marker='o',  cmap=None,  norm=None,  vmin=None,  vmax=None,  alpha=None,  linewidths=None,  verts=None,  hold=None,  **kwargs)
参数:

x,y:表示的是shape大小为(n,)的数组,也就是我们即将绘制散点图的数据点,输入数据。

s:表示的是大小,是一个标量或者是一个shape大小为(n,)的数组,可选,默认20。

c:表示的是色彩或颜色序列,可选,默认蓝色’b’。但是c不应该是一个单一的RGB数字,也不应该是一个RGBA的序列,因为不便区分。c可以是一个RGB或RGBA二维行数组。

marker:MarkerStyle,表示的是标记的样式,可选,默认’o’。

cmap:Colormap,标量或者是一个colormap的名字,cmap仅仅当c是一个浮点数数组的时候才使用。如果没有申明就是image.cmap,可选,默认None。

norm:Normalize,数据亮度在0-1之间,也是只有c是一个浮点数的数组的时候才使用。如果没有申明,就是默认None。

vmin,vmax:标量,当norm存在的时候忽略。用来进行亮度数据的归一化,可选,默认None。

alpha:标量,0-1之间,可选,默认None。

linewidths:也就是标记点的长度,默认None。

3.代码实现

1.导入库

# 导入画图工具
import matplotlib.pyplot as plt
# 导入数组工具
import numpy as np
# 导入数据集生成器
from sklearn.datasets import make_blobs
# 导入KNN 分类器
from sklearn.neighbors import KNeighborsClassifier
# 导入数据集拆分工具
from sklearn.model_selection import train_test_split

2.生成数据集

# 生成样本数为200,特征数量为2的数据集
data = make_blobs(n_samples=200, n_features=2, centers=2, cluster_std=1.0, random_state=8)
X, Y = data

# 将生成的数据集进行可视化
plt.scatter(X[:,0], X[:,1],s=80, c=Y,  cmap=plt.cm.spring, edgecolors='k')
plt.show()

生成的数据集结果为: 

3.默认K=5使用邻近算法进行分类 并且进行训练

clf = KNeighborsClassifier()
clf.fit(X, Y)

4. 对训练值的结果进行分类

# 绘制图形
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()])

5.绘制图形

z = z.reshape(xx.shape)
plt.pcolormesh(xx, yy, z, cmap=plt.cm.Pastel1)
plt.scatter(X[:, 0], X[:, 1], s=80, c=Y, cmap=plt.cm.spring, edgecolors='k')
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
plt.title("Classifier:KNN")

 6.标出我们待测样本,并对它进行分类

# 把待分类的数据点用五星表示出来
plt.scatter(6.75, 4.82, marker='*', c='red', s=200)

# 对待分类的数据点的分类进行判断
res = clf.predict([[6.75, 4.82]])
plt.text(6.9, 4.5, 'Classification flag: ' + str(res))

完整代码 

# 导入画图工具
import matplotlib.pyplot as plt
# 导入数组工具
import numpy as np
# 导入数据集生成器
from sklearn.datasets import make_blobs
# 导入KNN 分类器
from sklearn.neighbors import KNeighborsClassifier
# 导入数据集拆分工具
from sklearn.model_selection import train_test_split

# 生成样本数为200,特征数量为2的数据集
data = make_blobs(n_samples=200, n_features=2, centers=2, cluster_std=1.0, random_state=8)
X, Y = data

# 将生成的数据集进行可视化
#plt.scatter(X[:,0], X[:,1],s=80, c=Y,  cmap=plt.cm.spring, edgecolors='k')
#plt.show()

clf = KNeighborsClassifier()
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], s=80, c=Y, cmap=plt.cm.spring, edgecolors='k')
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
plt.title("Classifier:KNN")

# 把待分类的数据点用五星表示出来
plt.scatter(6.75, 4.82, marker='*', c='red', s=200)

# 对待分类的数据点的分类进行判断
res = clf.predict([[6.75, 4.82]])
plt.text(6.9, 4.5, 'Classification flag: ' + str(res))

plt.show()

4.实验结果 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值