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
| """ Wave2Body 推理管道测试 论文:arXiv:2607.18875 """
import torch import numpy as np
def test_wave2body(): """Wave2Body 完整推理测试""" print("=" * 60) print("Wave2Body 推理测试") print("=" * 60) B, N = 2, 200 point_dim = 7 model = Wave2Body( point_dim=point_dim, hidden=256, num_radar_tokens=64, num_body_tokens=8, codebook_size=512, pose_dim=66 ) np.random.seed(42) point_cloud = torch.randn(B, N, point_dim) * 5 point_cloud[:, :, :3] += torch.tensor([2.0, 0.0, 1.0]) pose, root, tokens = model(point_cloud) print(f"输入: {point_cloud.shape} (B, N, dim)") print(f"输出姿态: {pose.shape} (B, J*3)") print(f"骨盆位置: {root.shape} (B, 3)") print(f"Body tokens: {tokens.shape} (B, num_tokens)") print() total = sum(p.numel() for p in model.parameters()) trainable = sum(p.numel() for p in model.parameters() if p.requires_grad) frozen = total - trainable print(f"总参数量: {total / 1e6:.2f}M") print(f"可训练参数: {trainable / 1e6:.2f}M ({trainable/total*100:.1f}%)") print(f"冻结参数: {frozen / 1e6:.2f}M ({frozen/total*100:.1f}%)") print() import time model.eval() with torch.no_grad(): for _ in range(10): _ = model(point_cloud) times = [] for _ in range(50): start = time.perf_counter() _ = model(point_cloud) times.append((time.perf_counter() - start) * 1000) print(f"推理延迟: {np.mean(times):.2f} ms (±{np.std(times):.2f})") print(f"理论帧率: {1000 / np.mean(times):.0f} fps") return model
def test_cross_domain(): """跨域泛化测试""" print("\n" + "=" * 60) print("跨域泛化测试") print("=" * 60) model = Wave2Body() model.eval() indoor_points = torch.randn(1, 200, 7) * 3 indoor_points[:, :, :3] += torch.tensor([1.5, 0, 0.8]) outdoor_points = torch.randn(1, 150, 7) * 8 outdoor_points[:, :, :3] += torch.tensor([5.0, 0, 2.0]) occluded_points = torch.randn(1, 80, 7) * 4 occluded_points[:, :, :3] += torch.tensor([2.0, 0, 1.0]) with torch.no_grad(): for name, points in [("室内近距离", indoor_points), ("室外远距离", outdoor_points), ("遮挡场景", occluded_points)]: pose, root, _ = model(points) print(f"{name}: 骨盆位置 = [{root[0,0]:.2f}, {root[0,1]:.2f}, {root[0,2]:.2f}], " f"姿态范围 = [{pose.min():.2f}, {pose.max():.2f}]")
def test_body_token_analysis(): """人体 Token 空间分析""" print("\n" + "=" * 60) print("人体 Token 空间分析") print("=" * 60) model = Wave2Body() codebook = model.body_tokenizer.codebook.weight print(f"码本大小: {codebook.shape}") print(f"码本距离统计: 均值={torch.cdist(codebook, codebook).mean():.4f}, " f"最大={torch.cdist(codebook, codebook).max():.4f}") poses = [] for _ in range(5): pc = torch.randn(1, 200, 7) * 5 with torch.no_grad(): _, _, tokens = model(pc) poses.append(tokens) all_tokens = torch.cat(poses, dim=0) print(f"\nToken 多样性分析:") print(f" 唯一 token 数: {len(torch.unique(all_tokens))}") print(f" Token 分布:") for t in all_tokens.flatten(): print(f" Token {t.item()}", end="") print()
if __name__ == "__main__": model = test_wave2body() test_cross_domain() test_body_token_analysis()
|