【机器学习实战】K- 近邻算法(KNN算法)

简介: 【机器学习实战】K- 近邻算法(KNN算法)

image.gif


K-近邻算法

一、概述

K-近邻算法,又称为 KNN 算法,是数据挖掘技术中原理最简单的算法。


KNN 的工作原理:给定一个已知类别标签的数据训练集,输入没有标签的新数据后,在训练数据集中找到与新数据最临近的 K 个实例。如果这 K 个实例的多数属于某个类别,那么新数据就属于这个类别。


简单理解为: 由那些离 X 最近的 K 个点来投票决定 X 归为哪一类



image.png


举个例子,可以用 KNN 算法来分类一部电影是爱情片还是动作片(利用打架镜头和接吻镜头来做大致判断)


image.png


这个表就是我们已有的数据集合,也就是训练样本集。

这个数据集有两个特征 - 打斗镜头数和亲吻镜头数。

除此之外,我们还知道每部电影的所属类型,即分类样本

那么这样子我们该如何运用KNN算法来判断表中的新电影所属的电影类别呢?如下图所示


image.png


从散点图中我们可以分析大致推断,这个电影很有可能是爱情片,因为它的距离和已知的三个爱情片更近一点。


KNN 算法是利用什么方法进行判断的呢?

没错,就是距离度量 ✨


在二维平面中可以使用高中就学过的距离计算公式


如果是多个特征拓展到 N维空间 的话, 我们可以使用欧氏距离(也称欧几里得度量),如下所示:


image.png


通过表中的计算结果,我们可以知道绿点标记的电影到爱情片《后来的我们》距离最近,为 29.1.但如果只靠这样来判断的话,这个算法应该叫 最近邻算法。


KNN算法的步骤如下(一般 k ≤ 20)


计算已知类别数据集中的点与当前点之间的距离

按照距离递增次序排序

选取与当前距离最小的k个点

确定前k个点所在类别的出现频率

返回前k个点出现频率最高的类别作为当前点的预测类别

通过统计,当 k = 4 的时候,这四部电影的类别统计为 爱情片 :动作片 = 3 : 1 ,出现频率最高的类别是爱情片,所以在 k = 4 的时候,新电影的类别为 爱情片


KNN的python实现

1.1构建已经分类好的原始数据集

import pandas as pd
rowdata={'电影名称':['无问西东','后来的我们','前任3','红海行动','唐人街探案','战狼2'],
         '打斗镜头':[1,5,12,108,112,115],
         '接吻镜头':[101,89,97,5,9,8],
         '电影类型':['爱情片','爱情片','爱情片','动作片','动作片','动作片']}
movie_data = pd.DataFrame(rowdata)
movie_data

image.png


 1.2.算已知类别数据集中的点与当前点之间的距离

new_data = [24, 67]
dist = list((((movie_data.iloc[:6, 1: 3] - new_data)**2).sum(1))**0.5)  * 对行求和


1.3将距离升序排列,然后选取距离最小的k个点

k = 4
dist_l = pd.DataFrame({'dist': dist, 'labels': (movie_data.iloc[:6, 3])})
dr = dist_l.sort_values(by = 'dist')[: k]
dr


1.4 确定前k个点所在类别的出现频率

re = dr.loc[:, 'labels'].value_counts()
re.index[0]
result = []
result.append(re.index[0])
result


封装函数

import pandas as pd
"""
函数功能:KNN分类器
参数说明:
    inX:需要预测的数据集
    dataSet:已知分类标签的数据集(训练集)
    k:k-近邻算法参数,选择距离最小的k个点
返回:
result:分类结果
"""
def classify0(inX, dataSet, k):
    result = []
    dist = list((((dataSet.iloc[:6, 1: 3] - inX)**2).sum(1))**0.5)
    dist_l = pd.DataFrame({'dist': dist, 'labels': (dataSet.iloc[:6, 3])})
    dr = dist_l.sort_values(by = 'dist')[: k]
    re = dr.loc[:, 'labels'].value_counts()
    result.append(re.index[0])
    return result

小结


分类器并不会得到百分比正确的结果,除此之外,分类器的性能也会受到很多因素的影响,比如k的取值就会在很大程度上影响了分类器的预测结果,还有分类器的设置、原始数据集等等。

为了测试分类效果,我们将原始数据集分为两部分一部分用来训练算法(称为训练集),一部分用来测试算法的准确率(称为测试集)



k-近邻算法之约会网站配对效果判定

海伦一直使用在线约会网站寻找适合自己的约会对象,尽管约会网站会推荐不同的人选,但她并不是每一个都喜欢,经过一番总结,她发现曾经交往的对象可以分为三类:

1.不喜欢的人

2.魅力一般的人

