Классификация модуляций с глубоким обучением

В этом примере показано, как использовать сверточную нейронную сеть (CNN) для классификации модуляций. Вы генерируете синтетический продукт, поврежденные каналом формы волны. Используя сгенерированные формы волны как обучающие данные, вы обучаете CNN классификации модуляций. Вы затем тестируете CNN с оборудованием программно определяемого радио (SDR) и беспроводными сигналами.

Предскажите тип модуляции Используя CNN

Обученный CNN в этом примере распознает эти цифровые восемь и три аналоговых типа модуляции:

  • Бинарное манипулирование сдвига фазы (BPSK)

  • Манипулирование сдвига фазы Quadrature (QPSK)

  • 8-ary сдвиг фазы, включающий (8-PSK)

  • 16-ary квадратурная амплитудная (16-QAM) модуляция

  • 64-ary квадратурная амплитудная (64-QAM) модуляция

  • 4-ary импульсная амплитудная модуляция (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"]);

Во-первых, загрузите обучивший сеть. Для получения дополнительной информации на сетевом обучении, смотрите раздел Training a CNN.

load trainedModulationClassificationNetwork
trainedNet
trainedNet = SeriesNetwork with properties:
         Layers: [28×1 nnet.cnn.layer.Layer]
     InputNames: {'Input Layer'}
    OutputNames: {'Output'}

Обученный CNN берет 1 024 поврежденных каналом выборки и предсказывает тип модуляции каждой системы координат. Сгенерируйте несколько систем координат PAM4, которым повреждают с Rician многопутевое исчезновение, центральная частота и дрейф времени выборки и AWGN. Используйте следующую функцию, чтобы сгенерировать синтетические сигналы протестировать CNN. Затем используйте CNN, чтобы предсказать тип модуляции систем координат.

  • randi: Сгенерируйте случайные биты

  • pammod PAM4-модулируйте биты

  • 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% используется для тестирования. Мы используем системы координат обучения и валидации во время сетевой учебной фазы. Итоговая точность классификации получена с помощью тестовых систем координат. Каждая система координат является 1 024 выборками долго и имеет частоту дискретизации 200 кГц. Для цифровых типов модуляции восемь выборок представляют символ. Сеть принимает каждое решение на основе одной систем координат, а не на нескольких последовательных системах координат (как в видео). Примите центральную частоту 902 МГц и 100 МГц для цифровых и аналоговых типов модуляции, соответственно.

Чтобы запустить этот пример быстро, используйте обучивший сеть и сгенерируйте небольшое количество учебных систем координат. Чтобы обучить сеть на вашем компьютере, выберите опцию "Train network now" (i.e. установите trainNow на истину).

trainNow = false;
if trainNow == верный
  numFramesPerModType = 10000;
else
  numFramesPerModType = 200;
end
percentTrainingSamples = 80;
percentValidationSamples = 10;
percentTestSamples = 10;

SPS = 8;                % Samples per symbol
солнцезащитный фактор = 1024;             % Samples per frame
symbolsPerFrame = солнцезащитный фактор / SPS;
фс = 200e3;             % Sample rate
ФК = [902e6 100e6];     % Center frequencies

Создайте ухудшения канала

Передайте каждый кадр через канал с

  • AWGN

  • Rician многопутевое исчезновение

  • Смещение часов, приводящее к центральному смещению частоты и дрейфу времени выборки

Поскольку сеть в этом примере принимает решения на основе одной систем координат, каждая система координат должна пройти через независимый канал.

AWGN

Канал добавляет AWGN с ОСШ 30 дБ. Реализуйте канал с помощью awgn функция.

Многопутевой Rician

Канал передает сигналы через Rician многопутевой исчезающий канал с помощью comm.RicianChannel Системный объект. Примите профиль задержки [0 1.8 3.4] выборки с соответствующими средними усилениями пути [0 - 2 - 10] дБ. K-фактор равняется 4, и максимальный эффект Доплера составляет 4 Гц, который эквивалентен скорости обхода на уровне 902 МГц. Реализуйте канал со следующими настройками.

Смещение часов

Смещение часов происходит из-за погрешностей внутренних источников часов передатчиков и приемников. Синхронизируйте причины смещения центральная частота, которая используется к downconvert сигнал к основной полосе и частота дискретизации цифро-аналогового преобразователя, чтобы отличаться от идеальных значений. Средство моделирования канала использует фактор смещения часов C, описанный как C=1+Δclock106, где Δclock смещение часов. Для каждой системы координат канал генерирует случайное Δclock значение от равномерно распределенного множества значений в области значений [-maxΔclock maxΔclock], где maxΔclock максимальное смещение часов. Смещение часов измеряется в частях на миллион (ppm). В данном примере примите максимальное смещение часов 5 страниц в минуту.

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

Смещение частоты

Подвергните каждую систему координат смещению частоты на основе фактора смещения часов C и центральная частота. Реализуйте канал с помощью comm.PhaseFrequencyOffset.

Смещение частоты дискретизации

Подвергните каждую систему координат смещению частоты дискретизации на основе фактора смещения часов 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: 30
        CenterFrequency: 902000000
             SampleRate: 200000
             PathDelays: [0 9.0000e-06 1.7000e-05]
       AveragePathGains: [0 -2 -10]
                KFactor: 4
    MaximumDopplerShift: 4
     MaximumClockOffset: 5

Можно просмотреть основную информацию о канале с помощью функции объекта info.

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:\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
    elapsedTime = 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 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
Generating data and saving in data files...
00:00:00 - Generating BPSK frames
00:00:01 - Generating QPSK frames
00:00:02 - Generating 8PSK frames
00:00:04 - Generating 16QAM frames
00:00:05 - Generating 64QAM frames
00:00:06 - Generating PAM4 frames
00:00:08 - Generating GFSK frames
00:00:09 - Generating CPFSK frames
00:00:11 - Generating B-FM frames
00:00:12 - Generating DSB-AM frames
00:00:13 - Generating SSB-AM frames
% 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)

