신경망 ODE를 사용한 동적 시스템 모델링
이 예제에서는 물리 시스템의 동특성을 학습하도록 신경망 상미분 방정식(ODE)을 사용하여 신경망을 훈련시키는 방법을 다룹니다.
신경망 ODE[1]는 ODE의 해에 의해 정의되는 딥러닝 연산입니다. 더 구체적으로, 신경망 ODE는 모든 아키텍처에 사용할 수 있는 연산이며 입력값이 주어지면 그에 따른 출력값이 다음 ODE의 수치 해로 정의됩니다.
이는 시간 지평(horizon) 에서 초기 조건 을 갖는 ODE입니다. ODE의 우변 는 모델이 훈련 과정에 학습하는 훈련 가능한 파라미터 세트 에 종속됩니다. 이 예제에서 는 완전 연결 연산과 비선형 활성화가 포함된 모델 함수로 모델링됩니다. 초기 조건 은 전체 아키텍처의 입력값(이 예제의 경우)이거나 이전의 어떤 연산에서의 출력값입니다.
이 예제에서는 다음 ODE로 설명되는 주어진 물리 시스템의 동특성 를 학습하도록 신경망 ODE를 갖는 신경망을 훈련시키는 방법을 다룹니다.
,
여기서 는 2×2 행렬입니다.
이 예제의 신경망은 초기 조건을 입력값으로 받고, 학습된 신경망 ODE 모델을 통해 ODE 해를 계산합니다.

초기 조건이 주어지면 신경망 ODE 연산은 ODE 모델의 해를 출력합니다. 이 예제에서는 완전 연결 계층, tanh 계층 및 또 다른 완전 연결 계층을 갖는 블록을 ODE 모델로 지정합니다.

이 예제에서 모델을 정의하는 ODE의 해는 명시적 룽게-쿠타(Explicit Runge-Kutta) (4,5) 도르만드-프린스(Dormand-Prince) 쌍을 사용하여 수치적으로 구해집니다[2]. 역방향 통과는 자동 미분을 사용하여 ODE 솔버의 각 연산을 통해 역전파해 나감으로써 훈련 가능한 파라미터 를 학습합니다.
학습된 함수 는 추가적인 초기 조건에 대해 동일한 모델의 해를 구할 때 우변으로 사용됩니다.
목표 동특성 데이터 합성하기
목표 동특성을 초기 조건이 x0인 선형 ODE 모델 로 정의하고, 시간 구간 [0 15]에서 ode45를 사용하여 수치 해 xTrain을 계산합니다. 정확한 ground truth 데이터를 계산하기 위해 ode45 수치 솔버의 상대 허용오차를 로 설정합니다. 나중에 신경망 ODE 모델을 사용해 근사된 동특성을 학습할 때 xTrain의 값을 ground truth 데이터로 사용할 수 있습니다.
x0 = [2; 0]; A = [-0.1 -1; 1 -0.1]; trueModel = @(t,y) A*y; numTimeSteps = 2000; T = 15; odeOptions = odeset(RelTol=1.e-7); t = linspace(0, T, numTimeSteps); [~, xTrain] = ode45(trueModel, t, x0, odeOptions); xTrain = xTrain';
훈련 데이터를 플롯에 시각화합니다.
figure plot(xTrain(1,:),xTrain(2,:)) title("Ground Truth Dynamics") xlabel("x(1)") ylabel("x(2)") grid on

