
简介面向无线通信方向的学习者这是一份围绕MIMO混合波束成形的Matlab工程资源重点解决大规模天线系统中数字与模拟波束联合设计问题。项目将深度学习引入波束成形提供从信道建模、信道状态信息处理到算法实现的完整代码框架同时保留了清晰的目录结构。压缩包共一百五十九个文件其中一百五十一个为Matlab源文件另有说明文本、配置及版本管理文件整体体积仅二百一十五KB轻量而便于携带。目前已有二百四十一人学习浏览适合希望通过实践理解混合波束成形原理的学生、研究人员与工程师。通过研读源码可掌握最小均方误差、最大似然等经典算法并能结合深度神经网络根据信道状态生成波束权重项目中关于信道矩阵构造、波束权值优化等模块也为后续二次开发或实验对比提供了直接参考。1. 为什么毫米波MIMO要引入深度学习做混合波束成形毫米波大规模 MIMO 系统里64×16 天线阵列往往只配 4 条射频链。全数字预编码在每个相干时间内对信道矩阵做一次 SVD 并不慢但硬件层面每根天线一条 RF 链的功耗和成本在基站端都压不住。混合波束成形把预编码拆成模拟域恒模矩阵和低维数字基带矩阵传统做法是用流形优化、交替最小化或码本匹配去逼近全数字性能收敛质量不差但每次信道更新都要迭代几十次在波束追踪场景里往往来不及。深度混合波束成形deepHybridBeamforming的核心思路是把信道矩阵到模拟/数字预编码的映射交给神经网络一次前向推理直接得到结果最贵的迭代优化被移到离线训练阶段。本文按 MATLAB 中最常见、最可靠的复现路径把信道生成、网络结构、训练损失、频谱效率评估和部署验证完整走一遍适合正在做 MIMO 物理层算法验证、或想用深度学习替换非凸优化模块的工程师。2. 从SVD失效到数据集构造用毫米波信道样本生成训练集2.1 恒模约束为什么让 SVD 不能直接用全数字预编码的最优解非常明确对信道矩阵 H 做 SVD取右奇异向量的前 Ns 列作为预编码方向。问题在于这个结果是任意复数矩阵每个元素的幅度和相位都可以自由变化而射频移相器只能提供相位旋转模拟预编码矩阵 FRF 的每个元素必须满足恒模约束。混合结构把预编码写成 F FRF * FBBFRF 是 Nt×Nrf 的恒模矩阵FBB 是 Nrf×Ns 的数字基带矩阵。加上恒模约束后问题变成带非线性等式约束的非凸优化SVD 得到的 V(:,1:Ns) 几乎不可能落到这个可行域里。传统算法如流形优化、正交匹配追踪OMP都针对这个非凸问题设计性能接近全数字但计算成本高。更麻烦的是5G 毫米波系统里信道变化快用户移动、波束切换都会产生新的信道估计结果每次都不迭代到收敛就无法保证性能。深度学习方案的做法是大量离线生成信道样本训练网络直接输出满足恒模与功率约束的 FRF、FBB在线推理时只有矩阵乘法和激活时间开销远低于迭代算法。常见的仿真环境里很多团队直接拿全数字 SVD 结果当标签把混合预编码当成回归任务来做。这个思路成立的前提是数据集能覆盖信道的空间相关性和能量尺度变化所以第一步要先把训练数据做对。2.2 用 Saleh-Valenzuela 模型在 MATLAB 里生成批量信道毫米波信道的标准简化模型是几何信道模型发射和接收之间通过若干个散射簇传播每个簇有若干条射线。MATLAB 里可以自己写这个生成函数不依赖额外工具箱function H genChannels(numSamples, Nt, Nr, Ncl, Nray) H zeros(Nr, Nt, numSamples); d 0.5; % 阵元间距单位波长 for i 1:numSamples Hk zeros(Nr, Nt); for c 1:Ncl AoD unifrnd(-pi/3, pi/3); % 离开角 AoA unifrnd(-pi/3, pi/3); % 到达角 alpha (randn 1j*randn) / sqrt(2); % 簇增益 for r 1:Nray phi_d AoD 0.02*2*pi*randn; % 簇内角度扩展 phi_a AoA 0.02*2*pi*randn; at exp(1j*2*pi*d*sin(phi_d)*(0:Nt-1)).; ar exp(1j*2*pi*d*sin(phi_a)*(0:Nr-1)).; beta (randn 1j*randn) / sqrt(2); % 射线增益 Hk Hk alpha * beta * ar * at; end end H(:,:,i) Hk / sqrt(Ncl*Nray); end end代码里 AoD 和 AoA 限制在正负 60 度范围内对应基站端常见的 120 度扇区覆盖阵元间距取半波长满足空间采样定理。每个簇有一个复增益 alpha簇内每条射线再有独立的小尺度衰落 beta这是 Saleh-Valenzuela 模型里最常用的两层结构。最后除以 sqrt(Ncl*Nray) 是为了让信道期望能量归一路径损耗不会对网络训练产生尺度干扰。用这个函数生成 20000 个训练样本时每个样本都要遍历所有簇和射线MATLAB 的脚本循环在样本数上来后确实慢但这是离线一次性成本。如果追求速度可以把簇和射线循环向量化或者用 parfor 替代最外层循环我在实际跑数据时通常用 parfor四核机器上能把生成时间缩短到原来的三分之一左右。2.3 用 HH 的归一化协方差作特征用右奇异向量作标签生成 H 之后还要构造网络输入和回归标签。直接输入 H 的实虚部当然可行但有两个问题一是 H 的绝对能量随路径损耗变化网络被迫去学增益缩放二是 SVD 的右奇异向量只由 HH 决定输入 H 等于让网络多学一层冗余的映射。常见做法是取 H 的厄米特协方差矩阵 R HH用迹归一化消除尺度再展成实值特征向量Vopt zeros(Nt, Ns, numSamples); X zeros(2*Nt*Nt, numSamples); for i 1:numSamples [~, ~, V] svd(H(:,:,i), econ); Vk V(:, 1:Ns); % 全数字最优方向 for k 1:Ns Vk(:, k) Vk(:, k) * exp(-1j*angle(Vk(1, k))); % 相位对齐 end R H(:,:,i) * H(:,:,i); R R / trace(R); % 去掉绝对增益 X(:, i) [real(R(:)); imag(R(:))]; Vopt(:, :, i) Vk; end这段代码里最容易被忽略的是相位对齐那一步。SVD 的奇异向量本身存在相位模糊同一个信道在不同随机种子下解出来的 V(:,1) 可能相差一个任意相位如果网络目标里有这种随机相位扰动损失曲线会一直抖动且难以收敛。把每列归一化到首元素为正实数可以让标签在样本之间保持语义一致这是此类训练任务里最有价值的排错技巧之一。特征选择上R 的维度是 Nt×Nt展开成实值后是 2NtNt网络输入会比较大。实际工程中也可以用 R 的上三角加主对角把输入压掉近一半但前提是网络实现里必须确保索引顺序一致。下表是三种常见输入形式的对比输入形式特征维度优点注意点H 实虚部展开2NrNt信息完整无额外计算能量尺度不稳定需额外归一Rtrace 归一化后实虚部2NtNt与 SVD 目标同秩尺度不变天线数大时输入维度平方增长角度域阵列响应特征与角度网格相关适合稀疏毫米波信道存在角度量化误差我一般选择第二种矩阵乘法开销量可以接受而且 trace 归一化之后网络对链路预算的变化不敏感训练出来的模型在低 SNR 和高 SNR 场景下都能保持稳定。3. 用 dlnetwork 定义混合预编码网络投影层、前向函数与损失3.1 全连接回归网络的结构选择在 MATLAB 的 Deep Learning Toolbox 里混合预编码网络不需要卷积或 Transformer 这类复杂结构一个三层全连接回归网络就足够。网络输出既要生成模拟预编码的实部和虚部也要生成数字预编码的实部和虚部输出维度是 2NtNrf 2NrfNs。以 Nt64、Nrf4、Ns2 为例输出维度是 528Nt 64; Nr 16; Nrf 4; Ns 2; featureDim 2*Nt*Nt; outDim 2*Nt*Nrf 2*Nrf*Ns; layers [ featureInputLayer(featureDim, Name, feat) fullyConnectedLayer(1024, Name, fc1) reluLayer(Name, relu1) fullyConnectedLayer(512, Name, fc2) reluLayer(Name, relu2) fullyConnectedLayer(outDim, Name, fc_out) ]; net dlnetwork(layers);网络容量主要由 Nt*Nt 的输入维度决定第一层用 1024 个神经元通常能提供足够表示能力。实际训练里如果发现 loss 降不下去优先把第二层从 512 加到 768而不是继续加深网络。原因是恒模投影是一个强非线性操作层数越多梯度在投影边界附近越容易震荡加宽比加深更容易稳定收敛。dlnetwork 与 trainNetwork 的区别在于dlnetwork 允许自定义前向函数和损失函数这对混合预编码这种需要中间层做结构化约束的任务非常关键。后面的单位模投影和功率归一化都要写在前向函数里trainNetwork 的标准训练流程做不到这一点。3.2 前向函数中的单位模投影与功率归一化网络原始输出只是普通实数向量要变成合法的混合预编码必须在 forward 之后做两步约束处理模拟部分的每一列投影到单位圆上合成后的总预编码矩阵归一化到 F 范数等于 sqrt(Ns)。如果把网络输出直接当权重用不满足硬件条件下游仿真全部没有意义。下面是一个可直接调用的前向函数function [FRF, FBB, F] hybridForward(net, dlX, Nt, Nrf, Ns) out forward(net, dlX); % [outDim, B] FRFraw out(1:2*Nt*Nrf, :); % 模拟预编码实虚部 FRFraw reshape(FRFraw, 2, Nt, Nrf, []); % [2,Nt,Nrf,B] FRF complex(FRFraw(1,:,:,:), FRFraw(2,:,:,:)); FRF FRF ./ abs(FRF); % 恒模投影 FBBraw out(2*Nt*Nrf1:end, :); % 数字预编码实虚部 FBBraw reshape(FBBraw, 2, Nrf, Ns, []); FBB complex(FBBraw(1,:,:,:), FBBraw(2,:,:,:)); FRF4 reshape(FRF, Nt, Nrf, 1, []); FBB4 reshape(FBB, 1, Nrf, Ns, []); F sum(FRF4 .* FBB4, 2); % [Nt,1,Ns,B] F reshape(F, Nt, Ns, []); % [Nt,Ns,B] p sqrt(sum(abs(F).^2, [1 2])); % 每个样本的功率 F F ./ p * sqrt(Ns); % 总功率约束到 Ns FBB FBB ./ p * sqrt(Ns); % 数字部分同步缩放 end用实虚部成对 reshape 成复数再把整个复数矩阵除以自己的模网络输出就精确落在单位圆上。相比直接输出相位角度再做 exp(1j*theta)这个做法避免了 2π 相位跳变带来的梯度不连续问题训练更稳定这是我在多次实验后确定下来的实现方式。矩阵乘部分刻意没用 pagemtimes而是用 reshape 加 sum。原因是 dlnetwork 的自动微分对基础运算支持最完整pagemtimes 在部分 MATLAB 版本里对复数 dlarray 的支持存在限制。用展开乘再求和的方式在 R2021b 之后的所有版本里都能稳定求梯度。数字预编码部分不做恒模约束因为它本身就在基带完成只需要在最后随总功率一起缩放保证发射总功率不超过 Ns 即可。如果 MATLAB 版本较老报出 complex dlarray 不支持自动微分的错误可以在损失函数最后加 real() 包裹让反传路径上始终只有实数值通常就能绕过去。3.3 为什么回归目标用 Vopt 而不是直接优化频谱效率损失函数定义在合成预编码 F 与全数字最优方向 Vopt 之间的均方误差上而不是直接用频谱效率公式function [loss, gradients] modelLoss(net, dlX, dlY, Nt, Nrf, Ns) [~, ~, F] hybridForward(net, dlX, Nt, Nrf, Ns); err F - dlY; % dlY: [Nt,Ns,B] loss sum(real(err).^2 imag(err).^2, all) / numel(err); loss real(loss); % 确保实标量 gradients dlgradient(loss, net.Learnables); end频谱效率才是通信系统真正关心的指标为什么不直接把它当损失函数原因有两点。第一logdet 形式的频谱效率对波束方向的变化非常敏感在可行域边缘梯度方向漂移明显训练初期会让网络在恒模投影边界附近反复震荡。第二最优混合预编码本来就不一定能达到全数字性能用 Vopt 做回归目标是给网络一个明确、平稳的学习目标先学会逼近全数字解再在需要时做频谱效率层面的微调这是混合预编码深度学习里最常见也最稳妥的两阶段路线。需要注意的是这个 MSE 损失存在一个非零下界因为恒模矩阵乘上低维数字基带矩阵的表示能力有限不可能完全拟合任意 Vopt 列空间。训练中看到 loss 停在 0.05 到 0.1 之间不再下降不一定是模型坏了很可能已经接近该配置下的表示上限。判断依据是最终频谱效率曲线的趋势而不是 loss 绝对值。错误做法现象原因与修正Vopt 未做相位对齐loss 长时间抖动、下降缓慢SVD 奇异向量相位随机回归目标不确定输入直接用 H 不归一化换 SNR 区间后性能明显退化特征尺度随信道能量变化改用 R/trace网络输出相位角度再过 exp训练震荡偶发 NaN相位存在周期间断改用实虚部投影隐藏层加到 6 层以上训练变慢且 loss 不降恒模约束本身强非线性加宽优先于加深4. 训练循环、超参数与频谱效率对比实验4.1 自定义训练循环与超参数设置使用 dlnetwork 时训练循环需要自己写。核心代码包括数据打包、模型损失调用、sgdm 参数更新三部分rng(0); trainSamples 20000; testSamples 2000; Htrain genChannels(trainSamples, Nt, Nr, 6, 10); [Xtrain, Vopt] buildData(Htrain, Nt, Nr, Ns); % 按 2.3 节生成 learnRate 2e-3; momentum 0.9; velocity []; miniBatchSize 128; numEpochs 60; numIter floor(trainSamples / miniBatchSize); for epoch 1:numEpochs idx randperm(trainSamples); for i 1:numIter bidx idx((i-1)*miniBatchSize1 : i*miniBatchSize); dlX dlarray(Xtrain(:,bidx), CB); dlY dlarray(Vopt(:,:,bidx), SSCB); [loss, grad] dlfeval(modelLoss, net, dlX, dlY, Nt, Nrf, Ns); [net, velocity] sgdmupdate(net, grad, velocity, learnRate, momentum); end fprintf(epoch %d, loss %.4f\n, epoch, extractdata(loss)); enddlX 的特征维度是 2NtNt格式标记 CB 表示列是样本dlY 是三维复数张量SSCB 表示两张量加批维度。这里用 dlfeval 而不是直接调用 modelLoss是因为梯度计算需要自动微分上下文。sgdmupdate 相比 adamupdate 在恒模投影约束下更容易稳定收敛如果换成 adam学习率建议降到 1e-3否则前几个 epoch 的损失波动会比较明显。训练时如果机器有 GPU在 dlarray 创建后可以执行 gpuArray 转换但要注意每次迭代的显存分配开销。20000 个样本、60 个 epoch、CPU 训练大约需要二十到四十分钟GPU 可以把时间压到五分钟左右。训练完成后保存网络权重评估阶段不再需要标签数据。超参数的经验配置如下表这个范围在不同天线配置下都适用超参数推荐范围关键现象学习率1e-3 ~ 3e-3过大时前 5 轮 loss 出现尖峰批大小128 ~ 512过小导致梯度噪声大loss 收敛慢fc1 宽度512 ~ 1024过窄时高 SNR 频谱效率偏低fc2 宽度256 ~ 768与 fc1 宽度联动优先加宽 fc2隐藏层数2 ~ 3 层更深无明显收益且训练时间线性增加4.2 用 MMSE 接收机计算混合预编码的频谱效率训练结束后要在测试集上比较深度混合预编码与全数字基准的频谱效率。接收端按线性 MMSE 合并器计算公式是 W (H F F^H H^H σ²I)^-1 H F因为 MMSE 合并器在固定发射预编码下能提供接近最优的互信息性能而且实现简单function R spectralEfficiency(H, F, snrLin, Ns) F F * sqrt(Ns) / norm(F, fro); % 功率归一化 W (H * (F*F) * H eye(size(H,1)) / snrLin) \ (H*F); G W * H * F; Rn W * W / snrLin; R real(log2(det(eye(Ns) G / Rn * G))); end代码里 G 是等效信道矩阵Rn 是合并后噪声的协方差矩阵。用\而不是 inv 求解 MMSE 合并器数值稳定性更好尤其是在天线数较多、矩阵接近病态的情况下。功率归一化的写法直接作用在 F 上保证发射总功率公平全数字基准也要做同样的归一化否则对比没有意义。全数字基准就是直接把 H 的 SVD 右奇异向量前 Ns 列作为 F同样传入 spectralEfficiency 函数。这里要注意 Vopt 的相位对齐不影响频谱效率因为频谱效率只取决于预编码张成的列空间每列乘任意相位因子不会改变结果。4.3 测试集批量评估与信道容量图像绘制测试集评估可以逐样本循环也可以把整个测试集分批前向后者效率更高。建议每批 256 个样本循环调用 hybridForward 得到所有样本的合成预编码 F再配合 spectralEfficiency 逐样本计算SNRdB -10:2:20; Rhyb zeros(size(SNRdB)); Rfull zeros(size(SNRdB)); for s 1:length(SNRdB) snrLin 10^(SNRdB(s)/10); tmpHyb 0; tmpFull 0; for i 1:testSamples Xb dlarray(Xtest(:,i), CB); Fpred hybridForward(net, Xb, Nt, Nrf, Ns); Fpred extractdata(Fpred); tmpHyb tmpHyb spectralEfficiency(Htest(:,:,i), Fpred, snrLin, Ns); % 全数字基准直接重新做 SVD [~, ~, V] svd(Htest(:,:,i), econ); Fopt V(:, 1:Ns); tmpFull tmpFull spectralEfficiency(Htest(:,:,i), Fopt, snrLin, Ns); end Rhyb(s) tmpHyb / testSamples; Rfull(s) tmpFull / testSamples; end figure; hold on; plot(SNRdB, Rfull, -o, LineWidth, 1.2); plot(SNRdB, Rhyb, --^, LineWidth, 1.2); xlabel(SNR (dB)); ylabel(Spectral Efficiency (bit/s/Hz)); legend(Full-digital SVD, Deep Hybrid, Location, northwest); grid on;这段代码直接画出 MIMO 信道容量图像横轴是 SNR纵轴是频谱效率。逐样本循环里有大量 dlarray 构造开销如果测试样本较多建议改成每 256 个样本组成一个批次送入 hybridForward速度能快一个数量级。结果曲线通常呈两个特征低 SNR 时深度混合预编码与全数字基准几乎重合差距在 0.3 bit/s/Hz 以内高 SNR 时差距逐渐拉大。如果 10 dB 处的差距超过 1 bit/s/Hz优先检查 Vopt 有没有做相位对齐其次是增加 fc2 宽度或增大训练样本里的散射簇数量。如果曲线在某个 SNR 点突然掉下去大概率是测试集里个别病态信道的功率归一化出了问题可以用中位数替代均值画图验证。5. 把代码用起来跨阵列复用、权重复用与蒙特卡洛验证5.1 阵列规模变化时重新训练还是迁移学习网络的输入维度与 NtNt 强绑定天线从 64 变成 128 时输入层维度不匹配不能直接加载旧权重。常见的做法是保留旧网络的权重结构在新网络里把 fc1 的输入维度扩展到 2128*128旧权重放入左上角新增区域用随机初始化填充然后以较小学习率微调。不过实际迭代下来我发现重新生成信道数据并从头训练往往更快因为信道生成和 SVD 标签计算是离线完成的在新规模下重新训练 60 个 epoch 也就十几分钟迁移学习省下的时间有限反而要额外处理维度映射的索引逻辑。如果训练数据来自虚拟阵列也就是用移动平台合成大孔径阵列的场景信道矩阵的秩分布和空间相关性会与固定阵列差异很大。此时即使用 trace 归一化的协方差矩阵作输入特征分布仍然会偏移。处理办法是在训练阶段随机采样不同的角度扩展参数让网络接触更宽的信道条件分布这比在测试阶段做任何特征矫正都有效。5.2 把权重导出成普通矩阵绕开 Coder 的复数限制dlnetwork 在 MATLAB Coder 里的代码生成支持有限尤其是复数中间层。部署到实时系统前我一般把网络权重从 Learnables 里导出转成纯矩阵运算的前向函数W1 extractdata(net.Learnables.Value{1}); b1 extractdata(net.Learnables.Value{2}); W2 extractdata(net.Learnables.Value{3}); b2 extractdata(net.Learnables.Value{4}); W3 extractdata(net.Learnables.Value{5}); b3 extractdata(net.Learnables.Value{6}); save(hybridModel.mat, W1, b1, W2, b2, W3, b3, ... Nt, Nrf, Ns);部署端前向就是矩阵乘加 ReLU最后接单位模投影和功率归一化。这段纯实矩阵运算可以直接用 MATLAB Coder 生成 C也可以在嵌入式平台手写实现。特征侧的 trace 归一化参数也要一并保存部署时从外部传入 R 矩阵先做 trace 归一化再送入网络保证训练和推理的数据尺度一致。5.3 蒙特卡洛测速别把 dlarray 构造时间算进推理延迟最后验证推理速度时最容易犯的错误是逐样本调用 hybridForward 并且把 dlarray 构造时间计进去。dlarray 在每次创建时都有框架调度开销单样本调用测出来的结果可能比批量推理慢几十倍不能反映真实系统的处理能力。我一般这样测Xb dlarray(Xeval(:, 1:256), CB); tic; for r 1:10 Fb hybridForward(net, Xb, Nt, Nrf, Ns); end tBatch toc / 10 / 256; % SVD 基准只能逐样本测 tsvd 0; for i 1:256 tic; [~,~,V] svd(Heval(:,:,i), econ); tsvd tsvd toc; end tsvd tsvd / 256; fprintf(Deep Hybrid: %.2f us/sample, SVD baseline: %.2f us/sample\n, ... tBatch*1e6, tsvd*1e6);批量推理把 256 个样本合成一个 dlarray前向计算里的矩阵乘可以充分利用并行能力测出来的单样本延迟才是真实部署时能达到的水平。SVD 基准每次都要做完整的特征分解无法批量加速这正是深度学习方案在时延上胜出的依据。对比时还要注意 CPU 与 GPU 的差异GPU 上批量推理优势更明显但通信系统基带处理通常跑在 CPU 上建议以 CPU 实测结果为准。本文还有配套的精品资源点击获取