65、基于卷积神经网络的调制分类(matlab)

 1、基于卷积神经网络的调制分类的原理及流程

基于卷积神经网络(CNN)的调制分类是一种常见的信号处理任务,用于识别或分类不同调制方式的信号。下面是基于CNN的调制分类的原理和流程:

原理:

  • CNN是一种深度学习模型,通过卷积层、池化层和全连接层等结构来提取数据中的特征。在调制分类任务中,CNN可以学习到调制信号的特征以区分不同的调制方式。
  • 输入到CNN模型的数据是经过预处理和特征提取后的信号样本,通常是时域信号或频域信号。CNN将这些信号作为输入,并通过网络中的不同层来提取特征并完成调制分类任务。

流程:

  1. 数据准备:准备好用于训练和测试的信号样本数据集,每个样本包含一个已知调制方式的信号。

  2. 数据预处理:对信号数据进行预处理,可能包括归一化、降噪、平滑处理等,以确保数据质量。

  3. 数据特征提取:将信号数据转换为适合CNN输入的格式,例如在时域或频域下进行信号特征提取,将其转换为矩阵形式。

  4. 构建CNN模型:定义CNN模型的结构,包括卷积层、池化层、激活函数层和全连接层等。可以根据具体需求自定义网络结构。

  5. 模型训练:使用训练集数据对CNN模型进行训练,通过反向传播算法不断调整模型参数以使模型输出尽可能接近真实标签。

  6. 模型评估:使用测试集数据评估训练好的模型性能,包括准确率、召回率等指标,对模型进行优化和调整。

  7. 模型应用:将训练好的CNN模型用于未知信号的调制分类,通过模型预测得到信号的调制方式。

  8. 参数调优:根据模型评估结果,调整模型结构、超参数等进行优化,以提高调制分类的准确性和性能。

在Matlab中,可以使用深度学习工具箱等相关工具进行CNN模型的搭建和训练

2、基于卷积神经网络的调制分类的说明

使用卷积神经网络 (CNN) 进行调制分类

生成合成的、通道减损波形。使用生成的波形作为训练数据,训练 CNN 进行调制分类

 

3、使用 CNN 预测调制类型

1)调制数据类型

二相相移键控 (BPSK)

四相相移键控 (QPSK)

八相相移键控 (8-PSK)

十六相正交调幅 (16-QAM)

六十四相正交调幅 (64-QAM)

四相脉冲振幅调制 (PAM4)

高斯频移键控 (GFSK)

连续相位频移键控 (CPFSK)

广播 FM (B-FM)

双边带振幅调制 (DSB-AM)

单边带振幅调制 (SSB-AM)

2)实现代码

modulationTypes = categorical(sort(["BPSK", "QPSK", "8PSK", ..."16QAM", "64QAM", "PAM4", "GFSK", "CPFSK", ..."B-FM", "DSB-AM", "SSB-AM"]));

3)加载训练网络代码

 

load trainedModulationClassificationNetwork
trainedNet
trainedNet = dlnetwork with properties:Layers: [19×1 nnet.cnn.layer.Layer]Connections: [18×2 table]Learnables: [22×3 table]State: [10×3 table]InputNames: {'Input Layer'}OutputNames: {'SoftMax'}Initialized: 1View summary with summary.

4、加载训练的网络

1)说明

经过训练的 CNN 接受 1024 个通道减损采样,并预测每个帧的调制类型

生成几个因莱斯多径衰落、中心频率和采样时间漂移以及 AWGN 而有所减损的 PAM4 帧。

以下函数生成合成信号来测试 CNN。然后使用 CNN 预测帧的调制类型。

randi:生成随机位

pammod (Communications Toolbox):PAM4 调制位

rcosdesign (Signal Processing Toolbox):设计平方根升余弦脉冲整形滤波器

filter:脉冲确定符号的形状

comm.RicianChannel (Communications Toolbox):应用莱斯多径通道

comm.PhaseFrequencyOffset (Communications Toolbox):应用时钟偏移引起的相位和/或频率偏移

interp1:应用时钟偏移引起的计时漂移

awgn (Communications Toolbox):添加 AWGN

2)实现代码

rng(123456)
% Random bits
d = randi([0 3], 1024, 1);
% PAM4 modulation
syms = pammod(d,4);
% Square-root raised cosine filter
filterCoeffs = rcosdesign(0.35,4,8);
tx = filter(filterCoeffs,1,upsample(syms,8));% Channel
SNR = 30;
maxOffset = 5;
fc = 902e6;
fs = 200e3;
multipathChannel = comm.RicianChannel(...'SampleRate', fs, ...'PathDelays', [0 1.8 3.4] / 200e3, ...'AveragePathGains', [0 -2 -10], ...'KFactor', 4, ...'MaximumDopplerShift', 4);frequencyShifter = comm.PhaseFrequencyOffset(...'SampleRate', fs);% Apply an independent multipath channel
reset(multipathChannel)
outMultipathChan = multipathChannel(tx);% Determine clock offset factor
clockOffset = (rand() * 2*maxOffset) - maxOffset;
C = 1 + clockOffset / 1e6;% Add frequency offset
frequencyShifter.FrequencyOffset = -(C-1)*fc;
outFreqShifter = frequencyShifter(outMultipathChan);% Add sampling time drift
t = (0:length(tx)-1)' / fs;
newFs = fs * C;
tp = (0:length(tx)-1)' / newFs;
outTimeDrift = interp1(t, outFreqShifter, tp);% Add noise
rx = awgn(outTimeDrift,SNR,0);% Frame generation for classification
unknownFrames = helperModClassGetNNFrames(rx);% Classification
scores1 = predict(trainedNet,unknownFrames);
prediction1 = scores2label(scores1,modulationTypes);

