exponenta event banner

Генерирование синтетических сигналов с использованием условной генеративной состязательной сети

В этом примере показано, как генерировать сигналы синтетического насоса с использованием условной генеративной состязательной сети.

Генеративные состязательные сети (GAN) могут использоваться для получения синтетических данных, которые напоминают реальные данные, вводимые в сети. GAN полезны, когда моделирование является дорогостоящим в вычислительном отношении или эксперименты являются дорогостоящими. Условные GAN (CGAN) могут использовать метки данных во время процесса обучения для генерации данных, относящихся к определенным категориям.

В этом примере моделируемые сигналы, полученные с помощью модели Simulink™ насоса, рассматриваются как «реальные» данные, которые играют роль набора обучающих данных для CGAN. CGAN использует 1-D сверточные сети и обучается с использованием пользовательского обучающего цикла и массива глубокого обучения. Кроме того, в этом примере используется анализ основных компонентов (PCA) для визуального сравнения характеристик генерируемых и реальных сигналов.

CGAN для синтеза сигналов

CGAN состоят из двух сетей, которые тренируются вместе в качестве противников:

  1. Генераторная сеть - учитывая метку и случайный массив в качестве входных данных, эта сеть генерирует данные с той же структурой, что и наблюдения обучающих данных, соответствующие той же метке. Целью генератора является генерирование помеченных данных, которые дискриминатор классифицирует как «реальные».

  2. Дискриминаторная сеть - учитывая партии помеченных данных, содержащих наблюдения как из обучающих данных, так и сгенерированные данные из генератора, эта сеть пытается классифицировать наблюдения как «реальные» или «сгенерированные». Цель дискриминатора состоит в том, чтобы не быть «обманутым» генератором, когда даны партии как реальных, так и сгенерированных помеченных данных.

В идеале эти стратегии приводят к созданию генератора, который генерирует убедительно реалистичные данные, соответствующие входным меткам, и дискриминатора, который усвоил сильные признаки, характерные для обучающих данных для каждой метки.

Загрузить данные

Смоделированные данные генерируются моделью насоса Simulink, представленной в примере Многоклассное обнаружение неисправностей с использованием смоделированных данных. Модель Simulink настроена на моделирование трех типов неисправностей: утечек цилиндров, блокированных входов и повышенного трения подшипников. Набор данных содержит 1575 выходных сигналов потока насоса, из которых 760 являются исправными сигналами, а 815 имеют одну неисправность, комбинации двух неисправностей или комбинации трех неисправностей. Каждый сигнал имеет 1201 выборку сигнала с частотой дискретизации 1000 Гц.

Загрузите и распакуйте данные во временном каталоге, местоположение которого определяется MATLAB ®tempdir команда. Если данные в папке отличаются от указанных в tempdirизмените имя каталога в следующем коде.

% Download the data
dataURL = 'https://ssd.mathworks.com/supportfiles/SPT/data/PumpSignalGAN.zip';
saveFolder = fullfile(tempdir,'PumpSignalGAN'); 
zipFile = fullfile(tempdir,'PumpSignalGAN.zip');
if ~exist(saveFolder,'dir')
    websave(zipFile,dataURL);
end

% Unzip the data
unzip(zipFile,saveFolder)

Zip-файл содержит набор обучающих данных и предварительно подготовленный CGAN:

  • simulatedDataset - Смоделированные сигналы и соответствующие им категориальные метки

  • GANModel - Генератор и дискриминатор обучены моделируемым данным

Загрузите набор обучающих данных и стандартизируйте сигналы, чтобы они имели нулевое среднее значение и единичную дисперсию.

load(fullfile(saveFolder,'simulatedDataset.mat')) % load data set
meanFlow = mean(flow,2);
flowNormalized = flow-meanFlow;
stdFlow = std(flowNormalized(:));
flowNormalized = flowNormalized/stdFlow;

Исправные сигналы помечаются как 1, а неисправные сигналы помечаются как 2.

Определение сети генератора

Определите следующую сеть с двумя входами, которая генерирует сигналы потока, данные множества случайных ценностей 1 на 1 на 100 и соответствующих этикеток.

