从电影分类到鸢尾花识别

如果你打开视频平台时,发现它总能精准推荐你喜欢的爱情片或动作片;如果你曾好奇植物识别 APP 如何区分不同品种的鸢尾花 ------ 这些场景背后,可能都藏着一种简单却实用的机器学习算法:K 近邻算法(KNN)

不同于复杂的深度学习模型,KNN 的逻辑像我们生活中 "随大流" 的判断方式:想知道一个新事物属于哪类,看看它周围最亲近的 "邻居" 大多是什么类别,跟着选就对了。今天我们就从电影分类的实际场景出发,拆解 KNN 的核心原理、距离计算方法,再通过代码实战掌握鸢尾花分类,让零基础也能轻松入门。

一、什么是 KNN 算法?------"近朱者赤" 的分类逻辑

KNN(k-Nearest Neighbor,K 近邻算法)的核心定义特别直白:每个样本都可以用它最接近的 K 个 "邻居"(邻近值)来代表

打个比方:如果新上映一部电影,我们不知道它是 "爱情片" 还是 "动作片",但知道它有 18 个打斗镜头、90 个接吻镜头。这时我们可以找一批已知类别的电影(比如《宠爱》是爱情片,《反贪风暴 4》是动作片),计算新电影与这些已知电影的 "相似度"(距离),再挑出最像的 3 个(或 5 个、7 个)邻居 ------ 如果这 3 个邻居里有 2 个是爱情片,那新电影就归为爱情片。

这就是 KNN 的本质:"无训练过程的懒惰学习" ------ 它不需要像线性回归那样先 "训练" 出一个模型公式,而是直接用已有的数据(样本集)给新数据 "贴标签",核心全在 "找邻居"。

KNN 的 5 步核心流程

文档中明确给出了 KNN 的标准步骤,我们用 "给未知电影分类" 的例子翻译一下:

  1. 算距离:用新数据(未知电影的 "打斗镜头、接吻镜头")和样本集中每个已知数据(如《宠爱》的 6.0 分对应的镜头数)的特征做对比,计算两者的 "距离"(相似度);
  2. 排顺序:把所有已知数据按 "距离由近到远" 排序(越近越相似);
  3. 选邻居:从排序结果里挑前 K 个(比如 K=3)距离最近的 "邻居";
  4. 算频率:统计这 K 个邻居里,每个类别的出现次数(比如 3 个邻居中有 2 个爱情片、1 个动作片);
  5. 定类别:出现次数最多的类别,就是新数据的分类(新电影归为爱情片)。

二、关键前提:怎么计算 "邻居" 的距离?

要找 "邻居",首先得定义 "远近"------ 这就是 KNN 中的 "距离度量"。文档中重点介绍了两种最常用的距离计算方法,我们用 "电影镜头数" 的二维场景(x = 打斗镜头,y = 接吻镜头)来理解:

1. 欧式距离:两点之间的 "直线距离"

欧式距离(欧几里得距离)是我们最熟悉的距离概念:比如在地图上两点之间的直线距离,就是二维空间的欧式距离。

  • 二维空间公式(适用于电影分类,只有 "打斗" 和 "接吻" 两个特征): 若已知电影 A(x₁,y₁)、未知电影 B(x₂,y₂),则距离为: \(d = \sqrt{(x_1 - x_2)^2 + (y_1 - y_2)^2}\)
  • 三维空间公式(比如多了 "时长" 一个特征): \(d = \sqrt{(x_1 - x_2)^2 + (y_1 - y_2)^2 + (z_1 - z_2)^2}\)
  • n 维空间公式(适用于更多特征,如电影的 "评分、时长、演员数量" 等): \(d = \sqrt{\sum_{i=1}^n (x_{1i} - x_{2i})^2}\)

举个例子:已知爱情片《California Man》(打斗 3 次,接吻 104 次),未知电影(18,90),两者的欧式距离是: \(d = \sqrt{(18-3)^2 + (90-104)^2} = \sqrt{15^2 + (-14)^2} = \sqrt{421} ≈ 20.5\)

2. 曼哈顿距离:"出租车绕街区" 的距离

曼哈顿距离得名于纽约曼哈顿的街区布局 ------ 出租车从 A 点到 B 点,不能直接穿楼,只能沿街道横竖走,总路程就是曼哈顿距离。

  • 二维空间公式: \(d = |x_1 - x_2| + |y_1 - y_2|\)