3)返回分类器预测 

prediction1
prediction1 = 7×1 categoricalPAM4 PAM4 PAM4 PAM4 PAM4 PAM4 PAM4 

4) 分类器还返回一个包含每一帧分数的向量

代码

helperModClassPlotScores(scores1,modulationTypes)

视图效果

3aa5555d0b43495989ff2829144c3a1c.png

5、生成用于训练的波形

1)说明1

为每种调制类型生成 10000 个帧,其中 80% 用于训练,10% 用于验证,10% 用于测试。

网络训练阶段使用训练和验证帧

使用测试帧获得最终分类准确度。每帧的长度为 1024 个样本,采样率为 200 kHz。对于数字调制类型,八个采样表示一个符号。

2)代码实现


trainNow = false;
if trainNow == truenumFramesPerModType = 10000;
elsenumFramesPerModType = 200;
end
percentTrainingSamples = 80;
percentValidationSamples = 10;
percentTestSamples = 10;sps = 8;                % Samples per symbol
spf = 1024;             % Samples per frame
fs = 200e3;             % Sample rate
fc = [902e6 100e6];     % Center frequencies

 3)说明2

创建通道减损

让每帧通过通道并具有

  • AWGN

  • 莱斯多径衰落

  • 时钟偏移,导致中心频率偏移和采样时间漂移

由于本示例中的网络基于单个帧作出决定,因此每个帧必须通过独立的通道。

AWGN

通道增加 SNR 为 30 dB 的 AWGN。使用 awgn (Communications Toolbox) 函数实现通道。

莱斯多径

通道使用 comm.RicianChannel (Communications Toolbox) System object™ 通过莱斯多径衰落通道传递信号。假设延迟分布为 [0 1.8 3.4] 个样本,对应的平均路径增益为 [0 -2 -10] dB。K 因子为 4,最大多普勒频移为 4 Hz,等效于 902 MHz 的步行速度。使用以下设置实现通道。

时钟偏移

时钟偏移是发射机和接收机的内部时钟源不准确造成的。

代码

maxDeltaOff = 5;
deltaOff = (rand()*2*maxDeltaOff) - maxDeltaOff;
C = 1 + (deltaOff/1e6);

4)说明3

 

频率偏移

基于时钟偏移因子 C 和中心频率,对每帧进行频率偏移。使用 comm.PhaseFrequencyOffset (Communications Toolbox) 实现通道。

采样率偏移

基于时钟偏移因子 C,对每帧进行采样率偏移。使用 interp1 函数实现通道,以 C×fs 的新速率对帧进行重新采样。

合并后的通道

使用 helperModClassTestChannel 对象对帧应用所有三种通道减损。

代码

channel = helperModClassTestChannel(...'SampleRate', fs, ...'SNR', SNR, ...'PathDelays', [0 1.8 3.4] / fs, ...'AveragePathGains', [0 -2 -10], ...'KFactor', 4, ...'MaximumDopplerShift', 4, ...'MaximumClockOffset', 5, ...'CenterFrequency', 902e6)
channel = helperModClassTestChannel with properties:SNR: 30CenterFrequency: 902000000SampleRate: 200000PathDelays: [0 9.0000e-06 1.7000e-05]AveragePathGains: [0 -2 -10]KFactor: 4MaximumDopplerShift: 4MaximumClockOffset: 5

5)波形生成

说明

创建一个循环,它为每种调制类型生成通道减损的帧并将这些帧及其对应标签存储在 MAT 文件中。通过将数据保存到文件中,您无需每次运行此示例时都生成数据。您还可以更高效地共享数据。

从每帧的开头删除随机数量的样本,以去除瞬变并确保帧相对于符号边界具有随机起点。

代码 

