应付深度学习期末三级项目,突发奇想从0构建模型,花费四天写训练,测试。由于基本是纯手写调试打印搭建出来,所以未必代码写的很流畅,欢迎大家改进完善。
一、Vgg16搭建
首先写的第一个网络是VGG16,按照书上的定义手写网络,下图是官方定义




可以看出Vgg16的网络结构非常简单,由13个卷积层加3个全连接层组成,输入224*224的三通道图片。非常纯的网络,卷积->激活函数->池化。最后拉成一维排列以进行全连接输出。其中一定要加入BN!!!!,否则模型训练效果极差且不收敛,BN为批归一化将图像数值压缩至0-1之间,BN的作用是加速训练,提升模型泛化能力,实际测试是必不可少的模块。
代码如下
from torch import nn
# -----------------------------------------------#
# 2024.10.14
# 自建base VGG16
# -----------------------------------------------#
class VGG16(nn.Module):
def __init__(self, num_classes):
super(VGG16, self).__init__()
self.conv = nn.Sequential(
nn.Conv2d(3, 64, kernel_size=3, padding=1),
nn.BatchNorm2d(64),
nn.ReLU(inplace=True),
nn.Conv2d(64, 64, kernel_size=3, padding=1),
nn.BatchNorm2d(64),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
nn.Conv2d(64, 128, kernel_size=3, padding=1),
nn.BatchNorm2d(128),
nn.ReLU(inplace=True),
nn.Conv2d(128, 128, kernel_size=3, padding=1),
nn.BatchNorm2d(128),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
nn.Conv2d(128, 256, kernel_size=3, padding=1),
nn.BatchNorm2d(256),
nn.ReLU(inplace=True),
nn.Conv2d(256, 256, kernel_size=3, padding=1),
nn.BatchNorm2d(256),
nn.ReLU(inplace=True),
nn.Conv2d(256, 256, kernel_size=3, padding=1),
nn.BatchNorm2d(256),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
nn.Conv2d(256, 512, kernel_size=3, padding=1),
nn.BatchNorm2d(512),
nn.ReLU(inplace=True),
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.BatchNorm2d(512),
nn.ReLU(inplace=True),
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.BatchNorm2d(512),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.BatchNorm2d(512),
nn.ReLU(inplace=True),
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.BatchNorm2d(512),
nn.ReLU(inplace=True),
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.BatchNorm2d(512),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2)
)
self.dense = nn.Sequential(
nn.Flatten(),
nn.Linear(512 * 7 * 7, 4096),
nn.Dropout(0.4),
nn.ReLU(inplace=True),
nn.Linear(4096, 4096),
nn.Dropout(0.4),
nn.ReLU(inplace=True),
nn.Linear(4096, num_classes)
)
def forward(self, x):
x = self.conv(x)
x = self.dense(x)
return x
################################################################################
# 测试模型
# model = VGG16(num_classes=2)
# input_tensor = torch.randn(1, 3, 224, 224) # 假设输入为一张 224x224 的 RGB 图像
# output = model(input_tensor)
# print(output.shape) # 输出的形状应为 (1, 2)
# print(output)
################################################################################
二、Resnet50
resnet精髓在于引入了残差连接,缓解了梯度消失的问题,通过坐“电梯”连接输入输出联动
在层数逐层加深的情况反向传播时梯度会无线趋近于0,比如第一层0.1,第二层0.01,以此类推趋近0梯度消失,但是如果此时将输入1加入,1+趋向0,此时梯度不为0。这块可以看下反向传播,推导下。
书上定义如下

两种残差连接结构图
模型参数的计算=3*3*64*64+3*3*64*64

模型参数的计算=1*1*256*64+3*3*64*64+1*1*64*256

import torch
import torch.nn as nn
# -----------------------------------------------#
# 2024.10.22
# resnet50
# -----------------------------------------------#
# 定义Residual Block
class ResidualBlock(nn.Module):
def __init__(self, in_channels, out_channels, stride=1, downsample=None):
super(R


9719

被折叠的 条评论
为什么被折叠?



