Протестируйте глубокую нейронную сеть с собранными данными, чтобы обнаружить олицетворение маршрутизатора WLAN

В этом примере показано, как обучить сверточную нейронную сеть (CNN) снятия отпечатков пальцев радиочастоты (RF) с собранными данными. Вы получаете кадры "неисправность" беспроводной локальной сети (WLAN) от действительных маршрутизаторов с помощью программно определяемого радио (SDR). Вы программируете второй SDR, чтобы передать неизвестные кадры "неисправность" и получить их. Вы обучаете CNN с помощью этих записанных сигналов. Вы затем программируете программно определяемое радио (SDR) как имитатор маршрутизатора, который передает сигналы маяка с адресом управления доступом медиа-контента (MAC) одного из известных маршрутизаторов, и используйте CNN, чтобы идентифицировать его как имитатора.

Для получения дополнительной информации об олицетворении маршрутизатора и валидации проектирования сети с симулированными данными, см. Проект Глубокая нейронная сеть с Симулированными Данными, чтобы Обнаружить пример Олицетворения Маршрутизатора WLAN.

Обучайтесь с собранными данными

Соберите набор данных 802.11a/g/n/ac OFDM невысокая пропускная способность (non-HT) кадры "неисправность" от действительных маршрутизаторов WLAN. Как описано в Проекте Глубокая нейронная сеть с Симулированными Данными, чтобы Обнаружить пример Олицетворения Маршрутизатора WLAN, только устаревшее длинное учебное полевое поле (L-LTF), существующее в преамбулах, используется в качестве учебных модулей во избежание любой зависимости по данным.

В этом примере данные были собраны с помощью сценария, изображенного в следующем рисунке. Наблюдатель является стационарным радио ADALM-PLUTO. Известные данные о маршрутизаторе были собраны можно следующим образом:

  1. Установите центральную частоту наблюдателя на основе канала WLAN, используемого маршрутизаторами

  2. Получите кадр "неисправность"

  3. Извлеките сигнал L-LTF

  4. Декодируйте Мак адрес, чтобы использовать в качестве метки

  5. Сохраните сигнал L-LTF вместе с его меткой

  6. Повторите шаги 2-5, чтобы собрать numFramesPerRouter системы координат от numKnownRouters маршрутизаторы.

Неизвестные кадры "неисправность" маршрутизатора симулированы с помощью мобильного радио ADALM-PLUTO в качестве передатчика. Это радио неоднократно передает кадры "неисправность" со случайным Мак адресом. Неизвестные данные о маршрутизаторе были собраны можно следующим образом:

  1. Сгенерируйте кадры "неисправность" со случайным Мак адресом

  2. Начните передавать кадры "неисправность" неоднократно с помощью радио ADALM-PLUTO

  3. Соберите NUMFRAMES кадры "неисправность"

  4. Извлеките сигнал L-LTF

  5. Сохраните системы координат L-LTF с меткой "Unknown"

  6. Переместите радио в другое местоположение

  7. Повторите шаги 3-6, чтобы собрать данные от NUMLOC местоположения

Этот объединенный набор данных известных и неизвестных маршрутизаторов используется, чтобы обучить ту же модель DL как в Проекте Глубокая нейронная сеть с Симулированными Данными Обнаруживать пример Олицетворения Маршрутизатора WLAN.

Этот пример загружает обучающие данные и обучил сеть от https://www.mathworks.com/supportfiles/spc/RFFingerprinting/RFFingerprintingCapturedData.tar.gz. Если у вас нет Интернет-соединения, можно загрузить файл вручную на компьютере, который соединяется с Интернетом, и сохраните в ту же директорию как текущие файлы в качестве примера. По причинам конфиденциальности Мак адреса были анонимизированы в загруженных данных. Чтобы реплицировать результаты этого примера, соберите свои собственные данные как описано в Приложении: Известный и Неизвестный Сбор данных Маршрутизатора.

rfFingerprintingDownloadData('captured')
Starting download of data files from:
	https://www.mathworks.com/supportfiles/spc/RFFingerprinting/RFFingerprintingCapturedData.tar.gz
Download and extracting files done