모델 파라미터를 정의하고 초기화하기
모델 함수는 dlode45에 대한 한 번의 호출로 구성되며, 이 호출로 40개의 시간 스텝에서 근사 동특성 로 정의된 ODE를 풉니다.
neuralOdeTimesteps = 40; dt = t(2); timesteps = (0:neuralOdeTimesteps)*dt;
dlode45 호출에 사용할 학습 가능한 파라미터를 정의하고 이를 변수 neuralOdeParameters에 수집합니다. 함수 initializeGlorot는 학습 가능한 파라미터의 크기 sz와 완전 연결 연산의 출력 개수 및 입력 개수를 입력값으로 받은 다음, Glorot 초기화를 사용하여 설정된 값을 갖는 기본 유형이 single형인 dlarray 객체를 반환합니다. 함수 initializeZeros는 학습 가능한 파라미터의 크기를 입력값으로 받고, 그 파라미터를 기본 유형이 single형인 dlarray 객체로 반환합니다. 초기화 예제 함수는 이 예제에 지원 파일로 첨부되어 있습니다. 이러한 함수에 액세스하려면 이 예제를 라이브 스크립트로 여십시오. 모델 함수의 학습 가능한 파라미터를 초기화하는 방법에 대한 자세한 내용은 Initialize Learnable Parameters for Model Function 항목을 참조하십시오.
파라미터 구조체를 초기화합니다.
neuralOdeParameters = struct;
ODE 모델의 완전 연결 연산에 대한 파라미터를 초기화합니다. 첫 번째 완전 연결 연산은 크기가 stateSize인 벡터를 입력값으로 받고, 그 길이를 hiddenSize로 늘립니다. 반대로, 두 번째 완전 연결 연산은 길이가 hiddenSize인 벡터를 입력값으로 받고, 그 길이를 stateSize로 줄입니다.
stateSize = size(xTrain,1); hiddenSize = 20; neuralOdeParameters.fc1 = struct; sz = [hiddenSize stateSize]; neuralOdeParameters.fc1.Weights = initializeGlorot(sz, hiddenSize, stateSize); neuralOdeParameters.fc1.Bias = initializeZeros([hiddenSize 1]); neuralOdeParameters.fc2 = struct; sz = [stateSize hiddenSize]; neuralOdeParameters.fc2.Weights = initializeGlorot(sz, stateSize, hiddenSize); neuralOdeParameters.fc2.Bias = initializeZeros([stateSize 1]);
모델의 학습 가능한 파라미터를 표시합니다.
neuralOdeParameters.fc1
ans = struct with fields:
Weights: [20×2 dlarray]
Bias: [20×1 dlarray]
neuralOdeParameters.fc2
ans = struct with fields:
Weights: [2×20 dlarray]
Bias: [2×1 dlarray]
신경망 ODE 모델 정의하기
이 예제의 ODE 모델 섹션에 나와 있는 함수 odeModel을 만듭니다. 이 함수는 시간 입력값(사용되지 않음)과 그에 대응하는 해, 그리고 ODE 함수 파라미터를 입력값으로 받습니다. 이 함수는 파라미터로 지정된 가중치와 편향을 사용하여 완전 연결 연산과 tanh 연산 및 또 다른 완전 연결 연산을 입력 데이터에 적용합니다.
모델 함수 정의하기
이 예제의 모델 함수 섹션에 나와 있는 함수 model을 만듭니다. 이 함수는 딥러닝 모델의 출력값을 계산합니다. 함수 model은 모델 파라미터와 입력 데이터를 입력값으로 받습니다. 이 함수는 신경망 ODE의 해를 출력합니다.
모델 손실 함수 정의하기
이 예제의 모델 손실 함수 섹션에 나와 있는 함수 modelLoss를 만듭니다. 이 함수는 모델 파라미터와 입력 데이터 및 이에 대응하는 목표값으로 구성된 미니 배치를 입력값으로 받고, 손실과 학습 가능한 파라미터에 대한 해당 손실의 기울기를 반환합니다.
훈련 옵션 지정하기
Adam 최적화에 대한 옵션을 지정합니다.
gradDecay = 0.9; sqGradDecay = 0.999; learnRate = 0.002;
크기가 200인 미니 배치를 사용하여 훈련을 1200번 반복합니다.
numIter = 1200; miniBatchSize = 200;
50회 반복마다 학습된 동특성의 해를 구하고, 이를 위상 다이어그램에 ground truth와 함께 나타내어 훈련 경로를 표시합니다.
plotFrequency = 50;
사용자 지정 훈련 루프를 사용하여 모델 훈련시키기
Adam 솔버에 대한 averageGrad 파라미터와 averageSqGrad 파라미터를 초기화합니다.
averageGrad = []; averageSqGrad = [];
TrainingProgressMonitor 객체를 초기화합니다. monitor 객체를 생성할 때 타이머가 시작되므로 이 객체를 훈련 루프와 가깝게 생성해야 합니다.
monitor = trainingProgressMonitor(Metrics="Loss",Info=["Iteration","LearnRate"],XLabel="Iteration");
사용자 지정 훈련 루프를 사용하여 신경망을 훈련시킵니다.
각 반복에 대해 다음을 수행합니다.
이 예제의 미니 배치 함수 만들기 섹션에 나와 있는
createMiniBatch함수를 사용하여 합성 데이터로부터 미니 배치를 생성합니다.이 예제의 모델 손실 함수 섹션에 나와 있는
dlfeval함수와modelLoss함수를 사용하여 모델 손실과 모델 기울기를 평가합니다.adamupdate함수를 사용하여 모델 파라미터를 업데이트합니다.훈련 진행 상황 플롯을 업데이트합니다.
numTrainingTimesteps = numTimeSteps; trainingTimesteps = 1:numTrainingTimesteps; plottingTimesteps = 2:numTimeSteps; iteration = 0; while iteration < numIter && ~monitor.Stop iteration = iteration + 1; % Create batch [X, targets] = createMiniBatch(numTrainingTimesteps, neuralOdeTimesteps, miniBatchSize, xTrain); % Evaluate network and compute loss and gradients [loss,gradients] = dlfeval(@modelLoss,timesteps,X,neuralOdeParameters,targets); % Update network [neuralOdeParameters,averageGrad,averageSqGrad] = adamupdate(neuralOdeParameters,gradients,averageGrad,averageSqGrad,iteration,... learnRate,gradDecay,sqGradDecay); % Plot loss recordMetrics(monitor,iteration,Loss=loss); % Plot predicted vs. real dynamics if mod(iteration,plotFrequency) == 0 || iteration == 1 % Use ode45 to compute the solution y = dlode45(@odeModel,t,dlarray(x0),neuralOdeParameters,DataFormat="CB"); plot(xTrain(1,plottingTimesteps),xTrain(2,plottingTimesteps),"r--") hold on plot(y(1,:),y(2,:),"b-") hold off xlabel("x(1)") ylabel("x(2)") title("Predicted vs. Real Dynamics") legend("Training Ground Truth", "Predicted") drawnow end updateInfo(monitor,Iteration=iteration,LearnRate=learnRate); monitor.Progress = 100*iteration/numIter; end


