ML算法——KNN随笔【全国科技工作者日创作】【机器学习】

news2024/9/28 17:30:25

9、K-Nearest Neighbors (KNN)

9.1、理论部分

K最邻近算法

  • 把一个物体表示成向量【特征工程】,且 KNN 需要考虑 【特征缩放】。
  • 标记每个物体的标签
  • 计算两个物体之间的距离/相似度
  • 选择合适的 K

未知点的判断基于已知点的距离,选出最近的K个点,投票选出未知点的最大可能。

计算两个物体之间的距离/相似度?

欧氏距离

∑ i = 1 n ( x i − x i ) 2 \sqrt{\sum_{i=1}^{n}(x_i^{} - x_i^{})^2} i=1n(xixi)2

其中,xi和xj是空间中的两个点,i和j表示维度。

点数K选取奇数的目的?

偶数更容易出现“平票”,奇数也不可避免地会出现平票(1:1:1)

使用 sklearn 实现,详见9.3。

选择合适的 k 对决策边界的影响?

决策边界:决定线性分类器、非线性分类器。

在这里插入图片描述

图中:

  • 线性
  • 非线性
  • 非线性【最陡峭】,过拟合。

KNN的决策边界举例:

在这里插入图片描述

边界越陡峭,越不稳定,希望得到平滑的边界,理论上,K↑,边界越平滑。

如何选择 K 值?

交叉验证:训练集进一步划分为训练集【train】+验证集【validation】

以常用的五折交叉验证为例,

在这里插入图片描述

  • 对 K= 1执行五次循环,取平均,作为 k= 1的成绩。

  • 换 K ,重复。

  • 千万不能用测试数据【X_test、y_test】来调参

在数据少时,可适当增加折数的合理性?

交叉验证可以通过增加折数来减少主观因素的影响,使得结果更加准确。

主观因素:主要指在进行数据分割的时候,因为某些人为因素导致分割不准确,进而对结果产生影响。比如,如果使用随机拆分数据的方式进行验证,因为随机拆分数据的时候存在不随机的情况,所以就会对验证效果产生影响。

KNN的优化方向

  • 时间复杂度 O(N),适合低维空间内使用,优化方向:KD-tree 在二维空间的优化、LSH(Locality Sensitivity Hashing)不再寻求完全准确的解,加快搜索。
  • 特征间的相关性处理,Mahalanobis Distance
9.2、实现
9.2.1、KNN 手写实现
from sklearn import datasets
from collections import Counter # 投票
from sklearn.model_selection import train_test_split
import numpy as np

def euc_dis(instance1, instance2):
    """
    计算欧氏距离
    :param instance1:样本1,array数组
    :param instance2: 样本2,array数组
    :return: 欧氏距离
    """
    d = np.sqrt(sum(instance1-instance2)**2)
    return d

def knn_classify(X , y, testInstance, k):
    """
    给未知点归类
    :param X: train——feature
    :param y: train——label
    :param testInstance:测试数据,array数组
    :param k:选择多少个 neighbors
    :return:最多元素
    """
    distances = [euc_dis(x, testInstance)for x in X]
    kneighbors = np.argsort(distances)[:k] #快排后,取前 k 个  || 优化?改用优先队列,维护前 k 个, O(NlogN)
    count = Counter(y[kneighbors]) # Counter([0,0,0,1,1,1,1,1,1])  -》 Counter({1: 6, 0: 3})
    return count.most_common()[0][0]   # [(1, 6), (0, 3)]  -》 1

#导入 iris 数据
iris = datasets.load_iris()
X = iris.data
y = iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=50)

#预测结果
predictions = [knn_classify(X_train, y_train, data, 3) for data in X_test]
correct = np.count_nonzero((predictions == y_test) == True)
# acc
print("Accuaracy is :%.3f" %(correct/len(X_test)))
9.2.2、KNN sklearn 实现

鸢尾花【三分类问题

from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier

读取数据 X,y

data = datasets.load_iris()
X = data.data   #N*D:sample * Dimension
y = data.target #label:(0,1,2)