Чтобы запустить этот пример быстро, используйте загруженную предварительно обученную сеть. Чтобы обучить сеть на вашем компьютере, выберите опцию "Train network now" (т.е. установите trainNow к истине). Обучение эта сеть занимает приблизительно 5 минут с помощью графического процессора Nvidia(R) Titan Xp. Обучение на центральном процессоре может привести к очень длинной учебной длительности.

trainNow = false;  %#ok<*UNRCH> 

Этот пример использует данные из четырех известных маршрутизаторов. Набор данных содержит 3 600 систем координат на маршрутизатор, где 90% используются в качестве учебных систем координат, и 10% используется в качестве тестовых систем координат.

numKnownRouters = 4;
numFramesPerRouter = 3600;
numTrainingFramesPerRouter = numFramesPerRouter * 0.9;
numTestFramesPerRouter = numFramesPerRouter * 0.1;
frameLength = 160;

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

Распадитесь собрал комплексные основополосные данные на его синфазные компоненты и квадратурные компоненты, и измените их в 2 матрицы x frameLength x 1 x numFramesPerRouter*numKnownRouters. Повторите тот же процесс для неизвестных данных о маршрутизаторе. Следующий код использует ранее собранные и предварительно обработанные данные. Чтобы использовать ваши собственные данные, сначала соберите данные как описано в Приложении: Известный и Неизвестный Сбор данных Маршрутизатора. Скопируйте новые файлы данных под названием rfFingerprintingCapturedDataUser.mat и rfFingerprintingCapturedUnknownFramesUser.mat к той же директории как этот пример. Затем обновите load команды, чтобы загрузить эти файлы.

if trainNow
  % Load known router data
  load('rfFingerprintingCapturedData.mat')
  
  % Create label vectors
  yTrain = repelem(MACAddresses, numTrainingFramesPerRouter);
  yTest = repelem(MACAddresses, numTestFramesPerRouter);
  
  % Separate between I and Q
  numTrainingSamples = numTrainingFramesPerRouter*numKnownRouters*frameLength;
  xTrainingFrames = xTrainingFrames(1:numTrainingSamples,1);
  xTrainingFrames = [real(xTrainingFrames), imag(xTrainingFrames)];
  numTestSamples = numTestFramesPerRouter*numKnownRouters*frameLength;
  xTestFrames = xTestFrames(1:numTestSamples,1);
  xTestFrames = [real(xTestFrames), imag(xTestFrames)];
  
  % Reshape dataset into an 2 x frameLength x 1 x numTrainingFramesPerRouter*numKnownRouters matrix
  xTrainingFrames = permute(...
    reshape(xTrainingFrames,[frameLength,numTrainingFramesPerRouter*numKnownRouters, 2, 1]),...
    [1 3 4 2]);
  
  % Reshape dataset into an 2 x frameLength x 1 x numTestFramesPerRouter*numKnownRouters matrix
  xTestFrames = permute(...
    reshape(xTestFrames,[frameLength,numTestFramesPerRouter*numKnownRouters, 2, 1]),...
    [1 3 4 2]);
  
  % Load unknown router data
  load('rfFingerprintingCapturedUnknownFrames.mat')
  
  % Number of training units
  numUnknownFrames = size(unknownFrames, 4);
  
  % Split data into 90% training and 10% test
  numUnknownTrainingFrames = floor(numUnknownFrames*0.9);
  numUnknownTest = numUnknownFrames - numUnknownTrainingFrames;
  
  % Add ADALM-PLUTO data into training and test datasets
  xTrainingFrames(:,:,:,(1:numUnknownTrainingFrames) + numTrainingFramesPerRouter*numKnownRouters) ...
    = unknownFrames(:,:,:, 1:numUnknownTrainingFrames);
  xTestFrames(:,:,:,(1:numUnknownTest) + numTestFramesPerRouter*numKnownRouters) ...
    = unknownFrames(:,:,:, (1:numUnknownTest) + numUnknownTrainingFrames);
  
  % Shuffle data
  vr = randperm(numKnownRouters*numTrainingFramesPerRouter+numUnknownTrainingFrames);
  xTrainingFrames = xTrainingFrames(:,:,:,vr);
  
  % Add "unknown" label and shuffle
  yTrain = [yTrain, repmat("Unknown", [1, numUnknownTrainingFrames])];
  yTrain = categorical(yTrain(vr));
  
  yTest = [yTest, repmat("Unknown", [1, numUnknownTest])];
  yTest = categorical(yTest);
