56、Ghost 模塊
論文《GhostNet: More Features from Cheap Operations》
1、作用:
Ghost 模塊是一種輕量級的特征提取模塊,旨在通過廉價操作生成更多特征圖,減少計算量的同時保持模型性能。傳統卷積神經網絡在生成特征圖時存在大量冗余計算,Ghost 模塊通過將特征圖生成過程分解為兩個步驟,有效減少了計算復雜度,特別適合移動端和嵌入式設備部署。
2、機制
Ghost 模塊的機制主要包括:
- 初始特征提取:使用少量卷積核(約為傳統卷積核數量的 1/m)生成初始特征圖,這些特征圖包含主要信息。
- 廉價變換生成額外特征:對初始特征圖應用一系列簡單的線性變換(如深度可分離卷積),生成額外的 “ghost” 特征圖,這些特征圖捕獲了原始特征圖的補充信息。
- 特征拼接:將初始特征圖和生成的 ghost 特征圖拼接在一起,形成最終的輸出特征圖。
通過這種方式,Ghost 模塊在保持與傳統卷積相似表達能力的同時,將計算量減少到原來的 1/m。
3、獨特優勢
- 計算高效:Ghost 模塊的計算復雜度顯著低于傳統卷積,例如在 ImageNet 分類任務中,GhostNet 的 FLOPs 比 MobileNetV3 減少了約 30%,但準確率相當。
- 輕量級設計:引入的參數數量極少,適合資源受限的設備。
- 通用性強:可以替代任何標準卷積層,無縫集成到現有的神經網絡架構中。
4、代碼
import torch
import torch.nn as nnclass 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_channelsinit_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])
57、CBAM(Convolutional Block Attention Module)
論文《CBAM: Convolutional Block Attention Module》
1、作用:
CBAM 是一種輕量級的注意力模塊,能夠同時關注通道和空間維度上的重要特征。與僅關注通道或空間的注意力機制不同,CBAM 通過串行方式依次應用通道注意力和空間注意力,自適應地增強有意義的特征并抑制無關特征,從而提升模型的表示能力。
2、機制
CBAM 模塊的機制主要包括:
- 通道注意力:通過全局最大池化和全局平均池化分別提取特征的通道統計信息,然后通過共享的多層感知機(MLP)處理這兩種統計信息,最后將結果相加并通過 Sigmoid 函數生成通道注意力權重。
- 空間注意力:在通道注意力的基礎上,對特征圖應用空間注意力。通過對通道維度進行最大池化和平均池化,然后將這兩個結果拼接并通過一個卷積層生成空間注意力權重。
- 特征重標定:將通道注意力權重和空間注意力權重依次應用到原始特征圖上,實現對特征的自適應增強和抑制。
3、獨特優勢
- 雙重注意力機制:同時關注通道和空間維度上的重要信息,比單一維度的注意力機制更全面。
- 輕量級設計:引入的參數和計算開銷極少,例如在 ResNet-50 中集成 CBAM 僅增加約 0.1% 的參數。
- 廣泛適用性:可以輕松集成到各種卷積神經網絡架構中,在圖像分類、目標檢測和語義分割等任務上均有顯著性能提升。
4、代碼
import torch
import torch.nn as nnclass 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_outreturn 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])
58、CoordConv 模塊
論文《An intriguing failing of convolutional neural networks and the CoordConv solution》
1、作用:
CoordConv 是一種改進的卷積操作,通過在輸入特征圖中添加坐標信息,幫助卷積神經網絡更好地理解空間關系。傳統卷積操作對輸入的平移具有等變性,無法顯式表示空間位置信息,這使得網絡在處理需要精確空間理解的任務(如目標檢測、語義分割)時存在困難。CoordConv 通過簡單地在輸入特征圖中添加坐標通道,顯著提升了網絡對空間關系的建模能力。
2、機制
CoordConv 模塊的機制主要包括:
- 坐標添加:在輸入特征圖的基礎上,添加兩個額外的通道,分別表示每個像素的歸一化 x 坐標和 y 坐標。例如,對于一個 H×W 的特征圖,添加的 x 坐標通道在所有行上的值為 [0/W, 1/W, ..., (W-1)/W],y 坐標通道在所有列上的值為 [0/H, 1/H, ..., (H-1)/H]。
- 標準卷積:在添加了坐標信息的特征圖上應用標準卷積操作。
通過這種方式,CoordConv 使網絡能夠顯式地利用空間位置信息,提高對空間變換的敏感性。
3、獨特優勢
- 簡單高效:只需在輸入特征圖中添加兩個通道,幾乎不增加計算復雜度和參數數量。
- 提升性能:在多個任務(如目標檢測、語義分割、姿態估計)上,CoordConv 能夠顯著提升模型性能,例如在 COCO 目標檢測任務中,使用 CoordConv 的網絡 mAP 提升了 2-3 個點。
- 廣泛適用性:可以替代任何標準卷積層,無縫集成到現有的神經網絡架構中。
4、代碼
import torch
import torch.nn as nn
import torch.nn.functional as Fclass AddCoords(nn.Module):"""添加坐標通道"""def __init__(self, with_r=False):super().__init__()self.with_r = with_rdef 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 outclass 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])
59、DropBlock 模塊
論文《DropBlock: A regularization method for convolutional networks》
1、作用:
DropBlock 是一種專為卷積神經網絡設計的正則化方法,通過隨機丟棄連續區域(塊)的特征,強制網絡學習更魯棒的特征表示。傳統的 Dropout 方法在全連接層中效果良好,但在卷積層中效果有限,因為卷積層的特征具有空間相關性,隨機丟棄單個神經元無法有效正則化。DropBlock 通過丟棄整個區域的特征,模擬了物體部分被遮擋的情況,提高了模型的泛化能力。
2、機制
DropBlock 模塊的機制主要包括:
- 塊丟棄:在訓練過程中,DropBlock 隨機選擇一些區域(塊),并將這些區域內的所有特征值置為 0。塊的大小通常是超參數,控制丟棄區域的規模。
- 自適應丟棄率:DropBlock 的丟棄率會隨著訓練進行而逐漸調整,通常在訓練初期使用較低的丟棄率,在訓練后期使用較高的丟棄率。
- 反向傳播:在反向傳播過程中,被丟棄的區域對梯度沒有貢獻,從而實現正則化效果。
3、獨特優勢
- 更有效正則化:相較于傳統 Dropout,DropBlock 在卷積神經網絡中能更有效地防止過擬合,提高模型泛化能力。
- 提升魯棒性:通過模擬物體部分被遮擋的情況,DropBlock 使模型學習到更具魯棒性的特征表示,在測試時對遮擋和噪聲更具抵抗力。
- 易于實現:DropBlock 可以很容易地集成到現有的神經網絡中,只需替換傳統的 Dropout 層。
4、代碼
import torch
import torch.nn as nn
import torch.nn.functional as Fclass DropBlock(nn.Module):"""DropBlock正則化模塊"""def __init__(self, block_size, keep_prob):super().__init__()self.block_size = block_sizeself.keep_prob = keep_probdef 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)# 生成maskbatch_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_sizemask = 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])
60、Swish 激活函數
論文《Searching for Activation Functions》
1、作用: Swish 是一種平滑的非線性激活函數,形式為\(f(x) = x \cdot \sigma(x)\),其中\(\sigma(x)\)是 Sigmoid 函數。與 ReLU 相比,Swish 具有平滑性和非單調性,能夠在某些情況下提供更好的性能。研究表明,Swish 在深層神經網絡中表現優于 ReLU,特別是在 ImageNet 分類和機器翻譯等任務上。
2、機制 Swish 激活函數的機制主要包括:
- 平滑性:Swish 函數在整個定義域內都是連續可導的,這有助于優化算法更穩定地收斂。
- 非單調性:當輸入為負數時,Swish 函數的輸出可以為負數,這使得它能夠學習更復雜的函數映射。
- 自門控特性:Swish 函數可以看作是一種自門控機制,其中x作為輸入,\(\sigma(x)\)作為門控信號,控制輸入的傳播程度。
3、獨特優勢
- 性能提升:在多個深度學習任務(如圖像分類、目標檢測、語音識別)上,Swish 激活函數能夠提供比 ReLU 更高的準確率。
- 平滑梯度:連續可導的特性使得 Swish 在訓練過程中梯度更加平滑,減少了梯度消失和爆炸的問題。
- 計算高效:Swish 的計算復雜度與 ReLU 相當,只需一次乘法和一次 Sigmoid 運算。
4、代碼
import torch
import torch.nn as nnclass 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])