分为训练数据 & 测试数据 (默认比例: 3/4 : 1/4)

X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=500)

构建KNN模型,K=3 & 训练

clf = KNeighborsClassifier(n_neighbors=3)
clf.fit(X_train, y_train)

计算准确率(二选一)

方法一

from sklearn.metrics import accuracy_score

acc  = accuracy_score(y_test,clf.predict(X_test))
print(acc)

方法二

import  numpy as np

correct = np.count_nonzero((clf.predict(X_test) == y_test) == True)
print(f'acc is {correct/len(X_test)}')

完整代码

#
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
#
data = datasets.load_iris()
X = data.data   #N*D:sample * Dimension
y = data.target #label:(0,1,2)
#
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=500)
#
clf = KNeighborsClassifier(n_neighbors=3)
clf.fit(X_train, y_train)
#
from sklearn.metrics import accuracy_score

acc  = accuracy_score(y_test,clf.predict(X_test))
print(acc)

KNN没有训练痕迹,那么 clf.fit() 在做什么?

它是机器学习中唯一一个不需要训练过程的算法,它在训练阶段只是把数据保存下来,训练时间开销为 0,等收到测试样本后进行处理。

knn 算法手写实现的意义?较 sklearn 实现的 knn 优势在哪里?

  1. 简单易理解:KNN算法非常简单,易于理解。通过自己实现该算法,可以更深入地了解KNN算法的工作原理。
  2. 可扩展性:自己实现KNN算法可以让你更好地了解如何扩展算法以适应不同的数据集和场景。例如,你可以尝试使用不同的距离度量(如曼哈顿距离或切比雪夫距离),或者调整K值以获得更好的性能。
  3. 性能优化:在大数据集上,KNN算法的计算复杂度较高。通过自己实现该算法,你可以对算法进行优化,例如使用KD树来加速搜索邻居。
  4. 无依赖:自己实现KNN算法可以让你更好地了解算法的内部工作原理,无需依赖外部库。

想更深入地了解KNN算法的工作原理,或者需要对算法进行定制和优化,自己实现KNN算法是有意义的。只是想快速应用到项目上,那么使用sklearn是更好的选择。

9.3、案例

二手车预测案例【回归问题】

import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
#读取数据
df = pd.read_csv('data.csv')

#清洗数据
# 把颜色独热编码
df_colors = df['Color'].str.get_dummies().add_prefix('Color: ')
# 把类型独热编码
df_type = df['Type'].apply(str).str.get_dummies().add_prefix('Type: ')
# 添加独热编码数据列
df = pd.concat([df, df_colors, df_type], axis=1)
# 去除独热编码对应的原始列
df = df.drop(['Brand', 'Type', 'Color'], axis=1)
# 数据转换
matrix = df.corr()
f, ax = plt.subplots(figsize=(8, 6))
sns.heatmap(matrix, square=True)
plt.title('Car Price Variables')

from sklearn.neighbors import KNeighborsRegressor
from sklearn.model_selection import train_test_split
from sklearn import preprocessing
from sklearn.preprocessing import StandardScaler
import numpy as np

X = df[['Construction Year', 'Days Until MOT', 'Odometer']]
y = df['Ask Price'].values.reshape(-1, 1)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=41)

X_normalizer = StandardScaler() # N(0,1) 
X_train = X_normalizer.fit_transform(X_train)
X_test = X_normalizer.transform(X_test)

y_normalizer = StandardScaler()
y_train = y_normalizer.fit_transform(y_train)
y_test = y_normalizer.transform(y_test)

knn = KNeighborsRegressor(n_neighbors=2)
knn.fit(X_train, y_train.ravel())

#Now we can predict prices:
y_pred = knn.predict(X_test)
y_pred_inv = y_normalizer.inverse_transform(y_pred)
y_test_inv = y_normalizer.inverse_transform(y_test)

# Build a plot
plt.scatter(y_pred_inv, y_test_inv)
plt.xlabel('Prediction')
plt.ylabel('Real value')