Создание Datastore

Используйте signalDatastore объект управлять файлами, которые содержат сгенерированные комплексные формы волны. Хранилища данных особенно полезны, когда каждый отдельный файл умещается в памяти, но целый набор не обязательно соответствует.

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

Преобразуйте комплексные сигналы к действительным массивам

Нейронная сеть для глубокого обучения в этом примере ожидает действительные входные параметры, в то время как полученный сигнал имеет комплексные основополосные выборки. Преобразуйте комплексные сигналы в действительные оцененные 4-D массивы. Выходные системы координат имеют размер 1 солнцезащитным фактором 2 N, где первая страница (3-я размерность) является синфазными выборками, и вторая страница является квадратурными выборками. Когда сверточные фильтры имеют размер 1 солнцезащитным фактором, этот подход гарантирует, что информация во мне и 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).

Импортируйте данные в память

Обучение нейронной сети является итеративным. В каждой итерации datastore считывает данные из файлов и преобразовывает данные прежде, чем обновить сетевые коэффициенты. Если совпадения данных в память о вашем компьютере, импортируя данные из файлов в память включают более быстрое обучение путем устранения этого повторного чтения из файла, и преобразуйте процесс. Вместо этого данные считаны из файлов и преобразованы однажды. Обучение эта сеть с помощью файлов данных на диске занимает приблизительно 110 минут, в то время как обучение с помощью данных в оперативной памяти занимает приблизительно 50 min.

Импортируйте все данные в файлах в память. Файлы имеют две переменные: frame и label и каждый read вызов datastore возвращает массив ячеек, где первым элементом является frame и вторым элементом является label. Используйте transform функции helperModClassReadFrame и helperModClassReadLabel, чтобы считать системы координат и метки. Используйте readall с "UseParallel" набор опции к true включить параллельную обработку функций преобразования, в случае, если у вас есть лицензия Parallel Computing Toolbox. Начиная с readall функция, по умолчанию, конкатенирует выход read функционируйте по первой размерности, возвратите системы координат в массиве ячеек и вручную конкатенируйте по 4-й размерности.

% Read the training and validation frames into the memory
pctExists = parallelComputingLicenseExists();
trainFrames = transform(trainDSTrans, @helperModClassReadFrame);
rxTrainFrames = readall(trainFrames,"UseParallel",pctExists);
rxTrainFrames = cat(4, rxTrainFrames{:});
validFrames = transform(validDSTrans, @helperModClassReadFrame);
rxValidFrames = readall(validFrames,"UseParallel",pctExists);
rxValidFrames = cat(4, rxValidFrames{:});

% Read the training and validation labels into the memory
trainLabels = transform(trainDSTrans, @helperModClassReadLabel);
rxTrainLabels = readall(trainLabels,"UseParallel",pctExists);
validLabels = transform(validDSTrans, @helperModClassReadLabel);
rxValidLabels = readall(validLabels,"UseParallel",pctExists);

Обучите CNN

Этот пример использует CNN, который состоит из шести слоев свертки и одного полносвязного слоя. Каждый слой свертки кроме последнего сопровождается слоем нормализации партии., исправил линейный модуль (ReLU) слой активации и макс. объединение слоя. В последнем слое свертки макс. слой объединения заменяется средним слоем объединения. Выходной слой имеет softmax активацию. Для руководства проектирования сети смотрите Советы Глубокого обучения и Приемы (Deep Learning Toolbox).

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' построить процесс обучения. На Титане NVIDIA Xp графический процессор сеть занимает приблизительно 25 минут, чтобы обучаться..

maxEpochs = 12;
miniBatchSize = 256;
options = helperModClassTrainingOptions(maxEpochs,miniBatchSize,...
  numel(rxTrainLabels),rxValidFrames,rxValidLabels);

Или обучите сеть или используйте, уже обучил сеть. По умолчанию этот пример использует обучивший сеть.

if trainNow == true
  elapsedTime = seconds(toc);
  elapsedTime.Format = 'hh:mm:ss';
  fprintf('%s - Training the network\n', elapsedTime)
  trainedNet = trainNetwork(rxTrainFrames,rxTrainLabels,modClassNet,options);
else
  load trainedModulationClassificationNetwork
