💭

深層強化学習を用いたロボット制御

に公開

0. 必要な技術・環境(学べる事)

・強化学習の基本理解
・深層学習の基本理解
・制御工学の知識、経験
・深層強化学習の理解

環境はHP Pavilion Aero 13bgを用いている。購入して10か月でマザーボードがいかれた。PCが悪いのか使い方が悪いのかは不明だが怖いのでそろそろデスクトップPCに移行したい。

1. はじめに

1.1 なんで深層強化学習?

ただの身の上話なので飛ばしても問題ないです。

近年4脚歩行ロボットや人型ロボットの隆盛が目まぐるしい。アメリカや、特に中国の技術進歩はとんでもない。私は高専時代の研究室に丁度Unitree Go1が納品され、4脚ロボットに胸が躍った。しかしその制御には逆運動学やPID制御のような古典制御が含まれてはいるが、メインとなっているのは現代制御、特に深層強化学習であった。そんなことを思っていたタイミングで東京大学の松尾研究室が主催されている「深層強化学習 Deep Learning 応用講座2024」に参加し、深く知ることが出来たおかげでより深く学ぶ意欲がわいた。また同時に友人と一緒にロボットを作ろうという話になったためモチベーションが最高潮に達し、今に至る。

1.2 本記事の目的

深層強化学習への学びが深まってきたこともあり、順序立てて学習内容をまとめたいと思い執筆している。またポートフォリオに含む内容として自分のスキルとして明確になるという理由もある。

1.3 制作の目標と開発フロー

深層強化学習を活用したロボット制御の目標は深層強化学習を理解し、独力で実装まで出来るようになることである。具体的には4脚歩行ロボットの制御を達成する。細かい達成目標はスクラップにまとめているので、気になる方はこちらをご覧ください。

次に開発のフローを示す。

  1. 深層強化学習の概要を体系的に理解する
  2. 深層強化学習のベースとなるQ学習およびDQN(Deep Q Network)について理解し、実装を通して理解を深める。
  3. ロボット制御に広く用いられているPPOについて理解し、を通して理解を深める。
  4. 必要に応じてPPOの派生手法を試す。
  5. 実機に反映させ、Sim2Realについて理解を深める。

以上のフローにもとづいて制作を進める。

2. 深層強化学習の概要

フローに従って章立てしていく。本章では深層強化学習(以降DRLとする:Deep Reinforce Learningの略)を体系的に理解するために深層学習、強化学習、深層強化学習それぞれについて概要をまとめる。

2.1 用語について

つもりでいたが深層学習や強化学習単体はいろんなサイトに十分まとまっているためほとんど割愛し、ここでは深層強化学習に必要な用語を再確認するだけにとどめる。

用語 説明
パラメータ ネットワークの構造を表す変数。重み値の集合?
エピソード 観測を始めてから観測をやめるまで。一定時間経過もしくは
報酬の条件達成(終了条件含む)が区切り
ホライズン 1エピソードの長さ。1000秒や1000回など
学習率 NNの各パラメータ更新に際して、1回当たりパラメータの大きさをどれだけ変化させるか
報酬 学習する際に、目的の動作の達成具合に応じて与える褒美。パブロフの犬みたいなもん。
価値関数 観測と行動を変数として持ち、将来的に得られる報酬の期待値を計算する関数
方策(Policy) 状態空間から観測した情報から次の行動を決める関数
最適方策 学習した結果、報酬が最適化されると見込まれた方策。価値関数が最大となる方策。
割引率 値が小さいほど、近い未来の結果を重視する
貪欲方策 方策更新において最適方策をとり続ける手法。過学習を起こすためε-貪欲方策が主。
ε-貪欲方策 確率εでランダムな行動をとる方策更新手法。εはランダムな行動をとるごとに小さくする
バイアス 予測値と真値とのずれ
バリアンス 過学習度合い(モデル依存性)。バイアスとバリアンスは基本トレードオフ
オンポリシー学習 学習に使うデータ(経験)が常に現在学習中の方策(policy)に従って得られる
オフポリシー学習 学習に使うデータが別の方策から得られていても構わない。比較

