04-机器学习与KNN算法
相册人物自动分类流媒体同类视频推荐手机语音服务:Hi Siri垃圾邮件自动识别机器学习是让计算机系统从数据中自动学习规律,并利用这些规律对新数据做出预测或决策,而无需人为编写明确的规则。与传统编程不同,机器学习是从数据中生成程序的过程。其核心不是写死的逻辑,而是通过数据驱动的方式,让模型自己学会如何完成任务。换句话说,传统程序是 “输入数据 + 程序代码 → 输出结果” ,而机器学习是 “输入数据
1、机器学习
正式学习之前,大家不妨一起思考一个问题:为什么我们需要机器学习(Machine Learning, ML)?
通过编程,我们可以让机器做一些基本的事情,比如最短路径规划(GPS导航),但是我们没有办法让机器具体实现某一段代码:比如去理解人类语言、疾病诊断、自动驾驶。我们能得出的结论就是,需要让这台机器自己去学会这些事情,这就是机器学习的初衷。机器学习作为整个AGI(Artificial General Intelligence)学习的重要基础部分(后面的DL学完,你会发现ML很多东西都会被DL替代),掌握其基础概念和理论还是非常值得的。
1.1、什么是机器学习
|
相册人物自动分类
|
流媒体同类视频推荐
|
手机语音服务:Hi Siri
|
垃圾邮件自动识别
|
机器学习是让计算机系统从数据中自动学习规律,并利用这些规律对新数据做出预测或决策,而无需人为编写明确的规则。与传统编程不同,机器学习是 从数据中生成程序 的过程。其核心不是写死的逻辑,而是通过数据驱动的方式,让模型自己学会如何完成任务。
换句话说,传统程序是 “输入数据 + 程序代码 → 输出结果” ,而机器学习是 “输入数据 + 输出结果 → 学习程序代码”。
机器学习的三大范式(三种不同的学习方式或学习框架):
老登程序员会问:机器学习的三范式了解吗?
监督学习
监督学习(Supervised Learning):数据有标签,目标是预测结果(如分类、回归)。
- 目标:主要是学会“输入(x)→输出(y)”的映射;
- 重要算法:KNN做分类或回归预测,如判断垃圾邮件、房能卖多少钱,需带标签训练数据
|
输入(X,即示例数据) |
输出(Y,即标签) |
应用 |
|
邮件 |
是否是垃圾邮件算法 |
垃圾邮件过滤器 |
|
音频 |
音频转换文本 |
语音识别 |
|
英文 |
中文/西班牙 |
机器翻译 |
|
用户信息+广告 |
用户是否点击过 |
精准广告推送 |
|
图片+车辆信息 |
车辆周边实时数据 |
自动驾驶 |
回归算法
关键特征:预测无限多个可能的数字中的任何一个,让我们举一个具体的例子,比如房屋价格预测
- 黄色、绿色都表示的是近期不同户型的售价
- 此时,根据不同的算法(直线预测、曲线预测)会得出同样户型不同的售价
|
|
|
这个就是机器学习中监督学习的第一种分类:回归。从无限多可能的数字/数据中学习一个映射关系,最终预测出一个连续型的数值结果。如接下来连续7天的温度、预测马拉松完赛时间、预测台风到达的时间....
代价函数与梯度下降
模型(比如线性回归、逻辑回归)在训练初期,参数是随机的,预测结果必然和真实值偏差很大。代价函数的作用就是:
- 量化偏差:把 “预测不准” 这个模糊概念,变成具体的数值(比如误差值 = 5.2);
- 指导优化:告诉模型 “往哪个方向调整参数”,才能让误差变小(比如通过梯度下降算法,沿着代价函数减小的方向更新参数)。
没有代价函数,模型就像 "无头苍蝇",不知道该如何优化自己,所以其作用是量化模型的预测误差。
但是代价函数也很消耗算力怎么办呢?为了最小化代价函数,找到让模型误差最小的最优参数,就引入了梯度下降。举个具体例子就懂了:
- 比如线性回归模型,它的公式是 y=w1x1+w2x2+b(w 是权重,b 是偏置,统称 “模型参数”);
- 模型训练初期,w 和 b 是随机赋值的,此时代价函数(MSE)会很大(预测误差大);
- 梯度下降的作用就是:一步步调整w、b的取值,让 MSE 不断减小,直到找到一组 w 和 b 让 MSE 达到最小值(此时模型预测最准)。
分类算法
关键特征:预测结果只有少量(个位数)的输出,如肿瘤良性/恶性、猫/狗、0/1/2,让我们举一个具体的例子,比如乳腺癌检测
- 可以只有一个输入,肿瘤大小,分类算法输出良性、恶性
- 也可以有多个输入,年龄+肿瘤大小,分类算法输出良性、恶性
|
|
|
分类算法的核心是学习类别并区分规律,和回归算法一致,仅输出不同。常见的如:垃圾邮件识别。疾病诊断、信用风险评估(根据用户收入+负债判断风险等级)、图片分类(宠物、建筑、美食)......
无监督学习
无监督学习(Unsupervised Learning):数据无标签,目标是发现结构(如聚类、降维)。
- 目标:发现无序数据中的结构或模式
- 重要算法:K-Means,做聚类分析,如用户分群、商品归类,不需要标签,只从无标签数据中找规律。
聚类算法
我正在学习《吴恩达机器学习》,此时右边推送了神经网络、深度学习等课程,这些课程都是动态更新的,因此不可能写死推荐关系,这就是机器学习的的聚类算法。类似的还有新闻推送、每日音乐...
模型自己事先不知道哪些视频跟视频之间有关联(上传视频的人不会说:我的课程跟xx课程是关联的),而是通过不断学习(如人类观看视频的行为习惯),将海量数据做归类统计特征,这就是无监督学习。

