GMOグローバルサイン・ホールディングスCTO室のZulfazli@zulfazlihussinです。
私はhakaru.aiの開発チームにてAI開発を担当しております。今回は、強化学習の手法の中で、方策を学習する手法の一つであるProximal Policy Optimization(PPO)を実装してみたいと思います。
強化学習について
強化学習は、与えられた状況に対して最適な行動を選ぶための学習を行い、報酬を最大化することです。エージェント(学習モデル)が状態に基づいて行動を選択し、その結果として報酬が与えられます。エージェントは報酬を最大化するために、環境との相互作用を通じて学習を進めます。ここで、環境、状態、行動、報酬、方策の意味は下記で説明します。
- 環境(Environment): エージェントが操作する対象となる外部の環境です。例えば、ゲームの世界、ロボットの制御対象などが環境として考えられます。
-
状態 (State): エージェントと環境の相互作用によって得られる情報です。例えば、ゲームでの現在の画面の状態や、ロボットでのセンサーからの情報などが考えられます。
-
行動 (Action): エージェントが状態に基づいて選択する行動です。例えば、ゲームでの駒の移動や攻撃の選択、ロボットでの特定の動作などが考えられます。
-
報酬 (Reward): エージェントが行動した結果として得られる数値的なフィードバックです。報酬には、エージェントの目標に合致するような行動に対して、より高い報酬が与えます。
-
方策 (Policy): エージェントが状態に基づいて行動を選択するための戦略です。方策は、与えられた状態においてどのような行動を選ぶかを決定するための関数やアルゴリズムとして定義されます。
エージェントは、ある状態で行動を選択し、環境に対する反応を観測し、報酬を受け取ることを繰り返し行います。このプロセスを通じて、エージェントは報酬を最大化するために最適な行動戦略を学習します。目標は、エージェントが報酬を最大化するための最適な行動ポリシーを見つけることです。
どんな手法があるのか?
強化学習の代表的な手法には、Q学習、SARSA、DQNなどがあります。
Q学習[1]は、状態と行動のペアの価値 (Q値) を学習するため、選択できる状態と行動が比較的少ない場合に適しています。例えば、迷路のような環境を解く場合に使用されます。迷路内の各位置に一意の番号を割り当てます。行動は ’上’: ’U’、’下’: ’D’、’左’: ’L’、’右’: ’R’のように記号で表します。迷路内の壁や障害物によって移動が制約される場合、エージェントは壁にぶつかったり、行き止まりに遭遇したりしないように最善の行動を選択します。エージェントは最短経路を見つけるために方策を学習し、最も報酬の高い行動を選択することによって、効率的にゴールに到達することが目指されます。
SARSA[2]はQ学習と同じように、状態と行動のペアの価値によって、次の行動を選択しますが、SARSAでは現在の行動と次の行動を両方考慮して行動を選択します。例えば、現在の方策で選択した行動で次の行動も選択します。迷路のタスクで、次の行動が壁に突き当たる場合、現在の行動で選択する確率が低くなります。
DQN(Deep Q-Network)[3]は、画像などの高次元の入力データを処理し、次の状態でのQ値が最大になるように、現在の行動価値関数を表すQ値を更新し行動を選択します。DQNは、Atariゲームやロボット制御など、視覚情報が重要な場合に特に有用です。例えば、Atariゲームにおいて、画像フレームからゲームの進行状況、キャラクターの位置、敵や障害物の位置などを含んでいます。これらの情報は、エージェントが現在の状況を把握し、ボタンを押す、レバーを引く、方向キーを押すなど適切な行動を選択します。
Proximal Policy Optimization(PPO)の手法について
もう一つの有名な手法はProximal Policy Optimization(PPO)[4]の手法です。PPOはDQNの手法と違って、次の状態を参考せず、過去に収集したデータ(状態)を元に、最適な行動を選択するための方策確率の関数を勾配法で更新します。PPOでは、現在の状態から各行動の方策確率を推定し、最適な行動を選択します。このように、エージェントは環境との相互作用を通じて自己学習を進めていくのです。今回はPPOに着目して、実装してみたいと思います。
PPOで強化学習を実装する
今回はPythonで簡単に実装できる強化学習用シミュレーションライブラリ OpenAI Gym を使って実装します。このライブラリを使って、カートに取り付けられた可動用具(pole)の環境(CartPole)を利用します。CartPoleでは取り付けられた可動用具(pole)を垂直に保つように、水平に移動できるカートを左右に動かせます。左右の移動に適切な制御をすることで、poleをバランスよく立てたままにすることを目指します。
CartPoleの環境では、エージェントが現在の状態を観測し、適切な行動を選択する必要があります。具体的には、poleが倒れかけた場合、バランスを保つためにカートを逆方向に動かす必要があります。エージェントが観測する状態はカートの位置、カートの速度、poleの角度、poleの角速度になります。gymで定義したCartPoleの環境を実装してみましょう。
import gym
from from pyvitualdisplay import Display
from gym.wrappers.monitoring.video_recorder import VideoRecorder
#学習環境設定
config = {
"env":"CartPole-v0", # 環境の名前
"framework":"torch", # 使用するpythonのフレームワーク
"model":{
"fcnbet_hiddens":[32], # 隠れ層のニューロンの数
"fcnet_activation":"linear" # 活性化関数
}
}
#テスト環境設定
env = gym.make("CartPole-v0")
# アクションは2つあります → 0 : 右を押す、1:左を押す
env.action_space
学習する前に、カートとpoleはどんな動きになるか見てみましょう。
display = Display(visible = False, size = (1400,900))
display.start()
# 学習前の動画を保存できるようにするために、初期設定
before_training = "before_training.mp4"
video = VideoRecorder(env, before_training)
# 環境の初期化
env.reset()
# 1000回のステップで実行し、動画として保存
for i in range(1000):
env.render()
video.capture_frame()
# observation = カートの位置、速度、ポールの角度、角速度
observation, reward, done, info = env.step(env.action_space.sample())
video.close()
env.close()
こちらでは実行した結果になります。結果で示しているように、ランダムで右と左へ移動させると、カートが不安定になり、バランスが取れず、画面外へ行ってしまいました。
カートが安定するようにするためには、方策をPPOで学習していきます。方策はどれぐらいpoleの角度、または、角速度でカートを右、または、左へ移動しないといけないのかということです。最適な行動を選択するための方策をPPOで学習していきます。
今回は RLlib のライブラリを使って、PPOで学習していきます。RLlibはPython向けの強化学習ライブラリです。RLlibは Ray という分散処理ライブラリ上で構築されており、スケーラブルなプロセスが可能で、大規模な強化学習タスクを処理することができます。
# PPOをimportする
import ray
from ray.rllib.algorithms.ppo.ppo import PPO
# 学習
ray.init( num_cpu = 3, include_dashboard = False, ignore_reinit_error = True, log_to_driver = False)
analysis = ray.tune.run("PPO", config = config, checkpoint_at_end = True)
# 学習後のパラメータを取得
trial = analysis.get_best_logdir("episode_reward_mean","max")
checkpoint = analysis.get_best_checkpoint(trial, "training_iteration", "max")
trainer = PPO(config = config)
trainer = restore(checkpoint)
# 学習後の動画を保存できるようにするために、初期設定
after_training = "after_training.mp4"
after_video = VideoRecorder(env, after_training)
observation = env.reset()
# 学習後のアクションを動画で保存
done = False
while not done:
env.render()
after_video.capture_frame()
action = trainer.compute_single_action(observation)
observation, reward, done, info = env.step(action)
after_video.close()
env.close()
学習後のアクションは下記になります。動画で分かるように、いい感じでバランスが取れていました。カートの左右の移動の制御が上手にできたのではないでしょうか。
終わり
ここで、この記事は以上になります。
最後までお読みいただきましてありがとうございました。