当前位置: 首页 > news >正文

PyTorch 实现 CIFAR-10 图像分类:从数据预处理到模型训练与评估

目录

整体说明

1. 导入必要的库

2. 数据预处理

3. 加载数据集

4. 定义类别名称

5. 构建卷积神经网络 (CNN)

6. 训练准备

7. 训练模型

8. 测试模型

9. 查看各类别准确率

10. 可视化预测结果

11. 保存模型

总结

卷积神经网络

一、先搞懂:这个网络是干嘛的?

二、网络的 “零件”:每层都在干嘛?

关键参数解释:

三、网络的 “工作流程”:forward 函数详解

步骤 1:x = self.pool(torch.relu(self.conv1(x)))

步骤 2:x = self.pool(torch.relu(self.conv2(x)))

步骤 3:x = x.view(-1, 16*5*5)

步骤 4:x = torch.relu(self.fc1(x)) 到 x = self.fc3(x)

四、举个例子:网络如何识别 “一只猫”?

五、为什么要这样设计?

总结:这个网络就像一个 “图片识别小助手”

Net、Criterion、Optimizer 的作用及参数

1. net = Net():创建一个 “学生”

2. criterion = nn.CrossEntropyLoss():一个 “评分老师”

3. optimizer = optim.SGD(...):一个 “辅导老师”

4. 关键参数白话解释

整体流程:学生做题→老师评分→辅导老师纠错

总结

模型训练:

整体说明

逐句解释

1. for epoch in range(10) # 训练10个轮次:

2. running_loss = 0.0

3. for i, data in enumerate(trainloader, 0):

4. inputs, labels = data # 获取输入和标签

5. optimizer.zero_grad()  # 梯度清零(避免累积)

6. outputs = net(inputs)   # 前向传播

7. loss = criterion(outputs, labels)  # 计算损失

8. loss.backward()   # 反向传播(计算梯度)

9. optimizer.step()  # 更新参数

10. running_loss += loss.item()

11. if i % 200 == 199:  # 每200个批次打印一次损失

12. print(...)

13. running_loss = 0.0

14. print('Finished Training')

总结:整个过程像极了学生刷题

用测试集评估模型训练效果

整体意思

逐句说明解释

1. correct = 0

2. total = 0

3. with torch.no_grad()  # 不计算梯度(测试时不需要):

4. for data in testloader:

5. images, labels = data

6. outputs = net(images)

7. _, predicted = torch.max(outputs.data, 1)  # 获取预测的类别索引

8. total += labels.size(0)

9. correct += (predicted == labels).sum().item()

10. print(...)

总结:就像学生期末考

通过分类统计分析模型的“偏科情况”

整体说明

逐句说明

1. class_correct = list(0. for i in range(10))

2. class_total = list(0. for i in range(10))

3. with torch.no_grad():

4. for data in testloader:

5. images, labels = data

6. outputs = net(images)

7. _, predicted = torch.max(outputs, 1)

8. c = (predicted == labels).squeeze()

9. for i in range(len(labels)):

10. label = labels[i]

11. class_correct[label] += c[i].item()

12. class_total[label] += 1

13. for i in range(10):

14. if class_total[i] > 0:

15. print(f'Accuracy of {classes[i]} : ...')

16. else: ...

总结:就像分析每门学科的成绩

通过可视化模型预测结果看模型真实水平

逐句说明

第一部分:定义图片显示工具(def imshow(img):)

第二部分:拿一批测试图片

第三部分:显示图片和真实标签

第四部分:显示模型的预测结果

总结:就像 “贴答案对比”


这里是使用 PyTorch 框架训练了一个卷积神经网络 (CNN) 来识别 CIFAR-10 数据集中的图像的完整例子。 

 

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
import numpy as np
import torchvision  # 添加torchvision导入用于make_grid# 定义数据预处理
transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])# 指定本地数据集路径(使用解压好的数据集)
data_path = r'D:\workspace_py\deeplean\data'  # 修改为你的实际路径# 加载训练集(使用本地解压好的数据集)
trainset = datasets.CIFAR10(root=data_path, train=True, download=False, transform=transform)
trainloader = DataLoader(trainset, batch_size=32, shuffle=True)# 加载测试集(使用本地解压好的数据集)
testset = datasets.CIFAR10(root=data_path, train=False, download=False, transform=transform)
testloader = DataLoader(testset, batch_size=32, shuffle=False)# 定义类别名称
classes = ('plane', 'car', 'bird', 'cat','deer', 'dog', 'frog', 'horse','ship', 'truck')# 定义卷积神经网络模型
class Net(nn.Module):def __init__(self):super(Net, self).__init__()self.conv1 = nn.Conv2d(3, 6, 5)self.pool = nn.MaxPool2d(2, 2)self.conv2 = nn.Conv2d(6, 16, 5)self.fc1 = nn.Linear(16 * 5 * 5, 120)self.fc2 = nn.Linear(120, 84)self.fc3 = nn.Linear(84, 10)def forward(self, x):x = self.pool(torch.relu(self.conv1(x)))x = self.pool(torch.relu(self.conv2(x)))x = x.view(-1, 16 * 5 * 5)x = torch.relu(self.fc1(x))x = torch.relu(self.fc2(x))x = self.fc3(x)return x# 创建模型实例
net = Net()# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)# 训练模型
for epoch in range(10):running_loss = 0.0for i, data in enumerate(trainloader, 0):inputs, labels = dataoptimizer.zero_grad()outputs = net(inputs)loss = criterion(outputs, labels)loss.backward()optimizer.step()running_loss += loss.item()if i % 200 == 199:print(f'[{epoch + 1}, {i + 1:5d}] loss: {running_loss / 200:.3f}')running_loss = 0.0print('Finished Training')# 测试模型
correct = 0
total = 0
with torch.no_grad():for data in testloader:images, labels = dataoutputs = net(images)_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()print(f'Accuracy of the network on the 10000 test images: {100 * correct / total} %')# 查看模型在测试集上对各类别的预测情况
class_correct = list(0. for i in range(10))
class_total = list(0. for i in range(10))
with torch.no_grad():for data in testloader:images, labels = dataoutputs = net(images)_, predicted = torch.max(outputs, 1)c = (predicted == labels).squeeze()for i in range(len(labels)):label = labels[i]class_correct[label] += c[i].item()class_total[label] += 1for i in range(10):if class_total[i] > 0:  # 防止除以零print(f'Accuracy of {classes[i]} : {100 * class_correct[i] / class_total[i]} %')else:print(f'Accuracy of {classes[i]} : No samples found')# 显示一些测试图像及其预测结果
def imshow(img):img = img / 2 + 0.5  # 反归一化npimg = img.numpy()plt.imshow(np.transpose(npimg, (1, 2, 0)))  # 从(C, H, W)转换为(H, W, C)plt.axis('off')  # 关闭坐标轴plt.show()# 获取一批测试图像
dataiter = iter(testloader)
images, labels = next(dataiter)  # 使用next()替代已弃用的.next()# 显示图像网格
imshow(torchvision.utils.make_grid(images))
print('GroundTruth: ', ' '.join('%5s' % classes[labels[j]] for j in range(4)))# 进行预测
outputs = net(images)
_, predicted = torch.max(outputs, 1)print('Predicted: ', ' '.join('%5s' % classes[predicted[j]] for j in range(4)))# 保存模型
torch.save(net.state_dict(), 'cifar10_model.pth')
print("模型已保存为 'cifar10_model.pth'")

