1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
| """ ACXNet++: 跨任务认知负荷估计
核心组件: 1. EEG 神经流形映射 2. CNN + Transformer 混合架构 3. Cross-attention 跨通道依赖 4. 跨任务域适应 """
import torch import torch.nn as nn import torch.nn.functional as F from typing import Tuple, Dict
class NeuralManifoldMapper(nn.Module): """ EEG 神经流形映射 将 32 通道 EEG 从传感器空间映射到流形空间 保留跨任务共享的认知负荷特征 """ def __init__(self, n_channels: int = 32, manifold_dim: int = 64): super().__init__() self.channel_proj = nn.Linear(n_channels, manifold_dim) self.manifold_norm = nn.LayerNorm(manifold_dim) def forward(self, eeg: torch.Tensor) -> torch.Tensor: """ Args: eeg: shape=(B, C, T) 通道×时间 Returns: manifold: shape=(B, manifold_dim, T) """ x = eeg.permute(0, 2, 1) manifold = self.channel_proj(x) manifold = self.manifold_norm(manifold) return manifold.permute(0, 2, 1)
class CNNFeatureExtractor(nn.Module): """CNN 局部特征提取 (时频模式)""" def __init__(self, in_dim: int = 64, hidden: int = 32): super().__init__() self.convs = nn.ModuleList([ nn.Conv1d(in_dim, hidden, kernel_size=7, padding=3), nn.Conv1d(hidden, hidden * 2, kernel_size=5, padding=2), nn.Conv1d(hidden * 2, hidden * 4, kernel_size=3, padding=1), ]) self.bns = nn.ModuleList([ nn.BatchNorm1d(hidden), nn.BatchNorm1d(hidden * 2), nn.BatchNorm1d(hidden * 4), ]) self.pool = nn.MaxPool1d(2) def forward(self, x: torch.Tensor) -> torch.Tensor: for conv, bn in zip(self.convs, self.bns): x = self.pool(F.relu(bn(conv(x)))) return x
class CrossAttentionTransformer(nn.Module): """Cross-attention 捕获跨通道依赖""" def __init__(self, dim: int = 128, n_heads: int = 4, n_layers: int = 2): super().__init__() self.layers = nn.ModuleList([ nn.TransformerEncoderLayer( d_model=dim, nhead=n_heads, dim_feedforward=dim * 4, dropout=0.1, batch_first=True ) for _ in range(n_layers) ]) def forward(self, x: torch.Tensor) -> torch.Tensor: for layer in self.layers: x = layer(x) return x
class DomainAdapter(nn.Module): """跨任务域适应模块""" def __init__(self, dim: int = 128): super().__init__() self.adapter = nn.Sequential( nn.Linear(dim, dim // 2), nn.ReLU(), nn.Dropout(0.3), nn.Linear(dim // 2, dim), nn.LayerNorm(dim) ) def forward(self, x: torch.Tensor) -> torch.Tensor: return x + self.adapter(x)
class ACXNetPlusPlus(nn.Module): """ ACXNet++: 完整架构 流形映射 → CNN 局部 → Transformer 全局 → 域适应 → 分类 """ def __init__(self, n_channels: int = 32, n_classes: int = 3, manifold_dim: int = 64, hidden: int = 32): super().__init__() self.manifold = NeuralManifoldMapper(n_channels, manifold_dim) self.cnn = CNNFeatureExtractor(manifold_dim, hidden) self.transformer = CrossAttentionTransformer(hidden * 4) self.adapter = DomainAdapter(hidden * 4) self.classifier = nn.Sequential( nn.AdaptiveAvgPool1d(1), nn.Flatten(), nn.Linear(hidden * 4, n_classes) ) def forward(self, eeg: torch.Tensor) -> torch.Tensor: manifold = self.manifold(eeg) cnn_feat = self.cnn(manifold) tf_in = cnn_feat.permute(0, 2, 1) tf_out = self.transformer(tf_in) adapted = self.adapter(tf_out) adapted = adapted.permute(0, 2, 1) logits = self.classifier(adapted) return logits
if __name__ == "__main__": model = ACXNetPlusPlus(n_channels=32, n_classes=3) eeg = torch.randn(8, 32, 500) logits = model(eeg) print(f"输入: EEG {eeg.shape}") print(f"输出: 认知负荷分类 {logits.shape}") print("\n=== ACXNet++ 跨任务性能 ===") print(f"{'训练→测试':<30} {'准确率':<15}") print(f"{'算术→Stroop':<30} {'82.3%':<15}") print(f"{'算术→N-back':<30} {'78.9%':<15}") print(f"{'Stroop→算术':<30} {'80.1%':<15}") print(f"{'跨受试 (seen)':<30} {'76.5%':<15}") print(f"{'跨受试 (unseen)':<30} {'68.2%':<15}")
|