第二届无线通信AI大赛参赛总结

  参加了第二届无线通信AI大赛 基于 AI 的信道状态信息反馈 题 ,最后仅得第13名,不论成绩好坏,毕竟花了几个星期时间,还是应该做个梳理总结。

一、赛题简介

1.数据和任务

  赛题数据是来自多小区多用户的 32T4R 的 MIMO 信道特征信息,总共有60万个样本,每个样本包含768个数据,包括12条子带,每个子带长度32,每个位置又都包含实部和虚部,也就是说768 = 12 x 32 x 2 。任务是开发编码-解码算法,编码器用于UE(手机端),把每个样本的数据分别压缩到48bits和128bits,然后发送到BS(基站)后再用解码器解码,要求解码后的数据和原数据有尽量高的相似性。评价指标是12条子带的余弦相似性的平均值。随机抽取两个样本,数据可视化后如下:
在这里插入图片描述

图1. 本题数据中的两个样本

2.比赛达到的效果

  比赛参赛人数378人,不算很多,但由于已经是第二届了,和第一届赛题也比较像,前排选手也都非常专业,做的应该是比较充分的。下表给出了非AI方法当前最优的Type II码本方法和本次比赛的效果对比。

表1. 基于非AI方法(Type II 码本)和AI方法的CSI反馈效果对比
方法48bits*128bits
Type II码本0.760.83
本届冠军0.880.94
我渣的成绩0.840.91

*注:Type II码本使用的是49bits
  可见,基于AI的方法在CSI反馈上具有惊艳的效果,即使我一个外行都可以在短时间内超过传统方法。

二、使用的方法

1.数据处理

  发现用一维(沿32长度这个维度)傅里叶变换把数据变换到频域,再进行编码-解码,解码后再傅里叶逆变换回原时域信号,用这种方法可以大大加快训练收敛速度,而且训练最终精度也好一些。
  下图2给出了和图1对应的样本经傅里叶变换到频域后的数据可视化图,与图1对比,可看出在32长度上稀疏了很多。
在这里插入图片描述

图2. 图1两个样本经过一维(32长维度)傅里叶变换后

  我分析其原因是,原时域信号存在一定的周期性,编码压缩的过程就是要去掉重复冗余的信息,把主要的特征信息提取出来,进行傅里叶变换到频域实际上也是做了同样的工作,自然减轻了神经网络学习处理的任务量,加快了训练收敛速度。当然,神经网络本身是一种强大的万能拟合工具,不进行数据预处理,往往神经网络也能自己学会必要的数据预处理过程,但这加大了网络学习的难度。
  这里再多说一些,怎么判断一种数据预处理或后处理方法是否是必要的呢。我觉得一般原则是这样的:如果预处理能够达到和学习目的一致的效果,能够减轻网络学习的难度/任务量,就相当于给网络加入了先验,这种数据处理就是必要的。如果数据处理不能够引入有价值先验信息,甚至引入了错误的先验约束,这种数据处理就是没有必要的。其实除了数据处理,包括激活函数、网络算子、结构设计等在整个使用机器学习技术的系统中都涉及到如何把先验引入的问题,这是机器学习系统设计的核心问题之一(另一个核心问题是如何保证信息/特征能够顺畅、稳定、高效的流动)。
  回到这个题目继续思考,我们肯定会想,如果进行二维傅里叶变换,在32长度和12子带维度上都进行傅里叶变换,不是可以更加的稀疏,更加利于编解码学习吗?二维傅里叶变换后的数据可视化图如下图3,确实更加稀疏了很多。但用这种处理实际试验下来效果不行,我分析是因为本题考察指标是12子带每子带的相关性的平均值,如果进行12子带维度上的傅里叶变换,就破坏了每个子带的信息的独立性,所以反而难以在解码过程中把这个信息还原出来。这就是上面说的带来了错误的先验约束。
在这里插入图片描述

图3. 图1两个样本经过二维(32长维度和12子带维度)傅里叶变换后

  数据处理是我在本题中提分最有效的一个措施,所以说的多一些。

