第【109】期--基于神经网络的OFDM峰均功率比降低方法--python完整代码

关注我,追更更多通信仿真代码!

文章目录

    • 摘要
    • [1. 引言](#1. 引言)
    • [2. OFDM信号模型与PAPR定义](#2. OFDM信号模型与PAPR定义)
      • [2.1 OFDM基带信号](#2.1 OFDM基带信号)
      • [2.2 峰均功率比(PAPR)](#2.2 峰均功率比(PAPR))
      • [2.3 PAPR统计评估:CCDF](#2.3 PAPR统计评估:CCDF)
      • [2.4 传统限幅滤波方法](#2.4 传统限幅滤波方法)
    • [3. 基于神经网络的PAPR降低方法](#3. 基于神经网络的PAPR降低方法)
      • [3.1 网络结构设计](#3.1 网络结构设计)
      • [3.2 训练数据生成](#3.2 训练数据生成)
      • [3.3 损失函数与优化器](#3.3 损失函数与优化器)
    • [4 仿真设计与分析](#4 仿真设计与分析)
      • [4.1 仿真参数设置](#4.1 仿真参数设置)
      • [4.2 CCDF性能对比](#4.2 CCDF性能对比)
      • [4.3 失真结果对比](#4.3 失真结果对比)
      • [4.4 部分代码](#4.4 部分代码)
    • [5 结论](#5 结论)

摘要

正交频分复用(OFDM)技术因其高频谱效率和抗多径衰落能力,在现代无线通信系统中得到广泛应用。然而,OFDM信号固有的高峰均功率比(PAPR)问题严重制约了功率放大器的工作效率。传统限幅滤波方法虽能有效降低PAPR,但会引入非线性失真和带外辐射。本文提出一种基于全连接神经网络的PAPR降低方法,通过训练网络学习原始OFDM信号与限幅滤波后信号之间的映射关系,实现低PAPR信号的智能生成。仿真结果表明,所提方法在PAPR抑制性能上可逼近传统限幅滤波方法,且具有降低信号失真的潜在优势。

1. 引言

  • 正交频分复用(Orthogonal Frequency Division Multiplexing, OFDM)技术凭借其频谱利用率高、抗频率选择性衰落强等优点,已被广泛应用于4G/5G移动通信、数字电视广播及无线局域网等标准中。然而,OFDM符号由多个正交子载波叠加而成,其时域信号包络具有较大的动态范围,导致高峰均功率比(Peak-to-Average Power Ratio, PAPR。高PAPR要求发射端功率放大器具有较大的线性动态范围,否则信号会因进入非线性区而产生失真,降低系统性能。

  • 为降低PAPR,研究者提出了多种技术,包括限幅(Clipping)、压缩扩展(Companding)、选择性映射(SLM)和部分传输序列等。其中,限幅滤波因实现简单且效果显著而备受关注,但其非线性操作会引入带内失真和带外辐射,需要在PAPR降低和信号质量之间折中。

  • 近年来,深度学习在通信物理层中的应用日益广泛,已有研究将其用于信道估计、信号检测和波形设计等领域。本文尝试利用神经网络学习限幅滤波的映射关系,以期在保持PAPR降低效果的同时减少非线性失真。具体而言,我们构建了一个全连接神经网络(Fully Connected Neural Network, FCNN),以原始OFDM时域信号的实部和虚部为输入,以限幅滤波后的信号实部和虚部为输出,通过监督学习拟合该映射。

2. OFDM信号模型与PAPR定义

2.1 OFDM基带信号

2.2 峰均功率比(PAPR)

2.3 PAPR统计评估:CCDF

2.4 传统限幅滤波方法

3. 基于神经网络的PAPR降低方法

3.1 网络结构设计

3.2 训练数据生成

3.3 损失函数与优化器

4 仿真设计与分析

参数 符号 说明
OFDM子载波数 K K K 根据系统带宽和频谱效率要求设定
循环前缀长度 C P CP CP 取 K / 4 K/4 K/4,以抵抗多径时延扩展
调制方式 16QAM 每子载波携带 μ = 4 \mu = 4 μ=4 比特
数据子载波数 N data N_{\text{data}} Ndata K K K 减去导频子载波数
导频子载波数 N pilot N_{\text{pilot}} Npilot 用于信道估计,等间隔分布
限幅比 C R \mathrm{CR} CR 限幅门限与信号均方根值的比值
低通滤波器阶数 n n n 用于抑制限幅引入的带外辐射
训练符号数 N sym N_{\text{sym}} Nsym 生成足够数量的OFDM符号用于训练和测试
训练集比例 ρ \rho ρ 总样本中用于训练的比例
神经网络隐藏层神经元数 N hidden N_{\text{hidden}} Nhidden 全连接网络中间层神经元个数
激活函数 tanh ⁡ \tanh tanh 隐藏层和输出层均使用双曲正切
损失函数 MSE 均方误差,定义为 L = 1 N ∑ i = 1 N ∣ y ( i ) − y ^ ( i ) ∣ 2 2 \mathcal{L} = \frac{1}{N} \sum_{i=1}^{N} | \mathbf{y}^{(i)} - \hat{\mathbf{y}}^{(i)} |_2^2 L=N1∑i=1N∣y(i)−y^(i)∣22
优化器 Adam 自适应矩估计优化算法
学习率 η \eta η 控制参数更新步长,通常设置为 10 − 3 10^{-3} 10−3 量级
批大小 B B B 每次迭代使用的样本数
训练轮数 E E E 完整遍历训练集的次数

4.1 仿真参数设置

4.2 CCDF性能对比

可以看到

  • 原始信号具有最高的PAPR,限幅滤波信号显著降低了PAPR,验证了限幅滤波的有效性。神经网络预测信号的CCDF曲线与限幅滤波曲线较为接近,说明神经网络能够较好地学习限幅滤波的映射关系。该结果表明,所提出的神经网络方法在PAPR抑制性能上可接近传统限幅滤波,且具有无需迭代计算、一次前向传播即可生成低PAPR信号的优点。

4.3 失真结果对比

可以看到:

  • 神经网络预测信号的 EVM 比限幅滤波信号低约 0.46 个百分点),在 20% 的尺度下,这个差异虽然相对小,但已可观测到趋势。更重要的是,在下面 SER 指标中差异更加明显。
  • 无噪声神经网络预测信号的 SER 仅为限幅滤波信号的 29%(0.000446 / 0.001532 ≈ 0.29),误符号率降低了 70%。这充分证明了神经网络在降低 PAPR 的同时,显著减少了信号失真,展现出明显的信号质量优势。在 AWGN 信道下,由于噪声主导了误码的产生,神经网络预测信号的 BER 曲线与限幅滤波信号接近。

4.4 部分代码

c 复制代码
# -*- coding: utf-8 -*-
"""
失真评估脚本
按 OFDM 符号分组,在频域计算 EVM 和 BER
"""

import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
import os

# ======================== 配置 ========================
K = 256  # 子载波数(必须与生成数据时一致)
trainingset_number = 9
filename_dataset_csv = f"training_data_{trainingset_number}.csv"
model_h5_file = f"saved_model_{trainingset_number}.h5"

# 16QAM 理想星座点(与 mapping_table 一致)
constellation = np.array([-3 - 3j, -3 - 1j, -3 + 3j, -3 + 1j,
                          -1 - 3j, -1 - 1j, -1 + 3j, -1 + 1j,
                          3 - 3j, 3 - 1j, 3 + 3j, 3 + 1j,
                          1 - 3j, 1 - 1j, 1 + 3j, 1 + 1j])


# ======================== 定义损失函数 ========================
def my_loss(y_true, y_pred):
    return tf.reduce_mean(tf.square(y_pred - y_true))


# ======================== 加载数据 ========================
if not os.path.exists(filename_dataset_csv):
    raise FileNotFoundError(f"数据文件不存在: {filename_dataset_csv}")

data = np.loadtxt(filename_dataset_csv, delimiter=',', skiprows=1)
total_samples = len(data)
num_symbols = total_samples // K
print(f"总采样点: {total_samples}, 可组成 {num_symbols} 个 OFDM 符号")

# 取完整符号数(截断尾部不足 K 个的点)
data = data[:num_symbols * K]
orig_complex = data[:, 0] + 1j * data[:, 1]
proc_complex = data[:, 2] + 1j * data[:, 3]

# ======================== 神经网络预测 ========================
if not os.path.exists(model_h5_file):
    raise FileNotFoundError(f"模型文件不存在: {model_h5_file},请先训练。")

model = tf.keras.models.load_model(
    model_h5_file,
    custom_objects={'my_loss': my_loss}
)
print("模型加载成功!")

# 分批预测
batch_size = 1024
pred_list = []
for start in range(0, total_samples, batch_size):
    end = min(start + batch_size, total_samples)
    batch = data[start:end, 0:2]
    pred = model.predict(batch, verbose=0)
    pred_list.append(pred)
pred_array = np.vstack(pred_list)
pred_complex = pred_array[:, 0] + 1j * pred_array[:, 1]

print("神经网络预测完成。")


# ======================== 按符号分组,计算频域符号 ========================
def get_freq_symbols(time_signal, K):
    """
    将时域信号按 K 个点分组,做 FFT,返回所有符号的频域子载波(复数矩阵)
    形状: (num_symbols, K)
    """
    num = len(time_signal) // K
    time_signal = time_signal[:num * K]
    freq = np.fft.fft(time_signal.reshape(num, K), axis=1)
    return freq  # shape (num, K)


# 获取三种信号的频域符号矩阵
freq_orig = get_freq_symbols(orig_complex, K)
freq_proc = get_freq_symbols(proc_complex, K)
freq_pred = get_freq_symbols(pred_complex, K)


# ======================== EVM 计算(频域) ========================
def compute_evm_freq(freq_symbols, constellation):
    """
    输入: freq_symbols 形状 (num_symbols, K),每个子载波的复数值
    计算所有符号、所有子载波的平均 EVM(百分比和 dB)
    """
    all_symbols = freq_symbols.flatten()  # 展平所有子载波
    errors = []
    for s in all_symbols:
        # 找最近星座点
        dists = np.abs(s - constellation)
        idx = np.argmin(dists)
        ideal = constellation[idx]
        errors.append(s - ideal)
    errors = np.array(errors)
    rms_error = np.sqrt(np.mean(np.abs(errors) ** 2))
    rms_ideal = np.sqrt(np.mean(np.abs(constellation) ** 2))
    evm_percent = (rms_error / rms_ideal) * 100
    evm_dB = 20 * np.log10(evm_percent / 100)
    return evm_percent, evm_dB


# 计算三种信号的 EVM
evm_orig_per, evm_orig_dB = compute_evm_freq(freq_orig, constellation)
evm_proc_per, evm_proc_dB = compute_evm_freq(freq_proc, constellation)
evm_pred_per, evm_pred_dB = compute_evm_freq(freq_pred, constellation)

print("\n========== EVM 对比(频域) ==========")
print(f"原始信号          : {evm_orig_per:.2f}%  ({evm_orig_dB:.2f} dB)")
print(f"限幅滤波信号      : {evm_proc_per:.2f}%  ({evm_proc_dB:.2f} dB)")
print(f"神经网络预测信号  : {evm_pred_per:.2f}%  ({evm_pred_dB:.2f} dB)")


# ======================== BER 仿真(频域) ========================
def demod_symbol(symbol, constellation):
    """硬判决,返回符号索引"""
    dists = np.abs(symbol - constellation)
    return np.argmin(dists)


def ser_compute(freq_symbols, constellation):
    """
    计算误符号率(SER):相对于理想符号(直接对原始信号判决)
    注意:由于原始信号本身有噪声,以原始信号的判决结果为参考可能不准确,
    但这里我们假设原始信号是无失真的,故以原始信号的判决为参考。
    """
    # 获取理想符号索引(从原始信号判决)
    ideal_idx = np.array([demod_symbol(s, constellation) for s in freq_orig.flatten()])
    # 对待测信号判决
    test_idx = np.array([demod_symbol(s, constellation) for s in freq_symbols.flatten()])
    return np.sum(test_idx != ideal_idx) / len(ideal_idx)


# 计算 SER
ser_orig = ser_compute(freq_orig, constellation)
ser_proc = ser_compute(freq_proc, constellation)
ser_pred = ser_compute(freq_pred, constellation)

print("\n========== 误符号率 (SER) 对比 ==========")
print(f"原始信号          : {ser_orig:.6f}")
print(f"限幅滤波信号      : {ser_proc:.6f}")
print(f"神经网络预测信号  : {ser_pred:.6f}")


# ======================== AWGN 下的 BER 曲线(频域加噪声) ========================
def add_awgn_freq(freq_symbols, snr_db):
    """在频域加 AWGN(保持符号功率)"""
    # 计算平均符号功率
    power = np.mean(np.abs(freq_symbols) ** 2)
    noise_power = power * 10 ** (-snr_db / 10)
    noise = np.sqrt(noise_power / 2) * (
                np.random.randn(*freq_symbols.shape) + 1j * np.random.randn(*freq_symbols.shape))
    return freq_symbols + noise


snr_range = np.arange(0, 25, 2)
ser_orig_list, ser_proc_list, ser_pred_list = [], [], []

# 以原始信号的判决为参考(无噪声理想判决)
ideal_idx = np.array([demod_symbol(s, constellation) for s in freq_orig.flatten()])

for snr in snr_range:
    # 加噪声
    rx_orig = add_awgn_freq(freq_orig, snr)
    rx_proc = add_awgn_freq(freq_proc, snr)
    rx_pred = add_awgn_freq(freq_pred, snr)

    # 判决
    idx_orig = np.array([demod_symbol(s, constellation) for s in rx_orig.flatten()])
    idx_proc = np.array([demod_symbol(s, constellation) for s in rx_proc.flatten()])
    idx_pred = np.array([demod_symbol(s, constellation) for s in rx_pred.flatten()])

    ser_orig_list.append(np.sum(idx_orig != ideal_idx) / len(ideal_idx))
    ser_proc_list.append(np.sum(idx_proc != ideal_idx) / len(ideal_idx))
    ser_pred_list.append(np.sum(idx_pred != ideal_idx) / len(ideal_idx))

# ======================== 绘制 BER 曲线 ========================
plt.figure(figsize=(8, 6))
plt.semilogy(snr_range, ser_orig_list, 'b-o', label='原始信号')
plt.semilogy(snr_range, ser_proc_list, 'r-s', label='限幅滤波信号')
plt.semilogy(snr_range, ser_pred_list, 'g-^', label='神经网络预测')
plt.xlabel('SNR (dB)')
plt.ylabel('误符号率 (SER)')
plt.title('不同信号在 AWGN 下的抗噪声性能(频域)')
plt.grid(True, which='both', linestyle='--', alpha=0.6)
plt.legend()
plt.tight_layout()
plt.savefig('ber_comparison.png', dpi=300)
plt.show()

print("\nBER 曲线已保存为 ber_comparison.png")
print("\n结论:若神经网络预测信号的 EVM 和 BER 低于限幅滤波信号,则说明其具有降低信号失真的优势。")

5 结论

本文提出了一种基于全连接神经网络的 OFDM 信号 PAPR 降低方法。仿真结果表明,该方法在 PAPR 抑制性能上可逼近传统限幅滤波技术,同时能显低信号失真。展现出在保持 PAPR 抑制效果的同时提升信号质量的潜力。该方法为高功率效率的 OFDM 系统设计提供了一种可学习的非线性信号处理思路。

完整仿真代码可见往期文章文末VX公众号(包含往期博客所有代码),所见即所得

相关推荐
麻雀飞吧44 分钟前
近期量化工具怎么选,先看你卡在哪一环
人工智能·python
阿图灵1 小时前
OpenCV 图像特征与匹配:SIFT 特征检测与 BFMatcher 暴力匹配
图像处理·人工智能·python·opencv·计算机视觉·sift
王志来137944730081 小时前
工控服务器机箱选型决策要素解析:匀天以“快全准省”构建价值坐标
运维·服务器·python·devops
Bruce_Liuxiaowei1 小时前
从基础理论开始学习人工智能(二):应用和方法——从拼图游戏到神经网络
人工智能·神经网络·学习
阿图灵1 小时前
OpenCV 实用技巧三连:视频转图片、图片转视频、Pillow 与 OpenCV 互转
图像处理·python·opencv·计算机视觉·音视频·pillow
GlueNa2SiO31 小时前
05-Flask表单处理与文件上传
笔记·python·学习·flask
一晌小贪欢1 小时前
Python办公16:PDF 强力缝合——将几十个 PDF 合并为单个文档并添加页码
开发语言·python·excel·数据可视化·python办公
qq_161111271 小时前
深入理解Python中的Contextlib库
python·装饰器·函数·上下文管理器·contextlib
迷迭香yy1 小时前
回测过拟合检测体系从样本内外到组合稳健性评估 IG50免费开源股票数据API接口
服务器·开发语言·数据库·人工智能·python