ここでは、強化学習のQ-learning をすでに知っていることを前提に解説します。

Q-learningの基本的な解説はあとでまとめたいと思います。

問題設定

フィンガロンの動きを生成するために、状態、行動、報酬、をどう定義したかを説明します。

状態

姿勢(3つのモーターの角度)が状態になりますので、一番直感的な表し方は3次元ベクトルを使って、


[math]s=(0, -45, 45) [/math]

のようになるでしょう。しかし、連続値の3次元となると探索空間が広すぎて問題がとても難しくなってしまいます。

そこで、歩行に関連しそうな条件を満たす(先端が上がりすぎないなど)、特定の姿勢を0番から20番まで21個選びました。例えば、0番と11番の姿勢は以下のようなものになりました。



真横から見た姿勢の例。図の上の3つの数字は、3つのモーターの角度を表しています。

これらの姿勢を状態[math]s_0 … s_{N – 1} [/math] として定義しました。[math]N = 21[/math] となります。

行動

行動[math]a[/math]は状態数に合わせて、21個定義しました。[math]a_i[/math]を実行したら、現在がいかなる状態であっても[math]s_i[/math]に遷移する、という単純なものです。

時刻[math]t[/math]において、状態[math]s(t)[/math]に対して、行動[math]a(t)[/math]を実行すると、次の時刻[math]t+1[/math]で報酬を受け取るとします。


[math]
s(t) \rightarrow a(t) \rightarrow r(t + 1)
[/math]

報酬

前進、後退、右旋回、左旋回、この4つの動きに対して報酬を定義しました。それぞれを[math]r_f, r_b, r_r, r_l[/math]とします。

状態[math]s[/math] にあるときに 行動[math]a[/math] を実行したときに、どれくらい前に進んだかが前進の報酬[math]r_f(s, a)[/math]となります。

時刻[math]t[/math]でのフィンガロンの位置を[math]\vec{g}(t)[/math]とし、その時の前方の方向を表す単位ベクトルを[math]\vec{v}[/math]、横方向を表す単位ベクトルを[math]\vec{h}[/math] とします。

進んだ大きさは、[math]d\vec{g} = \vec{g}(t+1) – \vec{g}(t) [/math] で表せます。

報酬は、[math]d\vec{g}[/math]が大きくて、かつ、進むべき方向[math]\vec{v}[/math] を向いているときに、大きく与えたいので、それらの内積とします。

しかし、これだけだと斜め方向に進んでも報酬が得られてしまいます。そこで、横方向の成分(横方向との内積の絶対値)に対してペナルティーを科しました。

式で表すと、


[math]
r_f = d\vec{g} \cdot \vec{v} – k \cdot \| d\vec{g} \cdot \vec{h} \|
[/math]

となります。[math]k[/math]は、ペナルティの度合いを調節するパラメータで、実装では[math]k=2[/math]としました。

後退に対しては、後ろに進んだ時に報酬が高くなるようにして、前進と同様の横方向のペナルティーを加えました。


[math]
r_b = -d\vec{g} \cdot \vec{v} – k \cdot \| d\vec{g} \cdot \vec{h} \|
[/math]

右旋回に対しては、時刻[math]t[/math]におけるフィンガロンの向きを[math]dig(t)[/math]として、シンプルに、


[math]
r_r = dig(t+1) – dig(t)
[/math]

としました。角度は、画像の上方向を0度、時計回りを正の方向とし、-180~180を取る値として定義しました。実際にプログラムに組む場合には、-180と180がつながっていることに注意して以下のようにしました。

同様に、左旋回に対しては、


[math]
r_l = – (dig(t+1) – dig(t))
[/math]

としました。

Q-learning

状態、行動、報酬を定義したので、Q-learningが適用できます。

復習ですが、Q-learningでは、Q値が重要な概念になってきます。Q値とは、ある状態[math]s[/math]で行動[math]a[/math]を選んだあとから、未来永劫でもらえる報酬の和の平均値です。


[math]
Q(s, a) =\langle r(t+1) + \gamma r(t+2) + \gamma^2 r(t+3) \cdots \rangle
[/math]

[math]\gamma[/math]は、割引率パラメータです。

Q値は状態[math]s[/math]と行動[math]a[/math]の関数です。全ての状態と行動に対して正しいQ値を知っていたら、状態[math]s[/math]での最適行動は、


[math]
a^* = argmax_{a’} Q(s, a’)
[/math]

となります。

Q-learning では、以下の手順で、正しいQ値を求めていきます。


1. Q値を初期化する

N x N の配列変数として[math]Q(s, a)[/math] を準備し、初期値(例えば0)をセットします。

2. 行動を決定し実行する

現時点でのQ値を使って、以下の行動確率に従って行動を決定します。softmax 法です。


[math]
P(a) = \frac{\beta \exp(Q(s, a)}{\sum_{a’}{\beta \exp(Q(s, a’))}}
[/math]

[math]\beta[/math] は、逆温度パラメータです。

3. 決定した行動を実行し、報酬を得る

結果、フィンガロンの姿勢が変わります。それに伴い、フィンガロンの位置も場合によっては変わります。

そこから、報酬[math]r(t)[/math]を計算します。

4. Q値を更新する

それに基づいてその前の時刻の[math]s(t-1), a(t-1)[/math] に対するQ値を以下の式で更新します。

Q値の更新式(1)


[math]
\begin{split}
Q(s(t-1), a(t-1)) & \leftarrow & (\alpha -1) Q(s(t-1), a(t-1)) \\
& & + \alpha [r(t) + \gamma \max_{a’} Q(s(t), a’)]
\end{split}
[/math]

[math]\alpha[/math]は学習率パラメータです。

5. 2~4を繰り返す

2~4を繰り返すことで徐々にQ値が正しい値に収束し、行動も最適なものに近づいていきます。しかし、Q値の大きさは、21 x 21 もあります。すべての要素が十分に収束するには相当の繰り返しが必要になります。このままフィンガロンに適用すると何十時間もかかってしまうでしょう。


モデルベース強化学習

フィンガロンの問題には、お得な性質があります。それは、行動[math]a_i[/math] を実行すると確実に状態が[math]s_i[/math]となることが分かっている、ということです。一般的な強化学習の問題設定では、この遷移は未知であり、さらに確率的であると考えています。

この状態遷移の規則を環境モデルと呼びます。環境モデルと報酬関数があれば、実際の行動を出力しなくとも、完全に計算のみでQ値の更新式(1)を実行することができます。

つまり、全ての[math]s[/math]と[math]a[/math]に対して、Q値が収束するまで(1)を繰り返せば、実際の行動なしで学習は完了してしまうのです。

フィンガロンの場合、環境モデルはある、と言えますが、残念ながら、報酬関数の方はありません。そこで、報酬関数は実際に動かすことによって作りました。

報酬関数[math]r(s, a)[/math]は、[math]s[/math]にいるときに[math]a[/math]を実行して移動した方向と大きさで決まります。これをすべての組み合わせ(21 x 21 通り)で試して記録することで、報酬関数を作りました。

実際には、同じ行動をとっても報酬は完全に一致しないので、4~5回ほど繰り返して中央値を報酬の推定値としました。

この方法により、20分もかからずに4種類の報酬関数(前進、後退、右旋回、左旋回)に対する最適行動規則を得ることができるようになりました。