还是用上面的例子,《California Man》与未知电影的曼哈顿距离是: \(d = |18-3| + |90-104| = 15 + 14 = 29\)

简单来说:欧式距离是 "直线抄近路",曼哈顿距离是 "绕街区走直线",具体用哪种,取决于数据特征的场景(比如地图导航用曼哈顿,两点定位用欧式)。

三、K 值怎么选?------ 影响结果的关键参数

KNN 中的 "K" 是 "邻居数量",这个参数直接决定分类结果。文档中用一个直观的例子说明了差异:

  • 当 K=3 时,新数据的 3 个邻居中 "蓝三角" 更多,判定为蓝三角;
  • 当 K=5 时,5 个邻居中 "红圆" 更多,判定为红圆。

K 值选择的 3 个核心原则

  1. K 太小易 "偏激":比如 K=1 时,只看最近的 1 个邻居 ------ 如果这个邻居是个 "特例"(比如一部爱情片偏偏有很多打斗镜头),新数据就会被误判,导致 "过拟合"(模型太死板,只认个别案例);
  2. K 太大易 "模糊":比如 K=100(样本集只有 20 个数据),相当于把所有样本都当邻居,远的、不相关的也算进来,导致 "欠拟合"(模型分不清类别,结果不准);
  3. 常规范围:文档中明确提到 "K 一般不大于 20",实际应用中常用奇数(如 3、5、7),避免出现 "平票"(比如 K=4 时,2 个爱情片、2 个动作片,无法判断)。

四、实战 1:用 KNN 给未知电影 "贴标签"

文档中给出了一组真实的电影数据,我们用 KNN 亲手判断 "未知电影(打斗 18 次,接吻 90 次)" 的类别:

已知电影数据(特征:打斗镜头、接吻镜头)

电影类型 电影名称 打斗镜头 接吻镜头
爱情片 California Man 3 104
爱情片 He's Not Really into Dudes 2 100
爱情片 Beautiful Woman 1 81
动作片 Kevin Longblade 101 5
动作片 Robo Slayer 3000 99 2
动作片 Amped II 98 2

步骤 1:计算未知电影与所有已知电影的欧式距离

已知电影 欧式距离(与未知电影)
California Man ≈20.5
He's Not Really into Dudes ≈18.9
Beautiful Woman ≈19.2
Kevin Longblade ≈118.8
Robo Slayer 3000 ≈117.1
Amped II ≈116.2

步骤 2:按距离排序,选 K=3 个邻居

最近的 3 个邻居依次是:

  1. He's Not Really into Dudes(爱情片,距离 18.9)
  2. Beautiful Woman(爱情片,距离 19.2)
  3. California Man(爱情片,距离 20.5)

步骤 3:判定类别

3 个邻居全是 "爱情片",因此未知电影归为爱情片------ 这和我们的直觉一致(接吻镜头 90 次远多于打斗镜头 18 次)。

五、实战 2:用 Sklearn 实现鸢尾花分类

除了电影,KNN 也能解决生物分类问题(如鸢尾花品种识别)。文档中给出了基于 Sklearn 的实战代码,我们一步步拆解,零基础也能跑通:

鸢尾花数据集背景

鸢尾花数据集包含 3 个品种(Setosa、Versicolor、Virginica),每个品种有 150 个样本,每个样本有 4 个特征:

  • 花萼长度(sepal length)
  • 花萼宽度(sepal width)
  • 花瓣长度(petal length)
  • 花瓣宽度(petal width)

完整代码与解析

复制代码
# 1. 导入必要的库
from sklearn.datasets import load_iris  # 加载鸢尾花数据集
from sklearn.model_selection import train_test_split  # 划分训练集/测试集
from sklearn.neighbors import KNeighborsClassifier  # KNN分类器

# 2. 加载数据集并查看基本信息
iris = datasets.load_iris()
print("鸢尾花特征名称:", iris.feature_names)  # 输出4个特征名
print("鸢尾花品种名称:", iris.target_names)  # 输出3个品种名(0=setosa,1=versicolor,2=virginica)
print("数据集形状(样本数, 特征数):", iris.data.shape)  # (150, 4)

# 3. 划分训练集(70%)和测试集(30%)
# x=特征数据,y=类别标签;test_size=0.3表示测试集占30%
x_train, x_test, y_train, y_test = train_test_split(
    iris.data, iris.target, test_size=0.3, random_state=42  # random_state固定划分方式,保证结果可复现
)