3.极具魅力得人

海伦收集约会数据已经有了一段时间,她把这些数据存放在文本文件datingTestSet.txt中,其中各字段分别为:


每年飞行常客里程

玩游戏视频所占时间比

每周消费冰淇淋公升数



1.准备数据

datingTest = pd.read_table('datingTestSet.txt',header=None)
datingTest.head()
datingTest.shape
datingTest.info()

2. 分析数据

%matplotlib inline
import matplotlib as mpl
import matplotlib.pyplot as plt
# 将不同标签用颜色区分
Colors = []
for i in range(datingTest.shape[0]):
    m = datingTest.iloc[i,-1]
    if m =='didntLike':
        Colors.append('black')
    if m =='smallDoses':
        Colors.append('orange')
    if m =='largeDoses':
        Colors.append('red')
# 绘制两两之间的散点图
plt.rcParams['font.sans-serif']=['Simhei'] #图中字体设置为黑体
pl=plt.figure(figsize=(12,8))
fig1=pl.add_subplot(221)
plt.scatter(datingTest.iloc[:,1],datingTest.iloc[:,2],marker='.',c=Colors)
plt.xlabel('玩游戏视频所占时间比')
plt.ylabel('每周消费冰淇淋公升数')
fig2=pl.add_subplot(222)
plt.scatter(datingTest.iloc[:,0],datingTest.iloc[:,1],marker='.',c=Colors)
plt.xlabel('每年飞行常客里程')
plt.ylabel('玩游戏视频所占时间比')
fig3=pl.add_subplot(223)
plt.scatter(datingTest.iloc[:,0],datingTest.iloc[:,2],marker='.',c=Colors)
plt.xlabel('每年飞行常客里程')
plt.ylabel('每周消费冰淇淋公升数')
plt.show()

image.png


3. 数据归一化


image.png



我们很容易发现,上面公式中差值最大的属性对计算结果的影响最大,也就是说每年飞行常客里程对计算结果的影响远远大于其他两个特征,原因仅仅是因为它的数值比较大,但是在海伦看来这三个特征是同等重要的,所以接下来我们要进行数值归一化的处理,使得这三个特征的权重相等。

数据归一化的处理方法有很多种,比如0-1标准化、Z-score标准化、Sigmoid压缩法等等


在这里我们使用最简单的0-1标准化,公式如下:

数据处理中0-1规范化和标准化 - 知乎 (01标准化)

def minmax(dataSet):
    minDf = dataSet.min()
    maxDf = dataSet.max()
    normSet = (dataSet - minDf)/(maxDf - minDf)
    return normSet


将我们的数据集带入函数,进行归一化处理


datingT = pd.concat([minmax(datingTest.iloc[:, :3]), datingTest.iloc[:,3]], axis=1)
datingT.head()


4. 划分训练集和测试集

通常来说,我们只提供已有数据的90%作为训练样本来训练模型,其余10%的数据用来测试模型的准确性

"""
函数功能:切分训练集和数据集
参数说明
    dataSet:原始数据集
    rate:训练集所占的比例
返回:切分好的训练集和数据集
"""
def randSplit(dataSet, rate = 0.9):
    n = dataSet.shape[0]
    m = int(n * rate)
    train = dataSet.iloc[:m, :]
    test = dataSet.iloc[m: ,:]
    test.index = range(test.shape[0])
    return train, test
train, test = randSplit(datingT)
train
test



5. 分类器针对于约会网站的测试代码

上面我们已经将原始数据进行归一化处理然后也切分了训练集和测试集,所以我们的函数的输出参数就可以是 traintest、和**k** (选择的距离最小的k个点)

"""
函数功能:KNN 算法分类器
参数说明:
    train:训练集
    test:测试集
    k:KNN参数,即距离最小的k个点
返回:预测好分类的测试集
"""
def datingClass(train, test, k):
    n = train.shape[0] - 1
    m = test.shape[0]
    result = []
    for i in range(m):
        dist = list((((train.iloc[:6, 1: 3] - test.iloc[1, :n])**2).sum(1))**5)
        dist_l = pd.DataFrame({'dist':dist, 'labels':(train.iloc[:, n])})
        dr = dist_l.sort_values(by = 'dist')[: k]
        re = dist.loc[:, 'labels'].value_counts()
        result.append(re.index[0])
    result = pd.Series(result)
    test['predict'] = result
    acc = (test.iloc[:,-1] == test.iloc[:, -2]).mean()
    print(f'模型预测准确率为{acc}')
    return test

最后,测试上述代码能否正常运行,使用上面生成的测试集和训练集导入分类器函数中,然后执行并查看分类结果


datingClass(train, test, 5)

image.png



 总结


k近邻