rng(12)
tic
numModulationTypes = length(modulationTypes);
channelInfo = info(channel);
transDelay = 50;
pool = getPoolSafe();
if ~isa(pool,"parallel.ClusterPool")dataDirectory = fullfile(tempdir,"ModClassDataFiles");
elsedataDirectory = uigetdir("","Select network location to save data files");
end
disp("Data file directory is " + dataDirectory)fileNameRoot = "frame";% Check if data files exist
dataFilesExist = false;
if exist(dataDirectory,'dir')files = dir(fullfile(dataDirectory,sprintf("%s*",fileNameRoot)));if length(files) == numModulationTypes*numFramesPerModTypedataFilesExist = true;end
endif ~dataFilesExistdisp("Generating data and saving in data files...")[success,msg,msgID] = mkdir(dataDirectory);if ~successerror(msgID,msg)endfor modType = 1:numModulationTypeselapsedTime = seconds(toc);elapsedTime.Format = 'hh:mm:ss';fprintf('%s - Generating %s frames\n', ...elapsedTime, modulationTypes(modType))label = modulationTypes(modType);numSymbols = (numFramesPerModType / sps);dataSrc = helperModClassGetSource(modulationTypes(modType), sps, 2*spf, fs);modulator = helperModClassGetModulator(modulationTypes(modType), sps, fs);if contains(char(modulationTypes(modType)), {'B-FM','DSB-AM','SSB-AM'})% Analog modulation types use a center frequency of 100 MHzchannel.CenterFrequency = 100e6;else% Digital modulation types use a center frequency of 902 MHzchannel.CenterFrequency = 902e6;endfor p=1:numFramesPerModType% Generate random datax = dataSrc();% Modulatey = modulator(x);% Pass through independent channelsrxSamples = channel(y);% Remove transients from the beginning, trim to size, and normalizeframe = helperModClassFrameGenerator(rxSamples, spf, spf, transDelay, sps);% Save data filefileName = fullfile(dataDirectory,...sprintf("%s%s%03d",fileNameRoot,modulationTypes(modType),p));save(fileName,"frame","label")endend
elsedisp("Data files exist. Skip data generation.")
endGenerating data and saving in data files...
00:00:09 - Generating 16QAM frames
00:00:11 - Generating 64QAM frames
00:00:13 - Generating 8PSK frames
00:00:15 - Generating B-FM frames
00:00:17 - Generating BPSK frames
00:00:20 - Generating CPFSK frames
00:00:22 - Generating DSB-AM frames
00:00:24 - Generating GFSK frames
00:00:26 - Generating PAM4 frames
00:00:28 - Generating QPSK frames
00:00:30 - Generating SSB-AM frames

6)效果显示

 实虚部振幅代码

helperModClassPlotTimeDomain(dataDirectory,modulationTypes,fs)

视图效果

382b3112ff3f47059e05480ea885a7cf.png

帧代码 

helperModClassPlotSpectrogram(dataDirectory,modulationTypes,fs,sps)

视图效果

e98df04bc485429e80b22d6ac0596484.png

7)创建数据存储代码

frameDS = signalDatastore(dataDirectory,'SignalVariableNames',["frame","label"]);

8) 拆分为训练、验证和测试代码

splitPercentages = [percentTrainingSamples,percentValidationSamples,percentTestSamples];
[trainDS,validDS,testDS] = helperModClassSplitData(frameDS,splitPercentages);

9) 将数据导入内存代码

% Read the training and validation frames into the memory
pctExists = parallelComputingLicenseExists();
trainFrames = transform(trainDS, @helperModClassReadFrame);
rxTrainFrames = readall(trainFrames,"UseParallel",pctExists);
validFrames = transform(validDS, @helperModClassReadFrame);
rxValidFrames = readall(validFrames,"UseParallel",pctExists);% Read the training and validation labels into the memory
trainLabels = transform(trainDS, @helperModClassReadLabel);
rxTrainLabels = readall(trainLabels,"UseParallel",pctExists);
validLabels = transform(validDS, @helperModClassReadLabel);
rxValidLabels = readall(validLabels,"UseParallel",pctExists);

6、训练 CNN

1)说明

使用的 CNN 由五个卷积层和一个全连接层组成。除最后一个卷积层外,每个卷积层后面都有一个批量归一化层、修正线性单元 (ReLU) 激活层和最大池化层。在最后一个卷积层中,最大池化层被一个全局平均池化层取代。输出层具有 softmax 激活。

2)实现代码

modClassNet = helperModClassCNN(modulationTypes,sps,spf);

3)配置网络代码 

maxEpochs = 20;
miniBatchSize = 1024;
trainingPlots = "none";
metrics = [];
verbose = true;
validationFrequency = floor(numel(rxTrainLabels)/miniBatchSize);
options = trainingOptions('sgdm', ...InitialLearnRate = 3e-1, ...MaxEpochs = maxEpochs, ...MiniBatchSize = miniBatchSize, ...Shuffle = 'every-epoch', ...Plots = trainingPlots, ...Verbose = verbose, ...ValidationData = {rxValidFrames,rxValidLabels}, ...ValidationFrequency = validationFrequency, ...ValidationPatience = 5, ...Metrics = metrics, ...LearnRateSchedule = 'piecewise', ...LearnRateDropPeriod = 6, ...LearnRateDropFactor = 0.75, ...OutputNetwork='best-validation-loss');

4)训练网络代码 

if trainNow == trueelapsedTime = seconds(toc);elapsedTime.Format = 'hh:mm:ss';fprintf('%s - Training the network\n', elapsedTime)trainedNet = trainnet(rxTrainFrames,rxTrainLabels,modClassNet,"crossentropy",options);
elseload trainedModulationClassificationNetwork
end

 5)训练结果评估代码