类似的还有电商、教育等平台的人群划分之后的定向商品推送,我们没有提前告知算法一些信息,比如这是第一类的人,那些是第二类的人,还有第三类等等。我们只是说这有一堆数据。我不知道数据里面有什么。我不知道谁是什么类型?我甚至不知道人们有哪些不同的类型?这些类型又是什么?但你能自动地找到数据中的结构吗?就是说你要自动地聚类那些个体到各个类,我没法提前知道哪些是哪些。因为我们没有给算法正确答案来回应数据集中的数据,所以这就是无监督学习。

简单来说,无监督学习算法,获取没有标签的数据并尝试自动将它们分组到集群中。除了聚类算法,常见的还有降维算法(人脸识别的特征预处理)、异常检测算法(信用卡交易欺诈识别)等,我们暂时无序深入了解。
强化学习
- 强化学习(Reinforcement Learning):通过与环境交互,学习最优策略(如游戏AI、机器人控制)
目标:学会“在环境中做决策”以获得最大奖励
例如:像训练一只狗:做对了给奖励(+1分),做错了惩罚(-1分),最终学会听指令
机器学习领域最常用的两种算法就是监督学习、无监督学习,强化学习了解即可
过拟合问题
过拟合就是模型 "死记硬背"训练数据(包括噪声和偶然规律),但不会 "举一反三",面对新数据时预测效果极差。比如学生刷题时死记硬背答案,考试遇到换题型的同类题就做错,本质是模型"学偏了"。
- 模型太复杂,数据不够"支撑"
- 训练数据有问题:数据量太少、噪声太多、数据分布不均 / 泄露
- 训练过程不当:迭代次数过多、特征工程过度导致模型被无关特征干扰
解决方案也根据不同场景而不同,常见
- 增加高质量训练数据(治本之策):数据量越大、越全面,模型越能学到真实规律,越难被噪声干扰
- 简化模型,降低复杂度:
-
- 避免使用高阶多项式回归,优先用简单的线性回归 / 逻辑回归;
- 神经网络:减少层数 / 神经元数量;
- 对决策树剪枝
- 最常用:加入正则化(限制模型参数):在代价函数中加入 “惩罚项”,让模型参数不能过大,从而避免模型过度拟合复杂特征
- 针对复杂模型:使用集成学习(降低方差):
-
- 随机森林:多个决策树并行训练,每个树用随机抽样的样本和特征,最后投票 / 平均结果激活函数
激活函数
激活函数让模型从"只会死算公式",变成"会灵活判断、学复杂规律"的学习者,看两个例子就知道了:
没有激活函数:模型是 “只会算直线的死脑筋”
假设模型是个学生,任务是 “根据‘学习时长’预测‘考试分数’”:
- 没有激活函数,学生只会一种算法:分数 = 0.8× 学习时长 + 50(典型线性关系,像画一条直线)。
- 结果就是:不管学习时长是 1 小时、10 小时、20 小时,分数都只按 “每多学 1 小时,加 8 分” 的固定规律涨—哪怕有人学 15 小时后疲劳了(分数不涨反降),有人学 3 小时就掌握核心(分数突增),这个学生也看不见,只会硬套公式算直线。
再比如更复杂的任务:“根据‘年龄、收入、浏览记录’判断‘用户是否买奢侈品’”。没有激活函数的模型,依然只能用 “线性公式” 判断(比如:购买概率 = 0.1× 年龄 + 0.3× 收入 + 0.2× 浏览次数 - 5),但现实中 “买奢侈品” 的规律是非线性的:
- 年轻人(25-35 岁)收入中等也可能买(追求品质);
- 老年人(60 + 岁)收入高也可能不买(消费保守);
- 光靠 “直线公式” 根本算不准这种复杂判断 —— 这就是没有激活函数的致命问题:只能处理简单的 “一刀切” 关系,搞不定现实中 “拐弯抹角” 的复杂规律。
有激活函数:模型是 “会灵活判断的聪明人”
激活函数就像给学生加了"判断能力"不再硬套直线公式,而是能根据情况 “灵活调整”,学会复杂规律。
例子 :用 ReLU 激活函数(最常用),解决 “学习时长与分数” 的非线性关系
ReLU 的逻辑很简单:“有用的信息就保留并放大,没用的就丢掉”(比如输入是正数就保留,负数就变成 0)。
- 给模型加了 ReLU 后,它能学到这样的规律:
-
- 学习时长<1 小时:输入是 “1”(正数),但模型判断 “这点时间没用”(通过 ReLU 转换后,贡献几乎为 0),分数还是 50 分左右;
- 1 小时<学习时长<10 小时:输入是正数,ReLU 保留并放大,分数快速上涨(比如每多学 1 小时,分数加 15 分);
- 学习时长>10 小时:输入是正数,但模型判断 “疲劳了”(通过后续层的 ReLU 组合),分数增长变慢甚至稳定(比如每多学 1 小时,分数只加 2 分)。
- 最终模型学到的不是 “直线”,而是 “先平、再陡涨、最后平缓” 的曲线 —— 完美贴合现实中 “学习效果” 的非线性规律。
没有激活函数,模型只能 “画直线、算死公式”,搞不定现实中的复杂规律;有了激活函数,模型就有了 “灵活判断、概率转换” 的能力,能学会 “学习疲劳曲线”“消费偏好”“图像分类” 这些非线性的真实规律 —— 就像学生从 “只会背公式” 变成 “会分析题目、灵活解题” 的学霸。
1.2、机器学习标准流程
一个典型的机器学习项目遵循以下步骤(以监督学习为例):
- 构建数据集
-
- 导入数据:从文件(CSV、JSON)、数据库或API中加载原始数据。
- 数据预处理:清洗缺失值、异常值,处理类别变量(如独热编码)。
- 划分数据集:
-
-
- 训练集(Training Set):用于训练模型(通常 60%-80%)。
- 验证集(Validation Set):用于调参和选择模型(可选,10%-20%)。
- 测试集(Test Set):用于最终评估模型性能(10%-20%),仅使用一次。
-
- 构建模型
-
- 选择算法:根据任务类型选择合适的模型,例如:
-
-
- 分类任务:KNN、逻辑回归、决策树、SVM
- 回归任务:线性回归、随机森林
-
-
- 特征工程(Feature Engineering):
-
-
- 提取或构造对任务有用的特征(如从日期中提取星期几)。
- 特征缩放:如标准化(Standardization),将特征转换为均值为0、方差为1的正态分布,避免某些特征因数值过大主导模型训练(对KNN、SVM等尤其重要)。
-
-
- 模型实例化:在代码中创建模型对象,如KNN小模型
model = KNeighborsClassifier()。
- 模型实例化:在代码中创建模型对象,如KNN小模型
- 模型训练(
.fit)使用训练集数据"训练"模型,即调整模型内部参数,使其尽可能拟合输入与输出关系。 - 模型预测(
.predict)将训练好的模型应用于新数据(如验证集或测试集),生成预测结果。 - 模型评估(
.score或专用指标)
- 使用评估指标判断模型性能:
-
- 分类任务:准确率(Accuracy)、精确率、召回率、F1分数
- 回归任务:均方误差(MSE)、R²分数
根据评估结果决定是否返回第2步调整模型(如换算法、调参数)。
🔄 这是一个迭代过程:不断尝试不同特征、模型和参数,直到性能满意。
1.3、应用场景
|
领域 |
应用示例 |
|
图像识别 |
人脸识别、医学影像分析、自动驾驶中的物体检测 |
|
自然语言处理 |
垃圾邮件过滤、机器翻译、情感分析、智能客服 |
|
推荐系统 |
电商商品推荐(如淘宝)、视频推荐(如抖音、Netflix) |
|
金融风控 |
信用评分、欺诈检测、股票趋势预测 |
|
医疗健康 |
疾病预测、药物研发、个性化治疗 |
|
工业制造 |
设备故障预测、质量检测、智能调度 |
1.4、主流算法模型
机器学习发展多年,涌现出大量经典算法。以下是几种主流模型的简要介绍,按复杂度递增排列:
|
模型 |
类型 |
特点 |
典型应用 |
|
线性回归 / 逻辑回归 |
监督学习 |
简单、可解释性强 |
房价预测、广告点击率 |
|
决策树 / 随机森林 |
监督学习 |
易于理解,抗过拟合 |
信用评分、客户分类 |
|
支持向量机(SVM) |
监督学习 |
在高维空间表现好 |
文本分类、图像识别 |
|
K均值聚类(K-Means) |
无监督学习 |
发现数据分组 |
用户画像、市场细分 |
|
主成分分析(PCA) |
无监督学习 |
降维、去噪 |
数据可视化、特征压缩 |
|
神经网络(Neural Networks) |
深度学习基础 |
拟合复杂非线性关系 |
图像、语音、文本处理 |
2、KNN案例-鸢尾花分类
在上一章中,我们学习了机器学习的基本流程。接下来,我们将通过一个经典且简单的实战案例——使用 K近邻算法(KNN)对鸢(yuan)尾花进行分类,来体验和了解机器学习的开发流程。

