exponenta event banner

Использование сети LSTM для линейной идентификации системы

Этот пример показывает, как использовать нейронные сети с длительной кратковременной памятью (LSTM) для оценки линейной системы, и сравнивает этот подход для оценки передаточной функции.

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

Передаточная функция

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

fourthOrderMdl = zpk(-4,[-9+5i;-9-5i;-2+50i;-2-50i],5e5);
[stepResponse,stepTime] = step(fourthOrderMdl);

Постройте график ответа на шаг передаточной функции.

plot(stepTime,stepResponse)
grid on
axis tight
title('Fourth-order mixed step response')

Figure contains an axes. The axes with title Fourth-order mixed step response contains an object of type line.

График Боде показывает полосу пропускания системы, которая измеряется как первая частота, где коэффициент усиления падает ниже 70,8% или около 3 дБ от ее значения постоянного тока.

bodeplot(fourthOrderMdl)

Figure contains 2 axes. Axes 1 contains an object of type line. This object represents fourthOrderMdl. Axes 2 contains an object of type line. This object represents fourthOrderMdl.

fb = bandwidth(fourthOrderMdl)
fb = 62.8858

Создание данных обучения

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

Данные о гауссовом шуме

Задайте свойства для случайного гауссова сигнала обучения шуму.

signalType = 'rgs'; % Gaussian 
signalLength = 5000; % Number of points in the signal
fs = 100; % Sampling frequency
signalAmplitude = 1; % Maximum signal amplitude

Генерация гауссова шумового сигнала с помощью idinput и масштабировать результат.

urgs = idinput(signalLength,signalType);
urgs = (signalAmplitude/max(urgs))*urgs';

Формирование временного сигнала на основе частоты дискретизации.

trgs = 0:1/fs:length(urgs)/fs-1/fs;

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

yrgs = lsim(fourthOrderMdl,urgs,trgs);
yrgs = yrgs';

Аналогично, создайте более короткий сигнал проверки подлинности для использования во время обучения сети.

xval = idinput(100,signalType);
yval = lsim(fourthOrderMdl,xval,trgs(1:100));

Создание и обучение сети

Следующая сетевая архитектура была определена с помощью байесовской процедуры оптимизации, где байесовская функция оптимизации затрат использует независимые данные проверки (см. сопровождающие bayesianOptimizationForLSTM.mlx для получения подробной информации). Хотя может работать несколько архитектур, эта оптимизация обеспечивает наиболее эффективную в вычислительном отношении. Процесс оптимизации также показал, что по мере увеличения сложности передаточной функции при применении LSTM к другим линейным передаточным функциям архитектура сети существенно не меняется. Скорее увеличивается количество эпох, необходимых для обучения сети. Количество скрытых единиц, необходимых для моделирования системы, зависит от того, сколько времени требуется для гашения динамики. В этом случае есть две отдельные части отклика: высокочастотный отклик и низкочастотный отклик. Для захвата низкочастотной характеристики требуется большее количество скрытых блоков. Если выбрано меньшее количество блоков, высокочастотная характеристика все еще моделируется. Однако оценка низкочастотной характеристики ухудшается.

Создайте архитектуру сети.

numResponses = 1;
featureDimension = 1;
numHiddenUnits = 100;
maxEpochs = 1000;
miniBatchSize = 200;

Networklayers = [sequenceInputLayer(featureDimension) ...
    lstmLayer(numHiddenUnits) ...
    lstmLayer(numHiddenUnits) ...
    fullyConnectedLayer(numResponses) ...
    regressionLayer];

Начальный уровень обучения влияет на успех сети. Использование начального уровня обучения, который является слишком высоким, приводит к высоким градиентам, что приводит к увеличению времени обучения. Более длительное время обучения может привести к насыщению полностью подключенного уровня сети. Когда сеть насыщается, выходы расходятся, а сеть выводит NaN значение. Следовательно, используйте значение по умолчанию 0,01, которое является относительно низким начальным уровнем обучения. Это приводит к монотонному уменьшению кривых остаточных и потерь. Используйте кусочно-скоростной график, чтобы не допустить захвата алгоритма оптимизации в локальных минимумах в начале процедуры оптимизации.

