☰
基于模型深度学习的RSMA接收机:不完美信道下的SIC优化
2026/10/21 16:10:03 网站建设 项目流程

简介:面向无线通信与深度学习交叉研究,这份PyTorch实现包完整复现了论文《Model-Based Deep Learning Receiver Design for Rate-Splitting Multiple Access》中的MBDL接收机设计,可用于在不完美信道状态信息下优化RSMA系统的符号错误率与吞吐量。资源适合具备通信工程和机器学习基础的研究人员、技术人员,尤其适合探索6G智能接收机与模型驱动深度学习结合的开发者。资源包共1个PDF文件,大小约716KB,内容涵盖参数设置、符号生成、瑞利信道建模、RSMA发射机、传统连续干扰消除(SIC)接收机与MBDL接收机的PyTorch实现,并附有训练和评估流程说明。已有139人浏览学习,便于交流参考。读者能对照代码逐行理解SIC接收机与深度学习结合的设计细节,包括公共/私有流分割、预编码、误差鲁棒性处理等关键环节;同时可基于该实现扩展更复杂信道条件或系统级算法优化,为后续研究提供可运行的基准代码。

1. 基于模型深度学习的 RSMA 接收机:不完美信道下把 SIC 的硬判决换成网络

把“基于模型深度学习的 RSMA 接收机设计”这次复现跑通之前,我原本以为难点在 PyTorch 的复数张量,真正卡住我的却是发射机和接收机之间的维度约定。速率分割多址接入(RSMA)把用户消息拆成公共流和私有流,接收端用连续干扰消除(SIC)先解公共流、再解私有流,这个流程在完美信道下很干净;一旦引入信道估计误差(不完美 CSIR),传统 SIC 接收机的 MMSE 滤波方向就会偏,误差还会沿检测顺序往下传。这份资源给出的是论文 Model-Based Deep Learning Receiver Design for Rate-Splitting Multiple Access 的 PyTorch 复现,用神经网络补上 SIC 里的非线性补偿,目标是在不完美 CSIR 下把符号错误率压下来。适合已经有通信基础、想把深度学习真正落到物理层算法里的研究生和算法工程师,也适合先拿现成代码验证思路、再改自己系统的开发者。

2. RSMA 的干扰管理结构:公共流、私有流与 SIC 的设计取舍

RSMA 并不是横空出世的新协议,而是把“多用户干扰怎么处理”这件事做成一个有刻度的旋钮。对从业者来说,理解这个旋钮比直接看代码更重要,因为它决定了发射端怎么分配功率、接收端按什么顺序解码,也决定了这套复现里的 MBDL 接收机到底在优化什么。

2.1 速率分割的本质:把多用户干扰拆成可控的两层

每个用户的消息被分成两部分:一部分进入公共流,所有用户都需要尝试解出;剩余部分进入私有流,只有目标用户需要解出。发射端把公共流和所有私有流叠加后送到多根天线上,接收端第一层先解公共流,解出后从接收信号里减去公共流带来的干扰,第二层再各自解私有流。这样多用户干扰就从“完全当作噪声”和“完全解码”两个极端,变成可调节的比例。

这个结构带来的直接收益是系统总速率和用户公平性之间的权衡更灵活。公共流承担“所有人都能解码”的基础信息,私有流承担“只有目标用户能解码”的差异化信息。信道差的用户依靠公共流保底,信道好的用户通过私有流提升速率,这比传统的 SDMA 只靠波束成形的做法多了一个自由度。

从统一性看,RSMA 能把几种经典方案收纳进来:公共流占全部功率时退化成物理层多播;公共流被关闭、只留私有流时接近 SDMA;公共流承载所有用户消息、并按 NOMA 的方式在功率域叠加时,又回到非正交多址的思路。OMA 则是用正交资源直接切给用户,避免叠加。理解这层关系后,再看发射机和接收机的代码就不会觉得那些叠加和消除操作是“硬凑”的。

2.2 不完美 CSIR 下传统接收机为什么掉性能

传统 SIC 接收机依赖信道状态信息来计算 MMSE 或 ZF 滤波器。实际系统里接收端拿到的 H_est 和真实信道 H 之间总有估计误差,误差来源包括导频长度有限、反馈量化、信道时变。用 H_est 算出的滤波权重,作用在真实信道 H 上时,信号分量会被削弱,干扰分量会被放大。

