残差网络(ResNet)

1.GoogleNet中的Inception块和ResNet中的残差块是两种不同的神经网络架构设计,用于解决深度神经网络中的梯度消失和网络退化问题。它们的主要区别在于如何处理网络的信息流和特征传递。
Inception块旨在通过同时使用多个不同大小的卷积核和池化层来捕获不同尺度的特征。Inception块内部的各个卷积分支并行进行,然后将它们的输出在特征维度上连接起来,形成一个更丰富的特征表示。但是,这种平行结构会导致参数数量急剧增加,可能会造成过拟合问题。
残差块的核心思想是引入跳跃连接,允许信息在网络中跳过几层,从而使网络拟合残差映射。这种残差映射更容易优化,且可以保留原始信息,有助于解决梯度消失问题,并允许训练更深的网络。
删除Inception块中的一些路径之后,它们与ResNet中的残差块可以有一些相似之处。特别是当Inception块中的某些分支被删除时,剩余的分支可以看作是具有跳跃连接的卷积结构,类似于残差块。这种情况下,Inception块的一部分变得类似于ResNet中的残差块,都具有了跨层直接传递信息的能力。

2 Likes

model, optimizer, dataset, resize = resnet-50, adam, fashion_mnist, 96
lr, num_epochs, batch_size = 0.001, 10, 64
epoch 9, loss 0.159, train acc 0.941, test acc 0.923

没看到代码里有将权重和偏置参数设成0,那里有恒等映射呢?

你理解错他的意思了,他是指不需要传这个参数,但是在reshape X时还是使用的1x1卷积层

这个模型要怎么跑呢?

X = torch.rand((1, 3, 224, 224))
resnet152(X)

这样会报错诶

RuntimeError Traceback (most recent call last)
Cell In[9], line 2
1 lr, num_epochs, batch_size = 0.05, 10, 256
----> 2 train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size, resize=96)
3 d2l.train_ch6(net, train_iter, test_iter, num_epochs, lr, d2l.try_gpu())

File ~\miniconda3\Lib\site-packages\d2l\torch.py:196, in load_data_fashion_mnist(batch_size, resize)
194 trans.insert(0, transforms.Resize(resize))
195 trans = transforms.Compose(trans)
→ 196 mnist_train = torchvision.datasets.FashionMNIST(
197 root=“…/data”, train=True, transform=trans, download=True)
198 mnist_test = torchvision.datasets.FashionMNIST(
199 root=“…/data”, train=False, transform=trans, download=True)
200 return (data.DataLoader(mnist_train, batch_size, shuffle=True,
201 num_workers=get_dataloader_workers()),
202 data.DataLoader(mnist_test, batch_size, shuffle=False,
203 num_workers=get_dataloader_workers()))

File ~\miniconda3\Lib\site-packages\torchvision\datasets\mnist.py:99, in MNIST.init(self, root, train, transform, target_transform, download)
96 return
98 if download:
—> 99 self.download()
101 if not self._check_exists():
102 raise RuntimeError(“Dataset not found. You can use download=True to download it”)

File ~\miniconda3\Lib\site-packages\torchvision\datasets\mnist.py:187, in MNIST.download(self)
185 try:
186 print(f"Downloading {url}“)
→ 187 download_and_extract_archive(url, download_root=self.raw_folder, filename=filename, md5=md5)
188 except URLError as error:
189 print(f"Failed to download (trying next):\n{error}”)

File ~\miniconda3\Lib\site-packages\torchvision\datasets\utils.py:378, in download_and_extract_archive(url, download_root, extract_root, filename, md5, remove_finished)
375 if not filename:
376 filename = os.path.basename(url)
→ 378 download_url(url, download_root, filename, md5)
380 archive = os.path.join(download_root, filename)
381 print(f"Extracting {archive} to {extract_root}")

File ~\miniconda3\Lib\site-packages\torchvision\datasets\utils.py:151, in download_url(url, root, filename, md5, max_redirect_hops)
149 # check integrity of downloaded file
150 if not check_integrity(fpath, md5):
→ 151 raise RuntimeError(“File not found or corrupted.”)

RuntimeError: File not found or corrupted.

这是有什么问题啊 :face_with_head_bandage:

你试过么?我觉着应该不会吧,net就算在GPU上,但应该也只是里面的参数在GPU上吧,其他的一些操作还是在CPU上。

你这个里面的卷积层数目不对吧?b2 b3 b4 b5分别应该有3 4 6 3个neck吧?

你这个是 激活 规范 卷积,人家题目是改成 规范 激活 卷积

把if语句放init里,在我自己测试的时候没感觉到有什么变化。原来花了85.1s,改了之后花了85.4s,
class Residual(nn.Module): #@save
def init(self, input_channels,num_channels,use_1x1conv = False,strides = 1):
super().init()
self.conv1 = nn.Conv2d(input_channels,num_channels,kernel_size=3,padding=1,stride=strides)
self.conv2 = nn.Conv2d(num_channels,num_channels,kernel_size=3,padding=1)
if use_1x1conv:
self.conv3 = nn.Conv2d(input_channels,num_channels,kernel_size=1,stride=strides)
else:
self.conv3 = nn.Identity()
self.bn1 = nn.BatchNorm2d(num_channels)
self.bn2 = nn.BatchNorm2d(num_channels)

def forward(self,X):
    Y = F.relu(self.bn1(self.conv1(X)))
    Y = self.bn2(self.conv2(Y))
    Y += self.conv3(X)
    return F.relu(Y)

什么时候用F.relu或者nn.ReLU,有区别吗?

if use_1x1conv:
            self.conv3 = nn.Conv2d(input_channels, num_channels,
                                   kernel_size=1, stride=strides)

对输入使用1*1,步长为2的卷积,不是相当于把“偶数位像素”的信息全部丢弃了吗?这样跟恒等映射不就矛盾了吗?

练习4中的改进弄了之后反而性能更差了,原本有0.92,改完只有0.91