Сеть:

  • Проекты и изменяют множества шума 1 на 1 на 100 к 4 на 1 1 024 множествами таможенным слоем.

  • Преобразовывает категорические этикетки во вложение векторов и изменяет их ко множества 4 на 1 на 1.

  • Конкатенация результатов с двумя входами по размеру канала. Выходной сигнал - массив 4 на 1 на 1025.

  • Сверхдискретизировал получающиеся множества к 1201 множествами 1 на 1, используя серию перемещенных слоев скручивания 1-D с пакетной нормализацией и слоев ReLU.

Для проецирования и изменения формы входного шума используйте пользовательский слой projectAndReshapeLayer, прилагается к этому примеру как вспомогательный файл. projectAndReshapeLayer объект увеличивает масштаб входа, используя полностью подключенный слой, и изменяет форму выхода на заданный размер.

Для ввода меток в сеть используйте imageInputLayer и укажите размер 1 на 1. Для встраивания и изменения формы вводимой метки используйте пользовательский слой embedAndReshapeLayer, прилагается к этому примеру как вспомогательный файл. embedAndReshapeLayer объект преобразует категориальную метку в одноканальный массив заданного размера с помощью встраивания и полностью подключенной операции. Для категориальных входных данных используйте размер встраивания 100.

% Generator Network

numFilters = 64;
numLatentInputs = 100;
projectionSize = [4 1 1024];
numClasses = 2;
embeddingDimension = 100;

layersGenerator = [
    imageInputLayer([1 1 numLatentInputs],'Normalization','none','Name','in')
    projectAndReshapeLayer(projectionSize,numLatentInputs,'proj');
    concatenationLayer(3,2,'Name','cat');
    transposedConv2dLayer([5 1],8*numFilters,'Name','tconv1')
    batchNormalizationLayer('Name','bn1','Epsilon',5e-5)
    reluLayer('Name','relu1')
    transposedConv2dLayer([10 1],4*numFilters,'Stride',4,'Cropping',[1 0],'Name','tconv2')
    batchNormalizationLayer('Name','bn2','Epsilon',5e-5)
    reluLayer('Name','relu2')
    transposedConv2dLayer([12 1],2*numFilters,'Stride',4,'Cropping',[1 0],'Name','tconv3')
    batchNormalizationLayer('Name','bn3','Epsilon',5e-5)
    reluLayer('Name','relu3')
    transposedConv2dLayer([5 1],numFilters,'Stride',4,'Cropping',[1 0],'Name','tconv4')
    batchNormalizationLayer('Name','bn4','Epsilon',5e-5)
    reluLayer('Name','relu4')
    transposedConv2dLayer([7 1],1,'Stride',2,'Cropping',[1 0],'Name','tconv5')
    ];

lgraphGenerator = layerGraph(layersGenerator);

layers = [
    imageInputLayer([1 1],'Name','labels','Normalization','none')
    embedAndReshapeLayer(projectionSize(1:2),embeddingDimension,numClasses,'emb')];

lgraphGenerator = addLayers(lgraphGenerator,layers);
lgraphGenerator = connectLayers(lgraphGenerator,'emb','cat/in2');

Постройте график структуры сети для генератора.

plot(lgraphGenerator)

Чтобы обучить сеть с помощью пользовательского цикла обучения и включить автоматическое дифференцирование, преобразуйте график слоев в dlnetwork объект.

dlnetGenerator = dlnetwork(lgraphGenerator);

Определение сети дискриминаторов

Определите следующую сеть с двумя входами, которая классифицирует реальные и сгенерированные сигналы 1201-на-1 с набором сигналов и их соответствующими метками.

Эта сеть:

  • Занимает 1201 сигналами 1 на 1, как введено.

  • Преобразовывает категорические этикетки во вложение векторов и изменяет их к 1201 множествами 1 на 1.

  • Конкатенация результатов с двумя входами по размеру канала. Выходной сигнал - массив 1201 на 1 на 1025.

  • Понижает выборку результирующих массивов до скалярных оценок прогнозирования, которые являются массивами 1 на 1, используя ряд 1-D слоев свертки с протекающими слоями ReLU со шкалой 0,2.

% Discriminator Network

scale = 0.2;
inputSize = [1201 1 1];

