見出し画像

強化学習とは

強化学習についてまとめてみたいと思います。

データを与えて学習させる「機械学習」の手法のひとつ

「教師あり学習」と「教師なし学習」と「強化学習」

強化学習とは、試行錯誤を通じて「価値を最大化するような行動」を学習するものです。
教師付き学習とよく似た問題設定ですが、与えられた正解の出力をそのまま学習すれば良いわけではなく、もっと広い意味での「価値」を最大化する行動を学習しなければなりません。

https://blog.brainpad.co.jp/entry/2017/02/24/121500



https://dse-souken.com/2021/05/18/ai-17/

このサイトのコードをColabで実行して迷路の最短ルートの結果を得ることができます。

必要ライブラリは"numpy"のみ

import numpy as np


gamma
将来価値の割引。小さいほど行動直後の利益を重視。また、この割引率の存在が効率的な学習の鍵となる。
Q学習では長期的な報酬をみていくので、1に近づくような数値を設定して強化学習を行っていくことが多い

alpha
学習率。大きいと1回の学習による値の更新が急激となる。小さいほど更新がゆるやかとなる。

gamma = 0.9
alpha = 0.1

報酬の設定です。まず、迷路ですが、

0   1   2
        -
3 | 4   5

6   7 | 8

とします。棒線が引いているところは通れないということにします。0から8までの数字を目当てにゴールを目指します。"0"がスタート"8"がゴールとします。

・各場所から移動できる箇所に報酬1を与え、それ以外を0とすることで移動できる方向を指示
・以下の行列の各行が場所に対応。0行目は迷路の位置0、1行目が迷路の位置1

0から8までの報酬を定義するので9個の配列は作ってそれぞれの報酬を入れていきます。例えば"0"の場合は"1"と"3"に進むことができるので

[0,1,0,1,0,0,0,0,0]

配列番号1と3のところに"1"を入れます。他も同じように設定すると

reward = np.array([[0,1,0,1,0,0,0,0,0],
                   [1,0,1,0,1,0,0,0,0],
                   [0,1,0,0,0,0,0,0,0],
                   [1,0,0,0,0,0,1,0,0],
                   [0,1,0,0,0,1,0,1,0],
                   [0,0,0,0,1,0,0,0,10000],
                   [0,0,0,1,0,0,0,1,0],
                   [0,0,0,0,1,0,1,0,0],
                   [0,0,0,0,0,1,0,0,0]])

8はゴールするのでそのルートである5→8の報酬を大きくしています。

最短経路となることには、割引率を設定していることが大きく関わっています。
0から1への移動したとき、5→8の大きな報酬を得るまでには少なくともあと3回行動する必要があります。
0から3への移動したとき、5→8の大きな報酬を得るまでには少なくともあと5回行動する必要があります。
つまり、0から3への移動の場合、5→8の大きな報酬に掛け算される割引率が2回多くなってしまうのです。

Q値(行動価値)の初期値を設定。今回は0を初期値とする。

Q = np.array(np.zeros([9,9]))

10,000回学習します。

for i in range(10000):
    p_state = np.random.randint(0,9) 
    n_actions = []  
    for j in range(9):
        if reward[p_state,j] >= 1:  
            n_actions.append(j)  
    n_state = np.random.choice(n_actions)  

Q学習に用いる「たった一つの数式」を利用して行動価値を学習していく

  Q[p_state,n_state] = (1-alpha)*Q[p_state,n_state]+alpha*(reward[p_state,n_state]+gamma*Q[n_state,np.argmax(Q[n_state,])])

最後に最短ルート表示関数の定義。Q値が最も高い行動を配列

np.argmax(Q[p_pos,])

"path"にappendで追加していきます。

def shortest_path(start):  
    path = [start]  
    p_pos = start  
    n_pos = p_pos
  
    while(n_pos != 8):  
        n_pos = np.argmax(Q[p_pos,])  
        path.append(n_pos)  
        p_pos = n_pos  
    return path

そしてその結果を出力

print(shortest_path(0))


スタートを"0"として最短経路を表示します。


以下参考ページのコードです。

import numpy as np

gamma = 0.9
alpha = 0.1

reward = np.array([[0,1,0,1,0,0,0,0,0],
                   [1,0,1,0,1,0,0,0,0],
                   [0,1,0,0,0,0,0,0,0],
                   [1,0,0,0,0,0,1,0,0],
                   [0,1,0,0,0,1,0,1,0],
                   [0,0,0,0,1,0,0,0,10000],
                   [0,0,0,1,0,0,0,1,0],
                   [0,0,0,0,1,0,1,0,0],
                   [0,0,0,0,0,1,0,0,0]])

Q = np.array(np.zeros([9,9]))

for i in range(10000):
    p_state = np.random.randint(0,9)   
    n_actions = []  
    for j in range(9):
        if reward[p_state,j] >= 1: 
            n_actions.append(j)  
    n_state = np.random.choice(n_actions) 

    Q[p_state,n_state] = (1-alpha)*Q[p_state,n_state]+alpha*(reward[p_state,n_state]+gamma*Q[n_state,np.argmax(Q[n_state,])])

def shortest_path(start):  
    path = [start]  
    p_pos = start 
    n_pos = p_pos  
    while(n_pos != 8):  
        n_pos = np.argmax(Q[p_pos,]) 
        path.append(n_pos)  
        p_pos = n_pos  
    return path

print(shortest_path(0))

この記事が気に入ったらサポートをしてみませんか?