Основанная на акустике генерация кода распознавания отказа машины на Raspberry Pi

Этот пример демонстрирует генерацию кода для Основанного на акустике Распознавания Отказа Машины с помощью долгой краткосрочной памяти (LSTM) сетевые и спектральные дескрипторы. Этот пример использует MATLAB® Coder™, Интерфейс MATLAB Coder для Библиотек Глубокого обучения, Пакет поддержки MATLAB для Оборудования Raspberry Pi, чтобы сгенерировать независимый исполняемый файл (.elf) файл на Raspberry Pi™, который усиливает эффективность Руки, Вычисляет Библиотеку. Входные данные состоят из записей timeseries акустики от неисправных или здоровых воздушных компрессоров, и выход является состоянием механической машины, предсказанной сетью LSTM. Этот независимый исполняемый файл на Raspberry Pi запускает классификатор потоковой передачи на входных данных, полученных от MATLAB, и отправляет вычисленную музыку к каждой метке к MATLAB. Взаимодействие между скриптом MATLAB и исполняемым файлом на вашем Raspberry Pi обработано с помощью пользовательского дейтаграммного протокола (UDP). Для получения дополнительной информации о предварительной обработке аудио и сетевом обучении, смотрите Основанное на акустике Распознавание Отказа Машины.

Требования в качестве примера

  • Интерфейс MATLAB Coder для пакета поддержки библиотек глубокого обучения

  • Процессор ARM, который поддерживает расширение NEON

  • ARM Вычисляет версию 20.02.1 Библиотеки (на целевом оборудовании ARM)

  • Переменные окружения для компиляторов и библиотек

Для поддерживаемых версий библиотек и для получения информации о подготовке переменных окружения, смотрите Необходимые условия для Глубокого обучения для MATLAB Coder (MATLAB Coder)

Подготовьте входной набор данных

Задайте частоту дискретизации fs из 16 кГц и windowLength из 512 выборок, как задано в Основанном на акустике Распознавании Отказа Машины. Установите numFrames к 100.

fs = 16000;
windowLength = 512;
numFrames = 100;

Чтобы запустить Пример на тестовом сигнале, сгенерируйте розовый шумовой сигнал. Чтобы проверить производительность системы на действительном наборе данных, загрузите воздушный набор данных компрессора [1].

downloadDataset = false;

if ~downloadDataset
    pinkNoiseSignal = pinknoise (windowLength*numFrames);
else
    % Download AirCompressorDataset.zip 
    компонент = 'audio';
    имя файла = 'AirCompressorDataset/AirCompressorDataset.zip';
    localfile = matlab.internal.examples.downloadSupportFile (компонент, имя файла);
    
    % Unzip the downloaded zip file to the downloadFolder
    downloadFolder = fileparts (localfile);
    if ~exist (fullfile (downloadFolder,'AirCompressorDataset'),'dir')
        разархивируйте (localfile, downloadFolder)
    end
    
    % Create an audioDatastore object dataStore, to manage, the data.
    dataStore = audioDatastore (downloadFolder,'IncludeSubfolders'TRUE,'LabelSource','foldernames');

    % Use countEachLabel to get the number of samples of each category in the dataset.
    countEachLabel (dataStore)
end

Распознайте отказ машины в MATLAB

Чтобы запустить классификатор потоковой передачи в MATLAB, загрузите и разархивируйте систему, разработанную в Основанном на акустике Распознавании Отказа Машины.

component = 'audio';
filename = 'AcousticsBasedMachineFaultRecognition/AcousticsBasedMachineFaultRecognition.zip';
localfile = matlab.internal.examples.downloadSupportFile(component,filename);

downloadFolder = fullfile(fileparts(localfile),'system');
if ~exist(downloadFolder,'dir')    
    unzip(localfile,downloadFolder)
end

Получить доступ к recognizeAirCompressorFault функция системы, добавляет downloadFolder к пути поиска файлов.

addpath(downloadFolder)

Создайте dsp.AsyncBuffer возразите, чтобы считать аудио способом потоковой передачи и dsp.AsyncBuffer объект накопить баллы.

audioSource = dsp.AsyncBuffer;
scoreBuffer = dsp.AsyncBuffer;

Загрузите предварительно обученную сеть и извлеките метки из сети.

airCompNet = coder.loadDeepLearningNetwork('AirCompressorFaultRecognitionModel.mat');
labels = string(airCompNet.Layers(end).Classes);

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

if ~downloadDataset
    signalToBeTested = pinkNoiseSignal;