运行结果:

D:\ProgramData\anaconda3\envs\py01\python.exe D:\workspace_py\deeplean\cifar10_classifier.py 
[1,   200] loss: 2.304
[1,   400] loss: 2.302
[1,   600] loss: 2.300
[1,   800] loss: 2.298
[1,  1000] loss: 2.295
[1,  1200] loss: 2.289
[1,  1400] loss: 2.270
[2,   200] loss: 2.125
[2,   400] loss: 2.032
[2,   600] loss: 1.988
[2,   800] loss: 1.904
[2,  1000] loss: 1.853
[2,  1200] loss: 1.820
[2,  1400] loss: 1.750
[3,   200] loss: 1.681
[3,   400] loss: 1.673
[3,   600] loss: 1.641
[3,   800] loss: 1.604
[3,  1000] loss: 1.598
[3,  1200] loss: 1.575
[3,  1400] loss: 1.547
[4,   200] loss: 1.516
[4,   400] loss: 1.515
[4,   600] loss: 1.509
[4,   800] loss: 1.481
[4,  1000] loss: 1.463
[4,  1200] loss: 1.443
[4,  1400] loss: 1.431
[5,   200] loss: 1.398
[5,   400] loss: 1.410
[5,   600] loss: 1.387
[5,   800] loss: 1.394
[5,  1000] loss: 1.374
[5,  1200] loss: 1.381
[5,  1400] loss: 1.345
[6,   200] loss: 1.344
[6,   400] loss: 1.325
[6,   600] loss: 1.335
[6,   800] loss: 1.295
[6,  1000] loss: 1.326
[6,  1200] loss: 1.288
[6,  1400] loss: 1.292
[7,   200] loss: 1.273
[7,   400] loss: 1.273
[7,   600] loss: 1.261
[7,   800] loss: 1.231
[7,  1000] loss: 1.265
[7,  1200] loss: 1.244
[7,  1400] loss: 1.230
[8,   200] loss: 1.208
[8,   400] loss: 1.226
[8,   600] loss: 1.204
[8,   800] loss: 1.202
[8,  1000] loss: 1.193
[8,  1200] loss: 1.197
[8,  1400] loss: 1.157
[9,   200] loss: 1.152
[9,   400] loss: 1.148
[9,   600] loss: 1.149
[9,   800] loss: 1.144
[9,  1000] loss: 1.141
[9,  1200] loss: 1.140
[9,  1400] loss: 1.147
[10,   200] loss: 1.105
[10,   400] loss: 1.090
[10,   600] loss: 1.115
[10,   800] loss: 1.109
[10,  1000] loss: 1.121
[10,  1200] loss: 1.089
[10,  1400] loss: 1.104
Finished Training
Accuracy of the network on the 10000 test images: 60.27 %
Accuracy of plane : 67.3 %
Accuracy of car : 73.9 %
Accuracy of bird : 52.5 %
Accuracy of cat : 35.3 %
Accuracy of deer : 50.7 %
Accuracy of dog : 47.3 %
Accuracy of frog : 80.7 %
Accuracy of horse : 64.8 %
Accuracy of ship : 65.8 %
Accuracy of truck : 64.4 %
GroundTruth:    cat  ship  ship plane
Predicted:    cat   car plane  ship
模型已保存为 'cifar10_model.pth'Process finished with exit code 0

整体说明

1. 导入必要的库

import torch

import torch.nn as nn

import torch.optim as optim

from torchvision import datasets, transforms

from torch.utils.data import DataLoader

import matplotlib.pyplot as plt

import numpy as np

import torchvision  # 添加torchvision导入用于make_grid

  1. torch:PyTorch 的核心库,提供张量计算和自动求导。
  2. torch.nn:用于构建神经网络的模块。
  3. torch.optim:包含优化算法(如 SGD、Adam)。
  4. torchvision:提供常用数据集 (CIFAR-10)、模型和图像变换工具。
  5. matplotlib:用于可视化图像和结果。

2. 数据预处理

transform = transforms.Compose([

    transforms.ToTensor(),

    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))

])

  1. transforms.Compose:将多个图像变换组合成流水线。
    1. ToTensor():将 PIL 图像或 NumPy 数组转换为张量,并归一化到 [0.0, 0]
    2. Normalize:进一步将像素值归一化到 [-1.0, 1.0](通过 (x-0.5)/0.5)。

3. 加载数据集

data_path = r'D:\workspace_py\deeplean\data'  # 修改为你的实际路径

trainset = datasets.CIFAR10(root=data_path, train=True, download=False, transform=transform)

trainloader = DataLoader(trainset, batch_size=32, shuffle=True)

testset = datasets.CIFAR10(root=data_path, train=False, download=False, transform=transform)

testloader = DataLoader(testset, batch_size=32, shuffle=False)

  1. CIFAR10:从本地路径加载数据集(download=False 表示不重新下载)。
    1. train=True:加载训练集(50,000 张图像)。
    2. train=False:加载测试集(10,000 张图像)。
  2. DataLoader:将数据集包装成迭代器,便于批量处理。
    1. batch_size=32:每次处理 32 张图像。
    2. shuffle=True:训练时打乱数据顺序,提高模型泛化能力。

4. 定义类别名称

classes = ('plane', 'car', 'bird', 'cat',

           'deer', 'dog', 'frog', 'horse','ship', 'truck')

CIFAR-10 数据集包含 10 个类别,每个类别对应一个索引(0-9)。

5. 构建卷积神经网络 (CNN)