elapsedTime = seconds(toc);
elapsedTime.Format = 'hh:mm:ss';
fprintf('%s - Classifying test frames\n', elapsedTime)
% Read the test frames into the memory
testFrames = transform(testDS, @helperModClassReadFrame);
rxTestFrames = readall(testFrames,"UseParallel",pctExists);% Read the test labels into the memory
testLabels = transform(testDS, @helperModClassReadLabel);
rxTestLabels = readall(testLabels,"UseParallel",pctExists);scores = predict(trainedNet,cat(3,rxTestFrames{:}));
rxTestPred = scores2label(scores,modulationTypes);
testAccuracy = mean(rxTestPred == rxTestLabels);
disp("Test accuracy: " + testAccuracy*100 + "%")

7、使用 SDR 进行测试

1)说明

使用 helperModClassSDRTest 函数,通过空口信号测试经过训练的网络的性能。要执行此测试,您必须有专用的 SDR 用于发送和接收。

2)代码实现

radioPlatform = "ADALM-PLUTO";switch radioPlatformcase "ADALM-PLUTO"if helperIsPlutoSDRInstalled() == trueradios = findPlutoRadio();if length(radios) >= 2helperModClassSDRTest(radios);elsedisp('Selected radios not found. Skipping over-the-air test.')endendcase {"USRP B2xx","USRP X3xx","USRP N2xx"}if (helperIsUSRPInstalled() == true) && (helperIsPlutoSDRInstalled() == true)txRadio = findPlutoRadio();rxRadio = findsdru();switch radioPlatformcase "USRP B2xx"idx = contains({rxRadio.Platform}, {'B200','B210'});case "USRP X3xx"idx = contains({rxRadio.Platform}, {'X300','X310'});case "USRP N2xx"idx = contains({rxRadio.Platform}, 'N200/N210/USRP2');endrxRadio = rxRadio(idx);if (length(txRadio) >= 1) && (length(rxRadio) >= 1)helperModClassSDRTest(rxRadio);elsedisp('Selected radios not found. Skipping over-the-air test.')endend
end

3)视图效果
e57411c7e7f0475f80bf53e17aee8802.png

8、总结

基于卷积神经网络(CNN)的调制分类在Matlab中可以通过深度学习工具箱等相关工具来实现。下面是对基于CNN的调制分类在Matlab中的关键步骤的总结:

总结步骤:

  1. 数据准备:准备带有标签的调制信号数据集,确保每个样本包含一个已知调制方式的信号。

  2. 数据预处理:对信号数据进行预处理,包括归一化、降噪等操作,以保证数据的质量。

  3. 数据特征提取:将信号数据转换为适合CNN输入的格式,可以在时域或频域下提取信号特征,并将其表示为矩阵形式。

  4. 构建CNN模型:定义CNN模型的结构,包括卷积层、池化层、激活函数层和全连接层等。可以根据具体需求自定义网络结构。

  5. 模型训练:使用训练集数据对CNN模型进行训练,通过反向传播算法不断调整模型参数以优化模型性能。

  6. 模型评估:使用测试集数据评估训练好的CNN模型的性能,包括准确率、召回率等指标,对模型进行优化和调整。

  7. 模型应用:将训练好的CNN模型用于未知信号的调制分类,通过模型预测得到信号的调制方式。

  8. 参数调优:根据模型评估结果,调整模型结构、超参数等进行优化,以提高调制分类的准确性和性能。

通过以上步骤,可以在Matlab中实现基于CNN的调制分类任务,从而对不同调制方式的信号进行准确分类和识别。在实际应用中,可以根据具体问题的需求对模型进行定制和调整,以获得更好的性能和效果。

9、源代码

代码

