【机器学习实战】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.缺点

  • 计算复杂性高;空间复杂性高
  • 计算量太大,所以一般数值很大的时候不用这个,但是单个样本又不能太少,否则容易发生误分
  • 样本不平衡问题(即某些类别的样本数量很多,某些类别的样本数量很少)
  • 可理解性比较差,无法给出数据的内在含义
目录
相关文章
|
4月前
|
负载均衡 算法 关系型数据库
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
本文聚焦 MySQL 集群架构中的负载均衡算法,阐述其重要性。详细介绍轮询、加权轮询、最少连接、加权最少连接、随机、源地址哈希等常用算法,分析各自优缺点及适用场景。并提供 Java 语言代码实现示例,助力直观理解。文章结构清晰,语言通俗易懂,对理解和应用负载均衡算法具有实用价值和参考价值。
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
|
30天前
|
机器学习/深度学习 算法 文件存储
神经架构搜索NAS详解:三种核心算法原理与Python实战代码
神经架构搜索(NAS)正被广泛应用于大模型及语言/视觉模型设计,如LangVision-LoRA-NAS、Jet-Nemotron等。本文回顾NAS核心技术,解析其自动化设计原理,探讨强化学习、进化算法与梯度方法的应用与差异,揭示NAS在大模型时代的潜力与挑战。
274 6
神经架构搜索NAS详解:三种核心算法原理与Python实战代码
|
12天前
|
机器学习/深度学习 资源调度 算法
遗传算法模型深度解析与实战应用
摘要 遗传算法(GA)作为一种受生物进化启发的优化算法,在复杂问题求解中展现出独特优势。本文系统介绍了GA的核心理论、实现细节和应用经验。算法通过模拟自然选择机制,利用选择、交叉、变异三大操作在解空间中进行全局搜索。与梯度下降等传统方法相比,GA不依赖目标函数的连续性或可微性,特别适合处理离散优化、多目标优化等复杂问题。文中详细阐述了染色体编码、适应度函数设计、遗传操作实现等关键技术,并提供了Python代码实现示例。实践表明,GA的成功应用关键在于平衡探索与开发,通过精心调参维持种群多样性同时确保收敛效率
56 7
|
12天前
|
机器学习/深度学习 边缘计算 人工智能
粒子群算法模型深度解析与实战应用
蒋星熠Jaxonic是一位深耕智能优化算法领域多年的技术探索者,专注于粒子群优化(PSO)算法的研究与应用。他深入剖析了PSO的数学模型、核心公式及实现方法,并通过大量实践验证了其在神经网络优化、工程设计等复杂问题上的卓越性能。本文全面展示了PSO的理论基础、改进策略与前沿发展方向,为读者提供了一份详尽的技术指南。
51 0
粒子群算法模型深度解析与实战应用
|
4月前
|
机器学习/深度学习 数据采集 人工智能
20分钟掌握机器学习算法指南
在短短20分钟内,从零开始理解主流机器学习算法的工作原理,掌握算法选择策略,并建立对神经网络的直观认识。本文用通俗易懂的语言和生动的比喻,帮助你告别算法选择的困惑,轻松踏入AI的大门。
|
5月前
|
机器学习/深度学习 存储 Kubernetes
【重磅发布】AllData数据中台核心功能:机器学习算法平台
杭州奥零数据科技有限公司成立于2023年,专注于数据中台业务,维护开源项目AllData并提供商业版解决方案。AllData提供数据集成、存储、开发、治理及BI展示等一站式服务,支持AI大模型应用,助力企业高效利用数据价值。
|
6月前
|
机器学习/深度学习 人工智能 自然语言处理
AI训练师入行指南(三):机器学习算法和模型架构选择
从淘金到雕琢,将原始数据炼成智能珠宝!本文带您走进数字珠宝工坊,用算法工具打磨数据金砂。从基础的经典算法到精密的深度学习模型,结合电商、医疗、金融等场景实战,手把手教您选择合适工具,打造价值连城的智能应用。掌握AutoML改装套件与模型蒸馏术,让复杂问题迎刃而解。握紧算法刻刀,为数字世界雕刻文明!
221 6
|
7月前
|
机器学习/深度学习 算法 数据安全/隐私保护
基于机器学习的人脸识别算法matlab仿真,对比GRNN,PNN,DNN以及BP四种网络
本项目展示了人脸识别算法的运行效果(无水印),基于MATLAB2022A开发。核心程序包含详细中文注释及操作视频。理论部分介绍了广义回归神经网络(GRNN)、概率神经网络(PNN)、深度神经网络(DNN)和反向传播(BP)神经网络在人脸识别中的应用,涵盖各算法的结构特点与性能比较。
|
7天前
|
传感器 机器学习/深度学习 算法
【使用 DSP 滤波器加速速度和位移】使用信号处理算法过滤加速度数据并将其转换为速度和位移研究(Matlab代码实现)
【使用 DSP 滤波器加速速度和位移】使用信号处理算法过滤加速度数据并将其转换为速度和位移研究(Matlab代码实现)
|
8天前
|
传感器 算法 数据挖掘
基于协方差交叉(CI)的多传感器融合算法matlab仿真,对比单传感器和SCC融合
基于协方差交叉(CI)的多传感器融合算法,通过MATLAB仿真对比单传感器、SCC与CI融合在位置/速度估计误差(RMSE)及等概率椭圆上的性能。采用MATLAB2022A实现,结果表明CI融合在未知相关性下仍具鲁棒性,有效降低估计误差。

热门文章

最新文章