またNN(ニューラルネットワーク)について軽くまとめる.NNは以下の3つの層に分かれている.

  1. 入力層:必要な情報(画像:ピクセルデータ,倒立振子:位置・速度・角度・角速度 etc)
  2. 中間層:入力層から特徴量を抽出していく過程.一般的に2層以上の中間層を持つ.隠れ層ともいう.
  3. 出力層:分類問題なら各事象の生起確率.回帰問題なら目的関数が一般的.
    あるいはその他必要なデータを取得することも可能?

さてここでややこしいのが中間層である.第一にハイパーパラメータが多い.ニューロン(ノード,ユニットとも言う)や層の数はハイパーパラメータであるため,新しい事象を学習させたい場合,しらみつぶし(あるいは何かしらの手順に則って)にハイパーパラメータを調整する必要がある.一般的に総数を増やすほど精度は上がるが,演算速度やメモリの問題が生じる.また過学習といった問題にも注意が必要である.層にもいろいろ種類があるので以下にまとめる.ただ、数値パラメータから学習をするだけなら全結合層だけで事足りることは多い。またユニット(重み空間の広さ)は学習速度と表現力のトレードオフ、層の深さは学習速度と複雑なタスクへの対応力のトレードオフになっている。

全結合層
最も基本的な結合層.1つ1つのノードが次の層の全てのノードとつながっている(重みをつけられて伝播している).

畳み込み層
大きなデータを(K個のカーネルに)分割し,それぞれのデータから局所的な特徴量を抽出する層.画像の分析に多く用いられるが,時系列データや音声データなどの入力にも対応できる(らしい).ノイズがよく混じるのでReLU関数を畳み込み層の後に入れるべき.

プーリング層
畳み込み層で得られた特徴データを集約するための層.畳み込み層はデータ量が一気に増えるので,重要な特徴量のみを得る必要があるため分割データそれぞれの解像度を下げるイメージ.詳細はこちら

正規化層
バッチ単位や層単位で正規化する層.平均が0,分散が1となるように正規化する.したがって活性化関数とは少し違う.

ドロップアウト層
毎エポック(学習回数)に隠れ層の出力を一定割合でランダムにドロップする(無視する)ための関数.

活性化関数
1ノードに対して1ノードの出力をする層というか関数.出力された特徴量をはっきりさせる役割を持つ.基本的には隠れ層1層ごとに活性化関数を挟むことが多い.

2.2 深層強化学習の体系

ひとくくりに深層強化学習といっても、そのアルゴリズムには種類がいろいろある。大別するとオフポリシーかオンポリシーか、行動が離散値か連続値か(=価値ベースか方策ベースか)などあるが、ここでは主要なアルゴリズムについてのみまとめる。

2.2.1 離散値制御アルゴリズムの体系

まず離散値制御アルゴリズムのベースになっているのはQ学習である。マルコフ決定過程かつ状態空間集合全て(つまり起こりうるあらゆる状態)とそれに対する報酬が分かっていれば、価値反復法を用いることで最適方策を求めることが出来る。これに対してQ学習は状態空間集合全て(つまり起こりうるあらゆる状態)とそれに対する報酬が分かっていなくても、関数近似を行い、また逐次的にサンプル数を増やすことで最適方策に収束させることが出来る という考えに基づいたアルゴリズムである。
しかしこれには問題がある。それはQ学習は全ての状態と行動に対する価値としてQ値を持つ。つまり状態と行動の種類が増えれば増えるほど、このQ値の総数(Q行列の大きさ)は増える。そのためテレビゲームやロボット制御ではメモリの限界が来てしまう。そこでQ学習に深層学習の概念を導入したのがDQN(Deep Q Network)である。さらにDQNは学習を安定させるためにターゲットネットワークと**経験再生(リプレイバッファ)**を導入した。ターゲットネットワークとは計算時の比較対象を一定期間固定することで計算を安定させる方法である。経験再生とは方策にあたえる観測情報を過去の観測から再利用する方法であり、リプレイバッファとは過去の観測を補完するデータセットを指す。