layersDiscriminator = [
    imageInputLayer(inputSize,'Normalization','none','Name','in')
    concatenationLayer(3,2,'Name','cat')
    convolution2dLayer([17 1],8*numFilters,'Stride',2,'Padding',[1 0],'Name','conv1')
    leakyReluLayer(scale,'Name','lrelu1')
    convolution2dLayer([16 1],4*numFilters,'Stride',4,'Padding',[1 0],'Name','conv2')
    leakyReluLayer(scale,'Name','lrelu2')
    convolution2dLayer([16 1],2*numFilters,'Stride',4,'Padding',[1 0],'Name','conv3')
    leakyReluLayer(scale,'Name','lrelu3')
    convolution2dLayer([8 1],numFilters,'Stride',4,'Padding',[1 0],'Name','conv4')
    leakyReluLayer(scale,'Name','lrelu4')
    convolution2dLayer([8 1],1,'Name','conv5')];

lgraphDiscriminator = layerGraph(layersDiscriminator);

layers = [
    imageInputLayer([1 1],'Name','labels','Normalization','none')
    embedAndReshapeLayer(inputSize,embeddingDimension,numClasses,'emb')];

lgraphDiscriminator = addLayers(lgraphDiscriminator,layers);
lgraphDiscriminator = connectLayers(lgraphDiscriminator,'emb','cat/in2');

Постройте график сетевой структуры дискриминатора.

plot(lgraphDiscriminator)

Чтобы обучить сеть с помощью пользовательского цикла обучения и включить автоматическое дифференцирование, преобразуйте график слоев в dlnetwork объект.

dlnetDiscriminator = dlnetwork(lgraphDiscriminator);

Модель поезда

Обучение модели CGAN с использованием пользовательского цикла обучения. Закольцовывать обучающие данные и обновлять сетевые параметры на каждой итерации. Для контроля за ходом обучения, отображение сгенерированных здоровых и неисправных сигналов с использованием двух фиксированных массивов случайных значений для ввода в генератор, а также график оценок двух сетей.

Для каждой эпохи перетасуйте обучающие данные и закольцовывайте мини-пакеты данных.

Для каждой мини-партии:

  • Создать dlarray Объект (Deep Learning Toolbox), содержащий массив случайных значений для сети генератора.

  • Для обучения GPU преобразуйте данные в gpuArray (Панель параллельных вычислений).

  • Оценка градиентов модели с помощью dlfeval (Deep Learning Toolbox) и функция помощника modelGradients.

  • Обновление параметров сети с помощью adamupdate (Deep Learning Toolbox).

Вспомогательная функция modelGradients принимает в качестве входных данных генераторные и дискриминаторные сети, мини-пакет входных данных и массив случайных значений и возвращает градиенты потерь относительно обучаемых параметров в сетях и оценок двух сетей. Функция потери определена в функции помощника ganLoss.

Укажите параметры обучения

Установите параметры обучения.

params.numLatentInputs = numLatentInputs;
params.numClasses = numClasses;
params.sizeData = [inputSize length(labels)];
params.numEpochs = 1000;
params.miniBatchSize = 256;

% Specify the options for Adam optimizer
params.learnRate = 0.0002;
params.gradientDecayFactor = 0.5;
params.squaredGradientDecayFactor = 0.999;

Настройте среду выполнения для запуска CGAN на CPU. Для запуска CGAN на GPU установите executionEnvironment комуgpu"или выберите параметр" Запустить на GPU "в редакторе Live Editor. Для использования графического процессора требуется Toolbox™ параллельных вычислений. Сведения о том, какие графические процессоры поддерживаются, см. в разделе Поддержка графических процессоров по выпуску (Панель инструментов параллельных вычислений).

executionEnvironment = "cpu";
params.executionEnvironment = executionEnvironment;

Пропустите процесс обучения, загрузив предварительно обученную сеть. Чтобы обучить сеть на компьютере, установите trainNow кому true или выберите опцию «Train CGAN now» в интерактивном редакторе.

trainNow = false;
if trainNow
    % Train the CGAN
    [dlnetGenerator,dlnetDiscriminator] = trainGAN(dlnetGenerator, ...
        dlnetDiscriminator,flowNormalized,labels,params); %#ok
else
    % Use pretrained CGAN (default)
    load(fullfile(tempdir,'PumpSignalGAN','GANModel.mat')) % load data set
end

