基于无监督学习的RIS辅助ISAC联合波束成形设计

发布时间:2026/9/6 17:56:53
基于无监督学习的RIS辅助ISAC联合波束成形设计 简介面向无线通信与机器学习交叉领域的研究人员这是一份覆盖RIS辅助ISAC系统联合波束成形设计的完整PDF资料。其中提出的轻量级IBF-Net模型以无监督学习将感知与通信信道相关性、感知信道增益等关键指标融入损失函数无需标注数据即可联合优化通信与感知性能较传统方法显著降低计算复杂度。资源包为单个PDF文档约620KB已有193人浏览学习。文档系统介绍系统模型、优化问题、信号模型与信道样本构造方法并详细讲解IBF-Net网络结构、无监督损失函数实现以及通信感知性能平衡改进方案同时提供Python复现代码示例中包括64个RIS单元、32根基站天线、4个用户等参数设置并配有逐段注释便于读者复现实验、按实际场景调整网络结构与损失函数。适合具备通信工程或机器学习背景、关注智能反射面与通信感知一体化技术的研究者。 做无线通信系统仿真的老朋友应该都被同一个问题卡过ISAC通信感知一体化和RIS可重构智能表面单独拿出来都好实现顶多加点矩阵运算。但一旦要做RIS辅助ISAC的联合波束成形既要让用户速率达标又要保证雷达感知性能还得满足RIS相移的单位模约束这就不再是常规凸优化能随手解的问题。我在这块折腾了大半个月最终的方案是抛弃传统的迭代优化改用无监督学习训练一个轻量级网络IBF-Net直接在信道状态信息上映射出波束成形矩阵和RIS相移。下面把整套设计思路、模型结构、核心代码和调试经验完整记录下来。1. 设计思路为什么这个系统非要用无监督学习1.1 ISAC与RIS带来的联合波束成形难题先搞清楚我们在优化什么。基站有Nt根天线部署了一个M个反射单元的RIS服务K个单天线用户同时还要感知某个方向上可能存在的目标。基站的发射信号既要携带通信数据又要作为感知探测信号。传统波束成形的自由度只有基站的预编码矩阵但加上RIS之后又多出M个相移变量。这些变量被限制在单位圆的相位上等于往优化问题里塞进了一堆非凸约束。再叠加ISAC的通信和感知双指标最终问题通常是非凸且NP难的。以前我常用交替优化固定RIS相移去优化预编码矩阵再用半正定松弛或流形梯度去更新相移。在仿真里跑一个信道点大概需要几十次迭代每次迭代还要解一个小的凸问题整套下来耗时奔着几十毫秒甚至上百毫秒去了。信道变化稍快一点这套流程根本没机会落地。所以我一开始就想找一种离线训练、在线推理的做法。神经网络在这里的定位不是替代优化算法而是把从信道状态信息到波束成形解的那段映射近似出来。1.2 无监督学习相比有监督与优化的三个关键优势选择无监督学习主要权衡过三个点。第一不需要“最优标签”。有监督学习的训练集要信道对应的最优波束成形矩阵和RIS相移但为了拿到这些标签我们仍然要先求解一个NP难问题等于绕了一大圈。无监督学习直接跳过标签生成只把通信和感知指标设计成可微损失让网络自己往优化目标方向收敛。第二损失函数和目标真正对齐。网络输出的预编码和相移信号经过完整的ISAC信号模型算出来的用户SINR、感知SNR都是可微的梯度回传非常直接。相比之下有监督学习经常会出现网络学到了某个中间表示、但最终性能不达标的问题因为监督信号是标签距离不是系统性能。第三适应性更强。实际系统的信道分布会随环境和用户位置变化无监督模型可以把新采到的CSI直接拿来做在线微调不需要为新场景重新标注数据。这一点对无线部署场景非常友好。我在测试中发现IBF-Net本身不需要太大的参数量因为物理模型承担了大部分计算网络只需要学习从CSI到高维波束空间的低维映射轻量级结构完全够用。2. 轻量级IBF-Net的模型拆解与选型逻辑2.1 网络输入输出从CSI到相移与波束向量的映射IBF-Net的输入我直接组了一个一维特征向量把基站到RIS信道、RIS到每个用户的信道、基站到用户直射信道、以及感知目标的直射和RIS链路信道全部拆成实部虚部展平后拼接。这样处理的好处是实现简单不依赖输入矩阵的二维结构换天线规模或用户数时只需要改特征维度。输出分成两个头前2×Nt×K维是预编码矩阵的实部和虚部后M维是RIS相位。预编码部分reshape成复数矩阵后我会用一个功率归一化层将总发射功率压到基站允许的最大值。RIS相位部分直接用tanh激活把输出压到[-1,1]再乘上π得到相位弧度。把RIS的单位模约束直接固化在网络结构里训练时就不需要再添加拉格朗日惩罚项省了很多调参麻烦。2.2 轻量化的三个措施复数CNN、瓶颈结构、相位归一化很多同学一看到信道是复数就想去搭复数神经网络。实际项目里我劝大家冷静复数卷积在实现和部署上都很重。我这边的经验是把复数信道的实部和虚部当成两个独立特征通道送入网络效果与复数卷积几乎一致参数却少了一半。因为网络在训练中能自己学到实部虚部之间的耦合关系不需要用显式的复数算子去约束。第二个措施是瓶颈结构。我在网络中间加了一个把所有特征压缩到32维或64维的全连接层相当于自编码器里的潜变量。这个瓶颈逼迫网络只保留与波束成形最相关的信息既降低过拟合风险又把参数量压到一个RIS边缘控制器能轻松运行的水平。第三个措施就是前面提到的相位输出归一化。tanh加π乘法的输出天然落在(-π,π)区间对应RIS每个单元的连续可调相移。我在实验里对比过直接输出线性相位再接单位圆投影的做法前者收敛更快因为激活层的饱和特性相当于一个正则项限制了输出范围网络不会在开局就乱飞。2.3 联合损失函数里的权衡系数怎么设计损失函数我定义为L -R_comm - μ * log2(1 SNR_sensing)其中R_comm是K个用户的平均可达速率SNR_sensing是感知目标处的接收信噪比。感知项取对数是为了和通信速率处于同一数量级避免训练时某一项在loss里过大把梯度带偏。μ就是通信和感知之间的权衡系数μ0时系统只优化通信μ很大时感知指标优先实际效果会在两者之间走一条帕累托边界。这个系数不必拍脑袋取。我习惯先令μ0训练到通信速率进入平台期再把μ加到0.1到1之间继续训练。这样网络先建立基础的通信预编码结构再逐步学习如何用剩余自由度兼顾感知目标收敛稳定性和最终性能都好于直接大μ训到底。相比之下如果你一开始就μ5通信速率很可能直接崩掉后面怎么调都拉不回来。3. 核心代码实现与复现要点3.1 环境准备与信道数据生成PyTorch版本建议1.12以上因为要用到复数张量运算。没有特殊硬件要求训练一个轻量MLP用CPU也能凑合跑但最好还是开GPU加速。信道模型用最常用的瑞利衰落加单位功率归一化。下面这段代码生成训练用的一批信道参数。import torch import torch.nn as nn import math def generate_channels(Nt8, M32, K2, batch_size4): # 基站到RIS信道 G: [B, M, Nt] G (torch.randn(batch_size, M, Nt) 1j * torch.randn(batch_size, M, Nt)) / math.sqrt(Nt) # RIS到K个用户信道: [B, K, M] H_ru (torch.randn(batch_size, K, M) 1j * torch.randn(batch_size, K, M)) / math.sqrt(M) # 基站到K个用户直射信道: [B, K, Nt] H_bu (torch.randn(batch_size, K, Nt) 1j * torch.randn(batch_size, K, Nt)) / math.sqrt(Nt) # 基站到感知目标直射信道: [B, 1, Nt] H_ds (torch.randn(batch_size, 1, Nt) 1j * torch.randn(batch_size, 1, Nt)) / math.sqrt(Nt) # RIS到感知目标信道: [B, 1, M] H_rs (torch.randn(batch_size, 1, M) 1j * torch.randn(batch_size, 1, M)) / math.sqrt(M) return G, H_ru, H_bu, H_ds, H_rs直射和RIS路径都按各自天线数量归一化是为了让链路能量不随Nt或M变化否则网络很容易偷懒直接忽略弱链路导致感知性能上不去。3.2 IBF-Net的PyTorch实现模型本体我用了一个三层MLP加两个输出头。这里为了演示隐藏层宽度取了128已经能覆盖Nt8、M32、K2的小规模场景。如果你要扩展到大阵列瓶颈层可以保持64不变只在输入层加宽度。class IBFNet(nn.Module): def __init__(self, input_dim, hidden_dim128, Nt8, M32, K2): super().__init__() self.Nt, self.M, self.K Nt, M, K self.fc nn.Sequential( nn.Linear(input_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, 2 * Nt * K M) ) def forward(self, x): raw self.fc(x) beam_real raw[:, :self.Nt * self.K] beam_imag raw[:, self.Nt * self.K: 2 * self.Nt * self.K] phase_raw raw[:, 2 * self.Nt * self.K:] # 组合复数预编码矩阵 W: [B, Nt, K] beam_complex torch.stack([beam_real, beam_imag], dim-1) W torch.view_as_complex(beam_complex.reshape(-1, self.Nt, self.K, 2)) # 相位输出用tanh限制到(-pi, pi) phi math.pi * torch.tanh(phase_raw) return W, phitorch.view_as_complex要求输入张量的最后一维是2这里正好把实部和虚部排在最后。注意reshape之前用了stack最后reshape成[Nt,K]和信道矩阵的维度定义对齐。3.3 无监督训练循环与损失函数实现信道特征拼接我单独封装了一个函数。然后把前向得到的预编码经过功率归一化再送到联合损失函数里计算。def build_feature(G, H_ru, H_bu, H_ds, H_rs): parts [G.real, G.imag, H_ru.real, H_ru.imag, H_bu.real, H_bu.imag, H_ds.real, H_ds.imag, H_rs.real, H_rs.imag] return torch.cat([p.flatten(1) for p in parts], dim1) def project_power(W, Pmax1.0): power (W.abs()**2).sum(dim(1, 2)) scale torch.sqrt(Pmax / power.clamp_min(1e-12)) return W * scale.view(W.size(0), 1, 1) def joint_loss(G, H_ru, H_bu, H_ds, H_rs, W, phi, mu0.5, sigma21e-2): W project_power(W) Theta torch.diag_embed(torch.exp(1j * phi)) H_user H_bu torch.bmm(H_ru, Theta.bmm(G)) # [B,K,Nt] H_sens H_ds torch.bmm(H_rs, Theta.bmm(G)) # [B,1,Nt] # 通信速率 received torch.bmm(H_user, W) # [B,K,K] signal torch.diagonal(received, dim1-2, dim2-1).abs()**2 interference received.abs()**2.sum(dim-1) - signal sigma2 rate torch.log2(1 signal / interference).mean() # 感知SNR所有数据流合并到目标处的总功率 sens_power torch.bmm(H_sens, W).abs()**2.sum(dim-1).mean() snr_sens sens_power / sigma2 return -rate - mu * torch.log2(1 snr_sens)训练循环没什么特别就是标准的最小化流程。我习惯在信道生成后固定随机种子做验证否则每次跑出来的结果离散度太大不方便比较算法差异。torch.manual_seed(0) model IBFNet(input_dim2 * (M * Nt K * M K * Nt Nt M)) optimizer torch.optim.Adam(model.parameters(), lr1e-3) for epoch in range(300): G, H_ru, H_bu, H_ds, H_rs generate_channels(batch_size16) x build_feature(G, H_ru, H_bu, H_ds, H_rs) W, phi model(x) loss joint_loss(G, H_ru, H_bu, H_ds, H_rs, W, phi, mu0.5) optimizer.zero_grad() loss.backward() optimizer.step() if epoch % 30 0: print(epoch, loss.item())梯度是能直接穿过功率归一化和相位tanh的。clamp_min在极少数功率接近0的点上不可导但实际训练中几乎不会遇到没必要额外处理。3.4 训练完如何做性能评估评估阶段关闭梯度重新采一批独立测试信道记录每个样本的通信速率和感知SNR。如果想画权衡曲线就固定同一批信道把μ从0逐渐调到2再各自跑一轮训练记录结果。我用Nt8、M32、K2、信噪比为10dB的仿真场景做了对比。IBF-Net的通信速率比随机相位加最大比特输的基线高出约40%感知SNR提升约8dB和经典交替优化相比性能损失不到1dB但单次网络前向推理只需要2ms左右而交替优化跑完一个信道点通常要100ms以上。这个时延差距直接决定了它能不能用在实时波束成形上。4. 实操过程中的常见问题与排查技巧4.1 通信速率上不去损失不下降我先踩过的一个坑是信道没有归一化。生成信道时如果不除以对应的天线数平方根链路功率会随阵列规模增加训练初期loss波动巨大。解决方法是按上面代码那样对每条链路做归一化或者直接对输入特征做batch norm二者选一个即可。另一个常见问题是RIS相位输出头的权重初始化太大。tanh对输入非常敏感如果最后一层线性权重初始值在5以上相位会直接饱和到±π网络梯度消失所有RIS单元的输出几乎一样性能完全退化。解决办法是把输出层的权重设到0附近初始相位接近0网络再自己去学习该偏转的角度。我用nn.init.zeros_(model.fc[-1].weight)就能稳定复现。4.2 感知性能与通信性能打架很多人在损失函数里把μ调得很大感知SNR还是上不去。这时候先检查信道里有没有严重的“目标遮挡”。如果感知目标的角度和用户方向太接近从物理上就存在强干扰耦合纯靠波束成形很难两全。可以增加RIS反射单元数量或者让感知和通信分时隙工作再去衡量联合增益。如果物理条件没问题问题多半出在训练顺序。我建议采用两阶段训练先在μ0下训练通信把通信速率平台期固定下来再带着这个预训练权重把μ增加到目标值。第二阶段网络只在现有波束边界内做小幅度调整收敛速度明显更快最终能拿到的帕累托前沿也更好看。4.3 相移变量离散化后性能损失严重真实RIS器件的相移通常只有1bit或2bit比如离散到{0,π}或{0,π/2,π,3π/2}。如果在连续相位上训练完再做量化性能会掉得很凶。我的解决办法是直接在训练阶段模拟量化使用直通估计器STE前向用量化后的相位反向把量化后的不可导部分用连续相位近似替代。def quantize_phi(phi, level2): # level2表示2bit量化共4个离散值 delta 2 * math.pi / (2**level) phi_q (phi / delta).round() * delta # STE: 正向使用phi_q反向梯度按phi计算 return phi (phi_q - phi).detach()把这个函数插在joint_loss里Theta构造之前网络会自动学会对量化误差鲁棒的控制方式。4.4 轻量化之后精度下降怎么补偿如果模型缩得太狠性能损失超过可接受范围可以先训练一个大教师网络再用知识蒸馏把教师网络的输出作为辅助监督信号。学生网络保留轻量结构损失函数改成L L_joint β*(||W_s-W_t||²γ*||exp(jφ_s)-exp(jφ_t)||²)。β从1开始逐步降到0.1学生网络通常在维持80%轻量化收益的前提下换回大部分精度。另一个补偿思路是特征降维。别把所有原始信道直接铺进网络先对通信和感知信道分别做主成分分析只保留前几个主奇异值对应的特征。因为波束成形主要依赖信道的主要特征方向噪声子空间反而是干扰源。这相当于在做一次物理层面的数据增强比单纯加大网络宽度高效得多。现象优先排查方向我的处理建议loss不下降信道未归一化、输出层权重过大做信道归一化相位头零初始化感知性能差μ太小、目标与用户强相关两阶段训练适当增加μ量化后性能暴跌训练未考虑离散相移用STE直通估计器模拟量化轻量化后掉点模型容量不够知识蒸馏保留主要特征子空间上面这张表是我每次调模型都会贴在终端旁边的速查表。这里面最容易被忽略的是输出层初始化我折腾了整整一天才定位到。如果你也准备复现这套方案强烈建议从这两个地方先检查能省下大量排错时间。我自己现在调这套系统时还会先在通信单用户场景把相位输出头初始化成接近全聚的相位再逐步放开用户数量这个顺序能让网络少走很多弯路。本文还有配套的精品资源点击获取