三类鸢尾花的特征标准
Setosa(山鸢尾)
学名:Iris setosa
特征:花瓣较小,花萼相对较大
典型特征值范围:
花萼长度:4.3-5.8 cm
花萼宽度:2.3-4.4 cm
花瓣长度:1.0-1.9 cm
花瓣宽度:0.1-0.6 cm
Versicolor(变色鸢尾)
学名:Iris versicolor
特征:中等大小,介于山鸢尾和维吉尼亚鸢尾之间
典型特征值范围:
花萼长度:4.9-7.0 cm
花萼宽度:2.0-3.4 cm
花瓣长度:3.0-5.1 cm
花瓣宽度:1.0-1.8 cm
Virginica(维吉尼亚鸢尾)
学名:Iris virginica
特征:花瓣最大,整体尺寸最大
典型特征值范围:
花萼长度:4.9-7.9 cm
花萼宽度:2.2-3.8 cm
花瓣长度:4.5-6.9 cm
花瓣宽度:1.4-2.5 cm
如果我们人类编码来判断一朵鸢尾花是属于哪个类型的话;就需要写很多if条件判断。
而如果机器学习的话就可以通过给出很多鸢尾花的样本数据,让机器自己学习这些样本信息;自己学会了上面三类鸢尾花的判断特征,再给它一朵鸢尾花就能自己判断出来是属于哪个类型的了。
2.1、开发环境准备
在运行KNN算法对鸢尾花进行分类的时候,需要利用到 scikit-learn、pandas、matplotlib等包,所以需要先下载安装。方式有如下:
2.1.1、创建虚拟环境
打开 Anaconda Prompt 创建conda虚拟环境:
# 创建名字为JAVA_AI的虚拟环境,这里会下载很多东西,约耗时3min
conda create -n JAVA_AI python=3.10



