如何将.sigmf-data文件中的IQ样本输入至CNN分类器
基于IQ样本的CNN分类器数据输入解决方案
问题背景
正在构建针对解调IQ样本的CNN分类器,架构要求如下:
- 包含2个卷积层、2个全连接层,共4层核心网络
- 输入为加有功率<-13dB高斯噪声的窗化解调IQ序列,每个复数IQ由实部、虚部两个实数表示,单样本长度128,维度为2×128
- 第一个卷积层:50个1×7尺寸的滤波器,后接ReLU激活
- 第二个卷积层:50个2×7尺寸的滤波器,后接ReLU激活
- 第一个全连接层:256个神经元,Dropout率50%,L2正则化参数0.0001
- 第二个全连接层:80个神经元,Dropout率50%,L2正则化参数0.0001
- 输出层:Softmax分类器,输出16类样本的概率
- 优化器:Adam,学习率0.0001;损失函数:交叉熵;基于TensorFlow Keras实现
现有16个.sigmf-data格式的IQ样本文件,单文件加载代码如下,但不清楚如何将IQ数据适配CNN输入格式:
signal = sigmffile.fromfile("Demod_WiFi_cable_X310_3123D76_IQ#1_run1.sigmf-data") samples = temp_signal.read_samples()
现有代码问题
原模型定义中输入形状((1,128,2,1))存在冗余维度,且未完成IQ样本的预处理流程,导致数据无法匹配模型输入要求。
完整解决方案
1. 数据加载与预处理
将复数IQ样本转换为CNN可接受的格式,同时生成对应类别标签:
import numpy as np from sigmf import sigmffile from tensorflow import keras from sklearn.model_selection import train_test_split def load_and_preprocess_iq_file(file_path, window_size=128, step_size=64): # 加载复数IQ样本 signal = sigmffile.fromfile(file_path) samples = signal.read_samples() # 拆分实部与虚部,得到(N, 2)形状的数组 iq_data = np.column_stack((samples.real, samples.imag)) total_samples = len(iq_data) # 滑动窗口生成固定长度的样本 windowed_samples = [] for start_idx in range(0, total_samples - window_size + 1, step_size): window = iq_data[start_idx:start_idx+window_size] windowed_samples.append(window) # 扩展通道维度,适配Conv2D输入格式:(样本数, 128, 2, 1) windowed_samples = np.array(windowed_samples) return np.expand_dims(windowed_samples, axis=-1) # 加载16个文件并生成标签 file_paths = [f"Demod_WiFi_cable_X310_3123D76_IQ#{i}_run1.sigmf-data" for i in range(1, 17)] X = [] y = [] for class_idx, file_path in enumerate(file_paths): # 处理当前文件的IQ样本 processed_samples = load_and_preprocess_iq_file(file_path) X.append(processed_samples) # 生成one-hot标签(16类) class_labels = np.zeros((len(processed_samples), 16)) class_labels[:, class_idx] = 1 y.append(class_labels) # 合并所有数据并划分训练/测试集 X = np.concatenate(X, axis=0) y = np.concatenate(y, axis=0) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
2. 修正后的模型定义
调整输入形状与预处理后的数据匹配,确保卷积层正确处理IQ样本:
# 定义CNN模型 model = keras.Sequential([ # 输入形状对应(128个IQ点, 实部/虚部2个特征, 1个通道) layers.Conv2D(filters=50, kernel_size=(7, 1), activation='relu', input_shape=(128, 2, 1)), layers.Conv2D(filters=50, kernel_size=(7, 2), activation='relu'), layers.Flatten(), layers.Dropout(rate=0.5), layers.Dense(units=256, activation='relu', kernel_regularizer=keras.regularizers.l2(0.0001)), layers.Dropout(rate=0.5), layers.Dense(units=80, activation='relu', kernel_regularizer=keras.regularizers.l2(0.0001)), layers.Dense(units=16, activation='softmax') ]) model.summary() # 编译模型 optimizer = keras.optimizers.Adam(learning_rate=0.0001) model.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=['accuracy']) # 训练模型 history = model.fit(X_train, y_train, epochs=50, batch_size=32, validation_split=0.1) # 评估模型性能 test_loss, test_acc = model.evaluate(X_test, y_test) print(f"测试集准确率: {test_acc:.4f}")
关键说明
- 数据适配:将复数IQ拆分为实部+虚部的二维特征,通过滑动窗口生成固定长度(128)的样本,扩展通道维度后匹配Conv2D的输入格式
- 模型修正:移除原输入形状中的冗余维度,确保卷积核尺寸(1×7、2×7)能在IQ序列的时间轴(128点)和特征轴(实部/虚部)上正确滑动
- 标签处理:16个文件对应16个类别,生成one-hot标签与Softmax输出、交叉熵损失函数匹配
内容的提问来源于stack exchange,提问作者Sourabh
相关产品推荐
相关产品推荐