DQNからの派生

さらにこのDQNは発表されてから5年の間でどんどん改良されていった。DQNのターゲットネットワークの中にもう1つターゲットネットワークを用いることで計算に冗長性を持たせたDouble DQN、学習効果の高い経験ほど優先度を高くしたPER、状態と行動を分けて監視することで効率化と微小変量への適応能力を持たせたDueling Network、Q値の改善ではなく収益の分布を均一化するようにしたCategorical Network(ようわからんかった。)、ノイズを与え続けることでデータの偏り(過学習)を抑えたNoisy Networkなどが生まれた。そしてそれらを統合し、1つのアルゴリズムに集約したのがRainbowというアルゴリズムである。Rainbowは上記以外にもう1つ、Multi Step Learningを取り入れた。これはマルチステップ先の行動に対する評価、つまり1ステップ先だけでなく数ステップ先までの報酬をトータルで評価するようにされた。

ここまでが基本的なQ学習からの派生であり、離散値制御アルゴリズムの主な手法である。

2.2.2 連続値制御アルゴリズムの体系

次に連続値制御アルゴリズムについてである。このベースになっているのはActor-Critic法と方策勾配法の2つである。

Actor-Critic法とは

Actor-Critic法は文字通り「行動するもの」と「批評するもの」によって成り立っている。またこの手法はQ学習のような価値関数ベースの手法と、次の章で述べる方策勾配法ベースの手法を組み合わせたようなアルゴリズムである。価値関数ベースの手法は安定した学習が可能である一方で複雑な問題や連続的な行動空間への対応が難しい。一方で方策勾配法ベースの手法では複雑な問題や連続的な行動空間に対応できるが学習が不安定になり易い。このメリットとデメリットを補い合うのがActor-Critic法である。
行動するものが方策による行動選択と状態空間の観測、批評するものがとった行動と観測情報、そして報酬から価値関数によって行動(方策)を評価する。この評価は将来得られる報酬の予測値:マルチステップ的な評価と実際に得られた報酬の差分を基に計算される。そしてこの評価に基づいて行動するものの方策が更新されることで適応をしていく手法である。

方策勾配法とは

従来の強化学習(Q学習など)では行動空間が有限にしか対応しておらず、また価値関数を最適化することで最適な方策を探す手法である。それに対して方策勾配法は価値関数ではなく直接最適な方策を探す手法である。これによって計算コストが削減され、より広い行動空間への対応が可能になる。
また方策勾配法が従来の強化学習と異なったのは「マルチステップ先の行動に対する評価」を取り入れることである。たとえばQ学習で使われる貪欲方策は1ステップ先の報酬が最大となる方策を選択する。しかしこれではトータル報酬が下がることがままある。将棋の戦略を考えたら分かり易いかもしれない(ここでは割愛)。方策更新と同様に方策評価もマルチステップ化することでより精度の高い強化学習を実現することが出来る。一方で評価と交信を行うステップ数を大きくするほど計算が複雑になるという課題がある。
そこでREINFORCEというアルゴリズムは方策勾配法のの方策評価にモンテカルロ近似を導入することで計算量を減らした。モンテカルロ近似によってt=0~∞までの勾配を近似される...らしい。しかしこのアルゴリズムだと勾配計算をする代償としてバリアンスが大きくなりすぎる欠点があった。そこで評価する際にλ方策評価という手法を取り入れた。これはλ^t(0≦λ≦1)の重みを用いて、より遠い未来の結果から得られる報酬ほどその影響を小さくするというものである。これによって過度なバリアンスを防ぐことが出来る。また経験則としてアドバンテージ関数がよく併用される。
そしてこのアドバンテージ関数を計算する際のノイズを低減するのがGAE(Generalized Advantage Estimation)である。
https://deus-ex-machina-ism.com/?p=70804
しかしここまできてもまだ学習の不安定性が問題だった。ある程度順調に学習が進んでも途中でいきなり性能がガクンと落ちることがアルゴリズムの性質上起こり易かった。そこで導入されるのが自然方策勾配法である。これは単調な性能向上をさせるために方策更新に制約を設けたものである。

