在处理脑电信号时通常会用到一些注意力机制,来给不同的脑电通道不同的权重,进而体现出不同脑电通道在分类中的重要性。下面整理几种常见的通道注意力机制,方便以后查阅。
常用注意力机制 SENet CBAM ECA
注意力机制
注意力机制最初是为了解决自然语言处理(NLP)任务中的问题而提出的,它使得模型能够在处理序列数据时动态地关注不同位置的信息。
注意力机制的核心思想是根据输入数据的不同部分,动态地调整模型的注意力,从而更加关注对当前任务有用的信息。
SENet(Squeeze-and-Excitation Network)
SENet原理
论文下载地址:https://arxiv.org/pdf/1709.01507v2.pdf
SENet(Squeeze-and-Excitation Network)是一种基于通道的注意力机制,旨在学习通道权重以增强特征图中每个通道的重要性。
SENet通道注意力机制的流程:
Squeeze:对于每个通道,计算其
全局平均池化
,得到一个通道特征值。这相当于将每个通道的空间信息进行压缩。Excitation:使用一个
全连接层
来学习通道权重,该全连接层包含一个Sigmoid激活函数
,用于生成一个通道注意力向量。这个注意力向量表示每个通道的重要性。将学习到的通道注意力向量乘以原始特征图,得到加权后的特征图,增强了每个通道的重要性。
以下是两个SENet的典型应用结构:
SENet Python实现
import torch
import torch.nn as nn
#%% 用于图像处理时的代码
class SEBlock(nn.Module):
def __init__(self, in_channels, reduction=16):
super(SEBlock, self).__init__()
self.avg_pool = nn.AdaptiveAvgPool2d(1)
self.fc = nn.Sequential(
nn.Linear(in_channels, in_channels // reduction),
nn.ReLU(inplace=True),
nn.Linear(in_channels // reduction, in_channels),
nn.Sigmoid()
)
def forward(self, x):
b, c, _, _ = x.size()
y = self.avg_pool(x).view(b, c)
y = self.fc(y).view(b, c, 1, 1)
return x * y
#%% 用于脑电处理时的代码,计算通道注意力
class SEBlock(nn.Module):
def __init__(self, in_channels, reduction=16):
super(SEBlock, self).__init__()
self.avg_pool = nn.AdaptiveAvgPool1d(1) # 在时间维度上压缩信号
self.fc = nn.Sequential(
nn.Linear(in_channels, in_channels // reduction),
nn.ReLU(inplace=True),
nn.Linear(in_channels // reduction, in_channels),
nn.Sigmoid()
)
def forward(self, x):
b, c, eegChan, _ = x.size() # (b, c, eegChan, samples)
y = torch.squeeze(self.avg_pool(x)) # (b, c, eegChan)
y = torch.unsqueeze(self.fc(y), dim=3) # (b, c, eegChan, 1)
return x * y