options = trainingOptions('adam', ...
    'MaxEpochs',maxEpochs, ...
    'MiniBatchSize',miniBatchSize, ...
    'GradientThreshold',10, ...
    'Shuffle','once', ...
    'Plots','training-progress',...
    'ExecutionEnvironment','gpu',...
    'LearnRateSchedule','piecewise',...
    'LearnRateDropPeriod',100,...
    'Verbose',0,...
    'ValidationData',[{xval'} {yval'}]);

loadNetwork = true; % Set to true to train the network using a parallel pool.
if loadNetwork
    load('fourthOrderMdlnet','fourthOrderNet')
else
    poolobj = parpool;
    fourthOrderNet = trainNetwork(urgs,yrgs,Networklayers,options);
    delete(poolobj)
    save('fourthOrderMdlnet','fourthOrderNet','urgs','yrgs');
end

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

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

Создайте ввод шага.

stepTime = 2; % In seconds
stepAmplitude = 0.1;
stepDuration = 4; % In seconds

% Construct step signal and system output.
time = (0:1/fs:stepDuration)';
stepSignal = [zeros(sum(time<=stepTime),1);stepAmplitude*ones(sum(time>stepTime),1)];
systemResponse = lsim(fourthOrderMdl,stepSignal,time);

% Transpose input and output signal for network inputs.
stepSignal = stepSignal';
systemResponse = systemResponse';

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

fourthOrderMixedNetStep = predict(fourthOrderNet,stepSignal);

figure
title('Step response estimation')
plot(time,systemResponse,'k', time, fourthOrderMixedNetStep)
grid on
legend('System','Estimated')
title('Fourth-Order Step')

Figure contains an axes. The axes with title Fourth-Order Step contains 2 objects of type line. These objects represent System, Estimated.

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

Инициализация сети и настройка подгонки

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

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

Установка начального состояния сети

Когда сеть выполняет оценку с использованием ступенчатого ввода от 0 до 1, состояния сети LSTM (сотовые и скрытые состояния уровней LSTM) смещаются к правильному начальному условию. Чтобы визуализировать это, извлеките ячейку и скрытое состояние сети на каждом шаге времени с помощью predictAndUpdateState функция.

Используйте только значения ячейки и скрытого состояния перед шагом, который происходит через 2 секунды. Определите маркер времени на 2 секунды и извлеките значения до этого маркера.