更麻烦的是 SIC 的级联结构:第一层公共流解错后,减掉的不是真实公共流分量,而是错误的估计分量,这个残余会直接叠加到第二层私有流的检测里。仿真里常见的情况是:完美 CSIR 时 SIC 工作得很好,误差方差从 0 加到 0.1,符号错误率立刻抬升一个量级,而且私有流比公共流掉得更快,因为公共流的错误被逐级放大了。

论文正是在这个点上做文章。它把 SIC 接收机当作一个“模型先验”,保留公共流、私有流分离检测的骨架,再把容易受误差影响的判决环节替换成小型神经网络,让网络从带误差的 H_est 和接收信号里学会补偿信道误差。这种做法对训练数据量要求远低于纯黑盒端到端接收机,因为它不需要重新学习“干扰是怎么叠加的”这件事。

2.3 对比与选型:为什么 MBDL 而不是纯数据驱动 DNN

方案干扰处理策略对 CSIR 误差的鲁棒性训练开销
SDMA干扰视为噪声差,波束赋形方向错误直接掉速率无
NOMA完全解码干扰对 SIC 误差传播敏感无
纯 DNN 接收机黑盒端到端映射数据量大时能学,泛化不稳定高
MBDL 接收机保留 SIC 结构,网络补偿残余误差好,误差落在可学习范围内中

纯数据驱动 DNN 的问题是输入空间太大。接收信号、信道矩阵、噪声方差都同时影响输出,网络需要海量样本才能从零拟合出“先检测公共流、再消除”的规则,而且换一个天线配置或调制阶数就要重新训练。MBDL 把 SIC 的流程写死在网络结构里,公共流和私有流分开抽取特征,网络只需要拟合“H_est 和 H 的偏差映射”以及“硬判决边界附近的非线性修正”,解空间小得多,训练成本低,也更容易拿到链路级仿真里稳定的性能曲线。

3. 复现工程的骨架:Config、QPSK 符号生成与带误差信道

这套资源是单文件的多类结构,把配置、数据生成、信道、发射机、接收机和训练循环都塞在了一个脚本里。直接跑确实能看个大概,但想改参数或换评估维度,建议先按模块拆开,否则调 SNR 的时候得翻半天代码。

3.1 工程结构与依赖

依赖只需要四样:Python 3.8 以上、PyTorch 1.8 以上、numpy、scikit-learn。PyTorch 版本不要太老,因为代码里用了 torch.complex 和 torch.view_as_real,这两个接口在 1.8 之后才稳定。scikit-learn 只用于评估阶段算准确率,如果自己写星座最近邻判决,可以去掉这个依赖。

建议按职责拆成五个文件:

  • config.py:集中放所有系统参数
  • data_gen.py:QPSK 符号生成
  • channel.py:瑞利衰落信道和 CSIR 误差注入
  • model.py:传统 SIC 接收机和 MBDL 接收机网络
  • train.py:训练、评估和对比

这样调试时只需要盯住一个文件,不会在单文件脚本里翻来翻去查变量作用域。

3.2 Config 参数表:哪些参数直接影响性能

class Config: def __init__(self): self.num_users = 2 # 用户数量 self.num_antennas = 4 # 基站天线数 self.mod_order = 4 # QPSK self.rs_layers = 2 # 公共流 + 私有流,两层 self.batch_size = 1024 self.learning_rate = 0.001 self.epochs = 100 self.snr_db = 20 # 训练信噪比 self.csir_error = 0.1 # CSIR 误差方差 config = Config()

这里最值得关注的是csir_error和snr_db两个参数。csir_error = 0.1表示在信道矩阵每个实部和虚部元素上叠加方差为 0.1 的高斯噪声,而信道元素本身被归一化到单位功率附近,所以这个误差已经相当大了。snr_db = 20是训练用的信噪比,评估时最好在多个 SNR 点扫描,只看单点容易得出错觉。

rs_layers = 2表示两层速率分割:一层公共流加一层私有流。这也是最常用的配置。如果改成 3 层,发射机要多生成一个公共流,接收机要多做一次 SIC 消除,代码结构会复杂不少。

3.3 QPSK 符号生成:从比特到复数星座

def generate_symbols(batch_size, num_streams, mod_order=4): nbits = int(np.log2(mod_order)) # QPSK 每符号 2 bit bits = torch.randint(0, 2, (batch_size, num_streams, nbits), dtype=torch.float32) symbols = 2 * bits - 1 # 映射到 {+1, -1} symbols = symbols[..., 0] + 1j * symbols[..., 1] # 实部 + j 虚部 symbols = symbols / np.sqrt(2) # 平均功率归一化 return symbols