else
    [allFiles,~] = splitEachLabel(dataStore,1);
    allData = readall(allFiles);
    signalToBeTested = allData(1);
    signalToBeTested = cell2mat (signalToBeTested);
end

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

write(audioSource,signalToBeTested);
resetNetworkState = true;

while audioSource.NumUnreadSamples >= windowLength
    
    % Get a frame of audio data
    x = read(audioSource,windowLength);
    
    % Apply streaming classifier function
    score = recognizeAirCompressorFault(x,resetNetworkState);
   
    % Store score for analysis
    write(scoreBuffer,score);
    
    resetNetworkState = false;
end

Вычислите распознанный отказ из баллов и отобразите его.

scores = read(scoreBuffer);
[~,labelIndex] = max(scores(end,:),[],2);
detectedFault = labels(labelIndex)
detectedFault = 
"Flywheel"

Постройте множество каждой метки для каждой системы координат.

plot(scores)
legend("" + labels,'Location','northwest') 
xlabel("Time Step")
ylabel("Score")
str = sprintf("Predicted Scores Over Time Steps.\nPredicted Class: %s",detectedFault);
title(str)

Сбросьте асинхронный буферный audioSource.

reset(audioSource)

Подготовьте код MATLAB к развертыванию

Этот пример использует dsp.UDPSender Системный объект, чтобы передать аудио кадр к исполняемому файлу, работающему на Raspberry Pi и dsp.UDPReceiver Системный объект, чтобы получить вектор счета от Raspberry Pi. Создайте dsp.UDPSender системный объект, чтобы отправить аудио, записанное в MATLAB к вашему Raspberry Pi. Установите targetIPAddress к IP-адресу вашего Raspberry Pi. Установите RemoteIPPort к 25000. Raspberry Pi принимает входной кадр аудио от того же порта с помощью dsp.UDPReceiver системный объект.

targetIPAddress = '172.31.164.247';
UDPSend = dsp.UDPSender('RemoteIPPort',25000,'RemoteIPAddress',targetIPAddress); 

Создайте dsp.UDPReceiver системный объект, чтобы получить предсказанные баллы от вашего Raspberry Pi. Каждый пакет UDP, полученный от Raspberry Pi, является вектором из баллов, и каждым векторным элементом является счет к состоянию воздушного компрессора. Максимальная длина сообщения для dsp.UDPReceiver объект составляет 65 507 байтов. Вычислите buffer size, чтобы вместить максимальное количество пакетов UDP.

sizeOfDoubleInBytes = 8;
numScores = 8;
maxUDPMessageLength = floor(65507/sizeOfDoubleInBytes);
numPackets = floor(maxUDPMessageLength/numScores);
bufferSize = numPackets*numScores*sizeOfDoubleInBytes;

UDPReceive = dsp.UDPReceiver("LocalIPPort",21000, ...  
    "MessageDataType","single", ...
    "MaximumMessageLength",numScores, ...
    "ReceiveBufferSize",bufferSize);

Создайте функцию поддержки, recognizeAirCompressorFaultRaspi, это принимает аудио кадр с помощью dsp.UDPReceiver и применяет классификатор потоковой передачи и отправляет предсказанный вектор счета в MATLAB с помощью dsp.UDPSender.

type recognizeAirCompressorFaultRaspi
function recognizeAirCompressorFaultRaspi(hostIPAddress)
% This function receives acoustic input using dsp.UDPReceiver and runs a
% streaming classifier by calling recognizeAirCompressorFault, developed in
% the Acoustics-Based Machine Fault Recognition - MATLAB Example. 
% Computed scores are sent to MATLAB using dsp.UDPSender.
%#codegen

%   Copyright 2021 The MathWorks, Inc.

frameLength = 512;

% Configure UDP Sender System Object
UDPSend = dsp.UDPSender('RemoteIPPort',21000,'RemoteIPAddress',hostIPAddress);

% Configure UDP Receiver system object
sizeOfDoubleInBytes = 8;
maxUDPMessageLength = floor(65507/sizeOfDoubleInBytes);
numPackets = floor(maxUDPMessageLength/frameLength);
bufferSize = numPackets*frameLength*sizeOfDoubleInBytes;
UDPReceiveRaspi = dsp.UDPReceiver('LocalIPPort',25000, ...
    'MaximumMessageLength',frameLength, ...
    'ReceiveBufferSize',bufferSize, ...
    'MessageDataType','double');

% Reset network state for first call
resetNetworkState = true;