모델 평가하기
모델을 사용하여 서로 다른 초기 조건으로 근사해를 구합니다.
모델 훈련에 사용된 초기 조건과는 다른 새 초기 조건 4개를 정의합니다.
tPred = t; x0Pred1 = sqrt([2;2]); x0Pred2 = [-1;-1.5]; x0Pred3 = [0;2]; x0Pred4 = [-2;0];
4개의 새 초기 조건에 대해 ode45를 사용하여 ODE의 실제 동특성의 해를 수치적으로 구합니다.
[~, xTrue1] = ode45(trueModel, tPred, x0Pred1, odeOptions); [~, xTrue2] = ode45(trueModel, tPred, x0Pred2, odeOptions); [~, xTrue3] = ode45(trueModel, tPred, x0Pred3, odeOptions); [~, xTrue4] = ode45(trueModel, tPred, x0Pred4, odeOptions);
학습된 신경망 ODE 동특성을 사용하여 수치적으로 ODE를 풉니다.
xPred1 = dlode45(@odeModel,tPred,dlarray(x0Pred1),neuralOdeParameters,DataFormat="CB"); xPred2 = dlode45(@odeModel,tPred,dlarray(x0Pred2),neuralOdeParameters,DataFormat="CB"); xPred3 = dlode45(@odeModel,tPred,dlarray(x0Pred3),neuralOdeParameters,DataFormat="CB"); xPred4 = dlode45(@odeModel,tPred,dlarray(x0Pred4),neuralOdeParameters,DataFormat="CB");
예측 시각화하기
이 예제의 실제 해 및 예측 해 함수 플로팅하기 섹션에 나와 있는 함수 plotTrueAndPredictedSolutions를 사용해 다양한 초기 조건에서 예측 해와 ground truth 해를 비교하여 시각화합니다.
figure subplot(2,2,1) plotTrueAndPredictedSolutions(xTrue1, xPred1); subplot(2,2,2) plotTrueAndPredictedSolutions(xTrue2, xPred2); subplot(2,2,3) plotTrueAndPredictedSolutions(xTrue3, xPred3); subplot(2,2,4) plotTrueAndPredictedSolutions(xTrue4, xPred4);

