В этом примере показано, как использовать сверточную нейронную сеть (CNN) для классификации модуляции. Вы генерируете синтетические сигналы с нарушением канала. Используя сгенерированные формы сигналов в качестве обучающих данных, вы обучаете CNN классификации модуляции. Затем необходимо протестировать CNN с помощью аппаратных средств программно-определяемого радио (SDR) и эфирных сигналов.
Обученный CNN в этом примере распознает эти восемь типов цифровой и три аналоговых модуляции:
Двоичная фазовая манипуляция (BPSK)
Квадратурная фазовая манипуляция (QPSK)
8-арная фазовая манипуляция (8-PSK)
16-арная квадратурная амплитудная модуляция (16-QAM)
64-мерная квадратурная амплитудная модуляция (64-QAM)
4-мерная амплитудно-импульсная модуляция (PAM4)
Гауссова частотная манипуляция (GFSK)
Непрерывная фазовая частотная манипуляция (CPFSK)
Широковещательное FM (B-FM)
Амплитудная модуляция с двойной боковой полосой (DSB-AM)
Модуляция амплитуды одной боковой полосы (SSB-AM)
modulationTypes = categorical(["BPSK", "QPSK", "8PSK", ... "16QAM", "64QAM", "PAM4", "GFSK", "CPFSK", ... "B-FM", "DSB-AM", "SSB-AM"]);
Сначала загрузите обученную сеть. Дополнительные сведения о сетевом обучении см. в разделе Обучение CNN.
load trainedModulationClassificationNetwork
trainedNettrainedNet =
SeriesNetwork with properties:
Layers: [28×1 nnet.cnn.layer.Layer]
InputNames: {'Input Layer'}
OutputNames: {'Output'}
Обученный CNN берет 1024 выборки с нарушением канала и предсказывает тип модуляции каждого кадра. Генерация нескольких кадров PAM4, которые повреждены замиранием многолучевого распространения Rician, дрейфом центральной частоты и временем дискретизации и AWGN. Используйте следующую функцию для генерации синтетических сигналов для тестирования CNN. Затем используйте CNN для прогнозирования типа модуляции кадров.
randi: Создание случайных битов
pammod PAM4-modulate биты
rcosdesign: Разработка квадратного корня для формирования косинусных импульсов
filter: Импульсная форма символов
comm.RicianChannelПрименение многолучевого канала Rician
comm.PhaseFrequencyOffsetПрименение сдвига фазы и/или частоты из-за смещения тактового сигнала
interp1Применение дрейфа синхронизации из-за смещения тактового сигнала
awgnДобавить 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 [prediction1,score1] = classify(trainedNet,unknownFrames);
Верните предсказания классификатора, которые аналогичны жестким решениям. Сеть правильно идентифицирует кадры как PAM4 кадры. Дополнительные сведения о генерации модулированных сигналов см. в разделе Функция helperModClassGetModulator.
prediction1
prediction1 = 7×1 categorical
PAM4
PAM4
PAM4
PAM4
PAM4
PAM4
PAM4
Классификатор также возвращает вектор баллов для каждого кадра. Оценка соответствует вероятности того, что каждый кадр имеет прогнозируемый тип модуляции. Постройте графики баллов.
helperModClassPlotScores(score1,modulationTypes)