Обучающий график ниже показывает пример оценок сетей генератора и дискриминатора. Дополнительные сведения о том, как интерпретировать оценки сети, см. в разделе Мониторинг хода обучения GAN и определение режимов общих сбоев (инструментарий глубокого обучения). В этом примере оценки как генератора, так и дискриминатора сходятся близко к 0,5, что указывает на то, что эффективность обучения является хорошей.

Синтезировать сигналы потока

Создать dlarray объект, содержащий партию 2 000 множеств случайных ценностей 1 на 1 на 100, чтобы ввести в сеть генератора. Сбросьте генератор случайных чисел для воспроизводимых результатов.

rng default

numTests = 2000;
ZNew = randn(1,1,numLatentInputs,numTests,'single');
dlZNew = dlarray(ZNew,'SSCB');

Укажите, что первые 1000 случайных массивов исправны, а остальные неисправны.

TNew = ones(1,1,1,numTests,'single');
TNew(1,1,1,numTests/2+1:end) = single(2);
dlTNew = dlarray(TNew,'SSCB');

Для генерации сигналов с помощью графического процессора преобразуйте данные в gpuArray объекты.

if executionEnvironment == "gpu"
    dlZNew = gpuArray(dlZNew);
    dlTNew = gpuArray(dlTNew);
end

Используйте predict функция на генераторе с партией множеств случайных ценностей 1 на 1 на 100 и этикеток, чтобы сгенерировать синтетические сигналы и вернуться шаг стандартизации, который Вы выполнили на оригинальных сигналах потока.

dlXGeneratedNew = predict(dlnetGenerator,dlZNew,dlTNew)*stdFlow+meanFlow;

Визуализация функций сигналов

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

Извлечение элементов

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

idxGenerated = 1:numTests;
idxReal = numTests+1:numTests+size(flow,2);

XGeneratedNew = squeeze(extractdata(gather(dlXGeneratedNew)));
x = [XGeneratedNew single(flow)];

features = zeros(size(x,2),14,'like',x);

for ii = 1:size(x,2)
    features(ii,:) = extractFeatures(x(:,ii));
end

Каждая строка features соответствует признакам одного сигнала.

Измените метки для сгенерированных здоровых и неисправных сигналов, а также реальных здоровых и неисправных сигналов.