# 查看Anaconda的虚拟环境
conda env list
# 激活 JAVA_AI 虚拟环境
conda activate JAVA_AI

这时候;打开 Anaconda Navigator 也可以看到新创建好的环境:

2.1.2、安装包
案例需要使用到的 scikit-learn、pandas、matplotlib等包其实Anaconda环境在创建的时候不指定python的话会默认安装;但是如果它的版本不是非常符合我们的期望的话可以指定版本安装对应的包。当然如果在虚拟环境中没有或者需要安装其它版本都可以按照下面方式安装:
方式一:逐个包安装
# pip install scikit-learn -i https://pypi.tuna.tsinghua.edu.cn/simple
# pip install scikit-learn==1.4.0 -i https://pypi.tuna.tsinghua.edu.cn/simple
# 如果通过设置过pip下载的镜像源的话,可以不指定 -i
# pip install scikit-learn==1.4.0 # 如果要指定版本的话,就这样写
pip install scikit-learn
# 安装pandas
pip install pandas
# 安装 matplotlib
pip install matplotlib



方式二:集成安装,在需要安装比较多包,或者项目中的时候建议使用:
先编写一个文件 requirements.txt 里面包含如下内容:
scikit-learn
pandas
matplotlib
到上面文件所在的路径打开 Anaconda Prompt 执行如下安装命令:
# pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install -r requirements.txt
或者直接在pycharm下打开终端;但是打开pycharm的终端出现如下问题的话:

说明PyCharm的conda路径没有配置好。检查如下:


能够打开PyCharm的终端之后,执行: pip install -r requirements.txt