end

Обучите CNN

Используйте ту же архитектуру NN и опции обучения как в обучении с симулированным примером данных.

poolSize = [2 1];
strideSize = [2 1];
% Create network architecture
layers = [
  imageInputLayer([frameLength 2 1], 'Normalization', 'none', 'Name', 'Input Layer')
  
  convolution2dLayer([7 1], 50, 'Padding', [1 0], 'Name', 'CNN1')
  batchNormalizationLayer('Name', 'BN1')
  leakyReluLayer('Name', 'LeakyReLu1')
  maxPooling2dLayer(poolSize, 'Stride', strideSize, 'Name', 'MaxPool1')
  
  convolution2dLayer([7 2], 50, 'Padding', [1 0], 'Name', 'CNN2')
  batchNormalizationLayer('Name', 'BN2')
  leakyReluLayer('Name', 'LeakyReLu2')
  maxPooling2dLayer(poolSize, 'Stride', strideSize, 'Name', 'MaxPool2')
  
  fullyConnectedLayer(256, 'Name', 'FC1')
  leakyReluLayer('Name', 'LeakyReLu3')
  dropoutLayer(0.5, 'Name', 'DropOut1')
  
  fullyConnectedLayer(80, 'Name', 'FC2')
  leakyReluLayer('Name', 'LeakyReLu4')
  dropoutLayer(0.5, 'Name', 'DropOut2')
  
  fullyConnectedLayer(numKnownRouters+1, 'Name', 'FC3')
  softmaxLayer('Name', 'SoftMax')
  classificationLayer('Name', 'Output')
  ];

Сконфигурируйте опции обучения, чтобы использовать оптимизатор ADAM с мини-пакетным размером 128. Используйте тестовые системы координат для валидации, поскольку оптимизация гиперпараметров была сделана в [1].

По умолчанию, ExecutionEnvironment установлен в 'auto', который использует графический процессор для обучения, если вы доступны. В противном случае, trainNetwork (Deep Learning Toolbox) использует центральный процессор для обучения. Чтобы явным образом установить среду выполнения, устанавливает ExecutionEnvironment к одному из 'cpu', 'gpu', 'multi-gpu', или 'parallel'. Выбор 'cpu' может привести к очень длинной учебной длительности.

if trainNow
  miniBatchSize = 128;
  
  % Training options
  options = trainingOptions('adam', ...
    'MaxEpochs',30, ...
    'ValidationData',{xTestFrames, yTest}, ...
    'ValidationFrequency',floor((numTrainingFramesPerRouter*numKnownRouters + numUnknownTrainingFrames)/miniBatchSize/3), ...
    'Verbose',false, ...
    'L2Regularization', 0.0001, ...
    'InitialLearnRate', 0.0001, ...
    'MiniBatchSize', miniBatchSize, ...
    'ValidationPatience', 5, ...
    'Plots','training-progress', ...
    'Shuffle', 'every-epoch');
  
  % Train the network
  capturedDataNet = trainNetwork(xTrainingFrames, yTrain, layers, options);
else
  load('rfFingerprintingCapturedDataTrainedNN.mat','capturedDataNet','xTestFrames','yTest','MACAddresses')
end

Следующий график показывает, что процесс обучения сети работает на компьютере с одним Титаном Nvidia Xp графический процессор, где сеть сходилась приблизительно в 10 эпох почти с 100%-й точностью. Итоговая точность сети составляет 100%.

Сгенерируйте матрицу беспорядка.

figure
yTestPred = classify(capturedDataNet,xTestFrames);
cm = confusionchart(yTest, yTestPred);
cm.Title = 'Confusion Matrix for Test Data';
cm.RowSummary = 'row-normalized';

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

