[监督学习] 分类(K近邻算法)

以下是本人整理的机器学习-监督学习有关知识,详细请看链接:

监督学习框架:思维导图-python.

KNN算法

一:KNN算法的概述
  邻近算法,或者说K最近邻(kNN,k-NearestNeighbor)分类算法是数据挖掘分类技术中最简单的方法之一。所谓K最近邻,就是k个最近的邻居的意思,说的是每个样本都可以用它最接近的k个邻居来代表,Cover和Hart在1968年提出了最初的邻近算法。
  KNN是一种分类(lassification)算法,它输入基于实例的学习(instance-based learning),属于懒惰学习(lazy learning)即KNN没有显式的学习过程,也就是说没有训练阶段,数据集事先已有了分类和特征值,待收到新样本后直接进行处理。与急切学习(eager learning)相对应。
  
  KNN是通过测量不同特征值之间的距离进行分类。 
  
  具体过程:通过计算待分类数据点,与已有数据集中的所有数据点的距离。取距离最小的前K个点,根据“少数服从多数”的原则,将这个数据点划分为出现次数最多的那个类别。
  当涉及到KNN,网上会有关很多这类图片,以下图片便于大家理解。

在这里插入图片描述
  通过计算待分类点Xu 与样本数据集合中每个点的距离,最近的K个样本点大多数属于红色类别,所以待分类点Xu被分为红色。

二:KNN算法的过程
  1)计算测试数据与各个训练数据之间的距离
  2)按照距离的递增关系进行排序
  3)选取距离最小的K个点
  4)确定前K个点所在类别的出现频率
  5)返回前K个点中出现频率最高的类别作为测试数据的预测分类

三:关于距离的计算
  距离 就是平面上两个点的直线距离。关于距离的度量方法,常用的有:欧几里得距离、余弦值(cos), 相关度 (correlation), 曼哈顿距离 (Manhattan distance)等。
  两个点或元组P1=(x1,y1)和P2=(x2,y2)的欧几里得距离是
在这里插入图片描述
  当样本点是n维时,距离公式可写成:
在这里插入图片描述
四:关于K值的选取
  
  K值: 临近数,即在预测目标点时取几个临近的点来预测。
 
K值得选取非常重要,因为:
  (1)如果当K的取值过小时,一旦有噪声得成分存在们将会对预测产生比较大影响,例如取K值为1时,一旦最近的一个点是噪声,那么就会出现偏差,K值的减小就意味着整体模型变得复杂,容易发生过拟合;
  (2)如果K的值取的过大时,就相当于用较大邻域中的训练实例进行预测,学习的近似误差会增大。这时与输入目标点较远实例也会对预测起作用,使预测发生错误。K值的增大就意味着整体的模型变得简单; 
  K的取值尽量要取奇数,一般情况下,K值会倾向选取较小的值,并使用交叉验证法选取最优K值。

Python实现过程

一:导入sklearn库

sklearn中的K近邻分类器在sklearn库中,可以使sklearn.neighbors.KNeighborsClassifier 创建一个K近邻分类器 。

from sklearn.neighbors import KNeighborsClassifier

主要参数有:

neigh = KNeighborsClassifier(n_neighbors= 3, weights = 'uniform', algorithm = 'auto') #设置最近的3个邻居作为分类的依据

n_ neighbors:用于指定分类器中K的大小(默认值为5,注意与kmeans的区别)。
weights:设置选中的K个点对分类结果影响的权重(默认值为平均权重“uniform”,可以选择“distance"代表越近的点权重越高,或者传入自己编写的以距离为参数的权重计算函数)。
algorithm:设置用于计算临近点的方法,因为当数据量很大的情况下计算当前点和所有点的距离再选出最近的k各点,这个计算量是很费时的,所以选项中有ball tree、kd_ tree和brute,分别代表不同的寻找邻居的优化算法,默认值为auto,根据训练数据自动选择。

二:案例一测试

尝试使用K近邻分类器,创建一组数据 x 和它对应的标签 y,并训练数据,通过对模型的训练建立模型后,输入测试集text = [[1.1], [2.1]],观察这两个测试点的结果。

from sklearn.neighbors import KNeighborsClassifier

X = [[0], [1], [2], [3]]
y = [0, 0, 1, 1]

neigh = KNeighborsClassifier(n_neighbors= 3, weights = 'uniform', algorithm = 'auto') # 设置最近的3个邻居作为分类的依据
neigh.fit(X, y) # 调用fit()函数,将训练数据X和标签y送入分类器进行学习

text = [[1.1], [2.1]] 
data = neigh.predict(text)
print(data)
print(neigh.score(X, y)) #返回评分

测试结果:

训练结果: [0 1]
训练结果评分: 1.0

其中n_ neighbors设置为3,即使用最近的3个邻居作为分类的依据,其他参数保持默认值,并将创建好的实例赋给变量neigh。调用fit()函数,将训练数据X和标签y送入分类器进行学习。neigh.fit(X, y)

输入测试点 [1.1],K近邻分类器通过计算该样本]与训练数据的距离,取0,1,2这3个邻居作为依据,根据“投票法”最终将样本分为类别0。
同理,输入测试点 [2.1],模型输出类别为1。
并最终可返回对模型的评分。