2.2、项目构建流程
- 构建数据集
-
- 导入数据
- 划分数据集(训练、验证、测试的数据比例)
- 构建模型
- 模型训练
- 模型预测
- 模型评估
数据 → 模型 → 训练 → 预测 → 评估,这个流程适用于所有 AI 项目构建。
我们训练构建的模型或者主流模型;它都有 “训练 → 保存 → 加载 → 使用” 流程(通用范式);这个流程是所有机器学习模型(无论大小)的通用生命周期:
[训练数据]
↓
【模型训练】 → 得到一个“学会规律”的模型
↓
【模型保存】 → 保存为文件(如 .pkl, .pt, .bin)
↓
【模型部署】 → 在服务器、APP、网页中加载使用
↓
【模型推理】 → 对新数据做预测(如判断一朵新花的种类)
2.3、项目演示
先编写python文件为:ml-iris-demo.py 的文件;复制内容如下:
# ==================== 1. 构建数据集 ====================
# 导入机器学习数据集模块
from sklearn import datasets
# 导入数据集划分工具
from sklearn.model_selection import train_test_split
# 1.1 导入数据:加载鸢尾花数据集
print("【1. 构建数据集】")
# 加载sklearn内置的鸢尾花数据集
iris = datasets.load_iris()
# 提取特征数据(150个样本,每个样本有4个特征:花萼长/宽,花瓣长/宽)
X = iris.data
# 提取标签数据(150个样本的类别标签,0=山鸢尾, 1=变色鸢尾, 2=维吉尼亚鸢尾)
y = iris.target
# 打印特征和标签数据的形状信息
print(f"数据形状: 特征 {X.shape}, 标签 {y.shape}") # 输出 数据形状: 特征 (150, 4), 标签 (150,)
# 打印类别名称数组(['setosa' 'versicolor' 'virginica'])
print(f"类别名称: {iris.target_names}")
# 1.2 划分数据集:训练集 + 测试集 (80% 训练, 20% 测试)
# 将数据集划分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(
X, y, # 输入特征和标签数据
test_size=0.2, # 测试集占总数据的20%
random_state=42, # 设置随机种子,值可以随意,每次保持一致即可,确保每次运行结果一致
stratify=y # 分层抽样,保持训练集和测试集中各类别比例一致
)
# 打印训练集样本数量
print(f"训练集大小: {X_train.shape[0]}") # 输出 训练集大小: 120
# 打印测试集样本数量
print(f"测试集大小: {X_test.shape[0]}") # 输出 测试集大小: 30
# ==================== 2. 构建模型 ====================
# 导入K近邻分类器
from sklearn.neighbors import KNeighborsClassifier
# 导入数据标准化工具
from sklearn.preprocessing import StandardScaler
print("\n【2. 构建模型】")
# 2.1 特征工程 + 标准化(KNN基于距离计算,必须进行标准化)
# 创建标准化器实例,将特征缩放为均值为0,方差为1的标准正态分布
scaler = StandardScaler()
# 在训练集上拟合并转换数据
X_train_scaled = scaler.fit_transform(X_train)
# 在测试集上仅进行转换(使用训练集的参数)
X_test_scaled = scaler.transform(X_test)
print("已完成特征标准化。")
# 2.2 选择模型:KNN分类器,设置K值为3
model = KNeighborsClassifier(n_neighbors=3)
print("已构建 KNN 模型 (K=3)。")
# ==================== 3. 模型训练 ====================
print("\n【3. 模型训练】")
# 使用训练数据训练KNN模型
model.fit(X_train_scaled, y_train)
print("✅ 模型训练完成!")
# ==================== 4. 模型预测 ====================
print("\n【4. 模型预测】")
# 使用训练好的模型对测试集进行预测
y_pred = model.predict(X_test_scaled)
# 打印预测结果数组
print(f"预测结果: {y_pred}")
# 打印测试集真实标签
print(f"真实标签: {y_test}")
print(f"样本预测对照: ")
# 遍历预测结果和真实标签,逐个对比
for i, (pred_label, true_label) in enumerate(zip(y_pred, y_test)):
# 获取预测类别的名称
pred_name = iris.target_names[pred_label]
# 获取真实类别的名称
true_name = iris.target_names[true_label]
# 打印每个样本的预测结果和真实结果,并用✅或❌标识正确与否
print(f" 样本{i+1}: 预测='{pred_name}' | 真实='{true_name}' {'✅' if pred_label == true_label else '❌'}")
# ==================== 5. 模型评估 ====================
# 输出模型评估开始信息
print("\n【5. 模型评估】")
# 计算模型在测试集上的准确率(正确预测的样本数/总样本数)
accuracy = model.score(X_test_scaled, y_test)
# 打印模型准确率(转换为百分比并保留两位小数)
print(f"模型在测试集上的准确率: {accuracy * 100:.2f}%")
# 可选:导入详细分类报告工具
from sklearn.metrics import classification_report
# 输出详细评估报告标题
print("\n详细评估报告:")
# 打印详细的分类评估报告,包括精确率、召回率、F1分数等指标
print(classification_report(y_test, y_pred, target_names=iris.target_names))
运行上述代码,我们可以分析查看:
【1. 构建数据集】
数据形状: 特征 (150, 4), 标签 (150,)
类别名称: ['setosa' 'versicolor' 'virginica']
训练集大小: 120
测试集大小: 30
【2. 构建模型】
已完成特征标准化。
已构建 KNN 模型 (K=3)。
【3. 模型训练】
✅ 模型训练完成!
【4. 模型预测】
预测结果: [0 2 1 1 0 1 0 0 2 1 2 2 2 1 0 0 0 1 1 1 0 2 1 1 2 1 1 0 2 0]
真实标签: [0 2 1 1 0 1 0 0 2 1 2 2 2 1 0 0 0 1 1 2 0 2 1 2 2 1 1 0 2 0]
样本预测对照:
样本1: 预测='setosa' | 真实='setosa' ✅
样本2: 预测='virginica' | 真实='virginica' ✅
样本3: 预测='versicolor' | 真实='versicolor' ✅
样本4: 预测='versicolor' | 真实='versicolor' ✅
样本5: 预测='setosa' | 真实='setosa' ✅
样本6: 预测='versicolor' | 真实='versicolor' ✅
样本7: 预测='setosa' | 真实='setosa' ✅
样本8: 预测='setosa' | 真实='setosa' ✅
样本9: 预测='virginica' | 真实='virginica' ✅
样本10: 预测='versicolor' | 真实='versicolor' ✅
样本11: 预测='virginica' | 真实='virginica' ✅
样本12: 预测='virginica' | 真实='virginica' ✅
样本13: 预测='virginica' | 真实='virginica' ✅
样本14: 预测='versicolor' | 真实='versicolor' ✅
样本15: 预测='setosa' | 真实='setosa' ✅
样本16: 预测='setosa' | 真实='setosa' ✅
样本17: 预测='setosa' | 真实='setosa' ✅
样本18: 预测='versicolor' | 真实='versicolor' ✅
样本19: 预测='versicolor' | 真实='versicolor' ✅
样本20: 预测='versicolor' | 真实='virginica' ❌
样本21: 预测='setosa' | 真实='setosa' ✅
样本22: 预测='virginica' | 真实='virginica' ✅
样本23: 预测='versicolor' | 真实='versicolor' ✅
样本24: 预测='versicolor' | 真实='virginica' ❌
样本25: 预测='virginica' | 真实='virginica' ✅
样本26: 预测='versicolor' | 真实='versicolor' ✅
样本27: 预测='versicolor' | 真实='versicolor' ✅
样本28: 预测='setosa' | 真实='setosa' ✅
样本29: 预测='virginica' | 真实='virginica' ✅
样本30: 预测='setosa' | 真实='setosa' ✅
【5. 模型评估】
模型在测试集上的准确率: 93.33%
详细评估报告:
precision recall f1-score support
setosa 1.00 1.00 1.00 10
versicolor 0.83 1.00 0.91 10
virginica 1.00 0.80 0.89 10
accuracy 0.93 30
macro avg 0.94 0.93 0.93 30
weighted avg 0.94 0.93 0.93 30
2.4、KNN算法原理
什么是KNN
KNN(K-Nearest Neighbors,K近邻算法) 是一种简单直观的监督学习算法,既可以用于分类,也可以用于回归。它的核心思想来自一句俗语:💬 “物以类聚,人以群分”。也就是说:一个样本的类别(或数值),由它周围最相似的 K 个“邻居”决定。
KNN原理(算法思想): 如果一个样本在特征空间中的 k 个最相似的样本中的大多数属于某一个类别,则该样本也属于这个类别

