一、传统编程:把规则写进去
学习之前,我们来看 传统编程 是怎么运行的

这也被称为:硬编码, 程序员把规则写进去,机器按规则执行
但是,如果规则太过复杂,复杂到程序员自己都说不清楚了,怎么办?
比如:你来形容 鸟
- 鸟有两条腿,坤也两条腿
- 鸟嘴巴是尖的,坤也是尖的
- 鸟有两翅膀,坤也是两翅膀
试图一直用规则穷举下去,会发现永远写不完,我们为什么能一眼看出来?只是我们见得多了,靠直觉,而不是靠规则
所以机器学习的核心思路:让机器自己从数据里 总结规则
一张图看清区别

二、监督学习:从数据里总结规律
学习也分多种,其中 监督学习 是最常用的

可能不太理解,画个图辅助一下

然后算法反复去看 数据 和 答案,不断调整自己内部参数,直到对大多数样本都能猜对为止,这个过程叫 迭代
每次猜错就微调一次,这个叫做 最小化误差
到这里看一下基本流程

那么机器是如何知道自己猜错了,并且往哪个方向调整的?
首先
答案是一开始就已经放在数据里面,在训练的时候,机器自动拿自己预测的去对比答案
其次,出现误差的处理步骤:
- 算出当前误差
- 算出误差对每个参数的斜率
- 朝正确答案方向微调参数
- 重复,直到答案正确
这个过程,叫做 梯度下降
为什么每次都是 微调 ?因为调太多,可能直接跳过 答案
那如果这个 微调 调的特别小,模型最后能训练好吗?
理论来说,可以,但是会导致训练时间、算力、电力等等消耗量极大,并且可能永远训练不完

三、SVM:找分类边界
假设你要把两类东西分开

你需要画一条线,把两类东西给分开
问题是,分开的线可以有无数条,如何去选择最好的那一条?
简单来说:你需要找到一条距离两边差不多相同的线
- margin:间距,也叫缓冲带
- 支撑向量:在 缓冲带 边缘的点, 决策边界 的位置,完全由这几个点决定

那如果出现下面这种,混在一起,根本画不出一条直线的怎么办
markdown
* 。 * 。 *
。 * 。 * 。
* 。 * 。 *
四、核函数:把不可分的问题搬到高维
核函数:把数据搬到高维空间的函数
一维困境:

用二维解决:

二维混乱时,就用三维解决
以上面的二维举例,把 * 的 z 轴提高,就好了
五、交互模式与 Anaconda
首先,现在用的是 Python 交互模式,为什么会是 Python ?
之前做 数据分析 主要用的是 Matlab 和 R,转折点在 2000 年

对比之前普通写程序的方式
普通写程序:
scss
写完这个文件(可能100行代码) -> 运行(一次性) -> 看结果(是否正确)
如果出错,也不知道是哪行错了,重新跑
交互模式:
shell
输入一行 -> 立马看到结果 -> 再输入下一行
>>> x = 5
>>> x * 3
15
>>>
三个实用特性:
- 输变量名能直接看值,不需要print()
- 逐行调试,随时检查中间结果
- 上下键调出历史命令
Anaconda:解决版本冲突
Anaconda:简单来说,解决版本冲突的,使环境各自独立,互不干扰
css
Anaconda
环境A(Python 3.8 + sklearn 0.24) ← 项目A用这个
环境B(Python 3.11 + sklearn 1.3) ← 项目B用这个
环境C(Python 3.9 + tensorflow) ← 深度学习用这个
六、数据集从哪来
一直在说数据集,那数据集怎么来的?数据长什么样?
1990年,NIST 收集了大量手写数据用于邮政编码识别,邮局需要机器自动读取信封上的数字,我们用的 digits 数据集就是它的精简版,1797张图,每张 8 x 8 像素
一张 8 x 8 的手写 0,
0 = 白 16 = 黑

画出来之后

数据的结构