class Net(nn.Module):

    def __init__(self):

        super(Net, self).__init__()

        self.conv1 = nn.Conv2d(3, 6, 5)  # 输入3通道,输出6通道,卷积核5x5

        self.pool = nn.MaxPool2d(2, 2)   # 池化层,降采样

        self.conv2 = nn.Conv2d(6, 16, 5) # 输入6通道,输出16通道

        self.fc1 = nn.Linear(16 * 5 * 5, 120)  # 全连接层

        self.fc2 = nn.Linear(120, 84)

        self.fc3 = nn.Linear(84, 10)    # 最终输出10个类别

    def forward(self, x):

        x = self.pool(torch.relu(self.conv1(x)))

        x = self.pool(torch.relu(self.conv2(x)))

        x = x.view(-1, 16 * 5 * 5)      # 展平为一维向量

        x = torch.relu(self.fc1(x))

        x = torch.relu(self.fc2(x))

        x = self.fc3(x)

        return x

  1. 网络结构
    1. 卷积层 1:提取低级特征(如边缘、颜色)。
    2. 池化层:压缩特征图,减少计算量。
    3. 卷积层 2:提取高级特征(如形状、纹理)。
    4. 全连接层:将特征映射到 10 个类别。
  2. 激活函数:ReLU(修正线性单元),引入非线性,增强模型表达能力。

6. 训练准备

net = Net()  # 创建模型实例

criterion = nn.CrossEntropyLoss()  # 交叉熵损失函数(用于分类)

optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)  # 随机梯度下降优化器

  1. 损失函数:衡量模型预测与真实标签的差异。
  2. 优化器:根据损失函数的梯度更新模型参数。
    1. lr=0.001:学习率(控制参数更新步长)。
    2. momentum=0.9:动量(加速收敛,减少震荡)。

7. 训练模型

for epoch in range(10):  # 训练10个轮次

    running_loss = 0.0

    for i, data in enumerate(trainloader, 0):

        inputs, labels = data  # 获取输入和标签

        optimizer.zero_grad()  # 梯度清零(避免累积)

        outputs = net(inputs)  # 前向传播

        loss = criterion(outputs, labels)  # 计算损失

        loss.backward()  # 反向传播(计算梯度)

        optimizer.step()  # 更新参数

        running_loss += loss.item()

        if i % 200 == 199:  # 200个批次打印一次损失

            print(f'[{epoch + 1}, {i + 1:5d}] loss: {running_loss / 200:.3f}')

            running_loss = 0.0

print('Finished Training')

  1. 训练流程
    1. 前向传播:输入图像通过网络得到预测结果。
    2. 计算损失:对比预测结果与真实标签。
    3. 反向传播:计算损失对参数的梯度。
    4. 参数更新:优化器根据梯度调整参数。
  2. 轮次 (epoch):整个数据集被训练的次数。

8. 测试模型

correct = 0

total = 0

with torch.no_grad():  # 不计算梯度(测试时不需要)

    for data in testloader:

        images, labels = data

        outputs = net(images)

        _, predicted = torch.max(outputs.data, 1)  # 获取预测的类别索引

        total += labels.size(0)

        correct += (predicted == labels).sum().item()

print(f'Accuracy of the network on the 10000 test images: {100 * correct / total} %')

  1. 准确率计算:模型在测试集上正确预测的样本数占总样本数的比例。

9. 查看各类别准确率

class_correct = list(0. for i in range(10))

class_total = list(0. for i in range(10))

with torch.no_grad():

    for data in testloader:

        images, labels = data

        outputs = net(images)

        _, predicted = torch.max(outputs, 1)

        c = (predicted == labels).squeeze()

        for i in range(len(labels)):

            label = labels[i]

            class_correct[label] += c[i].item()

            class_total[label] += 1

for i in range(10):

    if class_total[i] > 0:  # 防止除以零

        print(f'Accuracy of {classes[i]} : {100 * class_correct[i] / class_total[i]} %')

    else:

        print(f'Accuracy of {classes[i]} : No samples found')

  1. 类别准确率:模型在每个类别上的表现(例如,对 “飞机” 的识别准确率可能高于 “猫”)。

10. 可视化预测结果

def imshow(img):

    img = img / 2 + 0.5  # 反归一化(从[-1,1]回到[0,1]

    npimg = img.numpy()

    plt.imshow(np.transpose(npimg, (1, 2, 0)))  # 调整维度顺序(C,H,W → H,W,C

    plt.axis('off')  # 关闭坐标轴

    plt.show()

# 获取一批测试图像

dataiter = iter(testloader)

images, labels = next(dataiter)

# 显示图像和真实标签

imshow(torchvision.utils.make_grid(images))

print('GroundTruth: ', ' '.join('%5s' % classes[labels[j]] for j in range(4)))

# 显示预测结果

outputs = net(images)

_, predicted = torch.max(outputs, 1)

print('Predicted: ', ' '.join('%5s' % classes[predicted[j]] for j in range(4)))

  1. 图像展示
    1. 从测试集随机选取一批图像。
    2. 显示图像的真实标签和模型预测结果。

11. 保存模型

torch.save(net.state_dict(), 'cifar10_model.pth')

print("模型已保存为 'cifar10_model.pth'")

  1. 保存参数:将训练好的模型权重保存到文件,便于后续使用。

总结

这个代码实现了一个完整的深度学习流程:

  1. 数据准备:加载并预处理 CIFAR-10 数据集。
  2. 模型设计:构建卷积神经网络。
  3. 模型训练:通过优化器调整参数,最小化损失函数。
  4. 模型评估:在测试集上验证模型准确率。
  5. 结果可视化:展示模型预测效果。

作为小白,你可以尝试调整以下参数:

  1. 学习率 (lr):影响训练速度和稳定性。
  2. 批次大小 (batch_size):较大的批次可能加速训练,但需要更多内存。
  3. 网络层数:增加卷积层或全连接层可能提高准确率。
  4. 训练轮次 (epochs):增加轮次可能提高准确率,但也可能导致过拟合。

卷积神经网络

class Net(nn.Module):def __init__(self):super(Net, self).__init__()self.conv1 = nn.Conv2d(3, 6, 5)self.pool = nn.MaxPool2d(2, 2)self.conv2 = nn.Conv2d(6, 16, 5)self.fc1 = nn.Linear(16 * 5 * 5, 120)self.fc2 = nn.Linear(120, 84)self.fc3 = nn.Linear(84, 10)def forward(self, x):x = self.pool(torch.relu(self.conv1(x)))x = self.pool(torch.relu(self.conv2(x)))x = x.view(-1, 16 * 5 * 5)x = torch.relu(self.fc1(x))x = torch.relu(self.fc2(x))x = self.fc3(x)return x