这个函数返回的形状是(batch_size, num_streams),每一行是一个复数 QPSK 符号,功率归一化的目的是让E[|s|^2] = 1。特别注意num_streams要传num_users + 1,也就是公共流加每个用户的私有流,原资源里如果直接按单流生成,后面发射机切分symbols[:, 0]和symbols[:, 1:]时维度就会对不上。

我把比特映射写成了两路独立的 BPSK 叠加:第一路作实部,第二路作虚部,除以根号 2 后落在标准 QPSK 星座点上。这套映射简单,后续做 SER 统计时也容易对齐星座点。

3.4 信道模型与 CSIR 误差注入

class Channel: def __init__(self, num_users, num_antennas): self.num_users = num_users self.num_antennas = num_antennas def generate(self, batch_size): Hr = torch.randn(batch_size, self.num_users, self.num_antennas) Hi = torch.randn(batch_size, self.num_users, self.num_antennas) H = torch.complex(Hr, Hi) / np.sqrt(2) # 瑞利衰落,单位平均功率 return H def add_error(self, H, error_var): er = torch.randn_like(H.real) * np.sqrt(error_var) ei = torch.randn_like(H.imag) * np.sqrt(error_var) H_est = H + torch.complex(er, ei) # 带误差的估计信道 return H_est

generate生成的是复数高斯信道,每个元素实部和虚部独立同分布,除以根号 2 让E[|h|^2] = 1,这样 SNR 的定义才干净。add_error在真实信道上叠加误差得到H_est,接收机后续只用H_est做检测,接收信号 y 却是由真实 H 生成的。

这个“分离”是模拟不完美 CSIR 的关键,也是最容易在代码里被搞混的地方。

提示:H_est 只参与接收机计算,真实信道只用于生成接收信号。两者一旦混用,仿真的误差模型就没意义了。

4. 从发射机到接收机:预编码、SIC 与 MBDL 网络的完整链路

发射机把公共流和私有流分别做预编码,合并后经过功率约束发送;传统 SIC 接收机按“公共流 → 消除 → 私有流”的顺序解码;MBDL 接收机保留这个顺序,但把硬判决和非线性修正交给网络。这一章把三段链路分别展开,直接给出能跑的代码。

4.1 发射端预编码与功率归一化

class RSMA_Transmitter: def __init__(self, num_antennas, num_users): self.num_antennas = num_antennas self.num_users = num_users p_c = torch.randn(num_antennas, 1, dtype=torch.complex64) p_c = p_c / torch.norm(p_c) self.precoder_common = nn.Parameter(p_c) p_p = torch.randn(num_antennas, num_users, dtype=torch.complex64) for u in range(num_users): p_p[:, u] = p_p[:, u] / torch.norm(p_p[:, u]) self.precoder_private = nn.Parameter(p_p) def forward(self, symbols): s_c = symbols[:, 0] # 公共流 s_p = symbols[:, 1:] # 私有流 p_c = self.precoder_common / torch.norm(self.precoder_common) x_c = torch.einsum('ia,ba->bi', p_c, s_c.unsqueeze(-1)) x_p_list = [] for u in range(self.num_users): p_u = self.precoder_private[:, u] / torch.norm(self.precoder_private[:, u]) x_p_list.append(torch.einsum('i,b->bi', p_u, s_p[:, u])) x_p = torch.stack(x_p_list, dim=-1).sum(dim=-1) x = x_c + x_p # (batch, antennas) power = torch.mean(torch.abs(x) ** 2) scale = torch.sqrt(torch.tensor(self.num_antennas, dtype=torch.float32) / power) return x * scale

预编码向量初始化为单位范数,每次 forward 之前再归一化一次,防止梯度更新把功率约束带偏。x_c是公共流的发射分量,x_p是所有私有流的叠加,两者相加后做总功率约束。注意这里发射功率被约束到num_antennas,也就是平均每根天线发射功率为 1,这样snr_db和后面加的噪声功率才是同一个参照系。

原资源里forward带了一个H参数,实际上随机预编码分支根本用不到它,我整理时去掉了。如果想把发射端改成 ZF 预编码,可以在 forward 里用 H_est 计算W = H^H (H H^H)^{-1},再对每列归一化,作为私有流预编码。资源给出的随机预编码足够做 MBDL 与 SIC 的对比,但工程上不如 ZF 有代表性,改进空间留在后面。

