华为杯笔记
传统定位方法局限性
- 现有技术: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))。
- MDS:最小化高维/低维距离差异(
- 位置校正:利用锚点将虚拟坐标转换为绝对大地坐标。
四、评价与提交要求
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 | 端到端学习 | 卷积+全连接 | 中等 | 最高 | 数据充足,计算资源充足 |
| DNN | Triplet网络 | 全连接网络 | 高 | 高 | 需要学习判别性特征 |
| 协方差+AE+LS | 协方差矩阵 | 自编码器+LS | 低 | 低 | 快速原型验证 |
| 协方差+AE+MLP | 协方差矩阵 | 自编码器+MLP | 中等 | 中等 | 平衡精度和效率 |
推荐方案:
- 最佳精度:CNN方案
- 平衡选择:协方差+AE+MLP方案
- 快速验证:协方差+AE+LS方案
CNN
参数初始化
-
使用wandblogger来分析(初始化,配置)
-
预处理数据集
将数据保存为.joblib存到磁盘
使用tqdm库来显示进度条
-
训练cnn神经网络
trainer.fit方法来训练模型
-
模型评估
model.eval() 锚点+参考点与预测点比较
-
将扇区外面的点拽回边界
-
输出预测点的坐标
-
计算MSE
-
关闭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列表,构建了一系列全连接层,中间可以包含Dropout和ReLU层以减少过拟合和引入非线性。
前 向传播 (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_dims、norms和dropout。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
-
使用auto encode(非监督)来降维:

-
使用LS来修正坐标点
效果不佳
cov_ae_mlp
采用MLP来修正坐标点
效果不佳
cov_pca_ls
- PCA降维
- 使用LS来修正坐标点
效果不佳
cov_tsne_ls
T-SNE降维
效果不佳
DNN

不知道出了什么问题
预训练:
-
加噪处理
添加随机时延噪声和多径噪声
-
图像化处理
以图像形式模拟CSI,转换绝对坐标为距离与角度,统一输出空间
-
2D-FFT处理
对CSI图像进行2D-FFT处理,增强子载波与天线间的特征差异。
半监督迭代训练阶段:
-
模型微调
线性插值生成数据,微调预训练模型
-
深度集成学习
度量预测差异,选取差异小的点,平均后作为高置信度伪标签
-
扇区微调
使用伪标签在各扇区微调模型并获得预测
-
迭代优化
迭代替换低分结果,逐步提升模型精度