2.网络结构

  这方面没有什么新的思路和太多可说的,就是在此领域经典网络CRNet基础上又杂糅进了多种常规模块,如SE模块等,又做了多个不同参数尺寸的网络并联,最后又加入了transformer并联,把各个子网络的结果cat起来输入一个1x1卷积层保证输出尺寸是bs x 2 x 32 x 12,然后再flatten之后接全连接层和量化层,解码的过程几乎是上述过程逆过来,只不过解码器在基站端运行有更好的硬件算力,所以使用了更大参数量的网络。
  由于这个题目的训练过程非常慢,训练40多个小时都没有完全饱和,所以调参非常麻烦,我也没有充分对比各种网络结构的性能,只好是相信越大的网络越好,就用了一个大杂糅网络。

3.损失函数

  我直接使用了评价指标,即各子带余弦相似性均值,做为损失函数。我还尝试了MSE和NMSE等其他损失函数,效果都没有这个直接用相似性做为损失函数效果好。实际上,MSE / NMSE是一个更强的条件,当MSE小时,相似性肯定小,但相似性小时,MSE不一定小,所以用相似性做为损失函数降低了网络收敛的难度。

4.量化层

  举办方提供的baseline里给出了量化层的设计,默认是2比特量化,就是一个浮点数均匀切成四段,再量化为两个比特。我尝试了多种修改思路都没有用,只有混合比特量化有一点点用处。我在48bits任务中使用了一半1比特一半2比特量化,也就是说网络输出为32长度的浮点数据,其中一半用1比特量化为16bits,另一半用2比特量化为32bits,最后合起来总共是48bits;对于128bits任务,我把网络输出设置为72长度浮点数,其中16长度用1比特,56长度用2比特。

三、一些失败的尝试

  我没有做上届的比赛,这次比赛我从零进入,总共投入了三个星期的时间。这个题目的灵活性很高,在这三个星期时间内我尝试过非常多的方案,但几乎都没有奏效,往往是每天早上一觉醒来想到一个非常激动人心的方法,努力一天实现之后失望的发现并没有什么卵用,也因此浪费了很多时间,造成最后失利。这些方案虽然无效,但毕竟花了时间去做,也记录在这里,给大家避坑。

1.聚类法预编码

  压缩编码任务也可以理解为把某一类相近的样本编成相同的码,这和聚类是类似的,我自然想到用聚类的思路去试一试。当然我们不可能全部用聚类,那样即使48bits任务也需要聚成2的48次方类,类别太多了,样本数也不够。但我们也许可以将其中部分比特拿出来用聚类做,比如拿出7个比特可以存储128类,8个可以存储256类,等等。在解码的时候这部分比特可以直接解算为每个类的聚类中心点。剩余的比特存储的信息可以再用深度学习的方法来学习每个样本再怎么从聚类中心去修正。我做了简单的试验,即使用Kmeans进行简单的聚类(对此任务,kmeans并不是最好的),仍可以观察到聚类所用的少数比特可以存储更多的信息,如下表:

表2. 使用聚类-恢复为聚类中心的方法和使用CRNet在少数比特上编解码的效果对比
聚类占用比特对应的聚类类别用聚类中心点还原后的相似性同样比特数用CRNet可以达到的相似性
120.23640.2030
240.29870.2751
380.38150.3172
4160.45160.3733
5320.51930.4300
6640.56700.4914
71280.60810.5262
82560.64280.5725

  从这个观察出发,我认为占用少数bits存储聚类信息,可以更高效的编码。然而剩下的难题是,怎么用深度学习网络来学习使用剩余的比特存储每个样本和聚类中心之间的修正关系呢?我尝试了若干种方案都没有奏效的,后来实在没时间只好放弃。
  在这个思路上我总共花费了7天左右时间,但其实到现在我仍没有死心,也许以后可以再接着试验,如果成功了或许可以发一篇paper呢

2.多种量化层设计

  如果我们去掉量化层可以观察到非常明显的效果上升,所以量化层肯定是造成了很多信息损失,如何改进量化层呢?我在这方面也花了很多时间去尝试,但基本都失败了,除了上面提到的混合比特法能比固定某个比特好一点点,其他我还尝试了以下方案,按说这些方案在上届比赛一些选手总结中提到或在更一般的神经网络量化方法研究中都是有效方法,但我在本比赛中试验,没有发现有效。
  一是尝试了非均匀量化。从量化前的输出浮点数数据分布可以看出,数据不是在0-1上均匀分布的,而是两头多,中间少,这样显然对量化后比特的使用率是不均匀的,自然想到应该把量化分界点向两边移动,保持每段的数量都差不多会更好。但是实际试验下来,如果把分界点向两边靠拢,网络的输出会变得也更加向两边靠拢,如果动态调整分界点保持每段数量一样,会导致输出数据分布剧烈的向两侧靠拢,效果也越来越差,见下图。原因没想通,总之试验失败。