Проверьте производительность обучившего сеть на классе "Неизвестный". Сгенерируйте кадры "неисправность" с Мак адресами известных маршрутизаторов и одного неизвестного маршрутизатора. Передайте эти кадры с помощью радио ADALM-PLUTO и получите использование другого радио ADALM-PLUTO. Поскольку канал и ухудшения RF, созданные между этими двумя радио, отличаются, чем те созданные между действительными маршрутизаторами и наблюдателем, нейронная сеть должны классифицировать все полученные сигналы как "Неизвестные". Если полученный Мак адрес является известным, то система объявляет источник как имитатора маршрутизатора. Если полученный Мак адрес является неизвестным, то система объявляет источник как неизвестный маршрутизатор. Чтобы выполнить этот тест, вам нужны два радио ADALM-PLUTO для передачи и приема. Кроме того, необходимо установить Коммуникационный Пакет поддержки Тулбокса для Радио ADALM-PLUTO.

Генерация сигналов

Сгенерируйте форму волны передачи, состоящую из кадров "неисправность" с различными Мак адресами. Передатчик неоднократно передает эти кадры WLAN. Приемник получает системы координат WLAN и определяет - ли это имитатор маршрутизатора, использующий полученный Мак адрес и цифровой отпечаток RF, обнаруженный обученным NN.

chanBW='CBW20';     % Channel Bandwidth
osf = 2;            % Oversampling Factor
frameLength=160;    % Frame Length in samples
% Create Beacon frame-body configuration object
frameBodyConfig = wlanMACManagementConfig;

% Create Beacon frame configuration object
beaconFrameConfig = wlanMACFrameConfig('FrameType', 'Beacon');
beaconFrameConfig.ManagementConfig = frameBodyConfig;

% Create interpolation and decimation objects
decimator = dsp.FIRDecimator('DecimationFactor',osf);

% Save known MAC addresses
knownMACAddresses = MACAddresses;
MACAddressesToSimulate = [MACAddresses, "ABCDEFABCDEF"];

% Create WLAN waveform with the MAC addresses of known routers and an
% unknown router
txWaveform = zeros(1540,5);
for i = 1:length(MACAddressesToSimulate)
  
  % Set MAC Address
  beaconFrameConfig.Address2 = MACAddressesToSimulate(i);
  
  % Generate Beacon frame bits
  [beacon, mpduLength] = wlanMACFrame(beaconFrameConfig, 'OutputFormat', 'bits');
  
  nonHTcfg = wlanNonHTConfig(...
    'ChannelBandwidth', chanBW,...
    "MCS", 1,...
    "PSDULength", mpduLength);
  txWaveform(:,i) = [wlanWaveformGenerator(beacon, nonHTcfg); zeros(20,1)];
end

txWaveform = txWaveform(:);

% Get center frequency for channel 153 in 5 GHz band
fc = helperWLANChannelFrequency(153, 5);
fs = wlanSampleRate(nonHTcfg);

txSig  = resample(txWaveform,osf,1);

% Samples per frame in Burst Mode
spf = length(txSig)/length(MACAddressesToSimulate);

runSDRSection = false;
if helperIsPlutoSDRInstalled()  
  radios = findPlutoRadio();
  if length(radios) >= 2
    runSDRSection = true;
  else
    disp("Two ADALM-PLUTO radios are needed. Skipping SDR test.")
  end
else
    disp("Communications Toolbox Support Package for Analog Devices ADALM-PLUTO Radio not found.")
    disp("Click Add-Ons in the Home tab of the MATLAB toolstrip to install the support package.")
    disp("Skipping SDR test.")
end


if runSDRSection
  % Set up PlutoSDR transmitter
  deviceNameSDR = 'Pluto';
  txGain = 0;
  txSDR = sdrtx(deviceNameSDR);
  txSDR.RadioID = 'usb:0';
  txSDR.BasebandSampleRate = fs*osf;
  txSDR.CenterFrequency = fc;
  txSDR.Gain = txGain;
  
  % Set up PlutoSDR Receiver
  rxSDR = sdrrx(deviceNameSDR);
  rxSDR.RadioID = 'usb:1';
  rxSDR.BasebandSampleRate = txSDR.BasebandSampleRate;
  rxSDR.CenterFrequency = txSDR.CenterFrequency;
  rxSDR.GainSource ='Manual';
  rxSDR.Gain = 30;
  rxSDR.OutputDataType = 'double';
  rxSDR.EnableBurstMode=true;
  rxSDR.NumFramesInBurst = 20;
  rxSDR.SamplesPerFrame = osf*spf;