# Now add the perfect prediction line
diagonal = np.linspace(500, 1500, 100)
plt.plot(diagonal, diagonal, '-r')
plt.xlabel('Predicted ask price')
plt.ylabel('Ask price')
plt.show()

print(y_pred_inv)
  • StandardScaler(),特征缩放函数
  • fit_transform(),根据给定数据集的特点来调整模型的参数,同时可以对数据进行转换
  • inverse_transform(),在scikit-learn中,转换回原始数据并不是通过计算数据中的协方差矩阵和特征向量来实现的

KNN如何解决回归问题的?

KNN用于回归问题时,模型从训练数据集中选择离该数据点最近的k个数据点,并且把这些数据的y值取均值,把求出的这个均值作为新数据点的预测值。【对应:分类中投票高者做结果】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/586860.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

pyjail初了解

前言 最近在各种比赛Misc方向都能多多小小看到Python jail题,通过eval或者exec等函数执行Python的代码获取shell,实现Python逃逸,但是我不是太会,因此找点题目做一下,总结一下。 常用Python的魔术方法 _init_:用于P…

chatgpt赋能python:Python中小数点保留的几种方法

Python中小数点保留的几种方法 作为一名Python工程师,我们经常需要对数字进行处理。在处理时,我们需要将数字进行格式化,例如保留小数点后几位或添加千位分隔符等。其中,保留小数点后几位是比较常见的需求。本文将介绍Python中小…

chatgpt赋能Python-python中怎么安装aip

概述 在现代的SEO中,使用机器学习和自然语言处理的API来分析关键字和网页内容已经成为一个普遍的实践。Google API是其中最受欢迎的一个,因为它可以提供多种功能,包括分析关键字、分析文本和图像识别等。 Python作为一种优秀的脚本语言&…

Linux Apache 配置与应用 【虚拟主机 连接保持 日志分割 分析系统 优化网页】

--------构建虚拟 Web 主机-------- 虚拟Web主机指的是在同一台服务器中运行多个Web站点,其中每一个站点实际上并不独立占用整个服务器,因此被称为“虚拟”Web 主机。通过虚拟 Web 主机服务可以充分利用服务器的硬件资源,从而大大降低网站构建…

《深入理解计算机系统(CSAPP)》第8章 异常控制流 - 学习笔记

写在前面的话:此系列文章为笔者学习CSAPP时的个人笔记,分享出来与大家学习交流,目录大体与《深入理解计算机系统》书本一致。因是初次预习时写的笔记,在复习回看时发现部分内容存在一些小问题,因时间紧张来不及再次整理…

chatgpt赋能python:Python合并函数:一个简单但有用的工具

Python合并函数:一个简单但有用的工具 Python是一种优雅而强大的编程语言,拥有许多内置的函数和库,可以让编程变得更加简单和高效。其中,合并函数是一个非常有用的工具,它可以让我们快速而灵活地合并和处理数据。 什…

5月30日第壹简报,星期二,农历四月十二

5月30日第壹简报,星期二,农历四月十二坚持阅读,静待花开1. 比亚迪:自主研发了常压油箱的燃油蒸汽排放控制技术,能符合蒸发排放法规标准, 愿与所有同行共享核心技术专利。2. 中国计划2030年前实现首次登月&a…

chatgpt赋能python:Python中升序和降序排序:什么是升序和降序以及如何使用Python进行排序

Python中升序和降序排序:什么是升序和降序以及如何使用Python进行排序 介绍 Python是一种强大的编程语言,可以用来处理各种类型的数据。其中包括对数据进行排序,Python具有方便且易于使用的排序功能。在Python中,可以使用升序和…

chatgpt赋能python:Python中可迭代对象的介绍

Python中可迭代对象的介绍 Python是一种高级编程语言,它具有简单易学、可读性强、功能强大等特点,成为了数据科学、机器学习、Web开发等领域的热门选择。Python中有很多重要的概念和功能,其中之一就是支持可迭代对象的概念。 在Python中&am…

chatgpt赋能python:Python中如何生成表格

