论文《GhostNet: More Features from Cheap Operations》
1、作用:
Ghost 模块是一种轻量级的特征提取模块,旨在通过廉价操作生成更多特征图,减少计算量的同时保持模型性能。传统卷积神经网络在生成特征图时存在大量冗余计算,Ghost 模块通过将特征图生成过程分解为两个步骤,有效减少了计算复杂度,特别适合移动端和嵌入式设备部署。
2、机制
Ghost 模块的机制主要包括:
通过这种方式,Ghost 模块在保持与传统卷积相似表达能力的同时,将计算量减少到原来的 1/m。
3、独特优势
4、代码
import torch
import torch.nn as nn
class GhostModule(nn.Module):
"""
Ghost模块 - 生成更多特征的轻量级模块
"""
def __init__(self, in_channels, out_channels, kernel_size=1, ratio=2, dw_size=3, stride=1, relu=True):
super().__init__()
self.out_channels = out_channels
init_channels = int(torch.ceil(torch.tensor(out_channels / ratio)))
init_channels = max(1, init_channels)
# 主要卷积
self.primary_conv = nn.Sequential(
nn.Conv2d(in_channels, init_channels, kernel_size, stride,
kernel_size//2, bias=False),
nn.BatchNorm2d(init_channels),
nn.ReLU(inplace=True) if relu else nn.Sequential(),
)
# 廉价操作生成ghost特征
self.cheap_operation = nn.Sequential(
nn.Conv2d(init_channels, init_channels*(ratio-1), dw_size, 1,
dw_size//2, groups=init_channels, bias=False),
nn.BatchNorm2d(init_channels*(ratio-1)),
nn.ReLU(inplace=True) if relu else nn.Sequential(),
)
def forward(self, x):
x1 = self.primary_conv(x)
x2 = self.cheap_operation(x1)
out = torch.cat([x1, x2], dim=1)
return out[:, :self.out_channels, :, :]
# 测试代码
if __name__ == '__main__':
# 实例化Ghost模块
model = GhostModule(in_channels=32, out_channels=64).cuda()
# 创建随机输入张量
input_tensor = torch.randn(2, 32, 32, 32).cuda()
# 前向传播
output_tensor = model(input_tensor)
# 验证输出形状
print(f"输入形状: {input_tensor.shape}")
print(f"输出形状: {output_tensor.shape}") # 预期: torch.Size([2, 64, 32, 32])
论文《CBAM: Convolutional Block Attention Module》
1、作用:
CBAM 是一种轻量级的注意力模块,能够同时关注通道和空间维度上的重要特征。与仅关注通道或空间的注意力机制不同,CBAM 通过串行方式依次应用通道注意力和空间注意力,自适应地增强有意义的特征并抑制无关特征,从而提升模型的表示能力。
2、机制
CBAM 模块的机制主要包括:
3、独特优势
4、代码
import torch
import torch.nn as nn
class ChannelAttention(nn.Module):
"""通道注意力模块"""
def __init__(self, in_channels, reduction_ratio=16):
super().__init__()
self.avg_pool = nn.AdaptiveAvgPool2d(1)
self.max_pool = nn.AdaptiveMaxPool2d(1)
self.fc = nn.Sequential(
nn.Conv2d(in_channels, in_channels // reduction_ratio, 1, bias=False),
nn.ReLU(),
nn.Conv2d(in_channels // reduction_ratio, in_channels, 1, bias=False)
)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
avg_out = self.fc(self.avg_pool(x))
max_out = self.fc(self.max_pool(x))
out = avg_out + max_out
return self.sigmoid(out)
class SpatialAttention(nn.Module):
"""空间注意力模块"""
def __init__(self, kernel_size=7):
super().__init__()
self.conv = nn.Conv2d(2, 1, kernel_size, padding=kernel_size//2, bias=False)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
avg_out = torch.mean(x, dim=1, keepdim=True)
max_out, _ = torch.max(x, dim=1, keepdim=True)
out = torch.cat([avg_out, max_out], dim=1)
out = self.conv(out)
return self.sigmoid(out)
class CBAM(nn.Module):
"""CBAM - 卷积块注意力模块"""
def __init__(self, in_channels, reduction_ratio=16, kernel_size=7):
super().__init__()
self.channel_att = ChannelAttention(in_channels, reduction_ratio)
self.spatial_att = SpatialAttention(kernel_size)
def forward(self, x):
x = x * self.channel_att(x)
x = x * self.spatial_att(x)
return x
# 测试代码
if __name__ == '__main__':
# 实例化CBAM模块
model = CBAM(in_channels=64).cuda()
# 创建随机输入张量
input_tensor = torch.randn(2, 64, 32, 32).cuda()
# 前向传播
output_tensor = model(input_tensor)
# 验证输出形状
print(f"输入形状: {input_tensor.shape}")
print(f"输出形状: {output_tensor.shape}") # 预期: torch.Size([2, 64, 32, 32])
论文《An intriguing failing of convolutional neural networks and the CoordConv solution》
1、作用:
CoordConv 是一种改进的卷积操作,通过在输入特征图中添加坐标信息,帮助卷积神经网络更好地理解空间关系。传统卷积操作对输入的平移具有等变性,无法显式表示空间位置信息,这使得网络在处理需要精确空间理解的任务(如目标检测、语义分割)时存在困难。CoordConv 通过简单地在输入特征图中添加坐标通道,显著提升了网络对空间关系的建模能力。
2、机制
CoordConv 模块的机制主要包括:
通过这种方式,CoordConv 使网络能够显式地利用空间位置信息,提高对空间变换的敏感性。
3、独特优势
4、代码
import torch
import torch.nn as nn
import torch.nn.functional as F
class AddCoords(nn.Module):
"""添加坐标通道"""
def __init__(self, with_r=False):
super().__init__()
self.with_r = with_r
def forward(self, x):
batch_size, _, height, width = x.size()
# 创建坐标通道
x_coords = torch.linspace(-1, 1, width).repeat(height, 1).to(x.device)
y_coords = torch.linspace(-1, 1, height).repeat(width, 1).t().to(x.device)
x_coords = x_coords.unsqueeze(0).unsqueeze(0)
y_coords = y_coords.unsqueeze(0).unsqueeze(0)
# 添加到输入张量
out = torch.cat([x, x_coords.repeat(batch_size, 1, 1, 1),
y_coords.repeat(batch_size, 1, 1, 1)], dim=1)
# 可选:添加半径坐标
if self.with_r:
rr = torch.sqrt(torch.pow(x_coords, 2) + torch.pow(y_coords, 2))
out = torch.cat([out, rr.repeat(batch_size, 1, 1, 1)], dim=1)
return out
class CoordConv(nn.Module):
"""CoordConv模块"""
def __init__(self, in_channels, out_channels, kernel_size,
stride=1, padding=0, dilation=1, groups=1, bias=True, with_r=False):
super().__init__()
self.add_coords = AddCoords(with_r)
in_channels += 2 # 添加x和y坐标通道
if with_r:
in_channels += 1 # 添加半径通道
self.conv = nn.Conv2d(in_channels, out_channels, kernel_size,
stride, padding, dilation, groups, bias)
def forward(self, x):
out = self.add_coords(x)
out = self.conv(out)
return out
# 测试代码
if __name__ == '__main__':
# 实例化CoordConv模块
model = CoordConv(in_channels=3, out_channels=16, kernel_size=3, padding=1).cuda()
# 创建随机输入张量
input_tensor = torch.randn(2, 3, 32, 32).cuda()
# 前向传播
output_tensor = model(input_tensor)
# 验证输出形状
print(f"输入形状: {input_tensor.shape}")
print(f"输出形状: {output_tensor.shape}") # 预期: torch.Size([2, 16, 32, 32])
论文《DropBlock: A regularization method for convolutional networks》
1、作用:
DropBlock 是一种专为卷积神经网络设计的正则化方法,通过随机丢弃连续区域(块)的特征,强制网络学习更鲁棒的特征表示。传统的 Dropout 方法在全连接层中效果良好,但在卷积层中效果有限,因为卷积层的特征具有空间相关性,随机丢弃单个神经元无法有效正则化。DropBlock 通过丢弃整个区域的特征,模拟了物体部分被遮挡的情况,提高了模型的泛化能力。
2、机制
DropBlock 模块的机制主要包括:
3、独特优势
4、代码
import torch
import torch.nn as nn
import torch.nn.functional as F
class DropBlock(nn.Module):
"""DropBlock正则化模块"""
def __init__(self, block_size, keep_prob):
super().__init__()
self.block_size = block_size
self.keep_prob = keep_prob
def forward(self, x):
if not self.training or self.keep_prob == 1.0:
return x
# 计算gamma值
gamma = (1.0 - self.keep_prob) / (self.block_size ** 2)
# 生成mask
batch_size, channels, height, width = x.size()
mask_shape = (batch_size, channels, height - (self.block_size - 1), width - (self.block_size - 1))
mask = torch.bernoulli(torch.full(mask_shape, gamma, device=x.device))
# 扩展mask到block_size
mask = F.pad(mask, (self.block_size//2, self.block_size//2, self.block_size//2, self.block_size//2))
mask = F.max_pool2d(mask, kernel_size=self.block_size, stride=1, padding=self.block_size//2)
mask = 1 - mask
# 应用mask并归一化
countM = mask.numel()
count_ones = mask.sum()
x = x * mask * (countM / count_ones)
return x
# 测试代码
if __name__ == '__main__':
# 实例化DropBlock模块
model = DropBlock(block_size=5, keep_prob=0.9).cuda()
# 创建随机输入张量
input_tensor = torch.randn(2, 32, 32, 32).cuda()
# 前向传播(训练模式)
model.train()
output_train = model(input_tensor)
# 前向传播(推理模式)
model.eval()
output_eval = model(input_tensor)
# 验证输出形状
print(f"输入形状: {input_tensor.shape}")
print(f"训练模式输出形状: {output_train.shape}") # 预期: torch.Size([2, 32, 32, 32])
print(f"推理模式输出形状: {output_eval.shape}") # 预期: torch.Size([2, 32, 32, 32])
论文《Searching for Activation Functions》
1、作用: Swish 是一种平滑的非线性激活函数,形式为\(f(x) = x \cdot \sigma(x)\),其中\(\sigma(x)\)是 Sigmoid 函数。与 ReLU 相比,Swish 具有平滑性和非单调性,能够在某些情况下提供更好的性能。研究表明,Swish 在深层神经网络中表现优于 ReLU,特别是在 ImageNet 分类和机器翻译等任务上。
2、机制 Swish 激活函数的机制主要包括:
3、独特优势
4、代码
import torch
import torch.nn as nn
class Swish(nn.Module):
"""Swish激活函数"""
def __init__(self):
super().__init__()
def forward(self, x):
return x * torch.sigmoid(x)
# 测试代码
if __name__ == '__main__':
# 实例化Swish激活函数
model = Swish().cuda()
# 创建随机输入张量
input_tensor = torch.randn(2, 32, 32, 32).cuda()
# 前向传播
output_tensor = model(input_tensor)
# 验证输出形状
print(f"输入形状: {input_tensor.shape}")
print(f"输出形状: {output_tensor.shape}") # 预期: torch.Size([2, 32, 32, 32])