%% 基于卷积神经网络的调制分类
%使用卷积神经网络 (CNN) 进行调制分类
%生成合成的、通道减损波形。使用生成的波形作为训练数据,训练 CNN 进行调制分类%% 使用 CNN 预测调制类型
%可识别以下八种数字调制类型和三种模拟调制类型
%二相相移键控 (BPSK)
%四相相移键控 (QPSK)
%八相相移键控 (8-PSK)
%十六相正交调幅 (16-QAM)
%六十四相正交调幅 (64-QAM)
%四相脉冲振幅调制 (PAM4)
%高斯频移键控 (GFSK)
%连续相位频移键控 (CPFSK)
%广播 FM (B-FM)
%双边带振幅调制 (DSB-AM)
%单边带振幅调制 (SSB-AM)
modulationTypes = categorical(sort(["BPSK", "QPSK", "8PSK", ..."16QAM", "64QAM", "PAM4", "GFSK", "CPFSK", ..."B-FM", "DSB-AM", "SSB-AM"]));%% 加载训练的网络load trainedModulationClassificationNetwork
trainedNet%经过训练的 CNN 接受 1024 个通道减损采样,并预测每个帧的调制类型
%生成几个因莱斯多径衰落、中心频率和采样时间漂移以及 AWGN 而有所减损的 PAM4 帧。
%以下函数生成合成信号来测试 CNN。然后使用 CNN 预测帧的调制类型。
%randi:生成随机位
%pammod (Communications Toolbox):PAM4 调制位
%rcosdesign (Signal Processing Toolbox):设计平方根升余弦脉冲整形滤波器
%filter:脉冲确定符号的形状
%comm.RicianChannel (Communications Toolbox):应用莱斯多径通道
%comm.PhaseFrequencyOffset (Communications Toolbox):应用时钟偏移引起的相位和/或频率偏移
%interp1:应用时钟偏移引起的计时漂移
%awgn (Communications Toolbox):添加 AWGN
% Set the random number generator to a known state to be able to regenerate
% the same frames every time the simulation is run
rng(123456)
% Random bits
d = randi([0 3], 1024, 1);
% PAM4 modulation
syms = pammod(d,4);
% Square-root raised cosine filter
filterCoeffs = rcosdesign(0.35,4,8);
tx = filter(filterCoeffs,1,upsample(syms,8));% Channel
SNR = 30;
maxOffset = 5;
fc = 902e6;
fs = 200e3;
multipathChannel = comm.RicianChannel(...'SampleRate', fs, ...'PathDelays', [0 1.8 3.4] / 200e3, ...'AveragePathGains', [0 -2 -10], ...'KFactor', 4, ...'MaximumDopplerShift', 4);frequencyShifter = comm.PhaseFrequencyOffset(...'SampleRate', fs);% Apply an independent multipath channel
reset(multipathChannel)
outMultipathChan = multipathChannel(tx);% Determine clock offset factor
clockOffset = (rand() * 2*maxOffset) - maxOffset;
C = 1 + clockOffset / 1e6;% Add frequency offset
frequencyShifter.FrequencyOffset = -(C-1)*fc;
outFreqShifter = frequencyShifter(outMultipathChan);% Add sampling time drift
t = (0:length(tx)-1)' / fs;
newFs = fs * C;
tp = (0:length(tx)-1)' / newFs;
outTimeDrift = interp1(t, outFreqShifter, tp);% Add noise
rx = awgn(outTimeDrift,SNR,0);% Frame generation for classification
unknownFrames = helperModClassGetNNFrames(rx);% Classification
scores1 = predict(trainedNet,unknownFrames);
prediction1 = scores2label(scores1,modulationTypes);
%返回分类器预测
prediction1
%分类器还返回一个包含每一帧分数的向量
%分数对应于每个帧具有预测的调制类型的概率。绘制分数图。
helperModClassPlotScores(scores1,modulationTypes)%% 生成用于训练的波形
%为每种调制类型生成 10000 个帧,其中 80% 用于训练,10% 用于验证,10% 用于测试。
%网络训练阶段使用训练和验证帧
%使用测试帧获得最终分类准确度。每帧的长度为 1024 个样本,采样率为 200 kHz。对于数字调制类型,八个采样表示一个符号。trainNow = false;
if trainNow == truenumFramesPerModType = 10000;
elsenumFramesPerModType = 200;
end
percentTrainingSamples = 80;
percentValidationSamples = 10;
percentTestSamples = 10;sps = 8;                % Samples per symbol
spf = 1024;             % Samples per frame
fs = 200e3;             % Sample rate
fc = [902e6 100e6];     % Center frequencies%创建通道减损:AWGN/莱斯多径衰落/时钟偏移,导致中心频率偏移和采样时间漂移
%AWGN:通道增加 SNR 为 30 dB 的 AWGN。使用 awgn (Communications Toolbox) 函数实现通道
%莱斯多径:通道使用 comm.RicianChannel (Communications Toolbox) System object™ 通过莱斯多径衰落通道传递信号。
%时钟偏移:时钟偏移是发射机和接收机的内部时钟源不准确造成的。
maxDeltaOff = 5;
deltaOff = (rand()*2*maxDeltaOff) - maxDeltaOff;
C = 1 + (deltaOff/1e6);%频率偏移:基于时钟偏移因子 C 和中心频率,对每帧进行频率偏移
%采样率偏移:基于时钟偏移因子 C,对每帧进行采样率偏移。
%合并后的通道:使用 helperModClassTestChannel 对象对帧应用所有三种通道减损
channel = helperModClassTestChannel(...'SampleRate', fs, ...'SNR', SNR, ...'PathDelays', [0 1.8 3.4] / fs, ...'AveragePathGains', [0 -2 -10], ...'KFactor', 4, ...'MaximumDopplerShift', 4, ...'MaximumClockOffset', 5, ...'CenterFrequency', 902e6)
%使用 info 对象函数查看有关通道的基本信息
chInfo = info(channel)%波形生成
% Set the random number generator to a known state to be able to regenerate
% the same frames every time the simulation is run
rng(12)
tic
numModulationTypes = length(modulationTypes);
channelInfo = info(channel);
transDelay = 50;
pool = getPoolSafe();
if ~isa(pool,"parallel.ClusterPool")dataDirectory = fullfile(tempdir,"ModClassDataFiles");
elsedataDirectory = uigetdir("","Select network location to save data files");
end
disp("Data file directory is " + dataDirectory)fileNameRoot = "frame";% Check if data files exist
dataFilesExist = false;
if exist(dataDirectory,'dir')files = dir(fullfile(dataDirectory,sprintf("%s*",fileNameRoot)));if length(files) == numModulationTypes*numFramesPerModTypedataFilesExist = true;end
endif ~dataFilesExistdisp("Generating data and saving in data files...")[success,msg,msgID] = mkdir(dataDirectory);if ~successerror(msgID,msg)endfor modType = 1:numModulationTypeselapsedTime = seconds(toc);elapsedTime.Format = 'hh:mm:ss';fprintf('%s - Generating %s frames\n', ...elapsedTime, modulationTypes(modType))label = modulationTypes(modType);numSymbols = (numFramesPerModType / sps);dataSrc = helperModClassGetSource(modulationTypes(modType), sps, 2*spf, fs);modulator = helperModClassGetModulator(modulationTypes(modType), sps, fs);if contains(char(modulationTypes(modType)), {'B-FM','DSB-AM','SSB-AM'})% Analog modulation types use a center frequency of 100 MHzchannel.CenterFrequency = 100e6;else% Digital modulation types use a center frequency of 902 MHzchannel.CenterFrequency = 902e6;endfor p=1:numFramesPerModType% Generate random datax = dataSrc();% Modulatey = modulator(x);% Pass through independent channelsrxSamples = channel(y);% Remove transients from the beginning, trim to size, and normalizeframe = helperModClassFrameGenerator(rxSamples, spf, spf, transDelay, sps);% Save data filefileName = fullfile(dataDirectory,...sprintf("%s%s%03d",fileNameRoot,modulationTypes(modType),p));save(fileName,"frame","label")endend
elsedisp("Data files exist. Skip data generation.")
end
%显示波形
helperModClassPlotTimeDomain(dataDirectory,modulationTypes,fs)helperModClassPlotSpectrogram(dataDirectory,modulationTypes,fs,sps)%创建数据存储
%使用 signalDatastore 对象来管理包含生成的复杂波形的文件
frameDS = signalDatastore(dataDirectory,'SignalVariableNames',["frame","label"]);
%拆分为训练、验证和测试
splitPercentages = [percentTrainingSamples,percentValidationSamples,percentTestSamples];
[trainDS,validDS,testDS] = helperModClassSplitData(frameDS,splitPercentages);
%将数据导入内存
%神经网络训练是迭代进行
% Read the training and validation frames into the memory
pctExists = parallelComputingLicenseExists();
trainFrames = transform(trainDS, @helperModClassReadFrame);
rxTrainFrames = readall(trainFrames,"UseParallel",pctExists);
validFrames = transform(validDS, @helperModClassReadFrame);
rxValidFrames = readall(validFrames,"UseParallel",pctExists);% Read the training and validation labels into the memory
trainLabels = transform(trainDS, @helperModClassReadLabel);
rxTrainLabels = readall(trainLabels,"UseParallel",pctExists);
validLabels = transform(validDS, @helperModClassReadLabel);
rxValidLabels = readall(validLabels,"UseParallel",pctExists);%% 训练 CNN
%CNN 由五个卷积层和一个全连接层组成
%一个卷积层外,每个卷积层后面都有一个批量归一化层、修正线性单元 (ReLU) 激活层和最大池化层
modClassNet = helperModClassCNN(modulationTypes,sps,spf);
%配置 TrainingOptionsSGDM 以使用小批量大小为 1024 的 SGDM 求解器
maxEpochs = 20;
miniBatchSize = 1024;
trainingPlots = "none";
metrics = [];
verbose = true;
validationFrequency = floor(numel(rxTrainLabels)/miniBatchSize);
options = trainingOptions('sgdm', ...InitialLearnRate = 3e-1, ...MaxEpochs = maxEpochs, ...MiniBatchSize = miniBatchSize, ...Shuffle = 'every-epoch', ...Plots = trainingPlots, ...Verbose = verbose, ...ValidationData = {rxValidFrames,rxValidLabels}, ...ValidationFrequency = validationFrequency, ...ValidationPatience = 5, ...Metrics = metrics, ...LearnRateSchedule = 'piecewise', ...LearnRateDropPeriod = 6, ...LearnRateDropFactor = 0.75, ...OutputNetwork='best-validation-loss');
%训练神网络
if trainNow == trueelapsedTime = seconds(toc);elapsedTime.Format = 'hh:mm:ss';fprintf('%s - Training the network\n', elapsedTime)trainedNet = trainnet(rxTrainFrames,rxTrainLabels,modClassNet,"crossentropy",options);
elseload trainedModulationClassificationNetwork
end%通过获得测试帧的分类准确度来评估经过训练的网络
elapsedTime = seconds(toc);
elapsedTime.Format = 'hh:mm:ss';
fprintf('%s - Classifying test frames\n', elapsedTime)
% Read the test frames into the memory
testFrames = transform(testDS, @helperModClassReadFrame);
rxTestFrames = readall(testFrames,"UseParallel",pctExists);% Read the test labels into the memory
testLabels = transform(testDS, @helperModClassReadLabel);
rxTestLabels = readall(testLabels,"UseParallel",pctExists);scores = predict(trainedNet,cat(3,rxTestFrames{:}));
rxTestPred = scores2label(scores,modulationTypes);
testAccuracy = mean(rxTestPred == rxTestLabels);
disp("Test accuracy: " + testAccuracy*100 + "%")%% 使用 SDR 进行测试
%使用 helperModClassSDRTest 函数,通过空口信号测试经过训练的网络的性能。
radioPlatform = "ADALM-PLUTO";switch radioPlatformcase "ADALM-PLUTO"if helperIsPlutoSDRInstalled() == trueradios = findPlutoRadio();if length(radios) >= 2helperModClassSDRTest(radios);elsedisp('Selected radios not found. Skipping over-the-air test.')endendcase {"USRP B2xx","USRP X3xx","USRP N2xx"}if (helperIsUSRPInstalled() == true) && (helperIsPlutoSDRInstalled() == true)txRadio = findPlutoRadio();rxRadio = findsdru();switch radioPlatformcase "USRP B2xx"idx = contains({rxRadio.Platform}, {'B200','B210'});case "USRP X3xx"idx = contains({rxRadio.Platform}, {'X300','X310'});case "USRP N2xx"idx = contains({rxRadio.Platform}, 'N200/N210/USRP2');endrxRadio = rxRadio(idx);if (length(txRadio) >= 1) && (length(rxRadio) >= 1)helperModClassSDRTest(rxRadio);elsedisp('Selected radios not found. Skipping over-the-air test.')endend
end