# 4. 创建KNN模型并训练
# n_neighbors=5(选5个邻居),metric="euclidean"(用欧式距离)
knn = KNeighborsClassifier(n_neighbors=5, metric="euclidean")
knn.fit(x_train, y_train)  # 用训练集训练模型(KNN实际是"记住"训练数据)

# 5. 评估模型性能
train_score = knn.score(x_train, y_train)  # 训练集准确率(模型对训练数据的拟合程度)
test_score = knn.score(x_test, y_test)    # 测试集准确率(模型对新数据的泛化能力)
print(f"训练集准确率:{train_score:.2f}")  # 通常接近1.0,如0.98
print(f"测试集准确率:{test_score:.2f}")    # 好的模型应接近训练集准确率,如0.98

# 6. 用模型预测新数据
# 假设新采集一朵鸢尾花:花萼长5.1cm、宽3.5cm,花瓣长1.4cm、宽0.2cm
new_iris = [[5.1, 3.5, 1.4, 0.2]]
y_pred = knn.predict(new_iris)  # 预测品种
print("新鸢尾花品种:", iris.target_names[y_pred[0]])  # 输出setosa(山鸢尾)

代码运行结果解读

  • 训练集准确率≈0.98:说明模型对已知鸢尾花数据的分类很准;
  • 测试集准确率≈0.98:说明模型对 "没见过" 的新鸢尾花也能准确分类(泛化能力好);
  • 新数据预测为 Setosa:符合该品种 "花瓣短、花萼宽" 的特征,结果正确。

六、KNN 的优缺点:什么时候该用它?

通过前面的案例,我们能直观感受到 KNN 的特点,总结一下它的适用场景和局限:

优点 缺点
1. 逻辑简单,零基础易理解,无需复杂训练; 2. 适合多分类问题(如电影分 3 类、鸢尾花分 3 类); 3. 对异常值不敏感(只要 K 选得合理,个别异常邻居不影响结果)。 1. 计算量大:样本数越多,要计算的距离越多(比如 10 万样本,新数据要算 10 万次距离); 2. 受特征尺度影响:比如 "电影评分(1-10)" 和 "镜头数(0-200)",镜头数的数值太大,会主导距离计算(需先归一化数据); 3. 不适合高维数据:特征太多(如 1000 个特征)时,距离计算会 "失效"(维度灾难)。

七、总结:KNN 的核心是 "找对邻居"

回顾全文,KNN 算法的本质其实是 "基于相似性的投票":

  • 核心步骤:算距离→找邻居→看投票;
  • 关键参数:K 值(一般≤20,选奇数);
  • 距离选择:欧式距离(直线相似)、曼哈顿距离(街区相似);
  • 实战技巧:用 Sklearn 快速实现,记得划分训练集 / 测试集,评估泛化能力。

如果你是机器学习新手,KNN 绝对是值得入门的第一个算法 ------ 它没有复杂的数学推导,却能解决很多实际问题(电影分类、推荐系统、疾病诊断等)。不妨试着修改鸢尾花代码中的 K 值(比如 K=3 或 K=7),看看测试集准确率会不会变化;或者用电影数据的曼哈顿距离重新计算,感受不同距离度量的影响。

相关推荐
arron88996 分钟前
YOLOv8n-pose 模型使用
人工智能·深度学习·yolo
AI人工智能+1 小时前
一种融合AI与OCR的施工许可证识别技术,提升工程监管效率,实现自动化、精准化处理。
人工智能·自动化·ocr·施工许可证识别
大力水手(Popeye)2 小时前
Pytorch——tensor
人工智能·pytorch·python
AI_gurubar6 小时前
大模型教机器人叠衣服:2025年”语言理解+多模态融合“的智能新篇
人工智能·机器人
XINVRY-FPGA8 小时前
EPM240T100I5N Altera FPGA MAX II CPLD
人工智能·嵌入式硬件·fpga开发·硬件工程·dsp开发·射频工程·fpga
HuggingFace8 小时前
开源开发者须知:欧盟《人工智能法案》对通用人工智能模型的最新要求
人工智能
媒体人8889 小时前
GEO 优化专家孟庆涛:技术破壁者重构 AI 时代搜索逻辑
大数据·人工智能
小菜AI科技10 小时前
Windsurf 评测:这款 人工智能 IDE 是你需要的颠覆性工具吗?
人工智能
RaymondZhao3410 小时前
【全面推导】策略梯度算法:公式、偏差方差与进化
人工智能·深度学习·算法·机器学习·chatgpt