3. DQN(Deep Q Network)の実装

開発過程はこちら

3.1 CartPole-v1を立たせる

Gymnasium(以降Gymとする)に標準搭載されているCartPole-v1を立たせる.そのために必要な要素を以下にまとめる.作成したプログラムはこちらのGithubページに公開する.
また本ページはこちらの記事を参考にさせていただいた.

以下本文

環境の準備

今回はGymが提供してくれているのでそれを導入するだけ.以下はランダム出力で倒立振子を制御するプログラム.1Episodeをリアルタイムで描画する設定.報酬は逐次書き換えられるのでトータル報酬を定義する必要がある.とは言えこれだけで簡単な描画が出来るのだから素晴らしい.
レンダーにhumanをを採用しているが学習が非常に遅くなるので要注意.

実際のコード
'''
observation:
 ([カートの位置,カートの速度,ポールの角度,ポールの角速度],reward, 終了条件×2,{Info})
(array([ 0.017, -0.01 ,  0.002, -0.01 ], dtype=float32), {})

rewardは常に1.rewardの累計を大きくするのが目標

'''
import gymnasium as gym
import numpy as np
import time

env=gym.make('CartPole-v1',render_mode='human')
total_reward = 0
(state,_)=env.reset()


def now_policy(state):
    time.sleep(0.1)  # Sleep for 100ms to slow down the rendering
    state = int(np.random.randint(0, 2))
    if state >= 1:
        action = 1
    else:
        action = 0
    print(state)
    return action

episode_over = False
while not episode_over:
    action = now_policy(state)
    observation, reward, terminated, truncated, info = env.step(action)
    episode_over = terminated or truncated
    print(observation, reward, terminated, truncated, info)
    total_reward += reward

print(total_reward)
env.close()

Q-Network

Q学習たる所以であるQ値を更新するネットワーク.状態(カートの位置,カートの速度,ポールの角度,ポールの角速度)が入力データ,価値関数Q値が出力データ.ここで問題となるのがハイパーパラメータである.今回のような条件だと入力データが小さくタスクもシンプルであるため2~3層で十分である.また画像や時系列データを扱う必要がないので今回は全結合層のみで問題ない.ユニット数は64,128,256が多いので,今回は64で試す.活性化関数はとりあえずReLUで良い.これで必要な要件が決定したのでQ-Networkを実装する.

実際のコード
# Q値を出力するためのニューラルネットワーク
class N_Network(nn.Module):
    def __init__(self):
        super().__init__()
        self.l1 = nn.Linear(parameters["input_size"], 128) # 入力4次元 → 隠れ層128ユニットへの全結合層(例:観測が4次元のとき)
        self.l2 = nn.Linear(128, 128)
        self.l3 = nn.Linear(128, parameters["action_size"])

    # この関数を実行すれば深層学習が出来る
    def forward(self, x):
        x = F.relu(self.l1(x))
        x = F.relu(self.l2(x))
        x = self.l3(x)
        return x

T-Network

Q学習の問題である不安定性を解消するためのネットワーク.Q学習では毎回正解ラベルが変わるため学習が不安定になる.そこで正解ラベルを定期的に更新する(毎回更新しない)ことで学習を安定させる.これはQ-Networkと構成が一緒なので,ループ中に更新作業を加えるだけで良いため実装なし.

経験再生(Experience Replay)

DQN(Q学習)はマルコフ決定過程に基づいている.そして時系列順にエピソードを繰り返すと現状態と1Horizon先の状態以外にも影響を受けてしまう.これはマルコフ決定過程ではないので,時系列順ではなくランダムにデータを入力する.リプレイバッファに必要な機能は以下の3つ.
1.入力データの収集
2.決められたbatch size分の入力データをランダムに取得
3.PyTorch用のTensor(テンソル)に変換