工程文件

https://download.csdn.net/download/XU157303764/89498445

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/864623.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot学习06-[SpringBoot与AOP、SpringBoot自定义starter]

SpringBoot自定义starter SpringBoot与AOP SpringBoot与AOP 使用AOP实现用户接口访问日志功能 添加AOP场景启动器 <!--添加AOP场景启动器--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</…

都2024了,现在搞本HCIE真的还来得及?

信息技术的迅猛发展&#xff0c;网络的飞速进步&#xff0c;网络工程师这一职业的需求也在不断增加。 作为华为认证体系中的顶级认证&#xff0c;HCIE一直以来都是网络工程师追求的目标之一。 都2024了&#xff0c;厂商认证都火了十几年来&#xff0c;很多人犹犹豫豫&#xff0…

Mybatis1(JDBC编程和ORM模型 MyBatis简介 实现增删改查 MyBatis生命周期)

目录 一、JDBC编程和ORM模型 1. JDBC回顾 2. JDBC的弊端 3. ORM模型 Mybatis和hibernate 区别: 4. mybatis 解决了jdbc 的问题 二、MyBatis简介 1. MyBatis快速开始 1.1 导入jar包 1.2 引入 mybatis-config.xml 配置文件 1.3 引入 Mapper 映射文件 1.3 测试 …