算法功能 分类(核心),回归

算法类型 有监督学习 - 惰性学习,距离类模型

数据输入 包含数据标签 y, 且特征空间中至少包含k 个训练样本 (k ≥ 1)

特征空间中各个特征的量纲需统一,若不统一则需要进行归一化处理

自定义的超参数 k (k ≥ 1)

模型输出 在KNN分类中,输出是标签中的某个类别

在KNN回归中,输出是对象的属性值,该值是距离输入的数据最近的k个训练样本标签的平均值  



1.优点

  • 简单好用,容易理解,精度高,理论成熟,即可以用来做分类也可以用来做回归
  • 可用于数值型数据和离散型数据
  • 无数据输入假定
  • 适合对稀有事件进行分类


2.缺点

  • 计算复杂性高;空间复杂性高
  • 计算量太大,所以一般数值很大的时候不用这个,但是单个样本又不能太少,否则容易发生误分
  • 样本不平衡问题(即某些类别的样本数量很多,某些类别的样本数量很少)
  • 可理解性比较差,无法给出数据的内在含义
目录
相关文章
|
29天前
|
机器学习/深度学习 算法 数据挖掘
K-means聚类算法是机器学习中常用的一种聚类方法,通过将数据集划分为K个簇来简化数据结构
K-means聚类算法是机器学习中常用的一种聚类方法,通过将数据集划分为K个簇来简化数据结构。本文介绍了K-means算法的基本原理,包括初始化、数据点分配与簇中心更新等步骤,以及如何在Python中实现该算法,最后讨论了其优缺点及应用场景。
97 4
|
8天前
|
算法
PAI下面的gbdt、xgboost、ps-smart 算法如何优化?
设置gbdt 、xgboost等算法的样本和特征的采样率
23 2
|
26天前
|
机器学习/深度学习 算法 数据挖掘
C语言在机器学习中的应用及其重要性。C语言以其高效性、灵活性和可移植性,适合开发高性能的机器学习算法,尤其在底层算法实现、嵌入式系统和高性能计算中表现突出
本文探讨了C语言在机器学习中的应用及其重要性。C语言以其高效性、灵活性和可移植性,适合开发高性能的机器学习算法,尤其在底层算法实现、嵌入式系统和高性能计算中表现突出。文章还介绍了C语言在知名机器学习库中的作用,以及与Python等语言结合使用的案例,展望了其未来发展的挑战与机遇。
43 1
|
1月前
|
机器学习/深度学习 自然语言处理 算法
深入理解机器学习算法:从线性回归到神经网络
深入理解机器学习算法:从线性回归到神经网络
|
1月前
|
机器学习/深度学习 人工智能 算法
【手写数字识别】Python+深度学习+机器学习+人工智能+TensorFlow+算法模型
手写数字识别系统,使用Python作为主要开发语言,基于深度学习TensorFlow框架,搭建卷积神经网络算法。并通过对数据集进行训练,最后得到一个识别精度较高的模型。并基于Flask框架,开发网页端操作平台,实现用户上传一张图片识别其名称。
93 0
【手写数字识别】Python+深度学习+机器学习+人工智能+TensorFlow+算法模型
|
2月前
|
机器学习/深度学习 人工智能 自然语言处理
【MM2024】阿里云 PAI 团队图像编辑算法论文入选 MM2024
阿里云人工智能平台 PAI 团队发表的图像编辑算法论文在 MM2024 上正式亮相发表。ACM MM(ACM国际多媒体会议)是国际多媒体领域的顶级会议,旨在为研究人员、工程师和行业专家提供一个交流平台,以展示在多媒体领域的最新研究成果、技术进展和应用案例。其主题涵盖了图像处理、视频分析、音频处理、社交媒体和多媒体系统等广泛领域。此次入选标志着阿里云人工智能平台 PAI 在图像编辑算法方面的研究获得了学术界的充分认可。
【MM2024】阿里云 PAI 团队图像编辑算法论文入选 MM2024
|
1月前
|
机器学习/深度学习 算法
深入探索机器学习中的决策树算法
深入探索机器学习中的决策树算法
41 0
|
1月前
|
机器学习/深度学习 算法 Python
机器学习入门:理解并实现K-近邻算法
机器学习入门:理解并实现K-近邻算法
36 0
|
2月前
|
机器学习/深度学习 算法 Java
机器学习、基础算法、python常见面试题必知必答系列大全:(面试问题持续更新)
机器学习、基础算法、python常见面试题必知必答系列大全:(面试问题持续更新)
|
2月前
|
机器学习/深度学习 算法 决策智能
【机器学习】揭秘深度学习优化算法:加速训练与提升性能
【机器学习】揭秘深度学习优化算法:加速训练与提升性能