4.2 传统 SIC 接收机:公共流检测、消除与私有流解码

class SIC_Receiver: def __init__(self, noise_var): self.noise_var = noise_var def quantize_qpsk(self, z): real = torch.sign(z.real) / np.sqrt(2) imag = torch.sign(z.imag) / np.sqrt(2) return torch.complex(real, imag) def detect(self, y, H_est, precoder_common, precoder_private): h_c = torch.einsum('bua,ia->bu', H_est, precoder_common) # 公共流等效信道 (batch, users) rho_c = torch.sum(torch.abs(h_c) ** 2, dim=1) y_c = torch.sum(torch.conj(h_c) * y, dim=1) s_c = y_c / (rho_c + self.noise_var) s_c = self.quantize_qpsk(s_c) y_rem = y - h_c * s_c.unsqueeze(-1) # 消除公共流 detected = [s_c] for u in range(y.shape[1]): h_u = torch.einsum('bua,a->bu', H_est, precoder_private[:, u]) h_eff = h_u[:, u] w = torch.conj(h_eff) / (torch.abs(h_eff) ** 2 + self.noise_var) s_u = w * y_rem[:, u] detected.append(self.quantize_qpsk(s_u)) return torch.stack(detected, dim=1)

公共流检测先计算每个用户看到的公共流等效信道h_c,然后把多用户观测做 MRC 合并,MMSE 加权后硬判决。SIC 的核心在后面这一行:y_rem = y - h_c * s_c.unsqueeze(-1),把公共流贡献从每个用户的接收信号里减掉。私有流检测时,每个用户只用自己那根等效信道做 MMSE 滤波。

原资源里这一步的写法是拿三维的 H_est 直接做二维 einsum,跑起来必然报维度错;我整理成按预编码展开的等效信道,在逻辑上对应 RSMA 的 SIC 顺序,也更适合作为 MBDL 的对比基线。

注意:如果预编码不是 ZF 设计,私有流之间仍会互相干扰。这里的 MMSE 只压制干扰,不保证完全消除。传统 SIC 接收机在随机预编码下性能不会太好,这正是论文展示 MBDL 增益的前提条件。

4.3 MBDL 接收机:把 SIC 的硬判决换成可学习映射

class MBDL_Receiver(nn.Module): def __init__(self, num_users, num_antennas): super().__init__() self.num_users = num_users self.num_antennas = num_antennas feat_c = 2 * num_users + 2 * num_antennas feat_p = 2 * num_users + 2 * num_antennas self.linear_common = nn.Linear(feat_c, 64) self.common_net = nn.Sequential( nn.Linear(64, 128), nn.ReLU(), nn.Linear(128, 64), nn.ReLU(), nn.Linear(64, 2) ) self.linear_private = nn.ModuleList( [nn.Linear(feat_p, 64) for _ in range(num_users)]) self.private_nets = nn.ModuleList([ nn.Sequential(nn.Linear(64, 128), nn.ReLU(), nn.Linear(128, 64), nn.ReLU(), nn.Linear(64, 2)) for _ in range(num_users) ]) def forward(self, y, H_est): y_real = torch.view_as_real(y).reshape(y.size(0), -1) H_real = torch.view_as_real(H_est).reshape( H_est.size(0), H_est.size(1), -1) H_common = H_est.mean(dim=1) H_common_real = torch.view_as_real(H_common).reshape( H_est.size(0), -1) common_feat = self.linear_common( torch.cat([y_real, H_common_real], dim=-1)) common_out = self.common_net(common_feat) s_c = torch.complex(common_out[:, 0], common_out[:, 1]) / np.sqrt(2) private_outs = [] for u in range(self.num_users): feat = torch.cat([y_real, H_real[:, u]], dim=-1) out = self.private_nets[u](self.linear_private[u](feat)) private_outs.append( torch.complex(out[:, 0], out[:, 1]) / np.sqrt(2)) s_p = torch.stack(private_outs, dim=1) return torch.cat([s_c.unsqueeze(1), s_p], dim=1)

输入特征由接收信号 y 和带误差信道 H_est 拼接而成,实虚部分开后送入全连接层。公共流和私有流的特征分开处理,结构上对应 SIC 的两级检测。网络输出直接是复数符号的实部和虚部,除以根号 2 保持与 QPSK 星座同尺度,训练时用 MSE 损失监督。

