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
| """ 论文:From Stress to Affect: Multimodal Deep Learning for Physiological Emotion Recognition arXiv: 2609.20991
核心方法:BiLSTM / TCN / Transformer 对比评估 """
import torch import torch.nn as nn
class PhysiologicalTransformer(nn.Module): """Transformer用于生理情感识别""" def __init__(self, num_sensors: int = 6, seq_len: int = 60, d_model: int = 128, num_heads: int = 4, num_layers: int = 4, num_classes: int = 3): super().__init__() self.sensor_embed = nn.Linear(num_sensors, d_model) self.pos_embed = nn.Parameter(torch.randn(1, seq_len, d_model)) encoder_layer = nn.TransformerEncoderLayer( d_model=d_model, nhead=num_heads, dim_feedforward=d_model*4, dropout=0.1, batch_first=True ) self.encoder = nn.TransformerEncoder(encoder_layer, num_layers) self.classifier = nn.Sequential( nn.LayerNorm(d_model), nn.Linear(d_model, num_classes) ) def forward(self, x): """x: (B, seq_len, num_sensors)""" x = self.sensor_embed(x) + self.pos_embed[:, :x.size(1)] x = self.encoder(x) x = x.mean(dim=1) return self.classifier(x)
class BilLSTM(nn.Module): """双向LSTM (EmoWear最佳模型)""" def __init__(self, num_sensors=6, hidden=128, num_layers=2, num_classes=3): super().__init__() self.lstm = nn.LSTM(num_sensors, hidden, num_layers, batch_first=True, bidirectional=True, dropout=0.3) self.classifier = nn.Sequential( nn.Linear(hidden*2, 64), nn.ReLU(), nn.Dropout(0.3), nn.Linear(64, num_classes) ) def forward(self, x): out, _ = self.lstm(x) last = out[:, -1, :] return self.classifier(last)
class TCN(nn.Module): """时序卷积网络""" def __init__(self, num_sensors=6, hidden=64, num_classes=3): super().__init__() self.tcn = nn.Sequential( nn.Conv1d(num_sensors, hidden, 3, padding=1), nn.BatchNorm1d(hidden), nn.ReLU(), nn.Conv1d(hidden, hidden*2, 3, dilation=2, padding=2), nn.BatchNorm1d(hidden*2), nn.ReLU(), nn.Conv1d(hidden*2, hidden*4, 3, dilation=4, padding=4), nn.BatchNorm1d(hidden*4), nn.ReLU(), nn.AdaptiveAvgPool1d(1) ) self.classifier = nn.Linear(hidden*4, num_classes) def forward(self, x): x = x.transpose(1, 2) x = self.tcn(x).squeeze(-1) return self.classifier(x)
if __name__ == "__main__": models = { "Transformer": PhysiologicalTransformer(), "BiLSTM": BilLSTM(), "TCN": TCN() } x = torch.randn(8, 240, 6) print("=== 生理情感识别模型对比 ===") for name, model in models.items(): out = model(x) params = sum(p.numel() for p in model.parameters()) print(f"{name}: output={out.shape}, params={params:,}") print(f"\n=== 论文结果 ===") print("WESAD: Transformer 99.02% ± 0.51% (多模态)") print("EmoWare Arousal: LSTM 91.80% ± 1.06%") print("EmoWare Valence: LSTM 89.96% ± 0.36%") print("采样频率: 4Hz即可")
|