こんにちは、AI研究所の三谷です。
今回は、Pythonを使って強化学習をする方法について徹底解説します!
強化学習を始めてみたい!と言う方は是非参考にしてください。
無料で強化学習を試そう
強化学習とは、機械学習と言われるAI(人工知能)の手法の一つです。
強化学習によってAI(人工知能)は行動を手に入れると言われているように、いろいろな行動を試してみて、一番いい行動を探し出す(探索)するという学習をします。
強化学習は、最先端で難しそうに感じる強化学習ですが、実際に強化学習を無料で簡単に試すことができるようになっています。
いくつかのステップは必要ですが、是非強化学習を体感してみてください。
強化学習を試すための準備として、以下の作業が必要です。
- Pythonのインストール
- Pycharmのインストール
- ChainerとChainerRLのインストール
- OpenAI Gymのインストール
Pythonは、AI(人工知能)や機械学習の分野で一般的に使われているプログラミング言語です。
プログラミング言語だけでも開発は可能ですが、それを簡単で便利な環境で実行するのが統合開発環境です。
統合開発環境にはいくつか種類があり、今回ご紹介するPycharmを始め、Anacondaなども有名です。
さらに、強化学習をするためのフレームワーク(ライブラリ)としてChainerとChainerRLを使用します。
これらは、深層学習(ディープラーニング)や強化学習のアルゴリズムが実装されているため、数行のコードで深層強化学習を行うこともできます。
最後に、強化学習を行うためのシミュレーション環境がOpenAI Gymです。
強化学習は、どのような行動が最適なのかを見つけ出す学習方法ですので、実際に行動をしてみる実行環境が必要です。
OpenAI Gymでは、先述したブロック崩しのゲームなどを行うためのシミュレーション環境がすでに用意されています。
ここからは、これらのインストール方法を順に見ていきましょう。
Pythonとは?
Pythonは、オープンソースで開発されているフリーのプログラミング言語の一つで、プログラミング言語の中でも「スクリプト言語」と呼ばれています。
Pythonは可読性の高いプログラミング言語で覚えやすいことが特徴です。
Pythonは多くの企業で使われており、アプリやソフトウェアの開発、データサイエンス、IoTの分野、さらには近年注目されているディープラーニングといったAIを支える技術分野でも積極的に活用されています。
Pythonのバージョンについて
Pythonにはバージョン2系とバージョン3系の2つのバージョンが存在します。
現在のPythonの利用状況は、最新のバージョン3系だけはなく古株のバージョン2系も多く利用されています。
しかし、現在のPythonの開発状況はバージョン3系の開発が積極的に行われており、バージョン2系は2020年にはサポートが打ち切られる予定であるため、今後はバージョン3系が広く使われることが予想されます。
※後ほど説明するOpenAI gymの実行環境としては、公式にはPython 2.7または3.5のLinuxとOSXとなっています。Windowsでも今回ご紹介する範囲は対応可能ですので、バージョンを3.5に設定してインストールをしてみてください。
Pythonのインストール方法
Pythonの公式サイト (https://www.python.org/ ) へアクセスし、インストーラーをダウンロードします。
「Download」で、「Python 3.x.x」を選択します。
※後ほど説明するOpenAI gymの実行環境としては、公式にはPython 2.7または3.5のLinuxとOSXとなっています。Windowsでも今回ご紹介する範囲は対応可能ですので、Pythonのバージョンは3.5に置き換えてインストールをしてみてください。
「Files」から、使用しているOS、希望するインストーラーを選択し、インストーラーをダウンロードします。
ダウンロードしたインストーラーを実行します。
「Add Python 3.x to PATH」にチェックを入れ、「Install Now」を押してインストールします。
macOSの場合は、「Add Python 3.x to PATH」にチェックを入れる作業は不要です。
インストールが終了したら、「Close」で閉じます。
Pycharmのインストール方法
今回は、Python向けの統合開発環境「PyCharm」を使用してみます。
PyCharmは、Pythonの統合開発環境(IDE)の一つで、Windows・macOS・Linuxで動作します。有償の Professional Edition と無償の Community Edition があります。
PyCharmの公式サイト ( https://www.jetbrains.com/pycharm/ ) へアクセスし、インストーラーをダウンロードします。
Communityの[Download]を選択します。
ダウンロードしたファイルを実行し、[Next]を選択し、インストールを進めます。
macOSの場合はアイコンをアプリケーションに追加するだけでインストールが完了するため、これ以降の作業は不要です。
デスクトップにショートカットが必要な場合、OSに合わせて32bitか64bitを選択します。
また、「.py」のチェックをONにすると、Pythonファイル(.py)をPyCharmに紐付けられます。これらのチェックは、不要な方は無しで進んでも問題ありません。[Next]で進み、インストールします。
「Run PyCharm Community Edition」のチェックを入れ、[Finish]で完了します。
「Do not import setting」を選択し、[ok]を選択します。
ChainerとChainerRLのインストール方法
「PyCharm」を使用すると、簡単にChainerとChainerRLのライブラリをインストールできます。
[Create New Project]で新しいプロジェクトを作成します。
Locationに任意の名前を入力し、[Create]をクリックします。
「Project :xxx」
– 「Project Interpreter」で、「+」マークを選択します。
検索ウィンドウで以下のライブラリを検索し、表示されたライブラリを選択し[Install Package]を選択します。
・Chainer
・ChainerRL
「Package ‘xxxxx’ installed successfully」が表示されたらインストールが完了です。
右上の「×」ボタンでダイアログを閉じます。
OpenAI gymのインストール方法
OpenAI Gymは、単独でインストールすることもできますが、強化学習ライブラリChainerRLにも一部が含まれています。
そのため、まず強化学習を簡単に試したい場合には、既にインストールしているChainerRLがあれば試すことができます。
OpenAI Gymについてはこちらの記事(強化学習用シミュレーションライブラリ「OpenAI Gym」の使い方.docx)でも詳しくご紹介しておりますので御覧ください。
強化学習を試してみよう~CartPole問題とは?
それでは実際にOpenAI Gymを使って、強化学習のプログラムを試してみましょう。
今回使用するのは、CartPole問題という、強化学習を行う上で一番始めによく試される問題です。
OpenAI gymのサイト(https://gym.openai.com/envs/CartPole-v1/)より、CartPole問題の詳細を確認します。
摩擦のないトラックに沿って動くカートにポールが取り付けられており、カートは横向きに+1または-1の力が加えられるようになっていて制御できます。
振り子が倒れないように左右の力を与え、維持できるようにすることが目的です。
ポールが直立したままで維持できたタイムステップごとに+1の報酬が与えられます。
エピソードは、ポールが垂直から15度を超えるときに終了するか、またはカートが中心から2.4ユニット以上移動すると終了します。
状態
番号 | 状態 | 最小値 | 最大値 |
---|---|---|---|
0 | カートの位置 | -4.8 | 4.8 |
1 | カートの速度 | -Inf | Inf |
2 | ポールの角度 | -24° | 24° |
3 | ポールの速度 | -Inf | Inf |
行動
番号 | 行動 |
---|---|
0 | 左にカートを押す |
1 | 右にカートを押す |
報酬
ポールが倒れなければ、1タイムステップごとに1の報酬が得られる
エピソードの終了条件
ポール角が±12°以上になること
カートの位置が±2.4を超える(カートの中央がディスプレイの端に達する)
エピソードの長さが200以上になった場合
強化学習を試してみよう:CartPole問題を実装してみる
ここでは、CartPole問題を実際にPythonのプログラムを書くことで実装してみます。
まずは強化学習は全くせず、常にカートを右に移動(行動)させるというプログラムを書いてみます。
ダイアログボックスから「Python File」を選びます。
「Name」に「cartpole_practice.py」と入力し[OK]をクリックします。
ライブラリをインポートします。
import gym
CartPoleのインスタンスを作成し、状態を初期化します。
#CarPoleの読み取りセットenv = gym.make("CarPole-v0")observation = env.reset()
行動を起こし、行動が行われた後の状態を確認します。今回は、ずっと右に動かし続ける動作をさせてみます。
#実行for i in range(50):action = 1 #右に押すobservation, reward, done, info = env.step(action) #情報を取得print("observation = " + str(observation))print("reward = " + str(reward))
ビジュアライズします。
env.render() #ビジュアライズ
ビジュアライズを終了します。
#終了env.close()[Run]-[Run]で「cartpole_practice.py」を選択し先ほど書いたソースコードを実行します。
以下のようなアニメーションが表示されます。
以下のような結果が表示されます。
observation = [ 0.02977195 0.15301161-0.04499931-0.2864956 ]reward = 1.0observation = [ 0.03283218 0.34874546-0.05072922-0.5930245 ]reward = 1.0observation = [ 0.03980709 0.54453946-0.06258971-0.90124568]reward = 1.0observation = [ 0.05069788 0.74045105-0.08061463-1.212927 ]reward = 1.0・・・
強化学習を試してみよう~Q学習でCartPole問題を学習させる方法
CartPole問題の環境が実行できたら、実際にQ学習を使用して学習をさせてみましょう。
Q学習はQテーブルを用意し、その行動価値観数Qを更新していくことで学習を進める手法でしたね。
[File]-[New]で新しくファイルを作成します。
ダイアログボックスから「Python File」を選びます。
「Name」に「cartpole.py」と入力し[OK]をクリックします。
使用するライブラリをインポートします。
import gymimport numpy as np
CartPole問題のシミュレーション環境を用意します。
# CartPole の読み込みenv = gym.make("CartPole-v0")
パラメータを設定します。max_number_of_steps は、1回の試行のstep数(コマ数)の最大数を指定します。初期値では1秒間に50コマの試行が行われるため、最大4秒の試行時間となります。
#各パラメータの設定num_digitized = 4 #各状態の離散数max_number_of_steps = 200 #1試行のstep数(コマ数)num_episodes = 500 #最大エピソード回数
初期のQテーブルを用意します。
# Qテーブルの用意q_table = np.random.uniform(low=-1, high=1, size=(num_digitized**num_digitized, 2))
状態の離散化処理を行ないます。
例えば、カート位置,カート速度,棒の角度,棒の角速度)=(1, 2, 3, 4)だった場合には、
1∗4⁰+2∗4¹+3∗4²+4∗4³=1+8+48+256=313
となり、状態313と定義されます。
つまり、カートと棒の位置や速度は様々に変化しますが、今回の場合、それぞれの位置や速度を4分割しておくことで、状態を1つの数字(Qテーブルの番号)として定義することができます。
#状態の離散化処理def bins(clip_min, clip_max, num):return np.linspace(clip_min, clip_max, num + 1)[1:1]def digitize_state(observation):cart_pos, cart_v, pole_angle, pole_v = observationcart_pos_digi = np.digitize(cart_pos, bins=bins(-2.4, 2.4, num_digitized))cart_v_digi = np.digitize(cart_v, bins = bins(-3.0, 3.0, num_digitized))pole_angle_digi = np.digitize(pole_angle, bins=bins(-0.5, 0.5, num_digitized))pole_v_digi = np.digitize(pole_v, bins=bins(-2.0, 2.0, num_digitized))return cart_pos_digi + cart_v_digi * num_digitized + pole_angle_digi * num_digitized ** 2 + pole_v_digi * num_digitized ** 3 #状態を表す番号を取得
ε-greedy 法の関数を定義します。
ε-greedy法は、最適な行動を取り続けるとはじめに発見した良さそうな行動のみを取り続けてしまうため、εの値に則ったランダムな行動を行うことでより良い行動がないかを探索する手法です。
εが0.5のとき、50%の確率でQ値に従い、50%の確率でランダムな行動を取ります。
#ε-greedydef get_action(next_state, episode): next_state = digitize_state(observation) epsilon = 0.5 * (1 / (episode + 1)) if epsilon <= np.random.uniform(0, 1): #もしεの値より一様乱数のほうが大きければ next_action = np.argmax(q_table[next_state])# Qテーブルの中で、次に取りうる行動の中で最も価値の高いものを選択 else: next_action = np.random.choice([0, 1])#それ以外はランダムな行動を取る return next_action
Qテーブルの更新関数を作成します。
# Qテーブルの更新def update_Qtable(q_table, state, action, reward, next_state): alpha = 0.2 gamma = 0.99 max_Q_next = max(q_table[next_state]) q_table[state, action] = q_table[state, action] + alpha * ( reward + gamma * max_Q_next-q_table[state, action]) return q_table
学習の繰り返しのコードを記載します。OpenAI gymの初期化と、状態の番号の取得、始めの行動の決定を行ないます。
#実行for episode in range(num_episodes): #試行数分繰り返す observation = env.reset() #初期化 state = digitize_state(observation) #倒立振子の状態番号を取得 action = np.argmax(q_table[state]) # Qテーブルの最大要素(0 or 1)を返す episode_reward = 0 #報酬のリセット
1試行分のループと、報酬の追加を記述します。
for step in range(max_number_of_steps): # 1試行のループ if episode % 10 == 0: # 10で割り切れたら env.render() #シミュレーション画像の表示 observation, reward, done, info = env.step(action) # Qテーブルの最大で行動。その結果を変数に格納 #報酬を与える if done an d step < max_number_of_steps-1: reward-= max_number_of_steps #棒が倒れたら罰則 episode_reward += reward #報酬を追加
t+1の状態を踏まえ、Qテーブルを更新します。
next_state = digitize_state(observation) # t+1での観測状態を、離散値に変換q_table = update_Qtable(q_table, state, action, reward, next_state)
ε-greedy法で次の行動を決定します。
action = get_action(next_state, episode) #ε-greedy法で次の行動を決定state = next_stateif done: break
エピソードの完了のタイミングで、エピソード数と報酬を表示します。
print('episode:', episode, 'R:', episode_reward)
Qテーブルをテキストファイルとして書き出します。
np.savetxt('Qvalue.txt', q_table)
Gymを終了します。
#終了env.close()[Run]-[Run]で「cartpole.py」を選択し先ほど書いたソースコードを実行します。
結果を確認します。
episode: 0 R:-174.0episode: 1 R:-181.0episode: 2 R:-191.0episode: 3 R:-153.0・・・episode: 496 R: 200.0episode: 497 R: 200.0episode: 498 R: 200.0episode: 499 R: 200.0
Pythonで強化学習をしよう まとめ
今回はPythonを使って強化学習をするやり方をご紹介しましたがいかがだったでしょうか。
いくつかの準備は必要でしたが、無料で強化学習のほとんどのことができるなんて、素晴らしい世の中になっていますよね!
是非この機会にPythonをインストールして強化学習の世界に飛び込んでみてください!