Python中如何生成表格 在数据分析和处理中,表格是一种常见的数据格式,并且在不同的场景下都有着不同的用途。Python作为一种高效的编程语言,可以帮助我们轻松地生成和操作表格数据。在本文中,我们将介绍Python中生成表格的方法&a…

IDEA控制台tomcat 乱码

问题 IDEA控制台tomcat 乱码 详细问题 项目部署至tomcat上,启动tomcat,IDEA控制台终端Server日志,Tomcat Localhost日志,Tomcat Catalina日志乱码 Server日志 D:\tomcat9\bin\catalina.bat run [2023-05-29 11:20:24,521] Art…

【Linux】在Ubuntu中卸载、下载mysql以及如何检查mysql是否卸载成功

介绍 这里是小编成长之路的历程,也是小编的学习之路。希望和各位大佬们一起成长! 以下为小编最喜欢的两句话: 要有最朴素的生活和最遥远的梦想,即使明天天寒地冻,山高水远,路远马亡。 一个人为什么要努力&a…

5.30黄金空头能否延续?今日多空如何布局?

近期有哪些消息面影响黄金走势?今日黄金多空该如何研判? ​黄金消息面解析:周一(5月29日)进入欧市盘中,对美国周末达成债务上限协议的乐观情绪推动风险情绪回升,与此同时,上周公布的美国PCE数据让美联储难…

ChatGPT Sorry, you have been blocked(抱歉,您已被屏蔽)的解决方法

最近在使用 ChatGPT 时大家遇到的最多的问题就是 Sorry, you have been blocked(抱歉,您已被屏蔽)了,之前的 Access denied 似乎都不常见了,今天老王就分享下这个问题的原因和解决方法。 一、ChatGPT 被屏蔽 blocked …

汇编调试及学习

汇编调试 打印寄存器的值 打印内存地址 打印8字节,就是64位 打印格式 是从低位取过来的 b 字节 h 双字节 w四字节 g八字节 前变基 后变基 。 后变基这个变基会发生变化的。前变基变基不会发生变化需要用!号。 前变基 , 加了&#xff0…

【Springcloud】RabbitMQ入门

文章目录 一、同步通讯与异步通讯1、同步调用的优缺点2、异步调用的优缺点 二、RabbitMQ1、MQ消息队列2、RabbitMQ的安装3、RabbitMQ的结构和概念4、RabbitMQ的消息模型5、入门案例 一、同步通讯与异步通讯 同步通讯就像打视频,两边可以实时得到相关信息。异步通讯…

打开复制过去的virtualbox文件之后,在打开时出现只有logs文件的解决方法

文章目录 前言 问题一 打开方式 注意事项 问题二 解决方法 总结 前言 打开复制过去的virtualbox文件之后,在打开时出现只有logs文件的解决方法 问题一 virtualbox虚拟机拷贝到其他电脑上面如何打开? 打开方式 将 VirtualBox 虚拟机拷贝到其他…

第三章 JVM内存概述

附录:精选面试题 Q:为什么虚拟机必须保证一个类的Clinit( )方法在多线程的情况下被同步加锁 ? A: 因为虚拟机在加载完一个类之后直接把这个类放到本地内存的方法区(也叫原空间)中了,当其他程序再来调这个类…

vue2.0中使用summernote富文本编辑器, 并实现上传图片至七牛

vue2.0中使用summernote富文本编辑器, 并实现上传图片至七牛 ackage.json 文件中添加所需的依赖库,然后执行 npm install 安装这些库 2. 在 src / main.js 文件中导入下列库文件 3. 由于summernote 使用 jQuery 库, 我们在组件里需要导入 jQuery才能使用, 为了方便起见,我们在 …

《深入理解计算机系统(CSAPP)》第7章 链接 - 学习笔记

写在前面的话:此系列文章为笔者学习CSAPP时的个人笔记,分享出来与大家学习交流,目录大体与《深入理解计算机系统》书本一致。因是初次预习时写的笔记,在复习回看时发现部分内容存在一些小问题,因时间紧张来不及再次整理…