network.py
初始化神经网络中的权重和偏置
def init_weights(net, init_type='normal', gain=0.02):
# 定义初始化函数
def init_func(m):
# 获取当前模块的类名
classname = m.__class__.__name__
# 如果模块有权重,并且是卷积层或全连接层
if hasattr(m, 'weight') and (classname.find('Conv') != -1 or classname.find('Linear') != -1):
# 根据指定的初始化类型进行权重初始化
if init_type == 'normal':
init.normal_(m.weight.data, 0.0, gain) # 正态分布初始化
elif init_type == 'xavier':
init.xavier_normal_(m.weight.data, gain=gain) # Xavier初始化
elif init_type == 'kaiming':
init.kaiming_normal_(m.weight.data, a=0, mode='fan_in') # Kaiming初始化
elif init_type == 'orthogonal':
init.orthogonal_(m.weight.data, gain=gain) # 正交初始化
else:
# 如果初始化类型不支持,抛出异常
raise NotImplementedError('initialization method [%s] is not implemented' % init_type)
# 如果模块有偏置项,则将其初始化为0
if hasattr(m, 'bias') and m.bias is not None:
init.constant_(m.bias.data, 0.0)
# 如果模块是BatchNorm2d层
elif classname.find('BatchNorm2d') != -1:
init.normal_(m.weight.data, 1.0, gain) # 权重初始化为正态分布
init.constant_(m.bias.data, 0.0) # 偏置初始化为0
# 打印当前使用的初始化类型
print('initialize network with %s' % init_type)
# 将初始化函数应用于网络的所有模块
net.apply(init_func)
这段代码的作用是初始化神经网络中的权重和偏置。具体来说:
函数定义:
init_weights
函数接收一个网络对象net
,一个初始化类型init_type
(如正态分布、Xavier、Kaiming 等),以及一个增益参数gain
。初始化函数:内部定义的
init_func
函数会遍历网络中的每一个层(模块),并根据层的类型初始化权重和偏置。权重初始化:
- 对于卷积层(
Conv
)和全连接层(Linear
),根据选择的初始化方法(如正态、Xavier、Kaiming、正交等)初始化权重。- 如果有偏置项,将其初始化为零。
BatchNorm层:对于批归一化层(
BatchNorm2d
),权重初始化为正态分布,偏置初始化为零。应用初始化:最后,使用
net.apply(init_func)
将初始化函数应用到整个网络,确保每一层都按照指定方式初始化。
卷积块
class conv_block(nn.Module):
def __init__(self, ch_in, ch_out):
# 初始化卷积块,接收输入通道数和输出通道数
super(conv_block, self).__init__()
# 定义一个顺序容器,包含两个卷积层和相关操作
self.conv = nn.Sequential(
nn.Conv2d(ch_in, ch_out, kernel_size=3, stride=1, padding=1, bias=True), # 第一个卷积层
nn.BatchNorm2d(ch_out), # 批归一化层,用于提高训练稳定性
nn.ReLU(inplace=True), # ReLU激活函数,使用原地操作以节省内存
nn.Conv2d(ch_out, ch_out, kernel_size=3, stride=1, padding=1, bias=True), # 第二个卷积层
nn.BatchNorm2d(ch_out), # 再次应用批归一化
nn.ReLU(inplace=True) # 再次使用ReLU激活函数
)
这段代码定义了一个卷积块(
conv_block
)的神经网络模块,通常用于构建卷积神经网络(CNN)。具体作用如下:
卷积层:包含两个卷积层,每个卷积层使用 3x3 的卷积核,输入和输出的通道数可以根据构造函数的参数设置。这种设计有助于提取图像特征。
批归一化:每个卷积层后面跟随一个批归一化层(
BatchNorm2d
),用于规范化输出,提高训练的稳定性,并加速收敛。激活函数:每个卷积层后面使用 ReLU 激活函数,增加网络的非线性能力。
输入和输出通道:构造函数接受输入通道数(
ch_in
)和输出通道数(ch_out
),允许在不同层之间灵活配置。
上采样卷积块
def forward(self, x):
# 将输入 x 通过卷积块处理
x = self.conv(x)
# 返回处理后的输出
return x
class up_conv(nn.Module):
def __init__(self, ch_in, ch_out):
# 初始化上采样卷积块,接收输入通道数和输出通道数
super(up_conv, self).__init__()
# 定义一个顺序容器,包含上采样和卷积层
self.up = nn.Sequential(
nn.Upsample(scale_factor=2), # 上采样,将特征图尺寸扩大 2 倍
nn.Conv2d(ch_in, ch_out, kernel_size=3, stride=1, padding=1, bias=True), # 卷积层,调整通道数
nn.BatchNorm2d(ch_out), # 批归一化层,规范化输出
nn.ReLU(inplace=True) # ReLU激活函数,增加非线性
)
def forward(self, x):
# 将输入 x 通过上采样卷积块处理
x = self.up(x)
# 返回处理后的输出
return x
这段代码定义了一个上采样卷积块(
up_conv
),主要用于图像处理和深度学习中的卷积神经网络(CNN)。具体作用如下:
上采样:通过
nn.Upsample(scale_factor=2)
,将输入特征图的尺寸扩大一倍。这在图像分割或生成任务中很常见,用于恢复图像的空间分辨率。卷积操作:
nn.Conv2d
层负责对上采样后的特征图进行卷积处理,提取特征并调整通道数。批归一化:
nn.BatchNorm2d
层用于规范化卷积层的输出,帮助提高训练的稳定性,加速收敛。激活函数:
nn.ReLU
激活函数引入非线性,使网络能够学习更复杂的特征。
循环块
class Recurrent_block(nn.Module):
def __init__(self, ch_out, t=2):
# 初始化循环块,接收输出通道数和循环次数
super(Recurrent_block, self).__init__()
self.t = t # 循环次数
self.ch_out = ch_out # 输出通道数
# 定义卷积序列,包括卷积、批归一化和ReLU激活
self.conv = nn.Sequential(
nn.Conv2d(ch_out, ch_out, kernel_size=3, stride=1, padding=1, bias=True), # 卷积层
nn.BatchNorm2d(ch_out), # 批归一化层
nn.ReLU(inplace=True) # ReLU激活函数
)
def forward(self, x):
# 前向传播函数
for i in range(self.t): # 根据 t 的值进行循环
if i == 0:
x1 = self.conv(x) # 第一次循环,直接对输入 x 进行卷积操作
# 在后续循环中,将当前输入 x 和上一层的输出 x1 相加,然后进行卷积
x1 = self.conv(x + x1)
return x1 # 返回最终的输出
这段代码实现了一个循环块(Recurrent Block),其主要功能包括:
循环处理:该块通过指定的循环次数
t
,重复对输入进行卷积操作。每次迭代都将当前输入与上一层的输出相加,从而实现特征的累积。残差连接:在
forward
方法中,第一次循环将输入x
经过卷积得到x1
,后续循环则将x1
与输入x
相加后再进行卷积。这种方式类似于残差网络(ResNet)的设计,帮助缓解深度网络的梯度消失问题。非线性特征学习:通过卷积层、批归一化和ReLU激活函数,该块能够学习复杂的非线性特征,适用于图像处理任务,如图像重建或图像分割。
RRCNN和单层卷积块
class RRCNN_block(nn.Module):
def __init__(self, ch_in, ch_out, t=2):
# 初始化RRCNN块,接收输入通道数、输出通道数和循环次数
super(RRCNN_block, self).__init__()
# 定义两个循环块(Recurrent Block)
self.RCNN = nn.Sequential(
Recurrent_block(ch_out, t=t), # 第一个循环块
Recurrent_block(ch_out, t=t) # 第二个循环块
)
# 定义1x1卷积,用于调整输入通道数
self.Conv_1x1 = nn.Conv2d(ch_in, ch_out, kernel_size=1, stride=1, padding=0)
def