実際のコード
class ReplayBuffer:
    # バッファーの定義,バッチサイズの代入
    def __init__(self, buffer_size, batch_size):
        self.batch_size = batch_size
        self.buffer_size = buffer_size
        self.buffer = deque(maxlen=buffer_size) # dequeはリストのようなもの

    #関数によっては__len__()という関数が内部で知らないうちに使われる)
    def __len__(self):
        return len(self.buffer)

    # フィードバック[カートの位置,カートの速度,ポールの角度,ポールの角速度]を取得しリプレイバッファに保存.
    # 溢れたら古いデータを削除.ここでの経験は[状態,行動,報酬,次の状態]の4つ
    def add(self, experience):
        self.buffer.append(experience)

    # バッファーからランダムにバッチサイズ分のデータを取得
    def sampling(self):
        datas = np.random.choice(self.buffer, self.batch_size, replace=False) # batch_size分のデータをランダムに取得
        
        # データを分割してそれぞれの変数に格納
        state = torch.tensor(np.stack([x[0] for x in datas]))
        action = torch.tensor(np.array([x[1] for x in datas]).astype(np.int64))
        reward = torch.tensor(np.array([x[2] for x in datas]).astype(np.float32))
        next_state = torch.tensor(np.stack([x[3] for x in datas]))
        done = torch.tensor(np.array([x[4] for x in datas]).astype(np.int32))
        return state, action, reward, next_state, done

方策の決定

方策とは,ある状態においてどのように行動を決定するかのルールである.方策の代表例として最適方策がある.これは価値関数に基づき,現在の状態で最適だと算出される行動を常に選択する方策である.しかしこれだと1手先しか考えておらず,「その場しのぎの最善」でしかない.そこで時々ランダムな行動を混ぜることで学習のバイアスを改善する手法がある.これをε貪欲方策という.今回はこれを採用する.

実際のコード
# ε-greedyポリシーに従って行動を選択
def select_action(self, state):
    if np.random.rand() <= self.epsilon:
        # εの確率でランダムな行動を選択
        return self.env.action_space.sample()
    
    # 1-εの確率で最適方策に基づいて価値関数を更新
    else:
        state = torch.FloatTensor(state).unsqueeze(0) # PyTorchのTensorに変換+バッチ形式に対応
        with torch.no_grad(): # 勾配計算を無効化
            return self.q_net(state).argmax().item()

パラメータ調整について

DQNで用いているハイパーパラメータは以下のとおりである。用語の詳細は本記事の2.1章にまとめてある。

    "sample" : {
        "lr": "学習率",
        "gamma": "割引率",
        "episodes": "学習エピソード数",
        "epsilon": "ε-greedy法の初期ε値",
        "buffer_size": "リプレイバッファのサイズ",
        "batch_size": "ミニバッチのサイズ",
        "td_interval": "ターゲットネットワークの更新間隔",
        "input_size": "入力サイズ",
        "action_size": "行動サイズ",
        "max_step": "1エピソードあたりの最大ステップ数"
    }

ネットワークの学習

ここが深層学習のメインといっても過言ではない.ニューラルネットワークの活用には「学習」と「出力の計算」の2つがある.
出力の計算とは,ただ入力データからネットワークを順伝搬して出力を計算することである.(N_Networkのforward関数に相当する)

一方で学習とは,損失関数をもとにニューラルネットの中にある重みを調整する過程である.DQNの場合,損失関数はTD誤差(QnetworkとTarget-networkのQ値の差)と平均二乗誤差を用いる.またこの損失関数をもとに誤差逆伝搬法によって勾配が計算し,それに基づいて重みをする.正直深層学習の詳細はなんとなくなのでまた勉強する.

この学習過程をまとめたコードを以下に示す.

