深度学习AI函数实例:动手跑通你的第一个模型
简单说:深度学习AI函数实例的核心就五个动作——造数据、搭网络、定损失、写循环、看结果,一个不到40行的脚本全包含。抄我这版能直接跑通,每个函数我都解释了参数为什么这么填。报错比代码本身更值得看,我把自己的翻车记录全贴出来了。
深度学习AI函数实例,我劝你别背。这篇文章里的每一行代码,都是我去年在出租屋里边报错边改出来的。当时网上教程的通病我全遇过:代码贴一半的、版本不对应跑不起来的、参数一个字不解释的。所以我写这篇时给自己立了规矩——代码全须全尾,参数逐个说人话,报错如实记录。
我们用PyTorch写一个手写数字识别模型。任务老掉牙了,但它是公认的最短路径:第一个模型的意义不是准确率,是让你亲手摸一遍"数据进来、预测出去、错误反传"的完整流程。跑通之后的视野完全不一样。
准备:深度学习AI函数实例运行前的环境
三样东西:Python 3.10以上、PyTorch 2.x、一块显卡或一颗耐心的CPU。没有显卡照样跑,MNIST数据集很小,CPU训练5分钟内出结果,我的老笔记本亲测过。装PyTorch别直接pip install torch完事,去pytorch.org首页,那里有个选择器,按你的系统和CUDA版本生成安装命令,照抄执行。
验证装没装对,开终端敲三行:
import torch
print(torch.__version__) # 打印版本号,2开头就对了
print(torch.cuda.is_available()) # 有显卡打True,没有打False
第三个打印False别慌,不是装坏了,只说明走CPU模式,入门完全够。我第一次看到False以为自己装了个寂寞,重装了三遍。冤。
实例第一段:造数据和搭网络的函数
这一段就两个函数:transforms.ToTensor()把图片变成数字矩阵,nn.Sequential()把三层网络串成一个整体。没有魔法,全是搭积木。先上代码,再逐行拆。
from torch import nn
from torchvision import datasets, transforms
data = datasets.MNIST(
root='data', # 存放位置,会自动建文件夹
train=True, # True取训练集6万张,False取测试集1万张
download=True, # 本地没有就下载,约12MB
transform=transforms.ToTensor() # 图片转张量,像素值压到0-1
)
说人话环节。图片在电脑里就是一堆数字,MNIST每张图28乘28个像素,每个像素0到255。ToTensor()干两件事:把数值除以255压进0-1区间(小数字训练更稳),再把形状整理成"1通道、高28、宽28"。不转行不行?行,但训练会像喝醉了一样晃。归一化对训练稳定的作用,是无数实验数据支撑的共识。
接着搭网络:
model = nn.Sequential(
nn.Flatten(), # 把1×28×28拉平成784个数字排一排
nn.Linear(784, 128), # 全连接:784个输入压缩成128个输出
nn.ReLU(), # 激活函数:负数归零,正数保留
nn.Linear(128, 10) # 再压成10个输出,对应数字0-9
)
Linear(784, 128)是最容易懵的函数。想象784个人排队进场,128个人出场,中间有个128行784列的表格决定谁能通过——这张表格就是模型要学的参数,共约10万个数,一开始全是随机数。ReLU更简单,一个门卫:负数不让过。别小看这个门卫,没有它,一百层网络等价于一层,这是数学上证明过的。这些概念用大白话展开讲,我在一层层网络到底在干什么里画过图。
实例第二段:损失函数和优化器的函数怎么选
两行代码:CrossEntropyLoss管打分,SGD管改进。前者告诉模型错得多离谱,后者决定每次改多少。学习率0.1是这份数据集的甜点区,我试过0.001,训了半小时像没训。
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.1)
这俩函数必须配对出现,少一个训练就无从谈起。CrossEntropyLoss接收模型的10个输出和正确答案,吐出一个数字——损失,数字越大错得越离谱。SGD(随机梯度下降)拿着这个损失,回头去微调那10万个参数,方向是让下一次损失变小。lr=0.1就是步子大小:太大会在最优点附近反复横跳,太小会挪到天荒地老。学习率这个参数的脾气,我在调参记录里写过一整节,见从模糊到能用的调参记录。
配对这件事我多说一句。要是换Adam优化器,lr得跟着改小一到两个数量级,0.001上下才正常。函数不是孤立用的,参数之间有搭配讲究,这是教程里最少人讲、实际最容易翻车的部分。
实例第三段:训练循环逐行讲
训练循环五步舞:取数据、算预测、算损失、清梯度、反传加更新。for循环每转一圈,模型进步一点点,转满三轮,准确率能到九成以上。整段贴出来。
for epoch in range(3): # 全部数据过三遍
for x, y in loader: # 每次取64张图
pred = model(x) # 前向:图片进,预测出
loss = loss_fn(pred, y) # 打分:错多少
optimizer.zero_grad() # 清空上一轮的梯度
loss.backward() # 反向:算出每个参数该改的方向
optimizer.step() # 更新:真的动手改参数
新手问爆了的问题:zero_grad()为什么必须写?因为PyTorch默认累加梯度,这轮不清零,上一轮的梯度会混进来,相当于改参数时参考了陈旧情报。我第一次删了这行,模型死活不收敛,loss下不去,查了两小时才发现。还有个容易忽视的点,loss.backward()和optimizer.step()的顺序不能反,先算方向再动步子,反了就是拿着旧地图找新路。
想看到过程的话,在循环里塞一行print(f'loss={loss.item():.4f}'),跑起来能看到数字一格一格往下掉。第一次看到那个数字从2.3掉到0.2的时候,我盯着屏幕傻笑,值了。想边跑边理解每个函数在框架里的位置,可以对照数据喂养到模型毕业那篇的流程图看。
我的报错全记录:这三关我替你守着
以下是本人真实翻车档案,按出现顺序排列。第一个报错,装完torch导入就红字:Microsoft Visual C++ Redistributable not found。Windows用户的见面礼。解法直接去微软官网下个VC运行库装上,一分钟的事,但当年我不知道,重装了两遍Python。
第二个,下载数据集卡死。MNIST服务器在国外,偶尔抽风。解法是挂上镜像或者手动下载数据包放进data文件夹,具体搜"MNIST手动下载"有详细步骤。第三个最阴险,代码不报错但loss纹丝不动。排查了一晚上,发现我把lr写成了0.000001,多敲了三个零。所以说参数别手敲,复制粘贴,然后检查小数点。新手踩坑不止环境这一处,认知上的坑我在入门五大误区里列过完整的清单。
话说回来,这些报错现在看都是小事,可当时每个都能卡我一晚上。所以真心建议:报错的时候别硬扛,把报错信息原样丢进搜索框,大概率已经有人踩过同一个坑。
跑通之后干什么?我的三步升级路线
第一改batch size感受速度变化,第二加层数观察准确率上限,第三换FashionMNIST数据集验证泛化。三个小实验做完,你对每个函数的手感就有了,比再读三篇教程管用。我自己就是这么干的:把batch从64改成512,显卡占用肉眼可见地涨了;把128那层改成256,准确率提了不到1%——层数和宽度不是越大越好,这是亲手试出来的认知,比背来的深。
第三步换数据集最有意思。FashionMNIST是衣服鞋子图,代码一行不用改,只换个数据集名字,模型照跑。同样的函数换个任务照样工作,那一刻你才算真理解了这些函数是通用的积木。往下走想复现论文或者做图像项目,路线参考第一次训练识别猫狗,那是我的下一个台阶。学AI路上函数只是入口,整体顺序怎么排看弯路排成的路标,都是我走过来的。
常见问题
一行代码都看不懂,能照着这篇做吗?
能,我写这篇就是假设你只有高中数学。先把代码跑起来看结果,再回头逐行理解,顺序反了容易劝退。要先补编程还是先跑代码的争论,可以看以为要先学编程的分析。
为什么我跑出来的准确率和你的不一样?
正常。初始参数是随机的,显卡和CPU的浮点运算也有差异,九成上下浮动两个点都属正常范围。别追求和别人一模一样的数字,要看loss是不是在稳定下降。
这些函数十年后还适用吗?
函数会变,背后的套路不变:打分、反馈、修正的循环写了三十年。深度学习框架迭代快,但概念稳定,PyTorch的函数文档在官方文档站常年更新,以那边为准。
学这个要多少数学?
跑通不需要,调优需要一点。矩阵乘法和导数概念够用到很后面,真到推导损失函数时再补也来得及。机器学习不写公式的讲法,不写公式也能讲明白那篇是专门干这个的。
这篇代码拿去直接抄,跑通了记得回来留言报个准确率,也欢迎转给那个总说"AI太难学"的朋友——他能跑通第一个模型,比你劝他一百句都管用。