헬퍼 함수
모델 함수
예측에 사용되는 신경망을 정의하는 model 함수는 한 번의 신경망 ODE 호출로 구성됩니다. 각 관측값에 대해, 이 함수는 수치 해의 출력 시점을 정의하는 시간 지점으로 구성된 벡터 tspan과 더불어 길이가 stateSize인 벡터를 입력값으로 받습니다. 이 벡터는 함수 odeModel을 ODE의 우변으로 사용하여 해를 수치적으로 구할 때 초기 조건으로 사용됩니다. odeModel 함수는 풀려는 ODE의 학습 가능한 우변 를 나타냅니다. 학습된 시스템이 자율 시스템이기 때문에 이 함수는 초기 조건에 관계없이 각 관측값에 벡터 tspan을 사용합니다. 즉, odeModel 함수는 시간에 명시적으로 종속되지 않습니다.
function X = model(tspan,X0,neuralOdeParameters) X = dlode45(@odeModel,tspan,X0,neuralOdeParameters,DataFormat="CB"); end
ODE 모델
odeModel 함수는 dlode45 호출에 사용되는 학습 가능한 우변입니다. 이 함수는 크기가 stateSize인 벡터를 입력값으로 받고, 길이가 hiddenSize가 되도록 벡터를 확대한 다음, 비선형 함수 tanh를 적용합니다. 그런 다음 길이가 stateSize가 되도록 벡터를 다시 압축합니다.
function y = odeModel(~,y,theta) y = tanh(theta.fc1.Weights*y + theta.fc1.Bias); y = theta.fc2.Weights*y + theta.fc2.Bias; end
모델 손실 함수
이 함수는 벡터 tspan과 초기 조건 X0 세트, 학습 가능한 파라미터 neuralOdeParameters 및 목표값 시퀀스 targets를 입력값으로 받습니다. 그리고 model 함수를 사용하여 예측값을 계산하고 이를 주어진 목표값 시퀀스와 비교합니다. 마지막으로, 손실과 신경망 ODE의 학습 가능한 파라미터에 대한 손실 기울기를 계산합니다.
function [loss,gradients] = modelLoss(tspan,X0,neuralOdeParameters,targets) % Compute predictions. X = model(tspan,X0,neuralOdeParameters); % Compute L1 loss. loss = l1loss(X,targets,NormalizationFactor="all-elements",DataFormat="CBT"); % Compute gradients. gradients = dlgradient(loss,neuralOdeParameters); end
미니 배치 함수 만들기
createMiniBatch 함수는 목표 동특성에 대한 관측값으로 구성된 배치를 만듭니다. 이 함수는 ground truth 데이터의 총 시간 스텝 수 numTimesteps와 각 관측값에 대해 반환될 연속된 시간 스텝 수 numTimesPerObs, 관측값 개수 miniBatchSize, ground truth 데이터 X를 입력값으로 받습니다.
function [x0, targets] = createMiniBatch(numTimesteps,numTimesPerObs,miniBatchSize,X) % Create batches of trajectories. s = randperm(numTimesteps - numTimesPerObs, miniBatchSize); x0 = dlarray(X(:, s)); targets = zeros([size(X,1) miniBatchSize numTimesPerObs]); for i = 1:miniBatchSize targets(:, i, 1:numTimesPerObs) = X(:, s(i) + 1:(s(i) + numTimesPerObs)); end end
실제 해 및 예측 해 함수 플로팅하기
plotTrueAndPredictedSolutions 함수는 실제 해 xTrue와 학습된 신경망 ODE 모델로 구한 근사해 xPred, 그리고 그에 대응되는 초기 조건 x0Str을 입력값으로 받습니다. 이 함수는 실제 해와 예측 해 사이의 오차를 계산하고, 이를 위상 다이어그램에 플로팅합니다.
function plotTrueAndPredictedSolutions(xTrue,xPred) xPred = squeeze(xPred)'; err = mean(abs(xTrue(2:end,:) - xPred), "all"); plot(xTrue(:,1),xTrue(:,2),"r--",xPred(:,1),xPred(:,2),"b-",LineWidth=1) title("Absolute Error = " + num2str(err,"%.4f")) xlabel("x(1)") ylabel("x(2)") xlim([-2 3]) ylim([-2 3]) legend("Ground Truth","Predicted") end
[1] Chen, Ricky T. Q., Yulia Rubanova, Jesse Bettencourt, and David Duvenaud. “Neural Ordinary Differential Equations.” Preprint, submitted December 13, 2019. https://arxiv.org/abs/1806.07366.
[2] Shampine, Lawrence F., and Mark W. Reichelt. “The MATLAB ODE Suite.” SIAM Journal on Scientific Computing 18, no. 1 (January 1997): 1–22. https://doi.org/10.1137/S1064827594276424.
Copyright 2021–2023 The MathWorks, Inc.
참고 항목
dlode45 | dlarray | dlgradient | dlfeval | adamupdate