卷积神经网络(LeNet)

(5)改成relu激活函数
image
损失下降的更快,测试精度略低于训练精度
(6)增加一个卷积层

net = nn.Sequential(
    nn.Conv2d(1, 6, kernel_size=5, padding=2), nn.ReLU(),
    nn.MaxPool2d(kernel_size=2, stride=2),
    nn.Conv2d(6, 16, kernel_size=5), nn.ReLU(),
    nn.Conv2d(16, 18,kernel_size=3, padding=1  ),
    nn.MaxPool2d(kernel_size=2, stride=2),
    nn.Flatten(),
    nn.Linear(18 * 5 * 5, 120), nn.Sigmoid(),
    nn.Linear(120, 84), nn.Sigmoid(),
    nn.Linear(84, 10))

image

16 * 5 * 5那块就是计算出来的,那里需要改一下数据

为什么我用MaxPool2d就不收敛而AvgPool2d就会收敛呢?求教

随便设计的,激活层换ReLU,池化换最大池化。
同时多来了一个卷积层和一个全连接层,
1×28×28 → 16×28×28 → 16×14×14 → 32×10×10 → 32×5×5 → 64×3×3 → 256 → 128 → 64 → 10
三层卷积最后是得到64×3×3的特征图(我感觉这种又小又深,挺好),跑出来确实效果不错。

6个是输出通道,输入通道是1个,因为Conv2d的参数就是(in_channels, out_channels)。

以此为例:

# 假设输入 X 是一个形状为 (batch_size, channels, height, width) 的张量
batch_size, channels, height, width = 16, 3, 30, 30
X = torch.randn(batch_size, channels, height, width)
net = nn.Sequential(
    nn.Conv2d(channels, 16, kernel_size=3, stride=1, padding=1),  # [16, 16, 30, 30]
    nn.ReLU(),  # [16, 16, 30, 30]
    nn.MaxPool2d(kernel_size=2, stride=2),  # [16, 16, 15, 15]
    nn.BatchNorm2d(16),  # [16, 16, 15, 15]
    nn.Flatten(),  # [16, 3600]
    nn.Linear(16 * (height//2) * (width//2), 64),  # [16, 64]
    nn.ReLU(),  # [16, 64]
    nn.Linear(64, 10),  # [16, 10]
    nn.Softmax(dim=1)  # [16, 10]
)

因为新用户只能插入一张图,很抱歉只能给出这一幅最重要的图,你可以继续在官网上查询。torch.nn — PyTorch 2.2 documentation

真的就是个玄学,层数增加,大家都知道会增加模型的拟合能力,但具体怎么解释没人能解释清楚。 :face_holding_back_tears:

在每个显示后面加上d2l.plt.pause(0.01)

其实在小规模数据时不见得GPU就比CPU快多少,GPU是把数据拷贝到显卡里然后用里面的多个运算核计算的,运算核会从显卡反复取数据,这也地花时间,所以如果数据量不够大,或者运算不能大规模集中在从显卡取少量次数时,GPU将无法发挥出它的并行优势,举个例子把,你有1000个运算核,然后显卡里有1000个字节数据,每个字节数据给对应的核然后进行各种操作最快,但如果你只有10个字节数据,则给10个运算核,如果接下来你运算几下,就把结果丢回显卡,然后再取,再算,再放回去,然后操作完送回CPU,再取10个数据进入GPU,那么一套下来时间将是前者的百倍起步


修改了讨论区的部分代码,每层的输出和卷积可视化网站内的效果相同
这个报错应该没有影响,但是不知道怎么去掉,显示maxpool2d层没有报错


这个报错有人遇到过吗

1 Like

为什么这里反向传播可以直接用l.backward(),而不用l.mean()或者l.sum?


在训练集上精度0.932,但测试集上直接达到1.000了。正常来说两者数值应该差距不大,造成这个结果的是什么呢?

改成MaxPool2d后不会收敛,需要调整学习率,你把0.9改成0.1就可以了

中间会占用缓存,等你模型运行完就自动释放掉了

以下是我设计的网络:

mynet = nn.Sequential(
    nn.Conv2d(1, 6, kernel_size=5, padding=2), nn.ReLU(),
    nn.MaxPool2d(kernel_size=2, stride=2),
    nn.Conv2d(6, 16, kernel_size=5), nn.ReLU(),
    nn.MaxPool2d(kernel_size=2, stride=2),
    nn.Flatten(),
    nn.Linear(16 * 5 * 5, 120), nn.ReLU(),
    nn.Linear(120, 84), nn.ReLU(),
    nn.Linear(84, 10))
lr, num_epochs = 0.1, 10
train_ch6(mynet, train_iter, test_iter, num_epochs, lr, d2l.try_gpu())

显示数据在进入第一层和第二层的图像

import torchvision
from torchvision import transforms
from torch.utils import data
trans = transforms.ToTensor()
mnist_test = torchvision.datasets.FashionMNIST(
    root="../data", train=False, transform=trans, download=True)
# mnist_test是一个10000行的数据,每一行是一个tuple (tensor 和标签),每个tensor是一张图片(1,28,28),mnist_test[i][0]表示第i张图片
X, _ = next(iter(data.DataLoader(mnist_test, batch_size=4)))
# DataLoader 返回 一个迭代器 指向一个 batch_size的数据
# X是一个tensor (bbatch_size,(img size))
d2l.show_images(X.reshape(4,28,28),1,4,titles=['input']*4)
X, _ = next(iter(data.DataLoader(mnist_test, batch_size=4)))
X=mynet[:1](X.to('cuda'))
X=X.to('cpu')
d2l.show_images(X[:,0:3,:,:].permute(1,0,2,3).detach().reshape(12,28,28),3,4,titles=['Conv2d']*12)
X, _ = next(iter(data.DataLoader(mnist_test, batch_size=4)))
X=mynet[:2](X.to('cuda'))
X=X.to('cpu')
d2l.show_images(X[:,0:3,:,:].permute(1,0,2,3).detach().reshape(12,28,28),3,4,titles=['ReLU']*12)