実際のコード
def calc_TDerror(states, actions, next_states, rewards, dones):
    # QネットワークとターゲットネットワークからQ値を取得(TD誤差を求めるため)
    actions = torch.LongTensor(actions).unsqueeze(1)  # [batch_size] → [batch_size, 1]
    q_values = Qnet(states) # → Q(s_t, ·) 全アクションのQ値を出力(形状:[batch_size, action_dim])
    # print(q_values, action)
    q_value = q_values.gather(1, actions).squeeze() # actionに対応するQ値を出力(形状:[batch_size]

    with torch.no_grad():
        next_q_max = Tnet(next_states).max(1)[0]
        q_value_target = rewards + (1 - dones) * parameters["gamma"] * next_q_max # Q値のターゲット値をベルマン方程式 に従って計算

    # Q値から価値関数とTD誤差を計算.TD誤差を最小化するようにQネットワークのパラメータを更新する
    loss = torch.nn.MSELoss()(q_value, q_value_target)

    # 深層学習のルールに従ってQネットワークのパラメータを更新
    optimizer.zero_grad() # 勾配を初期化
    loss.backward() # 誤差逆伝播法で勾配を計算
    optimizer.step() # Qネットワークのパラメータ(重み)を更新

コード全体

上記のコードをまとめ,ハイパーパラメータも追加したものを完成次第,Githubに公開する.(URLはページトップに記載)
また以下に学習結果を示す.安定していることが分かる.

学習した結果を制御に用いるには

さて,学習はこれで完了したがこのままでは本題の倒立制御が出来ていない.学習過程で倒立制御の「実験」はしてきたが,やりたいことは学習結果の「運用」である.
ということで学習結果(ネットワークの重みパラメータ)をPytorchの専用形式でファイルとして保存する.

try:
    torch.save(Qnet.state_dict(), MODEL_SAVE_PATH)
    print(f"モデルの重みを {MODEL_SAVE_PATH} に正常に保存しました。")
except Exception as e:
    print(f"モデルの重みの保存中にエラーが発生しました: {e}")

あとはこのパラメータをQネットワークにコピーして,stateをネットワークに入力すれば最適な行動actionが出力される.このとき学習はせず順伝搬をするだけであることに注意する.
出力用のファイルも上記のGithubページに公開する.

ランダム方策の重要性について

上記にないTipsとしてε減衰というものがある.これはε貪欲方策に用いるεを,ステップが進むにつれて小さくしていく手法である.最初は探索範囲を広げるためにランダムに行動した方が効率的だが,ランダム行動が多すぎると報酬を大きくするのが難しい.一方でεが最初から最後まで小さいままだと学習のバイアスが大きくなり過学習を起こしやすくなる.そこで最初のうちの幅広く探索を行い,ある程度探索が進んだらより報酬を最大化することに注力するように設計したものがε減衰である.


図:ε減衰をしなかった場合の学習


図:ε減衰をした場合の学習

3.2 MJCFモデルによる倒立振子を導入する

3.1で出来たことをそのまま流用する.ロボットモデルとシミュレーション環境,Gym.Envの変更をする.Geminiに作って頂いたものを調整したモデルを使用した。コードはこちら

以下本文

gym.envとwrapperの変更

まずは報酬と行動空間の変更を以下のように行う.報酬は現在の位置と角度を考慮し,角度の重みを大きくする.行動空間については右に押すか左に押すかしか決定できなかったため,これを-1から1にする.-1~0の間であれば左に,0~1の間であれば右にカートを動かすように設定する.またDQNは離散値しか計算できないので,内部的に処理を離散化する必要が生じる.分解能をとりあえず11としていたが、試行錯誤した結果分解能が低すぎたため学習が停滞する現象に陥った。計算負荷も体感では大きくならないので1023くらいにするべきだった。報酬はまあいい感じに調整しよう。僕は振動が大きすぎる結果になったのでトルク抑制の報酬項を追加した。

変数 変更前 変更後
reward 1 -(位置×0.2 + 角度×0.8)
action Discrete(11) {0, 1} [-1, 1]

https://gymnasium.farama.org/introduction/create_custom_env/

Wrapperの作成