Ubuntu Server 和 Ubuntu Desktop 组合使用

1.常见的组合使用方式 Ubuntu Server 和 Ubuntu Desktop 确实可以组合使用&#xff0c;但具体要看你的需求和使用场景。以下是一些常见的组合使用方式&#xff1a; 单一设备上安装&#xff1a;你可以在一台设备上同时安装 Ubuntu Server 和 Ubuntu Desktop。这样&#xff0c;你…

【ARM系列】1of N SPI

1 of N模式 SPI 概述配置流程 概述 GIC-600AE支持1 of N模式SPI。在此模式下可以将SPI target到多个core&#xff0c;并且GIC-600AE可以选择哪些内核接收SPI。 GIC-600AE只向处于powered up 并且使能中断组的core发送SPI。 GIC-600AE会优先考虑那些被认为是active的核&#xf…

OOCL东方海外不定位置旋转验证码识别代码

样例图如下 这款验证码的识别最大难度在于&#xff0c;旋转的位置不固定&#xff0c;需要识别旋转图片的位置。 第二大难点就是旋转角度的识别。所以我们采集了大量样例图片进行训练&#xff0c;如下图所示 最终训练得到的模型需要两张图片输入&#xff0c;才能完成旋转角度识…

阿里 Mobile-Agent-v2:基于大模型的安卓鸿蒙自动化工具

与之前介绍的 DigiRL类似, Mobile-Agent-v2是一个支持安卓和鸿蒙系统的自动化工具&#xff0c;它使用视觉模型理解手机屏幕&#xff0c;并利用 ADB 来实现操作手机&#xff0c;你可以在本地运行&#xff0c;或者通过手机截图在线体验 Mobile-Agent-v2 从演示来看&#xff0c;可…

短信接口平台的核心功能有哪些?如何使用?

短信接口平台怎么有效集成&#xff1f;选择短信接口平台的技巧&#xff1f; 短信接口平台作为一种重要的通信工具&#xff0c;广泛应用于各种企业和组织。通过短信接口平台&#xff0c;企业能够高效、便捷地与客户进行互动和沟通。AoKSend将详细介绍短信接口平台的核心功能。 …

Android --- 新电脑安装Android Studio 使用 Android 内置模拟器电脑直接卡死,鼠标和键盘都操作不了