L = [squeeze(TNew)+2;labels.'];

Теперь метки имеют следующие определения:

  • 1 - Генерируемые здоровые сигналы

  • 2 - Сформированные сигналы неисправности

  • 3 - Реальные здоровые сигналы

  • 4 - Реальные сигналы неисправности

Анализ основных компонентов

Выполните PCA для характеристик реальных сигналов и спроецируйте характеристики генерируемых сигналов в одно подпространство PCA. W - коэффициент и Y это счет.

% PCA via svd
featuresReal = features(idxReal,:);
mu = mean(featuresReal,1);
[~,S,W] = svd(featuresReal-mu);
S = diag(S);
Y = (features-mu)*W;

Из сингулярного вектора S, первые три сингулярных значения составляют 99% энергии в S. Элементы сигнала можно визуализировать, используя первые три основных компонента.

sum(S(1:3))/sum(S)
ans = single
    0.9923

Постройте график всех сигналов, используя первые три главных компонента. В подпространстве PCA распределение генерируемых сигналов аналогично распределению реальных сигналов.

idxHealthyR = L==1;
idxFaultR = L==2;

idxHealthyG = L==3;
idxFaultG = L==4;

pp = Y(:,1:3);

figure
scatter3(pp(idxHealthyR,1),pp(idxHealthyR,2),pp(idxHealthyR,3),'o')
xlabel('1st Principal Component')
ylabel('2nd Principal Component')
zlabel('3rd Principal Component')
hold on
scatter3(pp(idxFaultR,1),pp(idxFaultR,2),pp(idxFaultR,3),'d')
scatter3(pp(idxHealthyG,1),pp(idxHealthyG,2),pp(idxHealthyG,3),'s')
scatter3(pp(idxFaultG,1),pp(idxFaultG,2),pp(idxFaultG,3),'+')
view(-10,20)
legend('Real healthy','Real faulty','Generated healthy','Generated faulty', ...
    'Location','Best')
hold off

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

view(2)

Здоровые и неисправные сигналы лежат в одной и той же области подпространства PCA независимо от того, являются ли они реальными или генерируемыми, демонстрируя, что генерируемые сигналы имеют характеристики, аналогичные характеристикам реальных сигналов.

Прогнозирование меток реальных сигналов

Для дополнительной иллюстрации рабочих характеристик CGAN следует обучить классификатор SVM на основе сгенерированных сигналов и затем предсказать, является ли реальный сигнал исправным или неисправным.

Установите сгенерированные сигналы в качестве набора обучающих данных, а реальные сигналы в качестве набора тестовых данных. Измените числовые метки на символьные векторы.

LABELS = {'Healthy','Faulty'};
strL = LABELS([squeeze(TNew);labels.']).';

dataTrain = features(idxGenerated,:);
dataTest = features(idxReal,:);

labelTrain = strL(idxGenerated);
labelTest = strL(idxReal);

predictors = dataTrain; 
response = labelTrain;
cvp = cvpartition(size(predictors,1),'KFold',5);

Обучение классификатора SVM с использованием сгенерированных сигналов.

SVMClassifier = fitcsvm( ...
    predictors(cvp.training(1),:), ...
    response(cvp.training(1)),'KernelFunction','polynomial', ...
    'PolynomialOrder',2, ...
    'KernelScale','auto', ...
    'BoxConstraint',1, ...
    'ClassNames',LABELS, ...
    'Standardize',true);

Используйте обученный классификатор для получения прогнозируемых меток для реальных сигналов. Классификатор достигает точности прогнозирования выше 90%.

actualValue = labelTest;
predictedValue = predict(SVMClassifier,dataTest);
predictAccuracy = mean(cellfun(@strcmp,actualValue,predictedValue))
predictAccuracy = 0.9460

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

figure
confusionchart(actualValue,predictedValue)

Тематическое исследование

Сравните спектральные характеристики реальных и сформированных сигналов. Из-за недетерминированного поведения обучения GPU, если вы тренируете модель CGAN самостоятельно, ваши результаты могут отличаться от результатов в этом примере.

Частота вращения двигателя насоса составляет 950 об/мин, или 15,833 Гц, и поскольку насос имеет три цилиндра, поток, как ожидается, будет иметь основной ток при 3-х кратных 15,833 Гц, или 47,5 Гц, и гармоники при кратных 47,5 Гц. Постройте график спектра для одного случая реальных и сгенерированных здоровых сигналов. На графике генерируемый здоровый сигнал имеет относительно высокие значения мощности при 47,5 Гц и 2 раза 47,5 Гц, что точно так же, как и реальный здоровый сигнал.

Fs = 1000;
pspectrum([x(:,1) x(:,2006)],Fs)
set(gca,'XScale','log')
legend('Generated healthy','Real healthy')

При наличии неисправностей возникают резонансы при частоте вращения двигателя насоса 15,833 Гц и его гармониках. Постройте график спектров для одного случая реальных и сгенерированных неисправных сигналов. Генерируемый сигнал имеет относительно высокие значения мощности около 15,833 Гц и его гармоники, что аналогично реальному неисправному сигналу.

pspectrum([x(:,1011) x(:,2100)],Fs)
set(gca,'XScale','log')
legend('Generated faulty','Real faulty')

Постройте график спектров для другого случая реальных и сгенерированных неисправных сигналов. Спектральные характеристики генерируемых неисправных сигналов не очень хорошо соответствуют теоретическому анализу и отличаются от реального неисправного сигнала. CGAN все еще может быть улучшена путем настройки структуры сети или гиперпараметров.

pspectrum([x(:,1001) x(:,2600)],Fs)
set(gca,'XScale','log')
legend('Generated faulty','Real faulty')

Время вычисления

Моделирование Simulink занимает около 14 часов, чтобы генерировать 2000 сигналы потока насоса. Эта продолжительность может быть сокращена примерно до 1,7 часов с восемью параллельными работниками, если у вас есть Parallel Computing Toolbox™.

CGAN требует 1,5 часов для тренировки и 70 секунд для генерации такого же количества синтетических данных с помощью графического процессора NVIDIA Titan V.

См. также

(инструментарий для глубокого обучения) | (инструментарий для глубокого обучения) | (инструментарий для глубокого обучения)

Связанные темы