Wrapperに必要な要素は以下のとおりである。

Gym環境に必要な要素
1.観測空間の正規化:   倒立振子の位置、速度、角度、角速度を観測
2.報酬調整:          現在の位置と速度から報酬を決定
3.終了条件の調整 :    一定回数が経つor位置・角度が一定値以上になる
4.離散化(for DQN):  入力(台車の移動速度)を離散化する
5.フレームスキップ:  全てのステップを計算していると時間がかかる+実空間では処理間隔が生じるためデータ量を間引く
6.レンダリング設定

mainプログラムで呼び出すのはreset(), step(), close()のみ。それ以外はstep()に含まれる。

これをもとにWrapperを作成する。

パラメータ調整について

前述したが、DQNで用いているハイパーパラメータは以下のとおりである。現状ハイパーパラメータはChatGPTやGeminiと二人三脚で調整しているが、上手くいかないのでそれぞれのパラメータについて詳しく考えてみる。

    "sample" : {
        "lr": "学習率",
        "gamma": "割引率",
        "episodes": "学習エピソード数",
        "epsilon": "ε-greedy法の初期ε値",
        "buffer_size": "リプレイバッファのサイズ",
        "batch_size": "ミニバッチのサイズ",
        "td_interval": "ターゲットネットワークの更新間隔",
        "input_size": "入力サイズ",
        "action_size": "行動サイズ",
        "max_step": "1エピソードあたりの最大ステップ数"
    }

今まで起こった問題は以下のとおりである。
・そもそも学習が進まない
⇒離散化の分解能が小さすぎた
・学習が遅い
⇒初期εが小さすぎてランダム行動が多すぎた
・学習が途中まで順調に進むが、途中からいきなり質が落ちて停滞する
⇒リプレイバッファのサイズ、TN(ターゲットネットワーク)の更新間隔の問題
TNの更新間隔は短くするほど学習が早くなるが、不安定になり易い。
本来はPER(優先度付き経験再生)を導入するべき。
・stepが増えるほど振れ幅が大きくなる現象に陥る
⇒学習率が高すぎて過学習を起こしている

4. PPOの理解とシミュレーションの実装

4.1 PPOの理解

以前スクラップにメモったものをここにまとめなおす。

PPOの歴史と概要

PPOとはProximal Policy Optimizationの略であり、日本では近似ポリシー最適化と言われたりしている。PPOはActor-Critic法と方策勾配法から派生した深層強化学習アルゴリズムであり、方策ベースで連続制御を行うことが出来るため、ロボット制御に良く応用されている。ベースとなるのはActor-Critic法と方策勾配法であり、自然方策勾配法にActor-Criticのシステムを導入することで、なるべくステップ幅を大きくしたうえで単調な性能向上が実現されたのがTRPO(Trust Region Policy Optimization)である。しかしこの計算は非常に面倒である(ラグランジュの未定係数法を説き続ける)ため、より実装しやすくかつ性能を維持したのがPPOである。PPOは精度のわりに実装が簡単なのでロボット制御などの分野で幅広く使われているため優先的に勉強する。細かい計算や理屈は下記資料を参照。
https://www.andrew.cmu.edu/course/10-703/slides/Lecture_NaturalPolicyGradientsTRPOPPO.pdf

5. シミュレーションに導入

当初の想定ではOpenAI社が公開しているStable Baseline3のPPOライブラリをそのまま使えばいい感じに動くと考えていた。しかしその考えは甘すぎた。実際はそのPPOアルゴリズムをベースとして様々なテクニック(付加要素)を必要に応じて追加していかなければならない。そしてそのためにはPPOの中身、つまり計算過程とその目的を把握する必要がある。したがって本章ではシミュレーションに導入するための計算とそのコード、そして実際にシミュレーションを行った結果を示す。

詳細はこれからなので乞うご期待。

5.1 PPOの計算過程

5.2 実装

5.3 シミュレーション結果

6. PPOの派生手法の導入

7. Sim2Realについて理解を深める。

Discussion