用 train_test_split() 自动完成切分 训练集 和 测试集
为什么要切分 训练集 和 测试集 ?
训练集就像练习题,而测试集则是考试,如果你那测试集训练,就像提前把考试卷子做了很多遍,再去考. 这不就学会了,这叫背答案,这个背答案也被叫做 过拟合
那么问题来了, train_test_split()切分的时候,是随机切还是顺序切?
这里有个知识点补充一下,无论是随机切还是顺序切,图都不会重复,不存在训练集里面出现测试集的题目
如果按顺序切,假设数据集是按顺序排列的,最终切出来的
csharp
[1,2,3,4,5,6,7,8,9,10]
那么他只训练前面的 1 - 8 ,后面的 9,10 则不会抽到,测试时,完全没见过 9 ,10,所以测试分数会比较低
按照随机切,最终切出来
csharp
[1,3,5,7,9,2,4,6,8,10]
它就能训练到所有的数据,测试分数才有意义
reshape:把一维数据还原成二维图像
训练之前,我们要先亲自确认,标签的答案和图像长得是否一样
机器存储数据的方式为:
css
digits.data[0] = [0,0,5,13 ...]共64个数
但这是一维的,图片是二维的,一维我们无法去判断,这时就需要 reshape
reshape(8,8)
ini
第一行: [0,0,5 ... ,0]共八个数
...
第八行: [0,0,6 ... ,0]
8 x 8 = 64
imshow():把数字变成颜色
- 0 -> 白
- 8 -> 灰
- 16 -> 黑
用代码展示:
text
//选索引
index = 100
//取出数据
image = digits.data[100]
label = digits.target[100]
//折叠,展示
image_2d = image.reshape(8,8)
plt.imshow(image_2d)
plt.title(f"标签:{label}")
plt.show()
而且不能只看一看,要多看几张图,这也叫做 探索性数据分析(EDA),目的是 提前预判模型会在哪里出错
训练流程
总结一下上面的流程
第一步:导入工具
text
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score
- load_digits 数据集
- train_test_split 切分工具
- SVC SVM分类工具
- accuracy_score 评分工具
第二步:加载数据并切分
ini
digits = load_digits()
X_train, X_test, y_train, y_test = train_test_split(
digits.data, digits.target
)
切分后:
- x_train 1300张图
- y_train 1300 对应标签
- x_test 450张图
- y_test 450对应标签
第三步:创建模型并训练
scss
model = SVC()
model.fit(X_train,y_train)

第四步:预测并评估
scss
y_pred = model.predict(X_test)
print(accuracy_score(y_test, y_pred))
predict():经过 SVM 决策函数,输出的结果
makefile
输入:[0,0,4,5,9...] 一张没见过的图
经过SVM决策函数
输出:"1"
accuracy_score:判断准确率
ini
y_pred = [1,2,3,4,5,...] 模型猜的
y_test = [1,2,3,4,6,...] 正确答案
准确率 = 猜对的数量 / 总数 = 4 / 5 ≈ 0.8
上面的流程简单来说,就如图

这也是监督学习的通用骨架, 换掉 SVC(),填入其他算法,其余步骤也完全不用变
七、交叉验证:看模型稳不稳
核心思路:杜绝偶然事件,采取考多次,取平均
scss
from sklearn.model_selection import cross_val_score
model = SVC()
scores = cross_val_score(model, digits.data, digits.target, cv=3)
print(scores) #[0.96, 0.98, 0.97]
print(scores.mean()) #0.97
- cv 就是测试多少次
- scores 代表多次测试出来各自的准确度
- scores.mean() 代表各自准确度的平均值
如何去判断模型是否有问题,其中一个方法就是看测试数据
ini
情况1:
scores = [0.97,0.98,0.99]
mean = 0.97 波动小,稳定
情况2:
scores = [0.60, 0.98, 0.95]
mean = 0.84 波动大,不稳定
总结
最后,如果只用一句话去理解机器学习,那就是:机器学习不是把规则一条条写死,而是让机器从数据里自己总结规律。
前面讲到的监督学习、梯度下降、SVM、核函数、交互模式、Anaconda、数据集、reshape 和交叉验证,其实都在回答同一个问题:怎么让模型更容易学、学得更稳,也更方便验证结果。
所以这章真正想传达的,不是某一个具体算法,而是机器学习的基本思路:先用数据喂给模型,再用误差去调整模型,最后用测试和交叉验证确认它到底学得怎么样。