三:案例二测试

使用sklearn库中原有的鸢尾花数据进行分析,鸢尾花数据集 excel 展示可以点击下面链接查看。

鸢尾花数据展示: 数据-图片.

鸢尾花数据集每个样本有4个特征,共有0、1、2三种样本,交叉验证数据后成训练模型,输入测试集 text 进行模型验证。

# -*- coding: utf-8 -*-
# @Time    : 2020/4/8 16:22
# @Author  : Zudy
# @FileName: course4.py

'''
1.机器学习-监督学习(分类)
   运用鸢尾花数据集 实现 KNN 算法
'''

from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import load_iris # 导入鸢尾花训练集
from sklearn.model_selection import cross_val_score # 导入计算交叉检验值的函数cross_val_score


# 将鸢尾花数据赋值给变量iris
iris = load_iris()
data = iris.data # 鸢尾花数据作为特征,
target = iris.target # 鸢尾花数据作为目标结果[0,1,2],


neigh = KNeighborsClassifier(n_neighbors= 3)  # 创建K近邻分类器, 设置 K=3
cross_val_score(neigh, data, target, cv = 10) # 使用10折交叉验证

neigh.fit(data, target) # fit()训练模型
text = [
    [5.1, 3.5, 1.4, 0.2],
    [7., 3.2, 4.7, 1.4],
    [5.9, 3., 5.1, 1.8]]
pre_text_KNN = neigh.predict(text) # KNN 函数预测

print('运用 KNN近邻分类 预测分类结果:',pre_text_KNN)

测试结果:

运用 KNN近邻分类 预测分类结果: [0 1 2]

四:交叉验证获取最佳-K值

这里使用交叉验证法选取最优K值,一般情况下,K会倾向选取较小的值。

思路:通过遍历一定长度的数据,取不同的k值,用列表接收不同k值训练的分数,选取第一次分数最高的k值,即为最佳的k值。

# -*- coding: utf-8 -*-
# @Time    : 2020/4/2 13:55
# @Author  : Zudy
# @FileName: course_text.py

'''
1.使用sklearn的cross_val_score进行交叉验证
    1.1 交叉验证用于评估模型的预测性能,尤其是训练好的模型在新数据上的表现,可以在一定程度上减小过拟合。
    1.2 还可以从有限的数据中获取尽可能多的有效信息。
2. 使用交叉检验的方法可以用于任何带参数的模型预测,选取合适的参数 K'''

from sklearn import datasets   # 鸢尾花数据集
from sklearn.model_selection import train_test_split,cross_val_score   # 划分数据 交叉验证
from sklearn.neighbors import KNeighborsClassifier  # KNN模型
import matplotlib.pyplot as plt


iris = datasets.load_iris()       # 加载sklearn的鸢尾花数据集
x = iris.data        # 数据集
y = iris.target       # 每行数据所对应的标签

# 这里以1/3的来划分数据
train_X, test_X, train_y, test_y = train_test_split(x, y, test_size=1/3, random_state=3)
# 训练集训练结果  train_X, train_y
# 测试集测试结果  test_X, test_y


k_range = range(1,41)  # k值的取值范围
cv_scores = []    # 用来放每个模型的分数结果值
for k in k_range:
   # 改变KNN聚类的参数n_neighborsd的值,来选取合适的KNN模型的k
   neigh = KNeighborsClassifier(n_neighbors = k)
   score = cross_val_score(neigh, train_X, train_y, cv = 10, scoring = 'accuracy')
   cv_scores.append(score.mean())

plt.plot(k_range, cv_scores, 'ko-')
plt.xlabel('K值')
plt.ylabel('Accuracy')
plt.show()

通过图像可以观察最佳K值,最佳K=3。
在这里插入图片描述

在实际进行KNN模型训练时,我们可以发现K值过小时,相当于使用较小的邻域进行预测,如果邻居恰好是噪声点,会导致过拟合。随着K值不断增大,模型的精确度先增后减,第一次到达最大精确值是K=3,随着K值超过7时,距离较远的样本也会对预测起作用,导致预测错误,模型不精确度开始呈下降趋势。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章