本コンテンツでは、Pythonよる物理シミュレーション環境"PyBullet"および機械学習ライブラリ"PyTorch"を用いた車モデルの強化学習を行う方法を解説します。
PyBulletの導入と基本操作は、下のブログで紹介しています。
PyBullet / PyTorchのインストール
まずは、PyBulletとPyTorchそれぞれのインストール方法について解説します。PyBulletのインストールは、コマンドプロンプトから行います。コマンドプロンプトにて以下のコードを実行してください。
python -m pip install --upgrade pip
pip install pybullet
ひとつ目のコードでpipを最新状態にし、ふたつ目のコードでPyBulletをインストールすることができます。結果的に、"Successfully installed pybullet-(version)"が表示されれば成功です。
次に、PyTorchのインストール方法について解説します。PyTorchのインストールは公式ホームページを利用します。"PyTorch"と検索すると、公式ホームページがヒットします。はじめのページを下にスクロールすると、次のような表示が現れます。
それぞれの項目について、ご自身のパソコンに合ったものを選択すると、画像一番下の"Run this Command"にコマンドが表示されます。これをコピーし、コマンドプロンプトにペーストして実行することで、PyTorchをインストールすることができます。
ニューラルネットワーク
本コンテンツでは、ニューラルネットワークを用いた強化学習を行います。ニューラルネットワークは、人間の脳を模した仕組みとなっています。人間の脳は、生体ニューロンが信号を相互に伝達する構造になっています。下図に、生体ニューロンを示します。
生体ニューロンは大別すると、細胞体、樹状突起、軸索繊維、軸索末端から構成されます。
生体ニューロンが他の生体ニューロンと無数に組み合わさって構築されるのがニューラルネットワークであり、人間の脳の構造です。ニューラルネットワークの働きは、次のようになります。
① 樹状突起が前のニューラルネットワークから複数のシナプス入力を受け取る。
② 信号が細胞体から軸索繊維を通る。(軸索繊維は信号を通す回数が増えるほど太く強化され、信号を通しやすくなる。)
③ 軸索末端を通じて信号を処理し、次のニューラルネットワークに出力を伝える。
以上の構造を模したものが人工ニューロンです。人工ニューロンを下図に示します。
人工ニューロンは、樹状突起を入力信号x、細胞体をノードθ、軸索繊維を重みw、軸索末端を活性化関数Φおよび出力信号yと模倣します。人工ニューロンを組み合わせることで、人工ニューラルネットワークを構築します。
人工ニューラルネットワークの働きは、次のようになります。
① 前のニューラルネットワークから複数の入力xを受け取る。
② 入力の重要度に応じて重みwを加えたものを加算し、ノード(処理単位)θに伝える。
③ 加算後の値を活性化関数Φを通じて適切に変換し、出力値yを次のニューラルネットワークに伝える。
端的に言えば、人工ニューラルネットワークはとても複雑な関数と言えます。入力に対して得られる出力は、人工ニューロンの重みによります。適切な重みを学習することが人工ニューラルネットワークの目的となります。
しかし、適切な重みとはどのように学習するのでしょうか?それは、目標値と現在値の差(誤差)を最小化することです。下の図を見てください。
横軸が重み、縦軸が損失関数です。損失関数が最小のとき、誤差も最小となります。学習とは、損失関数の傾きが0、すなわちグラフの底に向かうように重みを更新していくことを指します。重みの更新には、誤差逆伝搬法を用います。
次に、ニューラルネットワークの層について解説します。ニューラルネットワークは人工ニューロンが集まった層と呼ばれる構造を持ちます。ニューラルネットワークの層は大まかに次のように分類できます。
入力層はデータが入力される層になります。すなわち、入力するデータの数だけニューロンを設定します。
中間層(隠れ層)はニューラルネットワークの表現能力を作る層になります。層数やノード数に応じて表現能力が上下するため、学習したい表現に応じて、適切に設定する必要があります。
出力層は結果を出力する層になります。すなわち、出力するデータの数だけニューロンを設定します。
活性化関数
表現の自由度をを上げる役割を持つ活性化関数Φを適切に設定することで、効率の良いニューラルネットワークを構築することができます。基本となる活性化関数を紹介します。
Linear関数
入力をそのまま出力します。回帰問題の出力層に用いられます。
PyTorch表記:nn.Linear(x, y)
ReLU関数
負の数を0とし、正の数をそのまま出力します。中間層で頻繁に用いられます。
PyTorch表記:nn.ReLU()
tanh関数
-1~1の範囲で出力します。中間層で用いられます。
PyTorch表記:nn.Tanh()
sigmoid関数
0~1の範囲で出力します。二項分類問題の出力層に用いられます。
PyTorch表記:nn.Sigmoid(x)
softmax関数
複数出力の合計が1になるように出力します。分類問題の出力層に用いられます。
PyTorch表記:nn.Softmax(x)
アルゴリズム
強化学習の流れを図に示します。
エージェントとは、学習を行う対象のことであり、本コンテンツでは車モデルを指します。
環境とは、エージェントと相互作用する対象のことであり、本コンテンツでは物理シミュレーション環境を指します。
学習の主体であるエージェントは、方策πを持ちます。方策とは、状態を与えたとき、行動を返す関数です。行動の結果として環境から返ってくる状態sと、状態sから設定する報酬rを利用し、最適な行動を学習します。
学習の際、根幹となるのは人工ニューラルネットワーク(ANN:Artifical Neural Network)です。人工ニューラルネットワークに特定の入力を加え、学習を進めることで、適切な出力を返せるようになります。
人工ニューラルネットワークの入力および出力の関係を図に示します。
入力には、障害物との距離を計測するLiDAR、車モデルの速度を用います。ニューラルネットワークを介して得られる出力は方策πです。
本コンテンツで行う強化学習の流れは、以下のようになります。
① エージェントを生成する。
② エージェントに入力を加え、出力である方策πに従って行動する。
③ 状態・行動・報酬を変数に保存する。
④ 10エピソードで1エポックとする。
⑤ 所定のエポック数、または条件を満たすまで②~④を繰り返す。
学習終了後、学習モデルを'model_weight'という名前で保存します。
ハイパーパラメータ
ニューラルネットワークによる学習において、あらかじめ人の手によって設定しておくパラメータをハイパーパラメータと言います。ハイパーパラメータには、具体的に以下のものが挙げられます。
① ニューラルネットワークの層数
② 損失関数の最小化アルゴリズム
③ 学習率
ニューラルネットワークの層数(①)を増やすことで、データ表現能力が上がりますが、結果的に得たい表現よりデータ表現能力が高すぎる場合、過学習を起こし、学習が上手く行きません。
損失関数の最小化アルゴリズム(②)を設定することで、損失関数の最小化方法を決定します。基本的にAdamを利用すれば問題ありません。
学習率(③)を設定することで、重みの更新を一度にどの程度変化させるかを決定します。値が高いほど学習のスピードが上がりますが、値が高すぎる場合、最適解を飛び越え、学習が上手く行きません。
実行結果
次の章で示すコードを実行することで、およそ1000~1500epoch程度で車モデルは壁との衝突をさけ、コーナーを曲がる動作を獲得します。
また、epoch-rewardグラフは次の通りです。