while true
    % Receive audio frame of size frameLength x 1
    x = UDPReceiveRaspi();

    if(~isempty(x))

        x = x(1:frameLength,1);

        % Apply streaming classifier function
        scores = recognizeAirCompressorFault(x,resetNetworkState);

        %Send output to the host machine
        UDPSend(scores);

        resetNetworkState = false;
    end
end

Сгенерируйте исполняемый файл на Raspberry Pi

Замените hostIPAddress с адресом вашей машины. Ваш Raspberry Pi отправляет предсказанные баллы в IP-адрес, который вы задаете.

hostIPAddress = coder.Constant('172.18.230.30');

Создайте объект настройки генерации кода сгенерировать исполняемую программу. Задайте выходной язык как C++.

cfg = coder.config('exe');
cfg.TargetLang = 'C++';

Создайте объект настройки для генерации кода глубокого обучения с ARM, вычисляют библиотеку, которая находится на вашем Raspberry Pi. Задайте архитектуру Raspberry Pi и присоедините объект настройки глубокого обучения к объекту настройки генерации кода.

dlcfg = coder.DeepLearningConfig('arm-compute');
dlcfg.ArmArchitecture = 'armv7';
dlcfg.ArmComputeVersion = '20.02.1';
cfg.DeepLearningConfig = dlcfg;

Используйте функцию Пакета поддержки Raspberry Pi raspi создать связь с вашим Raspberry Pi. В следующем блоке кода, замене:

  • raspiname с именем вашего Raspberry Pi

  • pi с вашим именем пользователя

  • password с вашим паролем

if (~exist('r','var'))
  r = raspi('raspiname','pi','password');
end

Создайте coder.hardware Объект (MATLAB Coder) для Raspberry Pi и присоединения это к объекту настройки генерации кода.

hw = coder.hardware('Raspberry Pi');
cfg.Hardware = hw;

Задайте папку сборки на Raspberry Pi.

buildDir = '~/remoteBuildDir';
cfg.Hardware.BuildDir = buildDir;

Используйте автоматически сгенерированный C++ основной файл, чтобы сгенерировать независимый исполняемый файл.

cfg.GenerateExampleMain = 'GenerateCodeAndCompile';

Вызовите codegen (MATLAB Coder) функция от MATLAB Coder, чтобы сгенерировать Код С++ и исполняемый файл на вашем Raspberry Pi. По умолчанию исполняемый файл Raspberry Pi имеет то же имя как функция MATLAB. Вы получаете предупреждение в журналах генерации кода that можно игнорировать потому что recognizeAirCompressorFaultRaspi имеет бесконечный цикл, который ищет аудио систему координат из MATLAB.

codegen -config cfg recognizeAirCompressorFaultRaspi -args {hostIPAddress} -report
 Deploying code. This may take a few minutes. 
Warning: Function 'recognizeAirCompressorFaultRaspi' does not terminate due to an infinite loop.

Warning in ==> recognizeAirCompressorFaultRaspi Line: 1 Column: 1
Code generation successful (with warnings): View report

Выполните распознавание отказа машины Используя развернутый код

Создайте команду, чтобы открыть recognizeAirCompressorFaultRaspi приложение на Raspberry Pi. Использование системы отправить команду в ваш Raspberry Pi.

applicationName = 'recognizeAirCompressorFaultRaspi';

applicationDirPaths = raspi.utils.getRemoteBuildDirectory('applicationName',applicationName);
targetDirPath = applicationDirPaths{1}.directory;

exeName = strcat(applicationName,'.elf');
command = ['cd ',targetDirPath,'; ./',exeName,' &> 1 &'];

system(r,command);

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

if ~downloadDataset
    signalToBeTested = pinkNoiseSignal;
else
    [allFiles,~] = splitEachLabel(dataStore,1);
    allData = readall(allFiles);
    signalToBeTested = allData(1);
    signalToBeTested = cell2mat (signalToBeTested);
end

Передайте одну аудио систему координат потоком за один раз, чтобы представлять систему, когда она была бы развернута во встроенной системе реального времени. Используйте сгенерированный файл MEX recognizeAirCompressorFault_mex вычислить функции аудио и выполнить классификацию глубокого обучения.

write(audioSource,signalToBeTested);

