未分类

普通人也能上手:从零训练一个手写数字识别AI

最近,各类AI大模型频频出现在信息流里,从ChatGPT到Alpaca,从ChatGLM到Bloom,更新速度让人产生“再不了解就落后”的紧迫感。

不过,真正训练大模型并不是普通人轻易能做的事。通常要准备大量高性能显卡,也就是常说的“炼丹卡”,或者直接使用超算资源,仅预算就会让多数人止步。

但AI已经进入日常,跟不上变化的人可能会被时代甩开。所以,普通人也有必要懂一点AI知识。与其只看产业影响和人类未来的宏大讨论,不如换一个工程师的做法:亲手搭建并运行一个很小的AI模型,通过完整流程理解它到底怎样工作。下面以手写数字识别为例,做一次接地气的入门实践。

AI模型如何工作

神经网络是AI中一类重要计算模型。深度学习借助神经网络完成特征学习和模式分析,在图像识别等场景中用得很多。手写数字识别是最基础的例子,适合观察一个神经网络模型如何运转。

MNIST是一个开源数据集,包含6万张手写数字图像,每张是28×28像素的黑底白字。有了它,就可以训练一个识别手写数字的模型,这个练习常被称为AI界的“Hello, world”。

实现时使用卷积神经网络(CNN),代码层面用PyTorch训练框架。PyTorch底层由C++开发,外层用Python调用,容易上手。先确认机器装有Python3,再安装PyTorch 2:

pip install torch torchvision torchaudio

如果电脑有CUDA环境,也可以安装GPU版本,训练会更快。

编写模型

环境准备好后,可以先让AI生成一段用CNN识别MNIST的PyTorch代码:

import torch.nn as nn

class NeuralNetwork(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(1, 32, 3, 1)
self.conv2 = nn.Conv2d(32, 64, 3, 1)
self.fc1 = nn.Linear(in_features=64 * 5 * 5, out_features=128)
self.fc2 = nn.Linear(in_features=128, out_features=10)

def forward(self, x):
x = nn.functional.relu(self.conv1(x))
x = nn.functional.max_pool2d(x, kernel_size=2)
x = nn.functional.relu(self.conv2(x))
x = nn.functional.max_pool2d(x, kernel_size=2)
x = x.view(-1, 64 * 5 * 5)
x = nn.functional.relu(self.fc1(x))
x = self.fc2(x)
return x

如果看不懂,可以继续问AI。简单说,这段代码定义了两个卷积层和两个全连接层:输入是1通道图片,经过卷积和池化后进入全连接层,最后输出10个分类结果,分别对应0到9这10个数字。

训练

接下来用MNIST训练模型。PyTorch已经集成这个数据集,下载、读取和加载都可以自动完成。数据集分成训练集和测试集:训练集用于学习,测试集用于检查效果。首次运行会自动下载并解压,解压后约55M。每批读取64张图片。

训练时先定义损失函数和优化器,再反复执行“前向计算—计算损失—反向传播—更新参数”,每轮结束后在测试集上评估准确率。核心流程可以写成:

loss_fn = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
epochs = 5

for t in range(epochs):
train(train_dataloader, device, model, loss_fn, optimizer)
test(test_dataloader, device, model)

torch.save(model.state_dict(), 'mnist.pth')

完整程序会打印每一轮的loss和accuracy,并把训练好的模型保存为mnist.pth。用CPU训练5轮,每轮大约30秒;如果使用GPU,速度会明显提升。运行结果中,loss从第1轮的0.177下降到第5轮的0.018,准确率从97.21%升到98.95%,最终接近99%。

使用模型

模型保存后,就可以拿真实手写图片测试。用PS手绘几张数字图片,加载mnist.pth,把图片调整为28×28,反色,再转成灰度张量,送入模型。程序通过softmax得到0到9各自的概率,取概率最大的类别作为预测结果。

关键处理步骤如下:

image = Image.open(path).convert('RGB').resize((28, 28))
image = ImageOps.invert(image)

trans = transforms.Compose([
transforms.Grayscale(1),
transforms.ToTensor()
])
image_tensor = trans(image).unsqueeze(0).to(device)

output = model(image_tensor)
probs = torch.nn.functional.softmax(output[0], 0)
predict = torch.argmax(probs).item()

对10张测试图片依次运行,程序会打印预期数字、实际预测和对应概率。把模型训练、评估、保存、加载、推理这一圈完整跑通后,就能对AI模型的工作方式形成直观认识,而不是只停留在概念和焦虑里。

Author

admin@cccoe.cn

发表回复