新电脑安装Android Studio 使用 Android 内置模拟器电脑直接卡死&#xff0c;鼠标和键盘都操作不了 大概原因就是,初始化默认Google的安卓模拟器占用的RAM内存是2048&#xff0c;如果电脑的性能和内存一般的话就可能卡死&#xff0c;解决方案是手动修改安卓模拟器的config文件&…

Python酷库之旅-第三方库openpyxl(20)

目录 一、 openpyxl库的由来 1、背景 2、起源 3、发展 4、特点 4-1、支持.xlsx格式 4-2、读写Excel文件 4-3、操作单元格 4-4、创建和修改工作表 4-5、样式设置 4-6、图表和公式 4-7、支持数字和日期格式 二、openpyxl库的优缺点 1、优点 1-1、支持现代Excel格式…

架构练习题目

【2022下架构真题第24题&#xff1a;红色】 24.在分布式系统中&#xff0c;中间件通常提供两种不同类型的支持&#xff0c;即&#xff08;27) A.数据支持和交互支持 B.交互支持和提供公共服务 C.数据支持和提供公共服务 D.安全支持和提供公共服务 解答&#xff1a;答案选择B。…

【知识图谱系列】(实例)python操作neo4j构建企业间的业务往来的知识图谱

本章节通过聚焦于"金额"这一核心属性&#xff0c;构建了一幅知识图谱&#xff0c;旨在揭示"销售方"与"购买方"间的商业互动网。在这张图谱中&#xff0c;绿色节点象征着购买方&#xff0c;而红色节点则代表了销售方。这两类节点间的紧密连线&…

苹果手机+AI手机概念股名单一览表

苹果智能将成为AI手机引领者&#xff0c;推动原生智能加速渗透&#xff0c;据Canlys预计2025年iOS操作系统将占据全球AI手机出货的55%。 AI手机端侧算力提升&#xff0c;将带动产业链部件升级创新 端侧算力提升或带动手机芯片及零部件升级&#xff0c;如 1&#xff09;SoC芯片&…

无人机智能追踪反制系统技术详解

随着无人机技术的飞速发展&#xff0c;无人机在各个领域的应用越来越广泛。然而&#xff0c;无人机的无序飞行和非法使用也带来了一系列安全隐患和威胁。因此&#xff0c;无人机智能追踪反制系统应运而生&#xff0c;成为维护公共安全和防止无人机滥用的重要工具。本文将详细介…

Java Lambda语法介绍

目录 一、概述 二、Lambda语法的历史 2.1 Lambda名字的含义 2.2 Lambda的历史 三、Lambda语法的核心接口 3.1 Lambda的四大核心接口 3.1.1 概述 3.1.2 Consumer 接口 3.1.3 Supplier 接口 3.1.4 Function 接口,> 3.1.5 Predicate 接口 四、Lambda的引用 4.1 概…

云海中的坚固灯塔:等保测评视角下的混合云安全策略与合规性深度剖析

在数字化浪潮的推动下&#xff0c;混合云架构以其独特的优势成为企业转型升级的得力助手。然而&#xff0c;随着数据资产向云端迁移&#xff0c;安全风险与合规挑战亦如影随形&#xff0c;成为企业前行的绊脚石。等保测评作为我国网络安全的一道坚实屏障&#xff0c;对于护航云…

Gartner发布软件供应链安全指南:软件供应链攻击造成的损失将从 2023 年的460亿美元上升到2031年的1380亿美元

软件供应链安全是一个关键的风险和合规性问题&#xff0c;但大多数组织都以分散的方式处理它。缺乏一个包罗万象的框架会遗留安全漏洞。通过实施三支柱框架&#xff0c;安全和风险管理领导者可以确保广泛的保护。 主要发现 对软件供应链的攻击给组织带来重大的安全、监管和运营…

【深度学习】pytorch训练中的一个大坑

使用的命令&#xff1a;iostat -x 5 可以看到 ssd的利用率已经满了。 之前在的数据集放在了 hdd上&#xff0c;训练结果特别慢。 所以我把它移动到了ssd上&#xff0c;然后训练参数用的 resume&#xff0c; 但是&#xff01;&#xff01;&#xff01;&#xff01;它把历史记住…

【C语言】19.预处理详解

文章目录 1.预定义符号2.#define定义常量3.#define定义宏4.带有副作用的宏参数5.宏替换的规则6.宏函数的对比7.#和##7.1 #运算符7.2 ## 运算符 8.命名约定9.#undef10.命令行定义11.条件编译12.头文件的包含12.1 头⽂件被包含的⽅式12.1.1 本地⽂件包含12.1.2 库⽂件包含 12.2 嵌…

甲骨文首次将LLMs引入数据库,集成Llama 3和Mistral,和数据库高效对话

信息时代&#xff0c;数据为王。数据库作为数据存储&管理的一种方式&#xff0c;正在以势不可挡的趋势与AI结合。 前有OpenAI 收购了数据库初创公司 Rockset&#xff0c;引发广泛关注&#xff1b;Oracle公司&#xff08;甲骨文&#xff09;作为全球最大的信息管理软件及服…