Прежде чем мы сможем использовать CNN для классификации модуляции или любой другой задачи, нам сначала нужно обучить сеть известным (или помеченным) данным. В первой части этого примера показано, как использовать функции Communications Toolbox, такие как модуляторы, фильтры и нарушения канала, для создания синтетических обучающих данных. Вторая часть посвящена определению, обучению и тестированию CNN для задачи классификации модуляции. В третьей части проверяются характеристики сети с использованием эфирных сигналов с использованием программно определяемых радиоопор (SDR).
Создайте 10 000 кадров для каждого типа модуляции, где 80% используется для обучения, 10% используется для проверки и 10% используется для тестирования. Мы используем кадры обучения и проверки на этапе обучения сети. Окончательную точность классификации получают с помощью тестовых кадров. Каждый кадр имеет длину 1024 выборки и частоту дискретизации 200 кГц. Для типов цифровой модуляции восемь выборок представляют символ. Сеть принимает каждое решение на основе отдельных кадров, а не нескольких последовательных кадров (как в видео). Предположим, центральная частота 902 МГц и 100 МГц для типов цифровой и аналоговой модуляции соответственно.
Для быстрого выполнения этого примера используйте обученную сеть и создайте небольшое количество учебных кадров. Чтобы обучить сеть на компьютере, выберите опцию «Обучить сеть сейчас» (т. е. установите trainNow в значение true).
trainNow =false; if trainNow == true numFramesPerModType = 10000; else numFramesPerModType = 500; end percentTrainingSamples = 80; percentValidationSamples = 10; percentTestSamples = 10; sps = 8; % Samples per symbol spf = 1024; % Samples per frame symbolsPerFrame = spf / sps; fs = 200e3; % Sample rate fc = [902e6 100e6]; % Center frequencies
Пропускать каждый кадр через канал с
AWGN
Многолучевое замирание Rician
Сдвиг тактового сигнала, приводящий к смещению центральной частоты и дрейфу времени выборки
Поскольку сеть в этом примере принимает решения на основе отдельных кадров, каждый кадр должен проходить через независимый канал.
Канал добавляет AWGN с SNR 30 дБ. Реализация канала с помощью awgn функция.
Канал пропускает сигналы через канал многолучевого замирания Rician с использованием comm.RicianChannel Системный объект. Предположим, что профиль задержки равен [0 1,8 3,4] отсчетов с соответствующими средними коэффициентами усиления пути [0 -2 -10] дБ. K-фактор равен 4, а максимальный доплеровский сдвиг равен 4 Гц, что эквивалентно скорости ходьбы при 902 МГц. Реализуйте канал со следующими настройками.
Смещение синхросигналов происходит из-за неточностей внутренних источников синхросигналов передатчиков и приемников. Сдвиг тактового сигнала приводит к тому, что центральная частота, которая используется для преобразования сигнала с понижением частоты в основную полосу частот, и частота дискретизации цифроаналогового преобразователя отличаются от идеальных значений. Имитатор канала использует коэффициент смещения тактового сигнала, выраженный как Δclock106, Δclock - смещение тактового сигнала. Для каждого кадра канал генерирует значение Δclock из равномерно распределенного набора значений в maxΔclock maxΔclock], maxΔclock является максимальным сдвигом тактового сигнала. Смещение часов измеряется в частях на миллион (ppm). В этом примере предположим, что максимальное смещение тактового сигнала составляет 5 ppm.
maxDeltaOff = 5; deltaOff = (rand()*2*maxDeltaOff) - maxDeltaOff; C = 1 + (deltaOff/1e6);
Сдвиг частоты
Подвергнуть каждый кадр сдвигу частоты, основанному на коэффициенте сдвига тактового сигнала и центральной частоте. Реализация канала с помощью comm.PhaseFrequencyOffset.
Смещение частоты дискретизации
Подвергнуть каждый кадр смещению частоты дискретизации на основе коэффициента сдвига тактового сигнала C. Реализовать канал с использованием interp1 функция для повторной выборки кадра с новой скоростью fs.
Используйте объект helperModClassStartChannel, чтобы применить все три ухудшения канала к кадрам.
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: 30
CenterFrequency: 902000000
SampleRate: 200000
PathDelays: [0 9.0000e-06 1.7000e-05]
AveragePathGains: [0 -2 -10]
KFactor: 4
MaximumDopplerShift: 4
MaximumClockOffset: 5
Просмотреть основную информацию о канале можно с помощью функции инфо-объекта.
chInfo = info(channel)
chInfo = struct with fields:
ChannelDelay: 6
MaximumFrequencyOffset: 4510
MaximumSampleRateOffset: 1
Создайте цикл, который генерирует кадры с нарушением канала для каждого типа модуляции и сохраняет кадры с соответствующими метками в файлах MAT. Сохранение данных в файлы устраняет необходимость создания данных при каждом выполнении этого примера. Кроме того, можно повысить эффективность совместного использования данных.
Удалите случайное число выборок из начала каждого кадра, чтобы удалить переходные процессы и убедиться, что кадры имеют случайную начальную точку относительно границ символов.
% Set the random number generator to a known state to be able to regenerate % the same frames every time the simulation is run rng(1235) tic numModulationTypes = length(modulationTypes); channelInfo = info(channel); transDelay = 50; dataDirectory = fullfile(tempdir,"ModClassDataFiles"); disp("Data file directory is " + dataDirectory)
Data file directory is C:\Users\esozer\AppData\Local\Temp\ModClassDataFiles
fileNameRoot = "frame"; % Check if data files exist dataFilesExist = false; if exist(dataDirectory,'dir') files = dir(fullfile(dataDirectory,sprintf("%s*",fileNameRoot))); if length(files) == numModulationTypes*numFramesPerModType dataFilesExist = true; end end if ~dataFilesExist disp("Generating data and saving in data files...") [success,msg,msgID] = mkdir(dataDirectory); if ~success error(msgID,msg) end for modType = 1:numModulationTypes fprintf('%s - Generating %s frames\n', ... datestr(toc/86400,'HH:MM:SS'), 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 MHz channel.CenterFrequency = 100e6; else % Digital modulation types use a center frequency of 902 MHz channel.CenterFrequency = 902e6; end for p=1:numFramesPerModType % Generate random data x = dataSrc(); % Modulate y = modulator(x); % Pass through independent channels rxSamples = channel(y); % Remove transients from the beginning, trim to size, and normalize frame = helperModClassFrameGenerator(rxSamples, spf, spf, transDelay, sps); % Save data file fileName = fullfile(dataDirectory,... sprintf("%s%s%03d",fileNameRoot,modulationTypes(modType),p)); save(fileName,"frame","label") end end else disp("Data files exist. Skip data generation.") end
Data files exist. Skip data generation.
% Plot the amplitude of the real and imaginary parts of the example frames % against the sample number helperModClassPlotTimeDomain(dataDirectory,modulationTypes,fs)

% Plot the spectrogram of the example frames
helperModClassPlotSpectrogram(dataDirectory,modulationTypes,fs,sps)
Использовать signalDatastore объект для управления файлами, содержащими сформированные сложные формы сигнала. Хранилища данных особенно полезны, когда каждый отдельный файл умещается в памяти, но вся коллекция не обязательно умещается.
frameDS = signalDatastore(dataDirectory,'SignalVariableNames',["frame","label"]);
Сеть глубокого обучения в этом примере ожидает реальных входных сигналов, в то время как принятый сигнал имеет сложные выборки основной полосы частот. Преобразуйте сложные сигналы в массивы 4-D с действительными значениями. Выходные кадры имеют размер 1-by-spf-by-2-by-N, где первая страница (3-е измерение) является синфазной выборкой, а вторая страница является квадратурной выборкой. Когда сверточные фильтры имеют размер 1 за spf, этот подход гарантирует, что информация в I и Q смешивается даже в сверточных слоях и лучше использует фазовую информацию. Дополнительные сведения см. в разделе helperModClassIQAsPages.
frameDSTrans = transform(frameDS,@helperModClassIQAsPages);
Затем разделите кадры на обучающие, проверочные и тестовые данные. Дополнительные сведения см. в разделе helperModClassSplitData.
splitPercentages = [percentTrainingSamples,percentValidationSamples,percentTestSamples]; [trainDSTrans,validDSTrans,testDSTrans] = helperModClassSplitData(frameDSTrans,splitPercentages);
Starting parallel pool (parpool) using the 'local' profile ... Connected to the parallel pool (number of workers: 6).
Evaluating tall expression using the Parallel Pool 'local': - Pass 1 of 2: Completed in 11 sec - Pass 2 of 2: Completed in 11 sec Evaluation completed in 25 sec
Обучение нейронной сети итеративно. При каждой итерации хранилище данных считывает данные из файлов и преобразует их перед обновлением сетевых коэффициентов. Если данные помещаются в память компьютера, импорт данных из файлов в память обеспечивает более быстрое обучение, исключая это повторное чтение из файла и процесс преобразования. Вместо этого данные считываются из файлов и преобразуются один раз. Обучение этой сети с использованием файлов данных на диске занимает около 110 минут, а обучение с использованием данных в памяти - около 50 минут.
Импортируйте все данные из файлов в память. Файлы имеют две переменные: frame и label и каждый read вызов хранилища данных возвращает массив ячеек, где первым элементом является frame и вторым элементом является label. Используйте transform функции helperModClassReadFrame и helperModClassReadLabel предназначены для чтения фреймов и меток. Использовать tall для параллельной обработки функций преобразования в случае наличия лицензии Parallel Computing Toolbox. С тех пор gather функция по умолчанию объединяет выходные данные read функция над первым измерением, возврат кадров в массиве ячеек и ручная конкатенация над четвертым измерением.
% Gather the training and validation frames into the memory
trainFramesTall = tall(transform(trainDSTrans, @helperModClassReadFrame));
rxTrainFrames = gather(trainFramesTall);Evaluating tall expression using the Parallel Pool 'local': - Pass 1 of 1: Completed in 4.3 sec Evaluation completed in 4.3 sec
rxTrainFrames = cat(4, rxTrainFrames{:});
validFramesTall = tall(transform(validDSTrans, @helperModClassReadFrame));
rxValidFrames = gather(validFramesTall);Evaluating tall expression using the Parallel Pool 'local': - Pass 1 of 1: Completed in 0.76 sec Evaluation completed in 0.78 sec
rxValidFrames = cat(4, rxValidFrames{:});
% Gather the training and validation labels into the memory
trainLabelsTall = tall(transform(trainDSTrans, @helperModClassReadLabel));
rxTrainLabels = gather(trainLabelsTall);Evaluating tall expression using the Parallel Pool 'local': - Pass 1 of 2: Completed in 4.6 sec - Pass 2 of 2: Completed in 7 sec Evaluation completed in 12 sec
validLabelsTall = tall(transform(validDSTrans, @helperModClassReadLabel)); rxValidLabels = gather(validLabelsTall);
Evaluating tall expression using the Parallel Pool 'local': - Pass 1 of 2: Completed in 0.7 sec - Pass 2 of 2: Completed in 0.85 sec Evaluation completed in 1.8 sec
В этом примере используется CNN, состоящий из шести слоев свертки и одного полностью подключенного слоя. За каждым уровнем свертки, за исключением последнего, следует уровень нормализации партии, уровень активации выпрямленного линейного блока (ReLU) и уровень максимального объединения. На последнем уровне свертки максимальный уровень объединения заменяется средним уровнем объединения. Выходной уровень имеет активацию softmax. Руководство по сетевому проектированию см. в разделе Советы и рекомендации по глубокому обучению (инструментарий для глубокого обучения).
modClassNet = helperModClassCNN(modulationTypes,sps,spf);
Следующая настройка TrainingOptionsSGDM (Deep Learning Toolbox) для использования решателя SGDM с размером мини-пакета 256. Установите максимальное количество эпох на 12, так как большее количество эпох не дает дальнейшего преимущества обучения. По умолчанию 'ExecutionEnvironment' свойство имеет значение 'auto', где trainNetwork использует графический процессор, если он доступен, или использует ЦП, если нет. Для использования графического процессора необходимо иметь лицензию Parallel Computing Toolbox. Установите начальную скорость обучения 2x10-2. Снижайте уровень обучения в 10 раз каждые 9 эпох. Набор 'Plots' комуtraining-progress' для построения графика хода обучения. На GPU NVIDIA Titan Xp обучение в сети занимает примерно 25 минут..
maxEpochs = 12;
miniBatchSize = 256;
options = helperModClassTrainingOptions(maxEpochs,miniBatchSize,...
numel(rxTrainLabels),rxValidFrames,rxValidLabels);Выполните обучение сети или используйте уже обученную сеть. По умолчанию в этом примере используется обученная сеть.
if trainNow == true fprintf('%s - Training the network\n', datestr(toc/86400,'HH:MM:SS')) trainedNet = trainNetwork(rxTrainFrames,rxTrainLabels,modClassNet,options); else load trainedModulationClassificationNetwork end
Как показывает график тренировочного прогресса, сеть сходится примерно в 12 эпохах с точностью более 95%.

Оценка обученной сети путем получения точности классификации для тестовых кадров. Результаты показывают, что сеть достигает точности около 94% для этой группы сигналов.
fprintf('%s - Classifying test frames\n', datestr(toc/86400,'HH:MM:SS'))
00:02:18 - Classifying test frames
% Gather the test frames into the memory
testFramesTall = tall(transform(testDSTrans, @helperModClassReadFrame));
rxTestFrames = gather(testFramesTall);Evaluating tall expression using the Parallel Pool 'local': - Pass 1 of 1: Completed in 0.68 sec Evaluation completed in 0.69 sec
rxTestFrames = cat(4, rxTestFrames{:});
% Gather the test labels into the memory
testLabelsTall = tall(transform(testDSTrans, @helperModClassReadLabel));
rxTestLabels = gather(testLabelsTall);Evaluating tall expression using the Parallel Pool 'local': - Pass 1 of 2: Completed in 0.7 sec - Pass 2 of 2: Completed in 0.86 sec Evaluation completed in 1.8 sec
rxTestPred = classify(trainedNet,rxTestFrames); testAccuracy = mean(rxTestPred == rxTestLabels); disp("Test accuracy: " + testAccuracy*100 + "%")
Test accuracy: 95.4545%
Постройте график матрицы путаницы для тестовых кадров. Как видно из матрицы, сеть путает кадры 16-QAM и 64-QAM. Эта проблема ожидается, поскольку каждый кадр содержит только 128 символов и 16-QAM является подмножеством 64-QAM. Сеть также путает QPSK и 8-PSK кадры, поскольку совокупности этих типов модуляции выглядят сходными после фазового поворота из-за замирания канала и сдвига частоты.
figure cm = confusionchart(rxTestLabels, rxTestPred); cm.Title = 'Confusion Matrix for Test Data'; cm.RowSummary = 'row-normalized'; cm.Parent.Position = [cm.Parent.Position(1:2) 740 424];

Протестируйте работу обученной сети с помощью эфирных сигналов с помощью функции helperModClassSDRTest. Для выполнения этого теста необходимо наличие специальных SDR для передачи и приема. Можно использовать два радиоприёмника ADALM-PLUTO или один радиоприемник ADALM-PLUTO для передачи и один радиоприемник USRP ® для приема. Необходимо установить пакет поддержки Communications Toolbox для ADALM-PLUTO Radio. При использовании радио USRP ® необходимо также установить пакет поддержки Communications Toolbox для радио USRP ®. helperModClassSDRTest функция использует те же функции модуляции, которые используются для генерации обучающих сигналов, и затем передает их с помощью радиомодуля ADALM-PLUTO. Вместо моделирования канала захватывайте сигналы с нарушением канала с помощью SDR, сконфигурированного для приема сигнала (радио ADALM-PLUTO или USRP ®). Использовать обученную сеть с тем же самымclassify функция, использованная ранее для прогнозирования типа модуляции. Выполнение следующего сегмента кода создает матрицу путаницы и распечатывает точность теста.
radioPlatform ="ADALM-PLUTO"; switch radioPlatform case "ADALM-PLUTO" if helperIsPlutoSDRInstalled() == true radios = findPlutoRadio(); if length(radios) >= 2 helperModClassSDRTest(radios); else disp('Selected radios not found. Skipping over-the-air test.') end end case {"USRP B2xx","USRP X3xx","USRP N2xx"} if (helperIsUSRPInstalled() == true) && (helperIsPlutoSDRInstalled() == true) txRadio = findPlutoRadio(); rxRadio = findsdru(); switch radioPlatform case "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'); end rxRadio = rxRadio(idx); if (length(txRadio) >= 1) && (length(rxRadio) >= 1) helperModClassSDRTest(rxRadio); else disp('Selected radios not found. Skipping over-the-air test.') end end end
При использовании двух стационарных радиоприемников ADALM-PLUTO, разделенных примерно 2 футами, сеть достигает 99% общей точности с помощью следующей матрицы путаницы. Результаты будут варьироваться в зависимости от экспериментальной настройки.

Для повышения точности можно оптимизировать параметры гиперпараметров, такие как количество фильтров, размер фильтра или оптимизировать структуру сети, такие как добавление дополнительных слоев, использование различных уровней активации и т.д.
Communication Toolbox предоставляет гораздо больше типов модуляции и нарушений канала. Дополнительные сведения см. в разделах Модуляция и распространение и Модели каналов. Также можно добавлять стандартные сигналы с помощью инструментов LTE, WLAN Toolbox и 5G Toolbox. Можно также добавить радиолокационные сигналы с помощью панели инструментов системы фазированной решетки.
Функция helperModClassGetModulator предоставляет функции MATLAB, используемые для генерации модулированных сигналов. Для получения дополнительной информации можно также ознакомиться со следующими функциями и системными объектами:
О'Ши, Т. Дж., Дж. Корган и Т. К. Клэнси. «Сети распознавания сверточной радиомодуляции». Препринт, представлен 10 июня 2016 года. https://arxiv.org/abs/1602.04105
О'Ши, Т. Дж., Т. Рой и Т. К. Клэнси. «Классификация радиосигналов, основанных на глубоком обучении по эфиру». Журнал IEEE выбранных тем в обработке сигналов. т. 12, номер 1, 2018, стр. 168-179.
Лю, Х., Д. Ян и А. Э. Гамаль. «Архитектура глубоких нейронных сетей для классификации модуляции». Препринт, представлен 5 января 2018 года. https://arxiv.org/abs/1712.00443v3