Skip to main content

华为杯笔记


传统定位方法局限性

  • 现有技术:ECID、TDoA、AoA、Multi-Cell RTT(依赖多基站协作)及指纹定位(需大量位置标签)。
  • 关键挑战:
    • 单站定位:传统多站算法失效,精度下降。
    • 低信噪比:多径与噪声干扰测量准确性。
    • NLOS场景:难以提取首径导致时延/角度误差。
    • 指纹库构建:依赖海量真实位置标签,成本高昂(见文档1.3节)。

3. 信道图谱定位原理

  • 核心思想:利用CSI(信道状态信息)隐含的环境特征,将高维CSI映射为低维虚拟坐标(Channel Charting),保持用户间相对位置关系。
  • 优势:
    • 减少位置标签依赖:仅需少量锚点校正绝对位置
    • 支持单站定位:突破多站协作限制

二、任务目标与数据说明

1. 任务简述

  • 输入:单个基站(BS)下多个点位的SRS信道数据 + 部分锚点(已知位置)。
  • 输出:所有点位(含未知位置点)的2D坐标估计(x, y)。
  • 关键约束:算法需在20分钟内完成所有场景计算

2. 数据组成

文件类型内容说明示例
RoundYCfgDataX.txt基站坐标、总点数(N_{tol})、锚点数(N_{anch})、天线数(ant=64)等参数0 0 30(BS坐标)
RoundYInputDataX.txt所有点位的信道数据(格式:Nport × Nant × Nsc × 2复数序列(实部+虚部)
RoundYInputPosX.txt锚点信息(索引 + 真实坐标)3 24.5454 64.2323
输出文件所有点位的估计坐标(小数点后4位,截断处理)-43.2343 56.7658

3. 关键参数

  • 天线配置:64T双极化,水平间距 0.5\lambda,垂直间距 2.0\lambda(频点3.5GHz)。
  • 子载波N_{sc}=408(100MHz带宽下4抽1,子载波间隔240KHz)。
  • 扇区范围:所有点位位于同一扇区,最大距离≤200m(扇区误判将导致误差恶化)

三、核心挑战与算法方向

1. 赛题难点

  • 锚点稀疏性:锚点数量少(N_{anch} \ll N_{tol})且空间分布不均。
  • 低维映射精度:需设计特征提取与相似性度量方法,保持高维CSI的局部几何结构。
  • 噪声与多径干扰:低信噪比场景下CSI可靠性下降。

2. 算法技术路径

  • 特征提取:从CSI中提取环境鲁棒性特征(如角度/时延分布)。
  • 相似性度量:欧式距离、余弦相关性等。
  • 低维映射算法:
    • MDS:最小化高维/低维距离差异(\min \sum (d_{ij} - \|z_i - z_j\|_2)^2)。
    • Siamese网络:同MDS目标,用神经网络优化。
    • Triplet网络:拉近相似样本,推开不相似样本(\max(\|z_i - z_j\|_2 - \|z_i - z_k\|_2 + M, 0))。
  • 位置校正:利用锚点将虚拟坐标转换为绝对大地坐标。

四、评价与提交要求

1. 评价指标

  • 定位误差:欧氏距离 d_i = \sqrt{(\hat{x}_i - x_i)^2 + (\hat{y}_i - y_i)^2}
  • 排名规则:按所有场景点位的平均误差排序(误差相同则并列排名)。

2. 提交规范

  • 输出文件:生成 RoundYOutputPosX.txt,每行格式为 x y(小数点后4位)

:赛题核心是利用稀疏锚点校正信道图谱生成的相对位置,需平衡特征鲁棒性、映射算法效率及噪声抑制能力。


五、算法方案对比

我们实现了四种主要的算法方案,每种方案都有其独特的特点和适用场景。

1. CNN方案(效果最好)

核心思想:使用卷积神经网络直接从CSI数据学习到位置映射关系

技术特点

  • 输入处理:CSI数据形状为 (4, 64, 408),包含4个通道(实部、虚部、幅度、相位)
  • 网络架构
    • 卷积层:Conv2d(4→128→256) + BatchNorm + ReLU + ResNetBlock2D
    • 全连接层:6144→1024→256→128→64→2
    • 总参数量:7.5M
  • 训练策略
    • 使用WandB进行实验跟踪
    • 数据增强:添加噪声(torch.randn_like(x) * 0.1
    • 时间对齐(TA)增强:add_ta(x, torch.randint(-2, 2, (x.shape[0],)))
    • 损失函数:MSE损失
    • 优化器:Adam(lr=1e-3)

优势

  • 端到端学习,无需手工特征工程
  • 卷积层能有效提取CSI的空间-频率特征
  • 残差连接提高训练稳定性
  • 数据增强提高泛化能力

效果:在测试中表现最佳,定位精度最高

2. DNN方案(Triplet+DNN)

核心思想:使用Triplet网络学习特征表示,再用DNN进行位置预测

技术特点

  • 特征提取:使用Triplet网络学习CSI的嵌入表示
  • 网络架构
    • 输入:Triplet特征向量
    • 隐藏层:4096→1024→512→256→128→64→2
    • 归一化:BatchNorm
  • 训练策略
    • 两阶段训练:先训练Triplet网络,再训练DNN
    • 使用锚点数据进行监督学习

优势

  • Triplet网络能学习到更好的相似性度量
  • 特征表示具有更好的判别性

劣势

  • 训练复杂度高,需要构造三元组
  • 对数据质量要求较高

3. 协方差+AE+LS方案(效果不佳)

核心思想:使用自编码器降维,再用最小二乘法进行位置校正

技术特点

  • 特征提取:使用协方差矩阵作为特征
  • 降维:自编码器将高维特征降至3维
  • 位置校正:最小二乘法拟合锚点位置

网络架构

  • 编码器:input_dim→1024→256→32→3
  • 解码器:3→32→256→1024→input_dim
  • 总参数量:10M

劣势

  • 最小二乘法假设线性关系,实际中CSI与位置关系复杂
  • 降维过程中可能丢失重要信息
  • 对噪声敏感

4. 协方差+AE+MLP方案

核心思想:使用自编码器降维,再用MLP进行非线性位置校正

技术特点

  • 特征提取:协方差矩阵特征
  • 降维:自编码器降至2维
  • 位置校正:MLP网络进行非线性映射

网络架构

  • 自编码器:input_dim→1024→256→32→2
  • MLP校正器:2→hidden_layers→2

优势

  • MLP能学习非线性映射关系
  • 相比LS方案有更好的表达能力

劣势

  • 仍然依赖协方差特征,可能不是最优特征表示
  • 两阶段训练,误差累积

方案对比总结

方案特征提取映射方法训练复杂度定位精度适用场景
CNN端到端学习卷积+全连接中等最高数据充足,计算资源充足
DNNTriplet网络全连接网络需要学习判别性特征
协方差+AE+LS协方差矩阵自编码器+LS快速原型验证
协方差+AE+MLP协方差矩阵自编码器+MLP中等中等平衡精度和效率

推荐方案

  • 最佳精度:CNN方案
  • 平衡选择:协方差+AE+MLP方案
  • 快速验证:协方差+AE+LS方案

CNN

参数初始化

  1. 使用wandblogger来分析(初始化,配置)

  2. 预处理数据集

    将数据保存为.joblib存到磁盘

    使用tqdm库来显示进度条

  3. 训练cnn神经网络

    trainer.fit方法来训练模型

  4. 模型评估

    model.eval() 锚点+参考点与预测点比较

  5. 将扇区外面的点拽回边界

  6. 输出预测点的坐标

  7. 计算MSE

  8. 关闭wandb分析

CNN架构

模型由 CNN 类和 LitCNN 类组成。以下是详细的模型架构解释:

1. CNN

CNN 类是基础的卷积神经网络模型,包含卷积层、批量归一化层(Batch Normalization)、激活函数层(ReLU)、全连接层(Fully Connected Layers)和可选的残差块(ResNetBlock2D)。

构造函数 (__init__ 方法)

def __init__(self, fc_dims: list, norms: list = [], dropout: float = 0):
super(CNN, self).__init__()
# input shape: (4, 64, 408)
self.conv_layers = nn.Sequential(
nn.Conv2d(in_channels=4, out_channels=128, kernel_size=[8, 8], stride=[8, 8]), # output shape: (128, 8, 51)
nn.BatchNorm2d(128),
nn.ReLU(),
ResNetBlock2D(128, 128),
nn.Conv2d(in_channels=128, out_channels=256, kernel_size=[4, 4], stride=4), # output shape: (256, 2, 12)
nn.BatchNorm2d(256),
nn.ReLU(),
nn.Flatten(),
)
fc_dims = [256 * 2 * 12] + fc_dims
self.fc_layers = nn.ModuleList()
for i in range(len(fc_dims) - 2):
self.fc_layers.append(nn.Linear(fc_dims[i], fc_dims[i+1]))
if dropout > 0:
self.fc_layers.append(nn.Dropout(p=dropout))
self.fc_layers.append(nn.ReLU())
self.fc_layers.append(nn.Linear(fc_dims[-2], fc_dims[-1]))
  • 输入形状: (4, 64, 408),表示输入数据有 4 个通道,每个通道的大小为 64x408。
  • 卷积层 (conv_layers):
    • 第一个卷积层:nn.Conv2d(in_channels=4, out_channels=128, kernel_size=[8, 8], stride=[8, 8]),输出形状为 (128, 8, 51)
    • 批量归一化层:nn.BatchNorm2d(128)
    • 激活函数层:nn.ReLU()
    • 残差块:ResNetBlock2D(128, 128)
    • 第二个卷积层:nn.Conv2d(in_channels=128, out_channels=256, kernel_size=[4, 4], stride=4),输出形状为 (256, 2, 12)
    • 批量归一化层:nn.BatchNorm2d(256)
    • 激活函数层:nn.ReLU()
    • 展平层:nn.Flatten(),将多维张量展平为一维向量。
  • 全连接层 (fc_layers):
    • fc_dims 列表包含了全连接层的维度,例如 [1024, 256, 128, 64, 2]
    • 初始维度由卷积层的输出形状决定,即 256 * 2 * 12 = 6144
    • 根据 fc_dims 列表,构建了一系列全连接层,中间可以包含 DropoutReLU 层以减少过拟合和引入非线性。

前向传播 (forward 方法)

def forward(self, x: torch.Tensor) -> torch.Tensor:
x = self.conv_layers(x)
for layer in self.fc_layers:
x = layer(x)
return x
  • 首先通过卷积层 conv_layers 处理输入 x
  • 然后依次通过全连接层 fc_layers 进行处理。
  • 最终返回网络的输出。

2. LitCNN

LitCNN 类继承自 lightning 库的 L.LightningModule,用于将 CNN 模型集成到 lightning 的训练框架中。

构造函数 (__init__ 方法)

def __init__(self, lr: float = 1e-3, **kwargs):
super(LitCNN, self).__init__()
self.model = CNN(**kwargs)
self.lr = lr
  • lr: 学习率,默认为 1e-3
  • \**kwargs: 传递给 CNN 类的其他参数,如 fc_dimsnormsdropout
  • self.model: 创建一个 CNN 模型实例。

前向传播 (forward 方法)

def forward(self, x: torch.Tensor) -> torch.Tensor:
return self.model(x)
  • 简单地调用 CNN 模型的前向传播方法。

训练步骤 (training_step 方法)

def training_step(self, batch, batch_idx):
x, y = batch

# Add noise to the input
x += torch.randn_like(x) * 0.1

# Add TA
x = add_ta(x, torch.randint(-2, 2, (x.shape[0],)))

y_hat = self(x)
loss = F.mse_loss(y_hat, y)
self.log('train_loss', loss)
return loss
  • 输入和目标: batch 包含输入数据 x 和目标数据 y
  • 添加噪声: x += torch.randn_like(x) * 0.1,在输入数据中添加少量噪声。
  • 添加 TA: x = add_ta(x, torch.randint(-2, 2, (x.shape[0],))),调用 add_ta 函数对输入数据进行处理,添加某种形式的变换或增强。
  • 前向传播: y_hat = self(x),通过 CNN 模型进行前向传播,得到预测结果 y_hat
  • 计算损失: loss = F.mse_loss(y_hat, y),使用均方误差(MSE)作为损失函数,计算预测结果与目标数据之间的损失。
  • 日志记录: self.log('train_loss', loss),记录训练损失。
  • 返回损失: return loss,返回损失值供 lightning 的训练循环使用。

配置优化器 (configure_optimizers 方法)

def configure_optimizers(self):
return torch.optim.Adam(self.parameters(), lr=self.lr)
  • Adam 优化器: 使用 Adam 优化器进行参数更新,学习率为 self.lr

效果好

cov_ae_ls

  1. 使用auto encode(非监督)来降维: image-20250507091018871

  2. 使用LS来修正坐标点

效果不佳

cov_ae_mlp

采用MLP来修正坐标点

效果不佳

cov_pca_ls

  1. PCA降维
  2. 使用LS来修正坐标点

效果不佳

cov_tsne_ls

T-SNE降维

效果不佳

DNN

不知道出了什么问题

预训练:

  1. 加噪处理

    添加随机时延噪声和多径噪声

  2. 图像化处理

    以图像形式模拟CSI,转换绝对坐标为距离与角度,统一输出空间

  3. 2D-FFT处理

    对CSI图像进行2D-FFT处理,增强子载波与天线间的特征差异。

半监督迭代训练阶段:

  1. 模型微调

    线性插值生成数据,微调预训练模型

  2. 深度集成学习

    度量预测差异,选取差异小的点,平均后作为高置信度伪标签

  3. 扇区微调

    使用伪标签在各扇区微调模型并获得预测

  4. 迭代优化

    迭代替换低分结果,逐步提升模型精度