You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

82 lines
2.6 KiB
Python

import torch
import torch.nn as nn
import ultralytics.nn.modules as um
import ultralytics.nn.tasks as ut
import sys
class ChannelAttentionDyn(nn.Module):
def __init__(self, reduction=16):
super().__init__()
self.reduction = reduction
self.avg_pool = nn.AdaptiveAvgPool2d(1)
self.max_pool = nn.AdaptiveMaxPool2d(1)
self.mlp = None
self.sigmoid = nn.Sigmoid()
def _build(self, c, device, dtype):
hidden = max(c // self.reduction, 1)
self.mlp = nn.Sequential(
nn.Conv2d(c, hidden, 1, bias=False),
nn.ReLU(inplace=True),
nn.Conv2d(hidden, c, 1, bias=False),
).to(device=device, dtype=dtype)
def forward(self, x):
if self.mlp is None:
self._build(x.shape[1], x.device, x.dtype)
else:
p = next(self.mlp.parameters())
if p.device != x.device or p.dtype != x.dtype:
self.mlp = self.mlp.to(device=x.device, dtype=x.dtype)
a = self.mlp(self.avg_pool(x))
m = self.mlp(self.max_pool(x))
return x * self.sigmoid(a + m)
class SpatialAttention(nn.Module):
def __init__(self, kernel_size=7):
super().__init__()
padding = kernel_size // 2
self.conv = nn.Conv2d(2, 1, kernel_size, padding=padding, bias=False)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
if self.conv.weight.device != x.device or self.conv.weight.dtype != x.dtype:
self.conv = self.conv.to(device=x.device, dtype=x.dtype)
avg = torch.mean(x, dim=1, keepdim=True)
mx, _ = torch.max(x, dim=1, keepdim=True)
w = self.sigmoid(self.conv(torch.cat([avg, mx], dim=1)))
return x * w
class CBAM(nn.Module):
def __init__(self, reduction=16, sa_kernel=7):
super().__init__()
self.ca = ChannelAttentionDyn(reduction=reduction)
self.sa = SpatialAttention(kernel_size=sa_kernel)
def forward(self, x):
return self.sa(self.ca(x))
# Register so torch/ultralytics can deserialize CBAM checkpoints.
um.CBAM = CBAM
ut.CBAM = CBAM
um.ChannelAttentionDyn = ChannelAttentionDyn
ut.ChannelAttentionDyn = ChannelAttentionDyn
um.SpatialAttention = SpatialAttention
ut.SpatialAttention = SpatialAttention
globals()["ChannelAttentionDyn"] = ChannelAttentionDyn
globals()["SpatialAttention"] = SpatialAttention
globals()["CBAM"] = CBAM
# Compatibility for checkpoints serialized with __main__.CBAM
main_mod = sys.modules.get("__main__")
if main_mod is not None:
setattr(main_mod, "ChannelAttentionDyn", ChannelAttentionDyn)
setattr(main_mod, "SpatialAttention", SpatialAttention)
setattr(main_mod, "CBAM", CBAM)