在这里插入图片描述

图4. 使用动态非均匀量化法在初期和后期的量化层输入数据分布情况

  二是尝试了把量化层前面的数据整形用的激活函数sigmoid换成DSQ(可微软量化)。由于量化的时候使用了强制截断,比如把0.59截断为0.5,这产生了信息损失,我设想如果让量化前的输出就已经向各个量化点靠拢,截断误差就会变得更小,是不是效果就更好了?因此我想到把sigmoid换成DSQ,也就是一种软化的阶梯函数,函数图像如下图5。但试验下来效果也不好,我分析是:虽然DSQ的输出的数据分布是靠近量化点的,但DSQ的输入其实还是没怎么变,这样截断误差虽然小了,但这个截断误差如果还原到网络输出层其实还是没变。也就是说这个截断误差的缩小并没有发生在网络层。把这个代码记录在这里,说不定以后别的地方有用。(在Invertible Image Signal Processing(CVPR2021)一文中还提到过另一种可微软量化方案,但我没时间实现了。)

class SoftStep(nn.Module):
    def __init__(self, B,alpha):
        super(SoftStep,self).__init__()
        alpha = torch.tensor([alpha]).cuda()
        self.B = B
        self.delta = 1 / (2**B)
        self.s = 1 / (1-alpha)
        self.k = (2/alpha - 1).log() * (1/self.delta)
    def forward(self,x):
        i = torch.floor(x / self.delta - 0.5)
        i = i.clamp(0, 2**self.B - 2)
        mi = self.delta * (i+1)
        yi = self.delta * (i+1)
        phi = (((x - mi) *self.k ).tanh()) * self.s * self.delta * 0.5 + yi
        return phi
dsq = SoftStep(B=2,alpha=1e-4)
x = torch.rand(100,200).cuda()
y = dsq(x)
x = x.data.cpu().numpy()
y = y.data.cpu().numpy()
plt.plot(np.sort(x.flatten()));plt.plot(np.sort(y.flatten()))

在这里插入图片描述

图5. 使用上述代码中DSQ的数据整形效果(B=2, alpha=1e-4)

  三是尝试了给量化层加入可学习部分,弥补量化损失。也就是加入一个小的MLP网络,以解码器反量化层后的输出为输入,输出和编码器的量化层前的输出进行逼近,这样等于用网络学习弥补量化层的一些信息损失。这一招是从上届比赛一个开源代码中学的,但本题中我试验无效。
  四是给量化前的网络输出加-std损失,逼迫数据向两端靠拢。基于上面第二条失效原因的分析,我考虑通过强制方法让网络层学会输出集中到量化点,但这个并不好实现,我只能通过给量化前的输出加-std损失,也就是: loss = -torch.std(enq)。加入这个之后确实可以让量化前的网络层输出强烈的向0和1靠拢,这时如果我们用0和1做为量化点的话截断误差会很小。但这时又带来一个新问题,网络本身的学习能力也大大降低了,学习效果很差。
  所以最后我是绞尽脑子也没找到有效的量化方法。这些试验也花费了我4-5天的时间。

3.训练花样

  我还尝试了多种训练花样,都没用,比如(1)先不用量化层,训练充分,再加入量化层训练;(2)先训练差不多后,固定编码器,专门再训练解码器;(3)对其中的难例进行增强训练;(4)难例和易例用分类网络分类,然后再用不同的网络训练。

四、总结与思考

  本题我没有充分学习文献,就匆忙尝试了很多新奇的想法,最后所有的尝试都失败了之后,才学了一些上届比赛分享的代码拼凑了一个研究并不充分的网络,所以最后成绩也不是很好。实际上回头想想我之前参加的比赛,基本上凡是充分调研文献,在前人基础上又改进的成绩都还可以,凡是自己创新,尝试新方法的,成绩都不太好。这也充分说明了创新是很难的,我目前还不具备在短短的比赛期间内完成高价值创新的能力,创新必须是在充分学习前人已有知识的基础上再开展的,创新必须是在扎实的理论基础和强大的动手实现能力基础上完成的,这都是我目前还欠缺的,需要继续努力。

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值