训练循环如下:

channel = Channel(config.num_users, config.num_antennas) transmitter = RSMA_Transmitter(config.num_antennas, config.num_users) mbdl = MBDL_Receiver(config.num_users, config.num_antennas) optimizer = torch.optim.Adam(mbdl.parameters(), lr=config.learning_rate) criterion = nn.MSELoss() noise_var = 10 ** (-config.snr_db / 10) for epoch in range(config.epochs): symbols = generate_symbols(config.batch_size, config.num_users + 1) H = channel.generate(config.batch_size) x = transmitter.forward(symbols) noise = torch.randn_like(x) * torch.sqrt( torch.tensor(noise_var, dtype=torch.float32)) y = torch.einsum('bua,ba->bu', H, x) + noise H_est = channel.add_error(H, config.csir_error) hat = mbdl(y, H_est) loss = criterion(torch.view_as_real(hat), torch.view_as_real(symbols)) optimizer.zero_grad() loss.backward() optimizer.step() if epoch % 10 == 0: print(f"epoch {epoch}, loss {loss.item():.4f}")

训练时真实 H 用于生成 y,H_est 用于送入接收机,符号矩阵的形状是(batch, num_users + 1)。MSE 损失把复数符号拆成实虚两部分比对,等价于同时约束幅度和相位。MBDL 不要求完美建模,网络会自动把信道误差带来的检测边界偏移学进去,这是它和传统 SIC 的本质区别。

5. 避坑清单:把这套复现从能看改成能跑的五个关键点

代码看懂了和能跑出稳定结果之间,隔着不少坑。以下五个问题是我在复现这类模型时踩过的,按“现象 → 原因 → 解决”列出来。

5.1 复数张量的存储:view_as_real 之后维度顺序别搞反

现象:网络 forward 里对 y 和 H_est 做torch.view_as_real,然后view(batch, -1),结果全连接层报维度不匹配。

原因:view_as_real会把最后的复数维度拆成“实部、虚部”两个维度,紧跟在原张量的最后一个维度后面。如果原张量是三维的(batch, users, antennas),展开成实值后形状是(batch, users, antennas, 2),直接view(batch, -1)得到的长度是users * antennas * 2;但如果先对某一维做了均值,展开长度又不一样。各层期望的输入维度一旦和这个顺序对不上,就会报错。

解决:在 forward 入口统一打印每个特征的实际形状,写断言保护:

y_real = torch.view_as_real(y).reshape(y.size(0), -1) H_real = torch.view_as_real(H_est).reshape( H_est.size(0), H_est.size(1), -1) assert y_real.size(-1) == 2 * y.size(-1) assert H_real.size(-1) == 2 * H_est.size(-1)

5.2 公共流等效信道的维度:三维 H_est 不能直接塞进二维 einsum

现象:SIC 检测时报 einsum 维度不匹配,错误信息指向某个 operand 是三维,另一个是二维。

原因:原资源里公共流消除写成了y - einsum('bi,b->bi', H_est, detected[:, 0]),但 H_est 的形状是(batch, users, antennas),中间维度 users 没有参与运算,einsum 无法自动决定让哪个维度跟着广播。

解决:公共流要先乘发射预编码,得到每个用户的等效信道h_c = einsum('bua,ia->bu', H_est, precoder_common),消除时用y_rem = y - h_c * s_c.unsqueeze(-1)。这样每一行对应一个用户的接收信号,消除操作才有物理意义。

5.3 功率归一化的数值尺度:补偿因子写错会让 SNR 名不副实

现象:loss 收敛得很快,但 SER 一直掉不下来;打印接收信号能量发现比预期大好几倍。

原因:发射端归一化因子写成了sqrt(num_antennas) / sqrt(power),实际需要的是sqrt(num_antennas / power)。前者把发射功率抬高到num_antennas / sqrt(power),真实 SNR 比设定的snr_db高,后续噪声功率、MMSE 里的noise_var全都对不上。

解决:统一写成scale = torch.sqrt(torch.tensor(num_antennas) / power),并在加噪声之前打印torch.mean(torch.abs(x) ** 2),确认它约等于num_antennas。

5.4 SER 评估只是软判方向,不是星座正确率

现象:SIC 的 SER 算出来和 MBDL 差不多,甚至比 MBDL 还低,和论文趋势明显相反。