end

Когда график процесса обучения показывает, сеть сходится приблизительно в 12 эпох больше чем с 95%-й точностью.

Оцените обучивший сеть путем получения точности классификации для тестовых систем координат. Результаты показывают, что сеть достигает приблизительно 94%-й точности для этой группы форм волны.

elapsedTime = seconds(toc);
elapsedTime.Format = 'hh:mm:ss';
fprintf('%s - Classifying test frames\n', elapsedTime)
00:01:25 - Classifying test frames
% Read the test frames into the memory
testFrames = transform(testDSTrans, @helperModClassReadFrame);
rxTestFrames = readall(testFrames,"UseParallel",pctExists);
rxTestFrames = cat(4, rxTestFrames{:});

% Read the test labels into the memory
testLabels = transform(testDSTrans, @helperModClassReadLabel);
rxTestLabels = readall(testLabels,"UseParallel",pctExists);

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];

Протестируйте с SDR

Проверьте производительность обучившего сеть с беспроводными сигналами с помощью функции helperModClassSDRTest. Чтобы выполнить этот тест, вы, должно быть, выделили SDRs для передачи и приема. Можно использовать два радио ADALM-PLUTO, или одно радио ADALM-PLUTO для передачи и один радио USRP® для приема. Необходимо установить Пакет поддержки Communications Toolbox для Радио ADALM-PLUTO. Если вы используете радио USRP®, необходимо также установить Пакет поддержки Communications Toolbox для Радио USRP®. helperModClassSDRTest функционируйте использует те же функции модуляции, как используется для генерации учебных сигналов, и затем передает их использующий радио ADALM-PLUTO. Вместо того, чтобы симулировать канал, получите поврежденные каналом сигналы с помощью SDR, который сконфигурирован для приема сигнала (ADALM-PLUTO или радио USRP®). Используйте обучивший сеть с тем же classify функция раньше ранее предсказывала тип модуляции. Выполнение следующего сегмента кода производит матрицу беспорядка и распечатывает тестовую точность.

radioPlatform = "ADALM-PLUTO";

switch radioPlatform
  case "ADALM-PLUTO"
    if helperIsPlutoSDRInstalled () == верный
      радио = findPlutoRadio ();
      if длина (радио)> = 2
        helperModClassSDRTest (радио);
      else
        disp'Selected radios not found. Skipping over-the-air test.')
      end
    end
  case {"USRP B2xx","USRP X3xx","USRP N2xx"}
    if (helperIsUSRPInstalled () == верный) && (helperIsPlutoSDRInstalled () == верный)
      txRadio = findPlutoRadio ();
      rxRadio = findsdru ();
      switch radioPlatform
        case "USRP B2xx"
          idx = содержит ({rxRadio.Platform}, {'B200','B210'});
        case "USRP X3xx"
          idx = содержит ({rxRadio.Platform}, {'X300','X310'});
        case "USRP N2xx"
          idx = содержит ({rxRadio.Platform}, 'N200/N210/USRP2');
      end
      rxRadio = rxRadio (idx);
      if (длина (txRadio)> = 1) && (длина (rxRadio)> = 1)
        helperModClassSDRTest (rxRadio);
      else
        disp'Selected radios not found. Skipping over-the-air test.')
      end
    end
end

При использовании двух стационарных радио ADALM-PLUTO, разделенных приблизительно на 2 фута, сеть достигает 99%-й общей точности со следующей матрицей беспорядка. Результаты будут варьироваться на основе экспериментальной настройки.

Дальнейшее исследование

Возможно оптимизировать параметры гиперпараметров, такие как количество фильтров, размера фильтра, или оптимизировать структуру сети, такую как добавление большего количества слоев, использование различных слоев активации, и т.д. улучшить точность.

Коммуникационный Тулбокс обеспечивает намного больше типов модуляции и ухудшений канала. Для получения дополнительной информации смотрите разделы Моделей Распространения и Модуляции и Канала. Можно также добавить стандартные определенные сигналы с LTE Toolbox, WLAN Toolbox и 5G Toolbox. Можно также добавить радарные сигналы с Phased Array System Toolbox.

функция helperModClassGetModulator обеспечивает, функции MATLAB раньше генерировали модулируемые сигналы. Можно также исследовать следующие функции и Системные объекты для получения дополнительной информации:

Ссылки

  1. О'Ши, T. J. Дж. Коргэн и Т. К. Клэнси. "Сверточные Радио-Сети Распознавания Модуляции". Предварительно распечатайте, представленный 10 июня 2016. https://arxiv.org/abs/1602.04105

  2. О'Ши, T. J. Т. Рой и Т. К. Клэнси. "Беспроводная основанная на глубоком обучении Радио-Классификация Сигнала". Журнал IEEE Выбранных Тем в Обработке сигналов. Издание 12, Номер 1, 2018, стр 168–179.

  3. Лю, X., Д. Янг и А. Э. Джамаль. "Архитектуры глубоких нейронных сетей для Классификации Модуляций". Предварительно распечатайте, представленный 5 января 2018. https://arxiv.org/abs/1712.00443v3

Похожие темы