end

L-LTF для классификации

Последовательность L-LTF, существующая в каждой преамбуле кадра "неисправность", используется в качестве входных модулей к системному объекту NN. rfFingerprintingNonHTFrontEnd, используется, чтобы обнаружить пакеты WLAN, выполнить задачи синхронизации и, извлечь последовательности L-LTF и данные. Кроме того, Мак адрес также декодируется. Кроме того, данные предварительно обрабатываются и классифицировали использование обучившего сеть.

if runSDRSection
  numLLTF = 20;       % Number of L-LTF captured for Testing
  
  rxFrontEnd = rfFingerprintingNonHTFrontEnd('ChannelBandwidth', 'CBW20');
  
  disp("The known MAC addresses are:");
  disp(knownMACAddresses)
  
  % Set PlutoSDR to transmit repeatedly
  disp('Starting transmitter')
  transmitRepeat(txSDR, txSig);
  
  % Captured Frames counter
  numCapturedFrames = 0;
  
  disp('Starting receiver')
  % Loop until numLLTF frames are collected
  while numCapturedFrames < numLLTF
    
    % Receive data using PlutoSDR
    rxSig = rxSDR();
    rxSig = decimator(rxSig);
    
    % Perform front-end processing and payload buffering
    [payloadFull, cfgNonHT, rxNonHTData, chanEst, noiseVar, LLTF] = ...
      rxFrontEnd(rxSig);
    
    if payloadFull
      
      % Recover payload bits
      recBits = wlanNonHTDataRecover(rxNonHTData, chanEst, ...
        noiseVar, cfgNonHT, 'EqualizationMethod', 'ZF');
      
      % Decode and evaluate recovered bits
      [mpduCfg, ~, success] = wlanMPDUDecode(recBits, cfgNonHT);
      
      if success == wlanMACDecodeStatus.Success
        % Update counter
        numCapturedFrames = numCapturedFrames+1;
        
        % Create real-valued input
        LLTF = [real(LLTF), imag(LLTF)];
        LLTF = permute(reshape(LLTF,frameLength ,[] , 2, 1), [1 3 4 2]);
        
        ypred = classify(capturedDataNet, LLTF);
        
        if sum(contains(knownMACAddresses, mpduCfg.Address2)) ~= 0
          if categorical(convertCharsToStrings(mpduCfg.Address2))~=ypred
            disp(strcat("MAC Address ", mpduCfg.Address2," is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED"))
          else
            disp(strcat("MAC Address ", mpduCfg.Address2," is known, fingerprint match"))
          end
        else
          disp(strcat("MAC Address ", mpduCfg.Address2," is not recognized, unknown device"));
        end
      end
    end
  end
  release(txSDR)
end
The known MAC addresses are:
    "71B63A2D0B83"    "A3F8AC0F2253"    "EF11D125044A"    "F636A97E07E7"
Starting transmitter
## Establishing connection to hardware. This process can take several seconds.
## Waveform transmission has started successfully and will repeat indefinitely. 
## Call the release method to stop the transmission.
Starting receiver
## Establishing connection to hardware. This process can take several seconds.
MAC Address A3F8AC0F2253 is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address F636A97E07E7 is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address A3F8AC0F2253 is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address F636A97E07E7 is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address 71B63A2D0B83 is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address EF11D125044A is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address ABCDEFABCDEF is not recognized, unknown device
MAC Address A3F8AC0F2253 is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address F636A97E07E7 is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address 71B63A2D0B83 is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address EF11D125044A is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address ABCDEFABCDEF is not recognized, unknown device
MAC Address A3F8AC0F2253 is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address F636A97E07E7 is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address 71B63A2D0B83 is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address EF11D125044A is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address ABCDEFABCDEF is not recognized, unknown device
MAC Address A3F8AC0F2253 is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address F636A97E07E7 is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED
MAC Address 71B63A2D0B83 is known, fingerprint mismatch, ROUTER IMPERSONATOR DETECTED

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