最相似可以通过欧氏距离:


|
分类的流程: 1)算出样本到每个训练样本的欧式距离 2)然后对距离升序排序 3)取出距离最近的K个训练样本 4)对这些样本进行 多数表决, 也就是看看哪个类型最多 5)将未知的样本归属到 出现次数最多的类别 |
回归流程: 1)计算未知样本到每一个训练样本的距离 2)将训练样本根据距离大小升序排列 3)取出距离最近的 K 个训练样本 4)把这个 K 个样本的目标值计算其平均值 5)将上述平均值作为将未知的样本预测的值 |
当K=5时;图中 打勾 的五部电影中,喜剧片 类型最多,所以 唐人街探案 被归类到喜剧片。
2.5、数据集导入分析
先在 JAVA_AI 的虚拟环境中安装可视化包
# Python 数据可视化库,主要用于创建统计图形
pip install seaborn

然后通过将鸢尾花的样本数据通过散点图了解的它的不同分类的特征情况:
# 绘制鸢尾花样本数据的散点图
# 导入pandas库,用于数据处理和分析
import pandas as pd
# 导入seaborn库,用于统计数据可视化
import seaborn as sns
# 从sklearn库中导入datasets模块,用于加载机器学习数据集
from sklearn import datasets
# 导入matplotlib.pyplot模块,用于创建图表
import matplotlib.pyplot as plt
# 加载sklearn内置的鸢尾花数据集
iris = datasets.load_iris()
# 打印鸢尾花数据集的特征名称 输出 ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
print(f"鸢尾花数据集的特征:{iris.feature_names}")
# 将鸢尾花数据转换为pandas DataFrame格式,列名为特征名称
iris_d = pd.DataFrame(iris.data, columns=iris.feature_names)
# 打印DataFrame当前数据,查看数据结构
print('\niris_d-->\n', iris_d)
# 在DataFrame中添加标签列,存储鸢尾花的类别(0, 1, 2)
iris_d['label'] = iris.target
# 将数字标签映射为实际的花名:0->setosa, 1->versicolor, 2->virginica
iris_d['species'] = iris_d['label'].map({0: 'setosa', 1: 'versicolor', 2: 'virginica'})
# 打印DataFrame的数据,查看数据结构
print('\niris_d-->\n', iris_d.head())
# 定义x轴特征为花萼长度
col1 = 'sepal length (cm)'
# 定义y轴特征为花瓣宽度
col2 = 'petal width (cm)'
# 使用seaborn绘制散点图,按物种分类显示不同颜色,不绘制回归线
sns.lmplot(x=col1, y=col2, data=iris_d, hue='species', fit_reg=False)
# 设置x轴标签
plt.xlabel(col1)
# 设置y轴标签
plt.ylabel(col2)
# 设置图表标题
plt.title('iris')
# 显示图表
plt.show()
执行后输出的散点图如下:

