このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
ニューラル ネットワークを使用した常微分方程式の求解
この例では、ニューラル ネットワークを使用して常微分方程式 (ODE) を解く方法を示します。
すべての微分方程式に閉形式解があるとは限りません。この種の方程式の近似解を求める従来式の数値アルゴリズムは数多くあります。しかし、ニューラル ネットワークを使用して ODE を解くこともできます。このアプローチには、閉じた解析形式で微分可能な近似解が得られるなど、いくつかの利点があります [1]。
この例では、以下を行う方法を説明します。
の範囲での学習データの生成。
を入力として受け取り、ODE を について解いた近似解を出力として返すニューラル ネットワークの定義。
カスタム損失関数でのネットワークの学習。
ネットワーク予測と解析解の比較。
ODE と損失関数
この例では、ODE
を、初期条件 で解きます。この ODE には以下の解析解があります。
ODE と初期状態を満たさず逸脱することにペナルティを課す、カスタム損失関数を定義します。この例では、損失関数は ODE 損失と初期条件損失の重み付き和であり、以下のようになります。
はネットワーク パラメーター、 は定数係数、 はネットワークによって予測された解、 は自動微分を使用して計算された予測解の導関数です。項 は ODE 損失であり、予測解が ODE の定義を満たすことからどれだけ逸脱するかを定量化します。項 は初期条件損失であり、予測解が初期条件を満たすことからどれだけ逸脱するかを定量化します。
入力データの生成とネットワークの定義
範囲 に 10,000 個の学習データ点を生成します。
x = linspace(0,2,10000)';
ODE を解くためのネットワークを定義します。入力は実数 であるため、入力サイズを 1 に指定します。
inputSize = 1;
layers = [
featureInputLayer(inputSize,Normalization="none")
fullyConnectedLayer(10)
sigmoidLayer
fullyConnectedLayer(1)
sigmoidLayer];
層配列から dlnetwork
オブジェクトを作成します。
dlnet = dlnetwork(layers)
dlnet = dlnetwork with properties: Layers: [5×1 nnet.cnn.layer.Layer] Connections: [4×2 table] Learnables: [4×3 table] State: [0×3 table] InputNames: {'input'} OutputNames: {'layer_2'} Initialized: 1 View summary with summary.
モデル勾配関数の定義
この例の最後にリストされている関数 modelGradients
を作成します。この関数は、dlnetwork
オブジェクト dlnet
、入力データ dlX
のミニバッチ、および初期条件損失に関連付けられた係数 icCoeff
を入力として受け取ります。この関数は、dlnet
の学習可能なパラメーターに関する損失の勾配と対応する損失を返します。
学習オプションの指定
ミニバッチ サイズを 100 として 15 エポック学習させます。
numEpochs = 15; miniBatchSize = 100;
SGDM 最適化のオプションを指定します。学習率に 0.5、学習率低下係数に 0.5、学習率低下周期に 5、モーメンタムに 0.9 を指定します。
initialLearnRate = 0.5; learnRateDropFactor = 0.5; learnRateDropPeriod = 5; momentum = 0.9;
損失関数の初期条件項の係数を 7 に指定します。この係数は、損失に対する初期条件の相対的寄与を指定します。このパラメーターを調整すると、学習の収束が速くなります。
icCoeff = 7;
モデルの学習
学習中にデータのミニバッチを使用するには、次のようにします。
学習データから
arrayDatastore
オブジェクトを作成。arrayDatastore
オブジェクトを入力として受け取るminibatchqueue
オブジェクトを作成し、ミニバッチ サイズを指定し、次元ラベル'BC'
(batch, channel) を使用して学習データを書式設定。
ads = arrayDatastore(x,IterationDimension=1);
mbq = minibatchqueue(ads,MiniBatchSize=miniBatchSize,MiniBatchFormat="BC");
既定では、minibatchqueue
オブジェクトは、基となる型が single
の dlarray
オブジェクトにデータを変換します。
GPU が利用できる場合、GPU で学習を行います。既定では、minibatchqueue
オブジェクトは、GPU が利用可能な場合、各出力を gpuArray
に変換します。GPU を使用するには、Parallel Computing Toolbox™ とサポートされている GPU デバイスが必要です。サポートされているデバイスについては、GPU 計算の要件 (Parallel Computing Toolbox)を参照してください。
学習の進行状況プロットを初期化します。
figure set(gca,YScale="log") lineLossTrain = animatedline(Color=[0.85 0.325 0.098]); ylim([0 inf]) xlabel("Iteration") ylabel("Loss (log scale)") grid on
SGDM ソルバーの速度パラメーターを初期化します。
velocity = [];
カスタム学習ループを使用してネットワークに学習させます。各エポックについて、データをシャッフルしてデータのミニバッチをループで回します。各ミニバッチで次を行います。
関数
dlfeval
およびmodelGradients
を使用して、モデルの勾配と損失を評価します。関数
sgdmupdate
を使用してネットワーク パラメーターを更新します。学習の進行状況を表示します。
learnRateDropPeriod
エポックごとに、学習率に learnRateDropFactor
を乗算します。
iteration = 0; learnRate = initialLearnRate; start = tic; % Loop over epochs. for epoch = 1:numEpochs % Shuffle data. mbq.shuffle % Loop over mini-batches. while hasdata(mbq) iteration = iteration + 1; % Read mini-batch of data. dlX = next(mbq); % Evaluate the model gradients and loss using dlfeval and the modelGradients function. [gradients,loss] = dlfeval(@modelGradients, dlnet, dlX, icCoeff); % Update network parameters using the SGDM optimizer. [dlnet,velocity] = sgdmupdate(dlnet,gradients,velocity,learnRate,momentum); % Display the training progress. D = duration(0,0,toc(start),Format="mm:ss.SS"); addpoints(lineLossTrain,iteration,loss) title("Epoch: " + epoch + " of " + numEpochs + ", Elapsed: " + string(D)) drawnow end % Reduce the learning rate. if mod(epoch,learnRateDropPeriod)==0 learnRate = learnRate*learnRateDropFactor; end end
モデルのテスト
予測と解析解を比較して、ネットワークの精度をテストします。
範囲 でテスト データを生成して、ネットワークが学習範囲 の外に外挿できるかどうかを確認します。
xTest = linspace(0,4,1000)';
テスト中にデータのミニバッチを使用するには、次のようにします。
テスト データから
arrayDatastore
オブジェクトを作成。arrayDatastore
オブジェクトを入力として受け取るminibatchqueue
オブジェクトを作成し、ミニバッチ サイズを 100 に指定し、次元ラベル'BC'
(batch, channel) を使用して学習データを書式設定。
adsTest = arrayDatastore(xTest,IterationDimension=1);
mbqTest = minibatchqueue(adsTest,MiniBatchSize=100,MiniBatchFormat="BC");
ミニバッチをループ処理し、この例の最後にリストされている関数 modelPredictions
を使用して予測を行います。
yModel = modelPredictions(dlnet,mbqTest);
解析解を求めます。
yAnalytic = exp(-xTest.^2);
解析解とモデル予測を対数スケールでプロットして比較します。
figure; plot(xTest,yAnalytic,"-") hold on plot(xTest,yModel,"--") legend("Analytic","Model") xlabel("x") ylabel("y (log scale)") set(gca,YScale="log")
モデルは、学習範囲 で解析解を正確に近似し、範囲 ではより低い精度で外挿します。
学習範囲 で平均二乗相対誤差を計算します。
yModelTrain = yModel(1:500); yAnalyticTrain = yAnalytic(1:500); errorTrain = mean(((yModelTrain-yAnalyticTrain)./yAnalyticTrain).^2)
errorTrain = single
4.3454e-04
外挿範囲 で平均二乗相対誤差を計算します。
yModelExtra = yModel(501:1000); yAnalyticExtra = yAnalytic(501:1000); errorExtra = mean(((yModelExtra-yAnalyticExtra)./yAnalyticExtra).^2)
errorExtra = single
17576710
平均二乗相対誤差が、学習範囲よりも外挿範囲において高くなっていることに注意してください。
モデル勾配関数
関数 modelGradients
は、dlnetwork
オブジェクト dlnet
、入力データ dlX
のミニバッチ、および初期条件損失に関連付けられた係数 icCoeff
を入力として受け取ります。この関数は、dlnet
の学習可能なパラメーターに関する損失の勾配と対応する損失を返します。損失は、ODE 損失と初期条件損失の重み付き和として定義されます。この損失の評価には、2 階微分が必要です。2 階自動微分を有効にするには、関数 dlgradient
を使用して、EnableHigherDerivatives
の名前と値の引数を true
に設定します。
function [gradients,loss] = modelGradients(dlnet, dlX, icCoeff) y = forward(dlnet,dlX); % Evaluate the gradient of y with respect to x. % Since another derivative will be taken, set EnableHigherDerivatives to true. dy = dlgradient(sum(y,"all"),dlX,EnableHigherDerivatives=true); % Define ODE loss. eq = dy + 2*y.*dlX; % Define initial condition loss. ic = forward(dlnet,dlarray(0,"CB")) - 1; % Specify the loss as a weighted sum of the ODE loss and the initial condition loss. loss = mean(eq.^2,"all") + icCoeff * ic.^2; % Evaluate model gradients. gradients = dlgradient(loss, dlnet.Learnables); end
モデル予測関数
関数 modelPredictions
は、dlnetwork
オブジェクト dlnet
と入力データの minibatchqueue
オブジェクト mbq
を受け取り、minibatchqueue
オブジェクトに含まれるすべてのデータを反復処理することによってモデル予測 y
を計算します。
function Y = modelPredictions(dlnet,mbq) Y = []; while hasdata(mbq) % Read mini-batch of data. dlXTest = next(mbq); % Predict output using trained network. dlY = predict(dlnet,dlXTest); YPred = gather(extractdata(dlY)); Y = [Y; YPred']; end end
参考文献
Lagaris, I. E., A. Likas, and D. I. Fotiadis. “Artificial Neural Networks for Solving Ordinary and Partial Differential Equations.” IEEE Transactions on Neural Networks 9, no. 5 (September 1998): 987–1000. https://doi.org/10.1109/72.712178.
参考
dlarray
| dlfeval
| dlgradient