stepMarker = time <= 2;
yhat = zeros(sum(stepMarker),1);
hiddenState = zeros(sum(stepMarker),200); % 200 LSTM units
cellState = zeros(sum(stepMarker),200);
for ntime = 1:sum(stepMarker)
    [fourthOrderNet,yhat(ntime)] = predictAndUpdateState(fourthOrderNet,stepSignal(ntime)');
    hiddenState(ntime,:) = fourthOrderNet.Layers(2,1).HiddenState;
    cellState(ntime,:) = fourthOrderNet.Layers(2,1).CellState;
end

Затем постройте график скрытых состояний и состояний ячеек за период до шага и подтвердите, что они сходятся к фиксированным значениям.

figure
subplot(2,1,1)
plot(time(1:200),hiddenState(1:200,:))
grid on
axis tight
title('Hidden State')
subplot(2,1,2)
plot(time(1:200),cellState(1:200,:))
grid on
axis tight
title('Cell State')

Figure contains 2 axes. Axes 1 with title Hidden State contains 200 objects of type line. Axes 2 with title Cell State contains 200 objects of type line.

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

initializationSignalDuration = 10; % In seconds
initializationValue = 0;
initializationSignal = initializationValue*ones(1,initializationSignalDuration*fs);

fourthOrderNet = predictAndUpdateState(fourthOrderNet,initializationSignal);

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

figure
zeroMapping = predict(fourthOrderNet,initializationSignal);
plot(zeroMapping)
axis tight

Figure contains an axes. The axes contains an object of type line.

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

fourthOrderMixedNetStep = predict(fourthOrderNet,stepSignal);

figure
title('Step response estimation')
plot(time,systemResponse,'k', ...
    time,fourthOrderMixedNetStep,'b')
grid on
legend('System','Estimated')
title('Fourth-Order Step - Adjusted State')

Figure contains an axes. The axes with title Fourth-Order Step - Adjusted State contains 2 objects of type line. These objects represent System, Estimated.

Корректировка смещения сети

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

bias = mean(predict(fourthOrderNet,initializationSignal));
fourthOrderMixedNetStep = fourthOrderMixedNetStep-bias;

figure
title('Step response estimation')
plot(time,systemResponse,'k',time,fourthOrderMixedNetStep,'b-')
legend('System','Estimated')
title('Fourth-Order Step - Adjusted Offset')

Figure contains an axes. The axes with title Fourth-Order Step - Adjusted Offset contains 2 objects of type line. These objects represent System, Estimated.

Выйти за пределы обучающего диапазона

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

Сдвиг во времени

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

stepTime = 3; % In seconds
stepAmplitude = 0.1;
stepDuration = 5; % In seconds
[stepSignal,systemResponse,time] = generateStepResponse(fourthOrderMdl,stepTime,stepAmplitude,stepDuration);

fourthOrderMixedNetStep = predict(fourthOrderNet,stepSignal);
bias = fourthOrderMixedNetStep(1) - initializationValue;
fourthOrderMixedNetStep = fourthOrderMixedNetStep-bias;

figure
plot(time,systemResponse,'k', time,fourthOrderMixedNetStep,'b')
grid on
axis tight

Figure contains an axes. The axes contains 2 objects of type line.

Сдвиг амплитуды

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

figure
histogram(urgs,'Normalization','pdf')
grid on

Figure contains an axes. The axes contains an object of type histogram.

Установите амплитуду ступенчатой функции в соответствии с процентилем распределения. Постройте график частоты ошибок как функции процентиля.

pValues = [60:2:98, 90:1:98, 99:0.1:99.9 99.99];
stepAmps = prctile(urgs,pValues); % Amplitudes
stepTime = 3; % In seconds
stepDuration = 5; % In seconds

stepMSE = zeros(length(stepAmps),1);
fourthOrderMixedNetStep = cell(length(stepAmps),1);
steps = cell(length(stepAmps),1);

for nAmps = 1:length(stepAmps)
    % Fourth-order mixed
    [stepSignal,systemResponse,time] = generateStepResponse(fourthOrderMdl,stepTime,stepAmps(nAmps),stepDuration);
    
    fourthOrderMixedNetStep{nAmps} = predict(fourthOrderNet,stepSignal);
    bias = fourthOrderMixedNetStep{nAmps}(1) - initializationValue;
    fourthOrderMixedNetStep{nAmps} = fourthOrderMixedNetStep{nAmps}-bias;
    
    stepMSE(nAmps) = sqrt(sum((systemResponse-fourthOrderMixedNetStep{nAmps}).^2));
    steps{nAmps,1} = systemResponse;
end

figure
plot(pValues,stepMSE,'bo')
title('Prediction Error as a Function of Deviation from Training Rrange')
grid on
axis tight

Figure contains an axes. The axes with title Prediction Error as a Function of Deviation from Training Rrange contains an object of type line.

subplot(2,1,1)
plot(time,steps{1},'k', time,fourthOrderMixedNetStep{1},'b')
grid on
axis tight
title('Best Performance')
xlabel('time')
ylabel('System Response')
subplot(2,1,2)
plot(time,steps{end},'k', time,fourthOrderMixedNetStep{end},'b')
grid on
axis tight
title('Worst Performance')
xlabel('time')
ylabel('System Response')

Figure contains 2 axes. Axes 1 with title Best Performance contains 2 objects of type line. Axes 2 with title Worst Performance contains 2 objects of type line.

Когда амплитуда отклика шага выходит за пределы диапазона обучающего набора, LSTM пытается оценить среднее значение отклика.

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

Изменение пропускной способности системы

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

  • Небольшая сеть с 5 скрытыми блоками и одним уровнем LSTM

  • Средняя сеть с 10 скрытыми блоками и одним уровнем LSTM

  • Полная сеть со 100 скрытыми блоками и одним уровнем LSTM

  • Глубокая сеть с 2 уровнями LSTM (каждый со 100 скрытыми блоками)

Загрузите обученные сети.

load('variousHiddenUnitNets.mat')

Создайте сигнал шага.

stepTime = 2; % In seconds
stepAmplitude = 0.1;
stepDuration = 4; % In seconds

% Construct step signal.
time = (0:1/fs:stepDuration)';

stepSignal = [zeros(sum(time<=stepTime),1);stepAmplitude*ones(sum(time>stepTime),1)];
systemResponse = lsim(fourthOrderMdl,stepSignal,time);

% Transpose input and output signal for network inputs.
stepSignal = stepSignal';
systemResponse = systemResponse';

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

smallNetStep = predict(smallNet,stepSignal)-smallNetZeroMapping(end);
medNetStep = predict(medNet,stepSignal)-medNetZeroMapping(end);
fullnetStep = predict(fullNet,stepSignal) - fullNetZeroMapping(end);
doubleNetStep = predict(doubleNet,stepSignal) - doubleNetZeroMapping(end);
 

Постройте график предполагаемого ответа.

figure
title('Step response estimation')
plot(time,systemResponse,'k', ...
    time,doubleNetStep,'g', ...
    time,fullnetStep,'r', ...
    time,medNetStep,'c', ...
    time,smallNetStep,'b')
grid on
legend({'System','Double Net','Full Net','Med Net','Small Net'},'Location','northwest')
title('Fourth-Order Step')

Figure contains an axes. The axes with title Fourth-Order Step contains 5 objects of type line. These objects represent System, Double Net, Full Net, Med Net, Small Net.

Обратите внимание, что все сети фиксируют высокочастотную динамику в отклике. Однако постройте график скользящего среднего откликов для сравнения медленной изменяющейся динамики системы. Способность ЛСТМ улавливать более долгосрочную динамику (низкочастотную динамику) линейной системы напрямую связана с динамикой системы и количеством скрытых блоков в ЛСТМ. Количество уровней в LSTM не напрямую связано с долгосрочным поведением, а скорее добавляет гибкость для корректировки оценки с первого уровня.

figure
title('Slow dynamics component')
plot(time,movmean(systemResponse,50),'k')
hold on
plot(time,movmean(doubleNetStep,50),'g')
plot(time,movmean(fullnetStep,50),'r')
plot(time,movmean(medNetStep,50),'c')
plot(time,movmean(smallNetStep,50),'b')
grid on
legend('System','Double Net','Full net','Med Net','Small Net','Location','northwest')
title('Fourth Order Step')

Figure contains an axes. The axes with title Fourth Order Step contains 5 objects of type line. These objects represent System, Double Net, Full net, Med Net, Small Net.

Добавление шума в измеренный отклик системы

Добавление случайного шума к выходному сигналу системы для изучения влияния шума на производительность LSTM. Для этого добавьте белый шум с уровнями 1%, 5% и 10% к измеренным откликам системы. Используйте шумные данные для обучения сети LSTM. Используя те же шумные наборы данных, оцените линейные модели с помощью tfest. Смоделировать эти модели и использовать смоделированные отклики в качестве базовой линии для сравнения производительности.

Используйте ту же пошаговую функцию, что и ранее:

stepTime = 2; % In seconds
stepAmplitude = 0.1;
stepDuration = 4; % In seconds

[stepSignal,systemResponse,time] = generateStepResponse(fourthOrderMdl,stepTime,stepAmplitude,stepDuration);

Загрузите обученные сети и оцените отклик системы.

load('noisyDataNetworks.mat')
netNoise1Step = predictAndAdjust(netNoise1,stepSignal,initializationSignal,initializationValue);
netNoise5Step = predictAndAdjust(netNoise5,stepSignal,initializationSignal,initializationValue);
netNoise10Step = predictAndAdjust(netNoise10,stepSignal,initializationSignal,initializationValue);

Оценщик передаточной функции (tfest) используется для оценки функции при вышеуказанных уровнях шума для сравнения устойчивости сетей к шуму (см. сопроводительное noiseLevelModels.m для получения дополнительной информации.

load('noisyDataTFs.mat')
tfStepNoise1 = lsim(tfNoise1,stepSignal,time);
tfStepNoise5 = lsim(tfNoise5,stepSignal,time);
tfStepNoise10 = lsim(tfNoise10,stepSignal,time);

Постройте график созданных откликов.

figure
plot(time,systemResponse,'k', ...
    time,netNoise1Step, ...
    time,netNoise5Step, ...
    time,netNoise10Step)
grid on
legend('System Response','1% Noise','5% Noise','10% Noise')
title('Deep LSTM with noisy data')

Figure contains an axes. The axes with title Deep LSTM with noisy data contains 4 objects of type line. These objects represent System Response, 1% Noise, 5% Noise, 10% Noise.

Теперь постройте график предполагаемых передаточных функций.

figure
plot(time,systemResponse,'k', ...
    time,tfStepNoise1, ...
    time,tfStepNoise5, ...
    time,tfStepNoise10)
grid on
legend('System Response','1% Noise','5% Noise','10% Noise')
title('Transfer functions fitted to noisy data')

Figure contains an axes. The axes with title Transfer functions fitted to noisy data contains 4 objects of type line. These objects represent System Response, 1% Noise, 5% Noise, 10% Noise.

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

msefun = @(y,yhat) mean(sqrt((y-yhat).^2)/length(y));

% LSTM errors
lstmMSE(1,:) = msefun(systemResponse,netNoise1Step);
lstmMSE(2,:) = msefun(systemResponse,netNoise5Step);
lstmMSE(3,:) = msefun(systemResponse,netNoise10Step);

% Transfer function errors
tfMSE(1,:) = msefun(systemResponse,tfStepNoise1');
tfMSE(2,:) = msefun(systemResponse,tfStepNoise5');
tfMSE(3,:) = msefun(systemResponse,tfStepNoise10');

mseTbl = array2table([lstmMSE tfMSE],'VariableNames',{'LSTMMSE','TFMSE'})
mseTbl=3×2 table
     LSTMMSE        TFMSE   
    __________    __________

    1.0115e-05    8.8621e-07
    2.5577e-05    9.9064e-06
    5.1791e-05    3.6831e-05

Шум оказывает одинаковое влияние как на LSTM, так и на результаты оценки передаточной функции.

Вспомогательные функции

function [stepSignal,systemResponse,time] = generateStepResponse(model,stepTime,stepAmp,signalDuration)
%Generates a step response for the given model.
%

%Check model type
modelType = class(model);
if nargin < 2
    stepTime = 1;
end

if nargin < 3
    stepAmp = 1;
end

if nargin < 4
    signalDuration = 10;
end

% Constuct step signal
if model.Ts == 0
    Ts = 1e-2;
    time = (0:Ts:signalDuration)';
else
    time = (0:model.Ts:signalDuration)';
end
stepSignal = [zeros(sum(time<=stepTime),1);stepAmp*ones(sum(time>stepTime),1)];
switch modelType
    case {'tf', 'zpk'}
        systemResponse = lsim(model,stepSignal,time);
    case 'idpoly'
        systemResponse = sim(model,stepSignal,time);
    otherwise
        error('Model passed is not supported')
end

stepSignal = stepSignal';
systemResponse = systemResponse';
end