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
| import torch import torch.nn as nn
class RePosNet(nn.Module): """RePos: 相对-绝对姿态分解网络""" def __init__(self, num_joints: int = 17, hidden_dim: int = 256): super().__init__() self.csi_encoder = nn.Sequential( nn.Conv1d(1, 64, kernel_size=7, padding=3), nn.BatchNorm1d(64), nn.ReLU(inplace=True), nn.Conv1d(64, 128, kernel_size=5, padding=2), nn.BatchNorm1d(128), nn.ReLU(inplace=True), nn.Conv1d(128, hidden_dim, kernel_size=3, padding=1), nn.BatchNorm1d(hidden_dim), nn.ReLU(inplace=True), ) self.pose_head = nn.Sequential( nn.Linear(hidden_dim, 512), nn.ReLU(inplace=True), nn.Dropout(0.3), nn.Linear(512, num_joints * 3) ) self.root_head = nn.Sequential( nn.Linear(hidden_dim, 256), nn.ReLU(inplace=True), nn.Linear(256, 3) ) self.environment_adapter = nn.Sequential( nn.Linear(hidden_dim, 128), nn.ReLU(inplace=True), nn.Linear(128, hidden_dim), nn.Tanh() ) def forward(self, csi_signal): """ Args: csi_signal: WiFi CSI 信号 (B, 1, N) N = 发射天线 × 接收天线 × 子载波数 Returns: pose_3d: 绝对 3D 姿态 (B, 17, 3) root_pos: 根节点位置 (B, 3) """ csi_feat = self.csi_encoder(csi_signal) global_feat = csi_feat.mean(dim=2) adapted_feat = self.environment_adapter(global_feat) relative_pose = self.pose_head(adapted_feat) relative_pose = relative_pose.view(-1, 17, 3) root_pos = self.root_head(adapted_feat) absolute_pose = relative_pose + root_pos.unsqueeze(1) return absolute_pose, root_pos
class RePosTrainer: """RePos 训练器""" def __init__(self, model, config): self.model = model self.optimizer = torch.optim.AdamW(model.parameters(), lr=1e-4) self.pose_weight = config.get('pose_weight', 1.0) self.root_weight = config.get('root_weight', 0.5) def compute_loss(self, pred_pose, pred_root, gt_pose, gt_root): """ 计算损失函数 Args: pred_pose: 预测姿态 (B, 17, 3) pred_root: 预测根节点 (B, 3) gt_pose: 真实姿态 (B, 17, 3) gt_root: 真实根节点 (B, 3) """ relative_gt = gt_pose - gt_root.unsqueeze(1) relative_pred = pred_pose - pred_root.unsqueeze(1) pose_loss = F.mse_loss(relative_pred, relative_gt) root_loss = F.mse_loss(pred_root, gt_root) total_loss = self.pose_weight * pose_loss + self.root_weight * root_loss return total_loss, {'pose_loss': pose_loss.item(), 'root_loss': root_loss.item()}
|