Соберите данные от своих собственных маршрутизаторов, как объяснено в Приложении: Известный и Неизвестный Сбор данных Маршрутизатора, обучите нейронную сеть с этими данными и проверьте производительность сети.

Приложение: Функции помощника

Приложение: известный и неизвестный сбор данных маршрутизатора

Используйте rfFingerprintingRouterDataCollection собрать данные от известного (i.e. доверяемый) маршрутизаторы. Эта функция извлекает сигналы L-LTF, существующие в 802.11a/g/n/ac OFDM Non-HT кадры маяков, переданные от коммерческих 802,11 оборудования. Для получения дополнительной информации смотрите IEEE® 802.11™ WLAN - Приемник Маяка OFDM с Оборудованием USRP® (Пакет поддержки Communications Toolbox для Радио USRP) пример. Сигналы L-LTF и соответствующие Мак адреса маршрутизатора используются, чтобы обучить RF, берущий отпечатки пальцев у нейронной сети. Этот метод работает лучше всего, если маршрутизаторы и их антенны фиксируются и трудно перемещаться непреднамеренно. Например, в большинстве офисных сред, маршрутизаторы смонтированы на потолке. Выполните эти шаги:

  1. Соедините радио ADALM-PLUTO со своим PC, чтобы использовать в качестве радио наблюдателя.

  2. Разместите радио в центральное расположение, где оно может получить сигналы от как можно большего количества маршрутизаторов. Зафиксируйте радио так, чтобы оно не перемещалось. Если возможно, место радио наблюдателя на потолке или высоко на стене.

  3. Определите номер канала маршрутизаторов. Можно использовать Wi-Fi приложение анализатора по телефону, чтобы узнать номера каналов.

  4. Запустите сбор данных путем выполнения "rfFingerprintingRouterDataCollection(channel)"где канал является номером канала Wi-Fi

  5. Контролируйте "макс. (abs (LLTF))" значение. Если это выше 1.2 или меньше, чем 0,01, настройте усиление приемника с помощью входа GAIN rfFingerprintingRouterDataCollection функция.

Используйте функции помощника rfFingerprintingUnknownClassDataCollectionTx и rfFingerprintingUnknownClassDataCollectionRx собрать данные от неизвестных маршрутизаторов. Эти функции устанавливают два радио ADALM-PLUTO передавать и получать сигналы L-LTF. Полученные сигналы объединены с известными сигналами маршрутизатора обучить нейронную сеть. Вам нужны два радио ADALM-PLUTO, предпочтительно соединенные с двумя отдельными PC. Выполните эти шаги:

  1. Соедините радио ADALM-PLUTO со стационарным PC, чтобы действовать как неизвестный маршрутизатор

  2. Запустите передачи путем выполнения "rfFingerprintingUnknownClassDataCollectionTx"

  3. Соедините другое радио ADALM-PLUTO с мобильным PC, чтобы действовать как наблюдатель

  4. Запустите сбор данных путем выполнения "rfFingerprintingUnknownClassDataCollectionRx". Эта функция по умолчанию собирает 200 систем координат на местоположение. Каждое местоположение представляет различный неизвестный маршрутизатор.

  5. Когда функция дает вам команду перемещаться в новое местоположение, перемещать радио наблюдателя в новое местоположение. По умолчанию эта функция собирает данные от 10 мест.

  6. Если наблюдатель не получает маяков, или это редко получает маяки, подвиньте наблюдателя поближе к передатчику.

  7. Если сбор данных сделан, вызовите "release(sdrTransmitter)"в сеансе работы с MATLAB радио передачи.

Выбранная библиография

[1] К. Сэнх, М. Белджиовайн, Ф. Чжоу, С. Рияз, С. Айоэннидис и К. Чоудхури, "Oracle: Оптимизированная Радио-классификация через Сверточные нейронные сети", IEEE INFOCOM 2019 - Конференция по IEEE по Computer Communications, Париж, Франция, 2019, стр 370-378.