注意:上述的散点图是根据鸢尾花的花萼长度、花瓣宽度生成的;它可以由花萼、花瓣的任意两个维度生成;所以不只是上面的这种组合。
2.6、模型应用
当如果模型训练好之后;有新的鸢尾花需要判断它是属于哪个分类的话:
# ==================== 1. 构建数据集 ====================
# 导入机器学习数据集模块
from sklearn import datasets
# 导入数据集划分工具
from sklearn.model_selection import train_test_split
# 1.1 导入数据:加载鸢尾花数据集
print("【1. 构建数据集】")
# 加载sklearn内置的鸢尾花数据集
iris = datasets.load_iris()
# 提取特征数据(150个样本,每个样本有4个特征:花萼长/宽,花瓣长/宽)
X = iris.data
# 提取标签数据(150个样本的类别标签,0=山鸢尾, 1=变色鸢尾, 2=维吉尼亚鸢尾)
y = iris.target
# 打印特征和标签数据的形状信息
print(f"数据形状: 特征 {X.shape}, 标签 {y.shape}") # 输出 数据形状: 特征 (150, 4), 标签 (150,)
# 打印类别名称数组(['setosa' 'versicolor' 'virginica'])
print(f"类别名称: {iris.target_names}")
# 1.2 划分数据集:训练集 + 测试集 (80% 训练, 20% 测试)
# 将数据集划分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(
X, y, # 输入特征和标签数据
test_size=0.2, # 测试集占总数据的20%
random_state=42, # 设置随机种子,值可以随意,每次保持一致即可,确保每次运行结果一致
stratify=y # 分层抽样,保持训练集和测试集中各类别比例一致
)
# 打印训练集样本数量
print(f"训练集大小: {X_train.shape[0]}") # 输出 训练集大小: 120
# 打印测试集样本数量
print(f"测试集大小: {X_test.shape[0]}") # 输出 测试集大小: 30
# ==================== 2. 构建模型 ====================
# 导入K近邻分类器
from sklearn.neighbors import KNeighborsClassifier
# 导入数据标准化工具
from sklearn.preprocessing import StandardScaler
print("\n【2. 构建模型】")
# 2.1 特征工程 + 标准化(KNN基于距离计算,必须进行标准化)
# 创建标准化器实例,将特征缩放为均值为0,方差为1的标准正态分布
scaler = StandardScaler()
# 在训练集上拟合并转换数据
X_train_scaled = scaler.fit_transform(X_train)
# 在测试集上仅进行转换(使用训练集的参数)
X_test_scaled = scaler.transform(X_test)
print("已完成特征标准化。")
# 2.2 选择模型:KNN分类器,设置K值为3
model = KNeighborsClassifier(n_neighbors=3)
print("已构建 KNN 模型 (K=3)。")
# ==================== 3. 模型训练 ====================
print("\n【3. 模型训练】")
# 使用训练数据训练KNN模型
model.fit(X_train_scaled, y_train)
print("✅ 模型训练完成!")
# ==================== 4. 模型预测 ====================
print("\n【4. 模型预测】")
# 使用训练好的模型对测试集进行预测
y_pred = model.predict(X_test_scaled)
# 打印预测结果数组
print(f"预测结果: {y_pred}")
# 打印测试集真实标签
print(f"真实标签: {y_test}")
print(f"样本预测对照: ")
# 遍历预测结果和真实标签,逐个对比
for i, (pred_label, true_label) in enumerate(zip(y_pred, y_test)):
# 获取预测类别的名称
pred_name = iris.target_names[pred_label]
# 获取真实类别的名称
true_name = iris.target_names[true_label]
# 打印每个样本的预测结果和真实结果,并用✅或❌标识正确与否
print(f" 样本{i+1}: 预测='{pred_name}' | 真实='{true_name}' {'✅' if pred_label == true_label else '❌'}")
# ==================== 5. 模型评估 ====================
# 输出模型评估开始信息
print("\n【5. 模型评估】")
# 计算模型在测试集上的准确率(正确预测的样本数/总样本数)
accuracy = model.score(X_test_scaled, y_test)
# 打印模型准确率(转换为百分比并保留两位小数)
print(f"模型在测试集上的准确率: {accuracy * 100:.2f}%")
# 可选:导入详细分类报告工具
from sklearn.metrics import classification_report
# 输出详细评估报告标题
print("\n详细评估报告:")
# 打印详细的分类评估报告,包括精确率、召回率、F1分数等指标
print(classification_report(y_test, y_pred, target_names=iris.target_names))
# ==================== 6. 新样本数据;对训练的模型预测 ====================
import numpy as np
# 对新的样本进行预测
new_samples = np.array([
[5.1, 3.5, 1.4, 0.2], # 新的鸢尾花测量数据
[6.2, 3.4, 5.4, 2.3],
[5.5, 2.3, 4.0, 1.3]
])
# 重要:对新数据进行与训练时相同的标准化处理
new_samples_scaled = scaler.transform(new_samples)
# 使用训练好的模型进行预测
predictions = model.predict(new_samples_scaled)
# 输出预测结果
iris = datasets.load_iris()
for i, pred in enumerate(predictions):
print(f"新样本{i+1}预测类别: {iris.target_names[pred]}")
执行上述代码,打印输出
新样本1预测类别: setosa
新样本2预测类别: virginica
新样本3预测类别: versicolor
标准化(Standardization),也叫 Z-score标准化,是一种常见的特征缩放(Feature Scaling)方法,用于将不同特征的数据转换到相同的尺度。
2.7、总结:KNN与大模型对比
我们从鸢尾花出发,用 KNN 算法完成了机器学习的完整流程:数据 → 模型 → 训练 → 预测 → 评估。
现在,让我们把视野放大,看看这个“简单”的 KNN 模型,与当前火热的 大模型(如 GPT、BERT、LLaMA) 之间,究竟有什么联系与区别。
|
维度 |
KNN(小模型) |
大模型(如 GPT) |
|
学习方式 |
从训练数据中学习“谁和谁像” |
从海量文本中学习“词与词之间的关系” |
|
目标 |
对新样本做出分类或回归 |
对新输入生成回答、翻译、写作等 |
|
核心思想 |
“物以类聚,人以群分” |
“上下文决定语义” |
|
依赖 |
训练数据的代表性 |
预训练数据的广度与质量 |
小模型:我们不用写 if 判断鸢尾花,而是让机器从数据中学。
中模型:神经网络能自动学习更复杂的特征,比如图像边缘、纹理。
大模型:Transformer 用海量文本训练,学会了语言的规律,所以能写文章、答问题。
共同本质:它们都不是靠人写规则运行的,而是通过“观察大量数据”自动总结出规律,并用于处理新任务。
我们现在了解到的KNN与大模型演进关系:
KNN → 线性模型 → 神经网络 → 深度学习 → Transformer → 大模型
- KNN:模型可以从数据中学习
- 神经网络 :可以用多层结构学习复杂特征
- Transformer :可以用注意力机制理解上下文
- 大模型 :当数据和参数足够大时,模型能涌现出“智能”行为
它们工程流程完全一致
|
步骤 |
KNN 示例 |
大模型 示例 |
|
1. 构建数据集 |
鸢尾花数据(150条) |
互联网文本(TB级) |
|
2. 构建模型 |
KNeighborsClassifier() |
AutoModelForCausalLM.from_pretrained("gpt2") |
|
3. 模型训练 |
.fit(X_train, y_train) |
在大规模语料上预训练 |
|
4. 模型预测 |
.predict(new_flower) |
.generate("请写一首诗") |
|
5. 模型评估 |
.score(X_test, y_test) |
困惑度(PPL)、人工评测 |
|
6. 模型保存加载 |
joblib.dump(model, 'knn.pkl') |
model.save_pretrained('./my_model') |
3、面试题
- AI模型平台有哪些,怎么使用
- 什么是机器学习
- 机器学习的应用场景
- 机器学习的标准流程(5步)
- 精确率
在所有被模型预测为“正类”的样本中,有多少是真的正类
- 召回率
在所有真实的正类样本中,有多少被模型成功找出来了
- F1分数
精确率和召回率的调和平均数;只有当两个数都较高时,结果才高。如果其中一个很低,F1 就会显著降低。既要准确,也要全面。公式(F1 = 2 * (Precision * Recall) / (Precision + Recall))
- 讲讲KNN的原理
- AI项目的一般流程
附件
更多推荐








所有评论(0)