C++
機械学習
物理シミュレーション
ニューラルネットワーク
実験

【ニューラルネットワークの基礎研究26】 放物運動の軌跡から粘性抵抗係数と慣性抵抗係数を見積もる

前回から「解析解は得られないが数値解が容易に得られる系で、学習の成果を簡単に検証できる問題」として、空気抵抗力が存在する放物運動を対象として物理的な運動を学習させています。前回は、空気抵抗力が存在する放物運動の軌跡から粘性抵抗係数を学習させ、うまく学習できることを確認しました。そこで今回は、空気抵抗力として粘性抵抗力に加えて速度の2乗に比例する慣性抵抗力が存在する運動の軌跡から、粘性抵抗係数と慣性抵抗係数を学習させてみます。

重力+空気抵抗力による物体の加速度ベクトル

$\mathbf{a}(t)= -\left( \frac{\gamma}{m}+ \frac{\beta}{m}\,|\mathbf{v}(t)|\right) \mathbf{v}(t) + \mathbf{g}$

$\gamma$が粘性抵抗係数、$\beta$が慣性抵抗係数です。数値計算については「【ルンゲ・クッタで行こう!】放物運動シミュレーション」を参照ください。

ニューラルネットワークの基本パラメータ

・ニューラルネットワークの構造:順伝播型ニューラルネットワーク(FFNN)
・学習方法:通常の勾配法(学習率固定、逆誤差伝搬法)
・学習率:eta = 0.01;
・ミニバッチ数:100 (サンプルは無限に用意できるためミニバッチという概念は存在しませんが、ランダムに用意したミニバッチ数分のサンプルに対する平均を用いて学習を進める)
・活性化関数(中間層):ReLU(ランプ関数)
・活性化関数(出力層):恒等関数
・損失関数:2乗和
※独立したネットワークを10個用意してそれぞれ個別に学習させて、学習効果の高かった上位5つの「学習回数」vs「損失値」をグラフ化します。

中間層1層のニューラルネットワーク(200-200-2)

学習回数に対する損失値

100,000回学習後のチェック

慣性抵抗係数を0.5、粘性抵抗係数を0, 0.5, 1.0, 1.5として、投射角度を0°から90°までそれぞれ計算した軌跡データからニューラルネットワークが推定した空気抵抗係数の値。 もし完璧に学習できていれば、それぞれ横一線になります。

学習がうまく行かなかったので、学習データの与え方を工夫してみます。これまで学習ごとにそれぞれ全くランダムに与えていた粘性抵抗係数と慣性抵抗係数のうち、慣性抵抗係数の与え方を変えます。具体的には、1回の学習は100回(ミニバッチ数)の平均で行っているので、この100回の慣性抵抗係数を0~1を等間隔に与えます。その結果が次図です。

中間層1層のニューラルネットワーク(慣性抵抗係数の与え方を工夫)

学習回数に対する損失値

100,000回学習後のチェック

慣性抵抗係数を0.5、粘性抵抗係数を0, 0.5, 1.0, 1.5として、投射角度を0°から90°までそれぞれ計算した軌跡データからニューラルネットワークが推定した空気抵抗係数の値。 もし完璧に学習できていれば、それぞれ横一線になります。

これでも全然だめなので、少し学習条件を緩和します。これまで、初速度は0~30までランダムで運動させていましたが、これを緩和して初速度を20で固定としてみます。その結果が次図です。

中間層1層のニューラルネットワーク(初速度を20に固定)

学習回数に対する損失値

100,000回学習後のチェック

慣性抵抗係数を0.5、粘性抵抗係数を0, 0.5, 1.0, 1.5として、投射角度を0°から90°までそれぞれ計算した軌跡データからニューラルネットワークが推定した空気抵抗係数の値。 もし完璧に学習できていれば、それぞれ横一線になります。

初速度を固定することで学習は進むことは確認できましたが、100,000回程度ではまだまだといった形です。

考察と次の課題

・運動の軌跡から直接粘性抵抗係数と慣性抵抗係数を学習させることは難しそう。
→ 速度データを加えることで可能になるかもしれないので、試してみる。
・指定したパラメータに対する飛距離を学習させてみる。

プログラムソース(C++)

http://www.natural-science.or.jp/files/NN/FFNNs_epoch_ProjectileMotion_AirResistance.zip
※VisualStudio2017のソルーションファイルです。GCC(MinGW)でも動作確認しています。