传统的算法是小强「写」的规则,神经网络是他「养」的生物:喂它数据,它自己长出连接;答对了奖励、答错了惩罚,一点点调权重——这就是深度学习。这学期从手推梯度开始,一路养出一个能认手写数字的 CNN,最后做出人脸识别签到系统。
手写感知机、推导梯度、搭建第一个神经网络,一路做到 MNIST 手写识别与人脸识别签到系统。
用故事和生活类比打开这学期的大门,先「知其所以然」再学语法。
传统的算法是小强「写」的规则,神经网络是他「养」的生物:喂它数据,它自己长出连接;答对了奖励、答错了惩罚,一点点调权重——这就是深度学习。这学期从手推梯度开始,一路养出一个能认手写数字的 CNN,最后做出人脸识别签到系统。
收进一堆信号,加权求和,超过阈值就「放电」。
加权激活蒙着眼下山,每一步都朝最陡的下坡方向迈。
损失最小化一小块一小块扫描特征,走到哪照到哪,图案在哪都认得。
局部特征数学(通用视觉能力)已经学好,来了直接学「认猫」新课。
预训练复用神经网络与PyTorch入门 —— 共 12 课时,全部知识点一网打尽。
import numpy as np
def neuron(x, w, b):
z = np.dot(x, w) + b # 加权求和 + 偏置
return 1 if z > 0 else 0 # 阶跃激活
x = np.array([2, 1]) # 输入信号
w = np.array([0.5, -1.0]) # 权重
print("输出:", neuron(x, w, b=0.0))输出: 1import numpy as np
w, lr = 5.0, 0.1 # 起点、步长
for step in range(10):
grad = 2 * w # f(w)=w² 的梯度
w = w - lr * grad # 朝下坡走一步
print(f"第{step+1}步: w = {w:.3f}")
print("山谷(最优点)在 w = 0")第1步: w = 4.000
第2步: w = 3.200
第3步: w = 2.560
…
第10步: w = 0.537
山谷(最优点)在 w = 0import torch
x = torch.tensor(3.0, requires_grad=True) # 开启求导
y = x ** 2 + 2 * x # y = x² + 2x
y.backward() # 自动算梯度
print("y 对 x 的梯度:", x.grad) # 2x+2 在 x=3 处y 对 x 的梯度: tensor(8.)import torch.nn as nn
net = nn.Sequential(
nn.Linear(2, 4), nn.ReLU(), # 隐藏层
nn.Linear(4, 1), nn.Sigmoid()) # 输出层
X = torch.tensor([[0.,0.],[0.,1.],[1.,0.],[1.,1.]])
y = torch.tensor([[0.],[1.],[1.],[0.]])
loss_fn = nn.BCELoss()
opt = torch.optim.Adam(net.parameters(), lr=0.01)
for i in range(2000): # 训练 2000 步
opt.zero_grad() # ① 清梯度
pred = net(X) # ② 前向
loss = loss_fn(pred, y) # ③ 算损失
loss.backward() # ④ 反向
opt.step() # ⑤ 更新
print("预测:", net(X).flatten().round())预测: tensor([0., 1., 1., 0.])import torch, torch.nn as nn
class Net(nn.Module):
def __init__(self):
super().__init__()
self.net = nn.Sequential(
nn.Flatten(),
nn.Linear(784, 128), nn.ReLU(),
nn.Linear(128, 10)) # 10 个数字类别
def forward(self, x):
return self.net(x)
model = Net()
opt = torch.optim.Adam(model.parameters(), lr=1e-3)
loss_fn = nn.CrossEntropyLoss()
# for X, y in train_loader: # DataLoader 小批量喂
# opt.zero_grad()
# loss = loss_fn(model(X), y)
# loss.backward(); opt.step()
print("训练后可达 97%+ 准确率")训练后可达 97%+ 准确率import torch.nn as nn
cnn = nn.Sequential(
nn.Conv2d(1, 32, 3, padding=1), # 卷积:提局部特征
nn.ReLU(),
nn.MaxPool2d(2), # 池化:特征减半抗位移
nn.Conv2d(32, 64, 3, padding=1), # 越往后特征越高级
nn.ReLU(),
nn.AdaptiveAvgPool2d(1), # 全局池化
nn.Flatten(),
nn.Linear(64, 10)) # 输出 10 类
# 输入 (批, 1通道, 28, 28) → 输出 (批, 10)(一个识图如识字的特征提取流水线)# 1998 年识别手写数字的网络,CNN 鼻祖
# 卷积(提特征) → 池化(压缩) → 全连接(做判断)
layers = [
"Conv 1×6@28×28 (5×5 卷积核)",
"AvgPool 2×2 (尺寸减半)",
"Conv 6×16@14×14",
"AvgPool 2×2 → 16×5×5",
"Flatten → FC120 → FC84 → FC10",
]
for l in layers:
print(" ", l)
print("精髓:层数加深 + 多卷积核 → 特征从边缘到整体逐级抽象") Conv 1×6@28×28 (5×5 卷积核)
AvgPool 2×2 (尺寸减半)
Conv 6×16@14×14
AvgPool 2×2 → 16×5×5
Flatten → FC120 → FC84 → FC10
精髓:层数加深 + 多卷积核 → 特征从边缘到整体逐级抽象from torchvision import transforms as T
aug = T.Compose([
T.RandomHorizontalFlip(), # 随机水平翻转
T.RandomRotation(15), # 随机旋转 ±15°
T.ColorJitter(0.2, 0.2), # 颜色抖动
T.ToTensor(),
])
# img = aug(img):同一张图,每次喂给模型的都不一样
print("一张图变一百张,模型不再死记硬背")一张图变一百张,模型不再死记硬背import torch
model = torchvision.resnet18(weights="DEFAULT")
for p in model.parameters(): # 冻结全部
p.requires_grad = False
model.fc = nn.Linear(512, 2) # 只换最后一层:猫/狗
# 只训练这最后一层的参数(几万 vs 上千万)(用预训练权重 + 少量数据即可达到高准确率)# 分类:这是猫 → 检测:猫在哪(画框)
# YOLO 一眼看全图,一次前向就输出所有框:
# [置信度, x中心, y中心, 宽, 高, 类别]
pred = [[0.92, 0.30, 0.40, 0.20, 0.35, "cat"],
[0.87, 0.70, 0.55, 0.25, 0.40, "dog"]]
for conf, cx, cy, w, h, cls in pred:
print(f"{cls}: 置信度 {conf:.0%}, 框=({cx:.0%},{cy:.0%}) {w:.0%}×{h:.0%}")
print("调用:from ultralytics import YOLO; YOLO('yolov8n.pt)")cat: 置信度 92%, 框=(30%,40%) 20%×35%
dog: 置信度 87%, 框=(70%,55%) 25%×40%
调用:from ultralytics import YOLO; YOLO('yolov8n.pt)import joblib
# 训练好的模型存盘,下次秒加载
# joblib.dump(model, "model.pkl")
# model = joblib.load("model.pkl")
print("sklearn 模型:joblib 一存一取")
print("PyTorch:torch.save(state_dict) → torch.load()")
print("部署三选一:")
print(" ① Web API(Flask + 一个 /predict 接口)")
print(" ② 手机端(模型转 ONNX / CoreML)")
print(" ③ 打包桌面小工具(Tkinter 界面)")sklearn 模型:joblib 一存一取
PyTorch:torch.save(state_dict) → torch.load()
部署三选一:
① Web API(Flask + 一个 /predict 接口)
② 手机端(模型转 ONNX / CoreML)
③ 打包桌面小工具(Tkinter 界面)# 流程:检测人脸 → 提取特征 → 比对库中特征
# 检测:face_recognition / OpenCV cascade
# 特征:128 维向量(同一人距离小,不同人距离大)
import numpy as np
def cosine(a, b):
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
me_today = np.array([0.11, 0.83, 0.42, 0.19])
me_photo = np.array([0.10, 0.85, 0.40, 0.21])
classmate = np.array([0.77, 0.12, 0.55, 0.93])
print("今天 vs 我的照片:%.3f(>0.8 → 是本人)" % cosine(me_today, me_photo))
print("今天 vs 同学:%.3f(低 → 不是同一人)" % cosine(me_today, classmate))今天 vs 我的照片:0.999(>0.8 → 是本人)
今天 vs 同学:0.491(低 → 不是同一人)每个知识点都要落到能跑、能玩、能演示的作品上。
期末项目是整学期知识点的综合检验场:综合运用。学生将独立完成需求拆解 → 功能实现 → 调试打磨 → 上台演示的完整闭环。
| 课次 | 主题 | 趣味项目 | 知识点 |
|---|---|---|---|
| 1 | 神经网络初探 | 感知机实现 | 神经元、激活函数 |
| 2 | 反向传播 | 手写推导梯度 | 梯度下降、链式法则 |
| 3 | PyTorch初体验 | 张量运算 | Tensor、自动求导 |
| 4 | 第一个神经网络 | XOR问题解决 | nn.Module、训练流程 |
| 5 | 手写数字识别 | MNIST分类 | DataLoader、优化器 |
| 6 | 卷积神经网络 | 猫和狗分类(入门) | CNN、池化、卷积 |
| 7 | CNN进阶 | 更准的图像分类 | 经典网络结构(LeNet) |
| 8 | 数据增强 | 让模型更鲁棒 | 翻转、裁剪、颜色变换 |
| 9 | 迁移学习 | 用预训练模型分类 | 冻结层、微调 |
| 10 | 目标检测入门 | 画框框出物体 | YOLO思想(概念+调用) |
| 11 | 模型保存与部署 | 把模型做成APP | 模型导出、推理 |
| 12 | 期末项目 | 人脸识别签到系统 | 综合运用 |
把一学期的知识点串成体系,看清来路与去向。
◀ 上一章:四年级 上学期 · 机器学习基础
下一章 ▶:五年级 上学期 · CV与NLP双方向
手写感知机、推导梯度、搭建第一个神经网络,一路做到 MNIST 手写识别与人脸识别签到系统。
结业时你将带走:2 个 AI 项目(CV+NLP)+ 云端 GPU 训练经验 + NOAI 复赛实力。
避开高频易错点,再用速查表把语法焊进肌肉记忆。
for epoch …:
loss.backward()
optimizer.step()
# 梯度越累越大for epoch …:
optimizer.zero_grad()
loss.backward()
optimizer.step()X = [[1,2],[3,4]] # 列表
net(X) # 报错X = torch.tensor(X, dtype=torch.float32)
net(X)lr = 1.0 # 来回震荡不收敛lr = 0.001model(X) # 测试时 BatchNorm 乱来model.eval()
with torch.no_grad():
model(X)| 功能 | 写法 | 一句话理解 |
|---|---|---|
| 建张量 | x = torch.randn(2, 3) | 带梯度的多维数组 |
| 自动求导 | loss.backward() | 反向传播算梯度 |
| 定义网络 | class Net(nn.Module): | 继承官方图纸 |
| 训练四步 | zero_grad → forward → backward → step | 每个 batch 的固定节拍 |
| 卷积层 | nn.Conv2d(1, 32, kernel_size=3) | 1通道进 32通道出 |
| 数据加载 | DataLoader(ds, batch_size=64) | 小批量喂食 |
| 保存模型 | torch.save(net.state_dict(), 'm.pt') | 存下学好的权重 |
| 推理模式 | model.eval() + torch.no_grad() | 考试专用姿势 |
按 A / B / C 三档难度自主选择:保底完成 A 组,学有余力挑战 B、C 组。