while audioSource.NumUnreadSamples >= windowLength
    x = read(audioSource,windowLength);
    UDPSend(x);
    score = UDPReceive();
    if ~isempty(score)    
        write(scoreBuffer,score');
    end
end

Вычислите распознанный отказ из баллов и отобразите его.

scores = read(scoreBuffer);
[~,labelIndex] = max(scores(end,:),[],2);
detectedFault = labels(labelIndex)
detectedFault = 
"Flywheel"

Постройте множество каждой метки для каждой системы координат.

plot(scores)
legend("" + labels,'Location','northwest') 
xlabel("Time Step")
ylabel("Score")
str = sprintf("Predicted Scores Over Time Steps.\nPredicted Class: %s",detectedFault);
title(str)

Отключите независимый исполняемый файл, работающий на Raspberry Pi.

stopExecutable(codertarget.raspi.raspberrypi,exeName)

Оцените время выполнения Используя альтернативный рабочий процесс функции PIL

Чтобы оценить время выполнения, потраченное независимым исполняемым файлом на Raspberry Pi, используйте PIL (процессор в цикле) рабочий процесс. Чтобы выполнить профилирование PIL, сгенерируйте функцию PIL для функции поддержки recognizeAirCompressorFault.

Создайте объект настройки генерации кода сгенерировать функцию PIL.

cfg = coder.config('lib','ecoder',true);
cfg.VerificationMode = 'PIL';

Установите ARM, вычисляют библиотеку и архитектуру.

dlcfg = coder.DeepLearningConfig('arm-compute');
cfg.DeepLearningConfig = dlcfg ;
cfg.DeepLearningConfig.ArmArchitecture = 'armv7';
cfg.DeepLearningConfig.ArmComputeVersion = '20.02.1';

Настройте связь со своим целевым компьютером.

if (~exist('r','var'))
  r = raspi('raspiname','pi','password');
end
hw = coder.hardware('Raspberry Pi');
cfg.Hardware = hw;

Установите каталог сборки и выходной язык.

buildDir = '~/remoteBuildDir';
cfg.Hardware.BuildDir = buildDir;
cfg.TargetLang = 'C++';

Позвольте профилировать и сгенерируйте код PIL. Файл MEX под названием recognizeAirCompressorFault_pil сгенерирован в вашей текущей папке.

cfg.CodeExecutionProfiling = true;
audioFrame = ones(windowLength,1);
resetNetworkStateFlag = true;
codegen -config cfg recognizeAirCompressorFault -args {audioFrame,resetNetworkStateFlag}
 Deploying code. This may take a few minutes. 
### Connectivity configuration for function 'recognizeAirCompressorFault': 'Raspberry Pi'
Location of the generated elf : /home/pi/remoteBuildDir/MATLAB_ws/R2021b/S/MATLAB/Examples/ExampleManager/sporwal.Bdoc21b.j1720794/deeplearning_shared-ex44063374/codegen/lib/recognizeAirCompressorFault/pil
Code generation successful.

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

totalCalls = 50;

for k = 1:totalCalls
    x = pinknoise(windowLength,1);
    score = recognizeAirCompressorFault_pil(x,resetNetworkStateFlag);
    resetNetworkStateFlag = false;
end
### Starting application: 'codegen\lib\recognizeAirCompressorFault\pil\recognizeAirCompressorFault.elf'
    To terminate execution: clear recognizeAirCompressorFault_pil
### Launching application recognizeAirCompressorFault.elf...
    Execution profiling data is available for viewing. Open Simulation Data Inspector.
    Execution profiling report available after termination.

Отключите выполнение PIL.

clear recognizeAirCompressorFault_pil
### Host application produced the following standard output (stdout) and standard error (stderr) messages:

### Connectivity configuration for function 'recognizeAirCompressorFault': 'Raspberry Pi'
    Execution profiling report: report(getCoderExecutionProfile('recognizeAirCompressorFault'))

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

executionProfile = getCoderExecutionProfile('recognizeAirCompressorFault');
report(executionProfile, ...
       'Units','Seconds', ...
       'ScaleFactor','1e-03', ...
       'NumericFormat','%0.4f');

Среднее время выполнения recognizeAirCompressorFault_pil функцией является 0.423 ms, который является значительно ниже 32 ms бюджет для эффективности в реальном времени. Первый вызов recognizeAirCompressorFault_pil использует вокруг 12 времена среднего времени выполнения, когда это включает загрузку сети и сброс состояний. Однако в действительной, развернутой системе, то время инициализации понесено только однажды. Этот пример заканчивается здесь. Для развертывания распознавания отказа машины на рабочих столах смотрите Основанную на акустике Генерацию кода Распознавания Отказа Машины с Intel MKL-DNN.

Ссылки

[1] Verma, Нищел К., и др. "Интеллектуальный основанный на условии Контроль Используя Акустические Сигналы для Воздушных Компрессоров". Транзакции IEEE на Надежности, издании 65, № 1, март 2016, стр 291–309. DOI.org (Crossref), doi:10.1109/TR.2015.2459684.