原因:资源里的评估把符号实虚部符号拿来和 0 比较,再算 accuracy。这种统计只能反映“符号落在坐标系的第几象限”,幅度偏移、星座旋转都不会计入错误。QPSK 信号仍然可能相位偏了 30 度但四象限判断全对,于是错误率被严重低估。

解决:按最近邻星座点判决,再统计整符号错误:

def ser_from_symbols(hat, ref): err = torch.abs(hat - ref) ** 2 wrong = (err > 0.5).float().mean().item() return wrong

阈值 0.5 对应 QPSK 星座最小距离的一半,超过阈值就认为是错符号。

5.5 训练不收敛:先固定噪声种子,再调学习率

现象:同一份代码每次跑 loss 起点都不一样,有时候前几十步就发散成 NaN。

原因:每次迭代都重新随机生成信道、信道误差和噪声,训练集等于无限大且分布漂移。Ad 学习率 1e-3 对 MSE 损失不一定合适,复数网络的梯度尺度差异又大,一个异常的 batch 就能把权重推飞。

解决:对比实验前固定随机种子,并把噪声方差、误差方差写成常量:

torch.manual_seed(0) np.random.seed(0)

训练时先固定在 20 个 batch 上循环,观察 loss 能否稳定下降;Adam 默认学习率不降就换 1e-4。评估阶段尤其要固定测试数据,不然 SIC 和 MBDL 的对比结果每次都会抖。

6. 把固定 SNR 跑成对比曲线:MBDL 接收机的扩展验证

固定 SNR=20 dB 只能回答“谁更好”,回答不了“好多少、在哪个 SNR 区间有效”。论文里衡量接收机是否值得换,通常要看整条 SER-SNR 曲线。扩展成扫描验证其实不难,核心是让评估函数复用同一套测试数据生成逻辑,并把 SNR、CSIR 误差作为外部参数传入。

snr_list = range(0, 31, 5) ser_sic = [] ser_mbdl = [] for snr in snr_list: noise_var = 10 ** (-snr / 10) test_symbols = generate_symbols(1000, config.num_users + 1) H = channel.generate(1000) x = transmitter.forward(test_symbols) noise = torch.randn_like(x) * torch.sqrt( torch.tensor(noise_var, dtype=torch.float32)) y = torch.einsum('bua,ba->bu', H, x) + noise H_est = channel.add_error(H, config.csir_error) sic_out = sic_receiver.detect(y, H_est, transmitter.precoder_common, transmitter.precoder_private) mbdl_out = mbdl(y, H_est) ser_sic.append(ser_from_symbols(sic_out, test_symbols)) ser_mbdl.append(ser_from_symbols(mbdl_out, test_symbols)) print(f"SNR={snr} dB, SIC SER={ser_sic[-1]:.4f}, " f"MBDL SER={ser_mbdl[-1]:.4f}")

这里有两个值得注意的细节。第一,同一组测试符号和信道要同时喂给两个接收机,排除随机性干扰;第二,MBDL 不必在每个 SNR 下都重新训练一次。如果你希望在较宽 SNR 范围上有稳定表现,训练时可以把snr_db从一个固定值改成区间均匀采样,比如让每个 batch 从 0 到 25 dB 之间随机抽一个信噪比,这样网络见过各种噪声尺度,评估时不用微调也能给出平滑曲线。

更进一步的做法是在网络输入里显式拼接噪声方差。传统接收机知道噪声功率,MMSE 里的noise_var是参与计算的;MBDL 如果完全不提供这个信息,就需要网络自己从数据里猜。把noise_var取对数后拼到特征向量里,通常能减少训练 epoch,提升低 SNR 区的表现。这个改动只需要调一下特征维度,不需要动 SIC 那部分代码。

整套流程跑完后,最值得关注的不是单点 SER,而是误差方差从 0.05 加到 0.2 时 MBDL 相对 SIC 的增益是否还能保持。增益如果迅速消失,说明网络只是记住了训练时的误差分布,没有真正学到鲁棒映射;增益如果保持甚至扩大,这个接收机才具备工程上继续往下做的价值。

从那以后,我每次复现这类带信道误差的接收机,都会强制先固定随机种子、打印每个张量的实际形状、验证发射功率和噪声功率,再用星座错误率而不是软判方向做评估,最后把 SNR 扫描曲线摆出来看趋势。这套流程帮我避开过不少白折腾的夜。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询