这段代码定义了一个卷积神经网络(CNN,专门用来处理图像。咱们用 “处理照片” 的生活场景来类比,一步步给你讲明白:

一、先搞懂:这个网络是干嘛的?

就像人眼识别照片里的东西(比如 “这是一只猫”),这个网络的作用是:

输入一张彩色图片 → 经过多层处理 → 输出 “这张图属于 10 个类别中的哪一个”(比如飞机、猫、汽车等)

它比普通的 “全连接网络” 厉害,因为它能像人眼一样,先看局部细节(比如边缘、颜色),再组合成整体特征(比如 “有耳朵 + 有尾巴 = 可能是猫”),特别适合处理图像。

二、网络的 “零件”:每层都在干嘛?

先看 __init__ 里定义的 “零件”,这些是网络的核心层:

零件名

白话解释(类比处理照片)

作用

self.conv1

第一个 “放大镜”,能看到图片里的边缘、颜色块等细节

提取低级特征(基础细节)

self.pool

一个 “缩小镜”,把图片缩小一半,保留关键信息

减少计算量,聚焦重要特征

self.conv2

第二个 “放大镜”,能看到更复杂的组合(比如 “边缘 + 颜色 = 眼睛”)

提取高级特征(组合细节)

self.fc1~fc3

三个 “分类器”,把前面看到的特征汇总,判断最终类别

从特征到类别的映射

关键参数解释:
  1. nn.Conv2d(3, 6, 5)
    1. 3:输入是彩色图片(有红、绿、蓝 3 个颜色通道)。
    2. 6:用 6 种不同的 “滤镜” 去看图片(每种滤镜提取一种细节)。
    3. 5:每个滤镜的大小是 5×5 像素(相当于用 5×5 的小方块扫过整个图片)。
  2. nn.MaxPool2d(2, 2)
    1. 把图片的高和宽都缩小一半(比如 32×32 的图→16×16),只保留每个小区域里最亮的像素(关键信息)。
  3. nn.Linear(16*5*5, 120)
    1. 全连接层,就像 “汇总报告”:把前面提取的所有特征(16×5×5 个数字)转换成 120 个 “关键特征值”。
    2. 最后 fc3 输出 10 个值,对应 10 个类别的 “可能性分数”(分数最高的就是网络认为的类别)。

三、网络的 “工作流程”:forward 函数详解

forward 函数定义了图片从输入到输出的 “处理步骤”,就像工厂的流水线:

步骤 1:x = self.pool(torch.relu(self.conv1(x)))
  1. 先用 conv1 这个 “放大镜” 扫一遍图片,提取边缘、颜色块等基础细节(得到 6 个特征图)。
  2. 再用 torch.relu 这个 “过滤器”:只保留有用的特征(把负数变成 0,相当于 “不重要的细节忽略掉”)。
  3. 最后用 pool 这个 “缩小镜” 把特征图缩小一半(6 个特征图都变小,减少计算量)。
步骤 2:x = self.pool(torch.relu(self.conv2(x)))
  1. conv2 这个 “高级放大镜” 看前面缩小后的特征图:把基础细节组合成更复杂的特征(比如 “边缘 + 颜色 = 圆形的眼睛”),得到 16 个更抽象的特征图。
  2. 再经过 relu 过滤和 pool 缩小,特征图变得更小,但保留的都是关键信息。
步骤 3:x = x.view(-1, 16*5*5)
  1. 前面的特征图是 “二维的”(像小图片),这一步把它 “摊平” 成一维的数字列表(比如 16 个 5×5 的特征图→16×5×5=400 个数字)。
  2. 就像把一堆照片剪成小碎片,再排成一条直线,方便后面的 “分类器” 处理。
步骤 4:x = torch.relu(self.fc1(x))x = self.fc3(x)
  1. fc1 把 400 个数字转换成 120 个 “关键特征值”(比如 “眼睛特征值”“尾巴特征值”)。
  2. fc2 再把 120 个值浓缩成 84 个更核心的特征。
  3. fc3 最后输出 10 个值,分别对应 10 个类别的 “可能性”(比如 “猫的可能性 = 90 分,狗的可能性 = 5 分”)。

四、举个例子:网络如何识别 “一只猫”?

  1. 输入:一张 32×32 的猫的彩色图片。
  2. conv1+pool:看到猫的耳朵边缘、毛色块(低级特征),图片缩小到 14×14(因为 5×5 滤镜扫描后会变小)。
  3. conv2+pool:把边缘和颜色组合,认出 “三角形的耳朵”“椭圆形的眼睛”(高级特征),图片缩小到 5×5。
  4. 摊平:把 5×5 的特征图变成 400 个数字。
  5. 全连接层:汇总这些数字,计算出 “猫” 的可能性最高,最终输出 “这是猫”。

五、为什么要这样设计?

  1. 卷积层(conv:只看局部细节,不用处理整个图片,计算量小,还能识别不同位置的相同特征(比如不管猫在图片左边还是右边,都能认出是猫)。
  2. 池化层(pool:缩小图片,减少计算量,同时让网络对图片的微小变形不敏感(比如猫稍微歪一点也能认出来)。
  3. ReLU 激活函数:给网络加入 “非线性” 能力,让它能识别复杂的特征(如果没有它,网络就是简单的线性模型,连曲线都认不出来)。
  4. 全连接层(fc:把前面学到的所有特征汇总,最终 “投票” 决定图片的类别。

总结:这个网络就像一个 “图片识别小助手”

它的工作逻辑和人眼很像:先看细节,再组合成整体,最后判断是什么。

你可以把它想象成一个 “流水线工厂”:

  1. 卷积层是 “采摘工”,挑出有用的细节;
  2. 池化层是 “打包工”,压缩信息;
  3. 全连接层是 “质检员”,最终判断产品类别。

这样设计的好处是:识别图片又快又准,比普通的神经网络更适合处理图像任务~

Net、Criterion、Optimizer 的作用及参数

# 创建模型实例
net = Net()# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

咱们用 “学生做题” 的场景来类比:

1. net = Net():创建一个 “学生”

  1. 这个 “学生”(模型)的大脑里装着咱们之前设计的神经网络(卷积层、全连接层等),就像一个刚开始学认图片的小孩,脑子里的 “知识”(网络参数)都是随机的,一开始啥也认不出来。
  2. 咱们的目标是:通过训练,让这个 “学生” 学会看图片识物(比如准确区分猫、飞机等)。

2. criterion = nn.CrossEntropyLoss():一个 “评分老师”

  1. 这个 “老师” 的作用是:给学生的答案打分,判断学生做得对不对、错得有多离谱。
  2. 比如:
    1. 学生把 “猫” 认成了 “狗”,老师会说 “错了,扣 5 分”;
    2. 学生把 “猫” 认成了 “飞机”,老师会说 “错得更离谱,扣 10 分”;
    3. 学生答对了,老师说 “没错,扣 0 分”。
  3. 这个 “扣多少分” 就是损失值,损失值越小,说明学生做得越好。

3. optimizer = optim.SGD(...):一个 “辅导老师”

  1. 这个 “辅导老师” 的作用是:根据评分老师的反馈(损失值),帮学生改错题,让学生下次做得更好。
  2. 具体来说,它会告诉学生:“上次这道题错了,下次应该往哪个方向改(调整大脑里的知识),改多大力度”。

4. 关键参数白话解释

  1. lr=0.001(学习率)

相当于 “改题的幅度”。比如学生把 “猫” 认成了 “狗”,辅导老师会说:“下次看图片时,多注意‘猫有尖耳朵’这个特征,调整的幅度小一点(0.001),别一下子改太猛”。

    1. 如果学习率太大(比如 10),学生可能 “矫枉过正”(这次认成狗,下次直接认成飞机);
    2. 如果学习率太小(比如 0.00001),学生改得太慢,学半天没进步。
  1. momentum=0.9(动量)

相当于 “惯性”。比如学生连续 3 次都把 “猫” 认错,而且每次辅导老师都指出 “应该多注意耳朵”,动量就会让学生 “顺着这个方向继续改”,加速进步。

    1. 就像推箱子:一开始推不动,推一会儿有了惯性,就越推越顺,不容易来回晃(减少训练时的 “震荡”)。

整体流程:学生做题→老师评分→辅导老师纠错

  1. 学生做题net(inputs) 让模型看图片,输出一个预测结果(比如 “这是狗”)。
  2. 老师评分criterion(outputs, labels) 对比预测结果和真实标签(比如真实是 “猫”),算出损失值(错得有多离谱)。
  3. 辅导老师纠错optimizer.step() 根据损失值的 “梯度”(错的方向和程度),调整模型里的参数(学生大脑里的知识),让下次预测更准。
  4. 重复以上步骤:做 10 轮题(10 个 epoch)后,学生就慢慢学会准确认图片了。

总结

  1. net 是 “学生”,负责做题(预测);
  2. criterion 是 “评分老师”,负责判断对错(算损失);
  3. optimizer 是 “辅导老师”,负责帮学生改题(调参数);
  4. lrmomentum 是辅导老师的 “教学技巧”,让学生学得又快又稳。

整个过程就像:一个啥也不会的小孩,在两位老师的帮助下,通过反复做题纠错,最终学会了准确识别图片~

模型训练:

for epoch in range(10):  # 训练10个轮次running_loss = 0.0for i, data in enumerate(trainloader, 0):inputs, labels = data  # 获取输入和标签optimizer.zero_grad()  # 梯度清零(避免累积)outputs = net(inputs)  # 前向传播loss = criterion(outputs, labels)  # 计算损失loss.backward()  # 反向传播(计算梯度)optimizer.step()  # 更新参数running_loss += loss.item()if i % 200 == 199:  # 每200个批次打印一次损失print(f'[{epoch + 1}, {i + 1:5d}] loss: {running_loss / 200:.3f}')running_loss = 0.0print('Finished Training')

D:\ProgramData\anaconda3\envs\py01\python.exe D:\workspace_py\deeplean\cifar10_classifier.py 
[1,   200] loss: 2.304
[1,   400] loss: 2.302
[1,   600] loss: 2.300
[1,   800] loss: 2.298
[1,  1000] loss: 2.295
[1,  1200] loss: 2.289
[1,  1400] loss: 2.270
[2,   200] loss: 2.125
[2,   400] loss: 2.032
[2,   600] loss: 1.988
[2,   800] loss: 1.904
[2,  1000] loss: 1.853
[2,  1200] loss: 1.820
[2,  1400] loss: 1.750
[3,   200] loss: 1.681
[3,   400] loss: 1.673
[3,   600] loss: 1.641
[3,   800] loss: 1.604
[3,  1000] loss: 1.598
[3,  1200] loss: 1.575
[3,  1400] loss: 1.547
[4,   200] loss: 1.516
[4,   400] loss: 1.515
[4,   600] loss: 1.509
[4,   800] loss: 1.481
[4,  1000] loss: 1.463
[4,  1200] loss: 1.443
[4,  1400] loss: 1.431
[5,   200] loss: 1.398
[5,   400] loss: 1.410
[5,   600] loss: 1.387
[5,   800] loss: 1.394
[5,  1000] loss: 1.374
[5,  1200] loss: 1.381
[5,  1400] loss: 1.345
[6,   200] loss: 1.344
[6,   400] loss: 1.325
[6,   600] loss: 1.335
[6,   800] loss: 1.295
[6,  1000] loss: 1.326
[6,  1200] loss: 1.288
[6,  1400] loss: 1.292
[7,   200] loss: 1.273
[7,   400] loss: 1.273
[7,   600] loss: 1.261
[7,   800] loss: 1.231
[7,  1000] loss: 1.265
[7,  1200] loss: 1.244
[7,  1400] loss: 1.230
[8,   200] loss: 1.208
[8,   400] loss: 1.226
[8,   600] loss: 1.204
[8,   800] loss: 1.202
[8,  1000] loss: 1.193
[8,  1200] loss: 1.197
[8,  1400] loss: 1.157
[9,   200] loss: 1.152
[9,   400] loss: 1.148
[9,   600] loss: 1.149
[9,   800] loss: 1.144
[9,  1000] loss: 1.141
[9,  1200] loss: 1.140
[9,  1400] loss: 1.147
[10,   200] loss: 1.105
[10,   400] loss: 1.090
[10,   600] loss: 1.115
[10,   800] loss: 1.109
[10,  1000] loss: 1.121
[10,  1200] loss: 1.089
[10,  1400] loss: 1.104
Finished Training

这段咱们还是用 “学生做题” 来类比,把这段 10 行代码想象成 “学生刷题进步的过程”

整体说明

这段段代码是让 “模型学生” 通过 10 轮练习(做题),从啥也不会慢慢变成 “图像识别高手” 的过程。就像学生刷 10 遍题库,每遍都查漏补缺,最后成绩越来越高。

逐句解释

1. for epoch in range(10) # 训练10个轮次:
  1. 说明:让学生把整个题库(训练集)做 10 遍,每遍叫 1 个 “轮次(epoch)”。
  2. 为啥要做 10 遍?就像你刷数学题,第一遍错很多,第二遍少一点,多刷几遍才能记牢。这里 10 遍是经验值,也可以改成 20 遍(但可能做太多遍会 “死记硬背”,反而考不好)。
2. running_loss = 0.0
  1. 说明:准备一个 “错题本”,记录这一轮做题的总错误量(损失值),刚开始是空的(0.0)。
3. for i, data in enumerate(trainloader, 0):
  1. 说明:把题库里的题分成一小批一小批(每批 32 张图片,之前设置的batch_size=32),让学生一道一道做。
  2. i是题号(从 0 开始),data是这道题的 “图片和正确答案”。
4. inputs, labels = data # 获取输入和标签
  1. 说明:从data里拿出 “题目(图片,inputs)” 和 “正确答案(标签,labels)”。
  2. 比如:题目是一张猫的图片,正确答案是 “cat”。
5. optimizer.zero_grad()  # 梯度清零(避免累积)
  1. 说明:让 “辅导老师” 先清空上一道题的纠错记录(梯度),避免影响这道题的判断。
  2. 就像改作业时,先擦掉上一题的批改痕迹,再改新题。
6. outputs = net(inputs)   # 前向传播
  1. 说明:让 “学生(net)” 看题目(图片),写出自己的答案(outputs)。
  2. 比如学生看到猫的图片,猜是 “dog”(一开始可能乱猜)。
7. loss = criterion(outputs, labels)  # 计算损失
  1. 说明:让 “评分老师(criterion)” 对比学生答案和正确答案,算出这道题的错误程度(loss,损失值)。
  2. 比如学生把 “cat” 猜成 “dog”,错误程度是 3 分;猜成 “plane”,错误程度是 8 分(错得越离谱,loss 越大)。
8. loss.backward()   # 反向传播(计算梯度)
  1. 说明:让 “评分老师” 分析错误原因,告诉 “辅导老师”:“学生哪里错了,应该往哪个方向改(计算梯度)”。
  2. 比如:“学生没注意猫的尖耳朵,下次要多关注这个特征”。
9. optimizer.step()  # 更新参数
  1. 说明:“辅导老师” 根据错误原因,帮学生调整脑子里的知识(更新模型参数)。
  2. 比如:“把‘尖耳朵’这个特征的重要性调高点,下次看到就不容易认错了”。
10. running_loss += loss.item()
  1. 说明:把这道题的错误分(loss)记到 “错题本” 上,累加起来。
11. if i % 200 == 199:  # 每200个批次打印一次损失
  1. 说明:每做完 200 道题,就看看错题本,总结一下最近的错误情况。
  2. 比如每做 200 道题,算一下平均每道题错多少分,方便了解进步情况。
12. print(...)
  1. 说明:打印出 “第几个轮次、第几道题、最近 200 道题的平均错误分”。
  2. 比如:[2,  400] loss: 1.234 表示 “第 2 轮,第 400 道题,最近 200 道题平均错 1.234 分”。
  3. 正常情况下,这个数会越来越小,说明学生进步了。
13. running_loss = 0.0
  1. 说明:总结完后,清空错题本,准备记录下 200 道题的错误。
14. print('Finished Training')
  1. 说明:10 轮题全做完了,训练结束!学生现在已经是 “图像识别小能手” 了。

总结:整个过程像极了学生刷题

  1. 多轮练习:刷 10 遍题库(10 个 epoch),反复巩固。
  2. 批量做题:一次做 32 道题(batch_size),效率更高。
  3. 即时纠错:每道题做完就评分、分析错误、改正(前向传播→算损失→反向传播→更新参数)。
  4. 定期总结:每 200 道题看一次平均错误,了解进步情况。

最后,随着训练进行,错误分(loss)越来越小,说明模型越来越会认图片了~

用测试集评估模型训练效果

correct = 0total = 0with torch.no_grad():  # 不计算梯度(测试时不需要)for data in testloader:images, labels = dataoutputs = net(images)_, predicted = torch.max(outputs.data, 1)  # 获取预测的类别索引total += labels.size(0)correct += (predicted == labels).sum().item()print(f'Accuracy of the network on the 10000 test images: {100 * correct / total} %')

这段代码是用来检查模型训练得好不好的,就像考完试后算分数一样。咱们还是用 “学生考试” 来类比,保证你一听就懂:

整体意思

让训练好的 “模型学生” 做一套 “期末测试卷(测试集)”,然后算出它的 “正确率”,看看它到底学会了多少。

逐句说明解释

1. correct = 0
  1. 说明:准备一个 “计数器”,记录学生做对了多少道题,一开始是 0。
2. total = 0
  1. 说明:再准备一个 “总题数计数器”,记录这套试卷一共有多少道题,一开始是 0。
3. with torch.no_grad()  # 不计算梯度(测试时不需要):
  1. 说明:“考试的时候不让学生改答案”。
  2. 因为测试只是为了看成绩,不需要像训练时那样 “纠错改题”,所以关闭 “梯度计算”(节省时间和内存)。
4. for data in testloader:
  1. 说明:把测试卷的题目分成一小批一小批(和训练时一样,每批 32 道题),让学生一道一道做。
5. images, labels = data
  1. 说明:从试卷里拿出 “题目(图片,images)” 和 “正确答案(标签,labels)”。
  2. 比如:题目是一张汽车的图片,正确答案是 “car”。
6. outputs = net(images)
  1. 说明:让 “学生(net)” 看题目写答案(outputs)。
  2. 这里的答案不是直接说 “是 car”,而是给 10 个类别打分(比如 “car 得 90 分,plane 得 5 分”),分数越高表示越可能是这个类别。
7. _, predicted = torch.max(outputs.data, 1)  # 获取预测的类别索引
  1. 说明:从学生给的 10 个分数里,挑出最高分对应的类别,作为最终答案。
  2. 比如:10 个分数里 “car” 最高,那就预测这道题的答案是 “car”。
  3. 前面的_是个占位符,意思是 “我们只关心最高分对应的类别,不关心具体分数是多少”。
8. total += labels.size(0)
  1. 说明:把这一批题的数量加到 “总题数计数器” 里。
  2. 比如这一批有 32 道题,就给total加 32,最后算出来的总题数是 10000(CIFAR-10 测试集的总图片数)。
9. correct += (predicted == labels).sum().item()
  1. 说明:数一数这一批题里学生做对了多少道,加到 “正确计数器” 里。
  2. predicted == labels:对比学生答案和正确答案,对的打勾(True),错的打叉(False)predicted : 预报。
  3. .sum():把打勾的数量加起来(比如这一批对了 25 道)。
  4. .item():把这个数量转换成普通数字,加到correct里。
10. print(...)
  1. 说明:最后算 “正确率” 并打印出来。
  2. 正确率 = 做对的题数 ÷ 总题数 × 100%
  3. 比如输出 “65%”,表示模型在 10000 张测试图片中,有 65% 的图片都认对了。

总结:就像学生期末考

  1. 闭卷考试with torch.no_grad() 确保只做题不纠错。
  2. 批量做题:一批批做完整套测试卷(10000 道题)。
  3. 打分规则:选最高分的类别作为答案,对的加分,错的不加分。
  4. 算正确率:最后用 “做对的题数 ÷ 总题数” 判断模型学得多好。

这个正确率越高(比如从 60% 升到 80%),说明模型训练得越好,越会认图片~

通过分类统计分析模型的“偏科情况”

# 查看模型在测试集上对各类别的预测情况
class_correct = list(0. for i in range(10))
class_total = list(0. for i in range(10))
with torch.no_grad():for data in testloader:images, labels = dataoutputs = net(images)_, predicted = torch.max(outputs, 1)c = (predicted == labels).squeeze()for i in range(len(labels)):label = labels[i]class_correct[label] += c[i].item()class_total[label] += 1for i in range(10):if class_total[i] > 0:  # 防止除以零print(f'Accuracy of {classes[i]} : {100 * class_correct[i] / class_total[i]} %')else:print(f'Accuracy of {classes[i]} : No samples found')

这段代码是更细致地检查模型的 “偏科情况”,就像考完试后不仅算总分,还要看每门学科的得分 —— 看看模型对哪些类别的图片特别擅长,对哪些又容易认错。咱们还是用 “学生考试” 来类比:

整体说明

算完 “总分(整体正确率)” 后,再细分到每个类别(比如 “猫”“飞机”“汽车”),单独算正确率。就像考完试后,不仅知道总分 65 分,还知道 “数学考了 80 分,语文只考了 50 分”,方便找到薄弱环节。

逐句说明

1. class_correct = list(0. for i in range(10))
  1. 说明:准备 10 个 “小计数器”,分别记录模型在 10 个类别上做对的题数(初始都是 0)。
  2. 比如索引 0 对应 “plane”,索引 1 对应 “car”,以此类推。
2. class_total = list(0. for i in range(10))
  1. 说明:再准备 10 个 “小总题数计数器”,记录每个类别总共有多少道题(初始都是 0)。
  2. 比如 “cat” 这个类别在测试集里有 1000 张图片,最后这个计数器就会变成 1000。
3. with torch.no_grad():
  1. 说明:和之前一样,“考试时只做题不改答案”,关闭梯度计算(节省资源)。
4. for data in testloader:
  1. 说明:把测试卷的题目分批拿出来,让模型一道一道做(每批 32 道题)。
5. images, labels = data
  1. 说明:拿出 “题目(图片)” 和 “正确答案(每个图片属于哪个类别)”。
  2. 比如这一批有 32 张图,对应的正确答案可能是 “cat、car、plane……”。
6. outputs = net(images)
  1. 说明:模型看图片后,给 10 个类别打分(比如 “这张图是 cat 的可能性 90 分,dog10 分”)。
7. _, predicted = torch.max(outputs, 1)
  1. 说明:模型从 10 个分数里挑最高的,作为这张图的预测类别(比如选 90 分的 cat)。
8. c = (predicted == labels).squeeze()
  1. 说明:对比 “模型预测的类别” 和 “正确类别”,对的打勾(True),错的打叉(False),再把结果整理成简单的列表。
  2. 比如这一批 32 道题,对比后得到 [True, False, True, ...](对、错、对……)。
9. for i in range(len(labels)):
  1. 说明:逐个检查这一批里的每一道题(比如 32 道题就循环 32 次)。
10. label = labels[i]
  1. 说明:拿出第 i 道题的正确类别(比如正确答案是 “cat”,对应索引 3)。
11. class_correct[label] += c[i].item()
  1. 说明:如果这道题做对了(c [i] 是 True),就给对应类别的 “正确计数器” 加 1。
  2. 比如第 i 道题正确类别是 “cat”(索引 3),且做对了,就给class_correct[3]加 1。
12. class_total[label] += 1
  1. 说明:不管做对做错,都给对应类别的 “总题数计数器” 加 1(统计这个类别共有多少题)。
  2. 比如第 i 道题是 “cat”,就给class_total[3]加 1。
13. for i in range(10):
  1. 说明:循环 10 个类别,分别算每个类别的正确率。
14. if class_total[i] > 0:
  1. 说明:如果这个类别有题(避免除以 0 的错误)。
15. print(f'Accuracy of {classes[i]} : ...')
  1. 说明:打印 “某个类别” 的正确率(做对的题数 ÷ 总题数 ×100%)。
  2. 比如输出 “Accuracy of cat : 55%”,表示模型对 “猫” 的图片,只有 55% 能认对。
16. else: ...
  1. 说明:如果某个类别没题(实际 CIFAR-10 每个类别都有题,这里是保险措施)。

总结:就像分析每门学科的成绩

[10,  1200] loss: 1.089
[10,  1400] loss: 1.104
Finished Training
Accuracy of the network on the 10000 test images: 60.27 %
Accuracy of plane : 67.3 %
Accuracy of car : 73.9 %
Accuracy of bird : 52.5 %
Accuracy of cat : 35.3 %
Accuracy of deer : 50.7 %
Accuracy of dog : 47.3 %
Accuracy of frog : 80.7 %
Accuracy of horse : 64.8 %
Accuracy of ship : 65.8 %
Accuracy of truck : 64.4 %
GroundTruth:    cat  ship  ship plane
Predicted:    cat   car plane  ship
模型已保存为 'cifar10_model.pth'Process finished with exit code 0

  1. 分类统计:给 10 个类别各准备一个 “错题本”,记录每个类别做对多少、总共有多少题。
  2. 逐题核对:每道题做完后,不仅算对错,还要记到对应类别的 “错题本” 里。
  3. 单独打分:最后按类别算正确率,比如 “飞机 90%、猫 50%”,一眼看出模型擅长什么、不擅长什么。

这样就能发现模型的 “偏科” 问题 —— 比如可能对 “汽车”“飞机” 这类形状规则的识别率高,对 “猫”“狗” 这类毛茸茸的识别率低,方便后续针对性改进~

通过可视化模型预测结果看模型真实水平

def imshow(img):img = img / 2 + 0.5  # 反归一化(从[-1,1]回到[0,1])npimg = img.numpy()plt.imshow(np.transpose(npimg, (1, 2, 0)))  # 调整维度顺序(C,H,W → H,W,C)plt.axis('off')  # 关闭坐标轴plt.show()# 获取一批测试图像dataiter = iter(testloader)images, labels = next(dataiter)# 显示图像和真实标签imshow(torchvision.utils.make_grid(images))print('GroundTruth: ', ' '.join('%5s' % classes[labels[j]] for j in range(4)))# 显示预测结果outputs = net(images)_, predicted = torch.max(outputs, 1)print('Predicted: ', ' '.join('%5s' % classes[predicted[j]] for j in range(4)))

这段代码的作用是把模型的预测结果可视化”,让你直观地看到:模型到底把图片认成了什么,和真实结果对不对得上。就像考试后,老师把你的答卷和标准答案一起贴出来给你看,一目了然。

逐句说明

第一部分:定义图片显示工具(def imshow(img):

这是一个 “图片查看器” 函数,专门用来把电脑里的图片数据正确显示出来。

  1. def imshow(img):
    1. 定义一个叫imshow的工具,专门用来显示图片(img就是要显示的图片数据)。
  2. img = img / 2 + 0.5
    1. 反归一化:之前预处理时,为了方便模型训练,把图片的像素值压缩到了[-1, 1](就像把照片调暗了)。这一步是把图片 “还原” 成我们人眼习惯的亮度(像素值变回[0, 1]),否则显示出来会很暗。
  3. npimg = img.numpy()
    1. 把 PyTorch 专用的 “张量” 格式图片,转换成普通的 NumPy 数组(因为显示图片的工具只认识这种格式)。
  4. plt.imshow(np.transpose(npimg, (1, 2, 0)))
    1. 调整图片格式
      1. 电脑存储图片的格式是(颜色通道, 高度, 宽度)(比如 “红 / 绿 / 蓝,28 像素高,28 像素宽”)。
      2. 但人眼看图片的习惯是(高度, 宽度, 颜色通道)(先看有多高多宽,再看颜色)。
      3. 这一步就是把格式转过来,让图片能正常显示(否则会变成奇怪的色块)。
  5. plt.axis('off')
    1. 关闭图片周围的坐标轴(数字和线条),让图片看起来更干净。
  6. plt.show()
    1. 弹出窗口,把处理好的图片显示出来。
第二部分:拿一批测试图片
  1. dataiter = iter(testloader)
    1. 把测试集(testloader)变成一个 “图片迭代器”,就像把一堆照片整理成一本 “相册”,可以一页一页往后翻。
  2. images, labels = next(dataiter)
    1. 从 “相册” 里翻出第一页,得到:
      1. images:这一页的图片(默认一次拿 4 张,后面只看前 4 张)。
      2. labels:这些图片的 “真实标签”(比如第 1 张是猫,第 2 张是汽车)。
第三部分:显示图片和真实标签
  1. imshow(torchvision.utils.make_grid(images))
    1. torchvision.utils.make_grid(images):把这 4 张图片拼成一张 “拼图”(方便一次性看)。
    2. imshow():用上面定义的工具,把这张拼图显示出来(你会看到 4 张测试图片)。
  2. print('GroundTruth: ', ' '.join('%5s' % classes[labels[j]] for j in range(4)))
    1. 打印这 4 张图片的 “真实答案”。
    2. 比如输出 GroundTruth:   cat   car plane   dog,意思是 “这 4 张图实际分别是猫、汽车、飞机、狗”。
    3. %5s 是为了让文字对齐,看起来整齐。
第四部分:显示模型的预测结果
  1. outputs = net(images)
    1. 让训练好的模型(net)“看” 这 4 张图片,输出 “预测分数”(每个类别打个分,分数越高,模型越觉得是这个类别)。
  2. _, predicted = torch.max(outputs, 1)
    1. 从每个图片的 10 个分数里,挑出最高分对应的类别,作为模型的 “最终预测结果”。
    2. 比如第 1 张图 “猫” 的分数最高,就预测它是猫。
  3. print('Predicted: ', ' '.join('%5s' % classes[predicted[j]] for j in range(4)))
    1. 打印模型的 “预测答案”。
    2. 比如输出 Predicted:   cat   car  bird   dog,意思是 “模型认为这 4 张图分别是猫、汽车、鸟、狗”。
    3. 和上面的 “真实答案” 对比,就能看出哪里对了(猫、汽车、狗),哪里错了(飞机被认成了鸟)。

总结:就像 “贴答案对比”

这部分代码做的事,相当于:

  1. 从测试卷里随机抽 4 道题(图片)。
  2. 把题目(图片)和标准答案(真实标签)贴出来。
  3. 再把学生(模型)的答案(预测结果)贴在旁边。
  4. 你一眼就能看出:模型哪些题做对了,哪些题做错了,错得离谱吗?

这样就不用只看干巴巴的正确率数字,能直观感受到模型的 “真实水平”~

实际运行效果:

有点悲剧 只有50% 准确率:

GroundTruth:    cat  ship  ship plane
Predicted:    cat   car plane plane

这要通过多种方法的综合应用,来提高 CIFAR-10 模型的准确性,这就是另外的话题了 本文只是举例说明从数据预处理到模型训练与评估的过程~~~

http://www.dtcms.com/a/290715.html

相关文章:

  • git bash命令不够完善,想整合msys2该怎么办?
  • 02-UE5蓝图初始的三个节点作用
  • 文娱投资的逆势突破:博派资本的文化旅游综合体战略
  • 阿里云宝塔Linux面板相关操作记录
  • 照片to谷歌地球/奥维地图新增功能:导出 GeoJSON 数据
  • 高级技术【Java】【反射】【注解】【动态代理】
  • c++:父类的析构函数定义为纯虚函数注意事项
  • “专属私有云”或“行业公有云(逻辑隔离的公共云专区)”两种主流部署模式到底有什么区别?政务云不就应该是专属的私有云么?政务云是不是不能混用?
  • 网络编程基础:从 OSI 模型到 TCP/IP 协议族的全面解析
  • 【AI高性能网络解析】第三期:数据快递,海量数据跨广域高效传输技术实践
  • 计算机网络:概述层---计算机网络的组成和功能
  • harbor镜像仓库由原来的v2.11.1版本升级到v2.13.1,数据不丢失
  • Taro 生命周期相关 API 详解
  • HTML整理
  • Lists的分批次操作
  • 安卓第一个项目
  • 信息学奥赛一本通 1576:【例 2】选课 | 洛谷 P2014 [CTSC1997] 选课
  • Netty中CompositeByteBuf的使用
  • 位标志法处理多选字段在数据库中的存储方式 查询效率与扩展性之间的权衡
  • https正向代理 GoProxy
  • 苹果最新系统iOS 17的调试和适配方法 - Xcode 14.3.1 真机调试指南
  • How does Misinformation Affect Large Language ModelBehaviors and Preferences?
  • Spring Boot 集成 RabbitMQ:普通队列、延迟队列与死信队列全解析
  • iOS WebView 调试实战 页面跳转失效与历史记录错乱的排查路径
  • 物流链上的智慧觉醒:Deepoc具身智能如何重塑搬运机器人的“空间思维”
  • 达梦数据库JSON_TABLE使用说明
  • grpc: debug: GRPC_TRACE
  • ESP32开发——基于idf框架使用NVS操作存储设备读写
  • 家庭服务具身智能机器人体系架构
  • 一次 POI 版本升级踩坑记录