統計的仮説検定を応用して強化学習のハイパーパラメタをチューニングするタスクの振り返り


# はじめに

2022年4月に投稿した[記事](https://qiita.com/asagao_iXaga3/items/4cdb62bc8b3b9ee1de24)で、格子状に結合した振動系を制御対象として、 強化学習のアルゴリズムでコントローラを設計するタスクに取り組んだ結果を報告しました。自己回帰構造を持つネットワーク(以下、RNN)で実装したコントローラを安定して学習することができなくて、悔しい思いをしました。RNNは、線形関数で実装した静的なネットワークに比べて構造が複雑であるため、強化学習の結果がばらついて、安定した結果を得ることができませんでした。

機械学習のタスクにおけるハイパーパラメタのチューニングに統計的仮説検定を応用したことがありませんでした。目視で判断することで議論に耐えられる結果が得られていたため、使う必要がなかったからです。

この記事では、統計的仮説検定を応用してコントローラの制御性能を分析することで、RNNで実装したコントローラのハイパーパラメタをチューニングするタスクに取り組んだ結果を報告します。

# タスクの定義

<!-- why -->
2022年4月に投稿した[記事](https://qiita.com/asagao_iXaga3/items/4cdb62bc8b3b9ee1de24)と同様に、結合振動系を制御するコントローラを設計します。制御対象とコントローラの詳細は、それぞれ、以下を参照下さい。

* [制御対象](https://qiita.com/asagao_iXaga3/items/4cdb62bc8b3b9ee1de24#%E5%88%B6%E5%BE%A1%E5%AF%BE%E8%B1%A1)
* [コントローラ](https://qiita.com/asagao_iXaga3/items/4cdb62bc8b3b9ee1de24#%E3%82%B3%E3%83%B3%E3%83%88%E3%83%AD%E3%83%BC%E3%83%A9)

<!-- what -->

コントローラは、Soft Actor-Critic [1],[2]で実装しました。actor network および critic network を、それぞれ、以下の通り実装しました。

```python

actor_net = ActorDistributionRnnNetwork(
	  observation_spec,
	  action_spec,
	  lstm_size = lstm_size,
	  input_fc_layer_params = (),
	  output_fc_layer_params = (),
	  continuous_projection_net=(
		  tanh_normal_projection_network.TanhNormalProjectionNetwork))

critic_net = CriticRnnNetwork(
		(observation_spec, action_spec),
		lstm_size = lstm_size,
		observation_fc_layer_params=None,
		action_fc_layer_params=None,
		joint_fc_layer_params=(32,),
		kernel_initializer='glorot_uniform',
		last_kernel_initializer='glorot_uniform')

```
`lstm_size`は、LSTM(Long Short Term Memory) セルのサイズを制御するハイパーパラメタです([参考](https://www.tensorflow.org/agents/api_docs/python/tf_agents/networks/actor_distribution_rnn_network/ActorDistributionRnnNetwork))。

このタスクでは、セルのサイズ`lstm_size`をチューニングします。セルのサイズ`lstm_size`は動特性の内部状態の次元を制御するため、数値を大きくとることでより柔軟にコントローラを設計できると期待できる一方で、学習結果に大きなばらつきが生じて、パラメタの効果を分析することが難しくなると予想できます。このため、ハイパーパラメタの効果の分析に仮説検定を使う意味がある、と考えます。

# 数値実験

## 手順

以下の手順でコントローラを学習しました。

1. セルのサイズ`lstm_size`を設定する。
2. actor network および critic network をそれぞれ初期化する
3. replay buffer を初期化する
4. 結合振動子を初期状態にする。
5. コントローラと結合振動子をつないで閉ループシミュレーションを開始する。
6. 閉ループシミュレーションの間に、一定の時間間隔$2\pi/8$で操作量を更新する。
7. 閉ループシミュレーションの間に、操作量を更新するごとに、操作量、結合振動子の観測出力、コストをreplay buffer に保存する。
8. 閉ループシミュレーションが終了したら、actor network, critic network のパラメタを強化学習のアルゴリズムで更新する。
9. 4. に戻る。
10. 4から9の手順を、学習の反復回数`episode`だけ繰り返す。
11. 2から10の手順を5回繰り返す。

手順4から手順7までの工程をエピソードと定義します。ある１つのエピソードで、初期時刻から終了時刻まで、結合振動子をコントローラで制御して、閉ループシミュレーションします。

コントローラの初期条件や負荷変動を乱数で決めているため、学習の結果にばらつきが出ます。安定した結果を得るために、手順11で、同一のパラメタに対して、5つのコントローラを、それぞれ独立に学習しました。

## ハイパーパラメタ

セルのサイズ`lstm_size`を4とした場合には、学習の反復回数`episode` を 16としました。セルのサイズ`lstm_size`を8あるいは16とした場合には、学習の反復回数`episode`を48まで延長しました。ネットワークが複雑になると、一般に、学習が収束するまでより多くの反復が必要になります。このため、セルのサイズ`lstm_size`ごとに、反復回数を設定しました。

* 結果(1)で、セルのサイズ`lstm_size`ごとに、学習の反復回数`episode`を決めた経緯を説明します。
* 結果(2)で、学習が収束したときの制御性能を使って、セルのサイズ`lstm_size`の効果を検証した結果を説明します。
* 結果(3)で、学習したコントローラの制御性能とベンチマークの制御性能を比較した結果を説明します。

実験で使ったハイパーパラメタを以下にまとめます。

表. コントローラを学習するときに設定したハイパーパラメタの一覧

|コスト関数|コントローラのネットワーク|セルのサイズ `lstm_size`|学習の反復回数`episode`|
|:-:|:-:|:-:|:-:|
| $c_{2}$ | RNN | 4 | 16 |
| $c_{2}$ | RNN | 8 | 48 |
| $c_{2}$ | RNN | 16 | 48 |

## 結果(1) 学習の反復回数の効果

### セルのサイズ`lstm_size` = 4の場合

学習の反復回数`episode`を16および32と、それぞれ設定して、コントローラを学習しました。学習したコントローラの制御性能の分布を図1.1の箱ひげ図に示します。

t検定の結果、学習の反復回数`episode` = 16および32、それぞれの制御性能の間には有意差がなく、学習の反復回数`episode`を16から、さらに32まで増やす効果は認められませんでした($t(8)=-0.36, p = .726$)。したがって、学習の反復回数`episode` = 16 において、学習は十分に収束したと判断しました。

![fig1-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2495166/528aba4a-4d23-a2fa-48b9-79a86d76b127.png)


図1.1. 学習の反復回数の制御性能に対する効果

### セルのサイズ`lstm_size` = 8の場合

学習の反復回数`episode`を48および64と、それぞれ設定して、コントローラを学習しました。学習したコントローラの制御性能の分布を図1.2の箱ひげ図に示します。

t検定の結果、学習の反復回数`episode` = 48および64、それぞれの制御性能の間には有意差がなく、学習の反復回数`episode`を48から、さらに64まで増やす効果は認められませんでした($t(8)=0.17, p = .871$)。したがって、学習の反復回数`episode` = 48 において、学習は十分に収束したと判断しました。

![fig1-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2495166/1e543342-ee81-566b-8adf-75954a59e0dc.png)


図1.2. 学習の反復回数の制御性能に対する効果

### セルのサイズ`lstm_size` = 16の場合

学習の反復回数`episode`を48および64と、それぞれ設定して、コントローラを学習しました。学習したコントローラの制御性能の分布を図1.3の箱ひげ図に示します。

t検定の結果、学習の反復回数`episode` = 48および64、それぞれの制御性能の間には有意差がなく、学習の反復回数`episode`を48から、さらに64まで増やす効果は認められませんでした($t(8)=-1.28, p = .235$)。したがって、学習の反復回数`episode` = 48 において、学習は十分に収束したと判断しました。

![fig1-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2495166/c775f47c-8126-7f06-bfb2-3d28584de706.png)

図1.3. 学習の反復回数の制御性能に対する効果

## 結果(2) セルのサイズ`lstm_size`の効果

セルのサイズ`lstm_size`(4,8,16)によって、学習したコントローラの制御性能が異なるか検証するために、1要因分散分析を行った結果、セルのサイズ`lstm_size`は有意ではありませんでした($F(2, 12) = 1.03, p = 0.387$)。つまり、セルのサイズ`lstm_size`を増やしてネットワークをより柔軟にしたとしても、制御性能を改善する効果は見られませんでした。

![fig2-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2495166/2dd2656d-4f94-1673-2e83-04f35009d4fd.png)

図2.1. セルのサイズ`lstm_size`の制御性能に対する効果


## 結果(3) ベンチマークの制御性能との比較

図3.1に、セルのサイズ`lstm_size`=4,8あるいは16において学習したコントローラの制御性能の箱ひげ図とベンチマークの制御性能（破線）を示します。

片側t検定を行った結果、学習したコントローラの制御性能は、ベンチマークの制御性能よりも有意に大きいという結果が得られました($t(13)=5.97, p < .001$)。したがって、コントローラの学習には改善の余地があると言えます。

![fig3-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2495166/9c6ef113-0547-2116-e8ac-62cd963b81b3.png)

図3.1. 学習したコントローラの制御性能の分布とベンチマークの制御性能


## 考察

LSTMを使ってコントローラを実装しましたが、ベンチマークの制御性能に到達することができませんでした。

* LSTMが十分な柔軟性を持っていることを踏まえると、仮説(1):「コントローラに操作量を決めるために必要なデータを与えていなかったために、ベンチマークの制御性能を実現できなかった」と考えることができます。

* また、LSTMは、入力信号にフィルタをかけて出力信号を算出するため、入力の変化を出力にすぐに反映することができません。このため、仮説(2):「actor network あるいは critic network の構造に直達項を含めていなかったためにベンチマークの制御性能を出すことができなかった」とも考えることができます。

仮説(1),(2)を検証するために、FIR(Finite Impulse Response)でネットワークを実装して、コントローラを学習したいと考えています。FIRの窓幅を調整することで、コントローラに取り込むデータを制御することができるので、仮説(1)を検証することができます。また、直近に観測されたデータをFIRに入力する、あるいは入力しない、を制御することで、仮説(2)を検証することができます。

皆さんなら、ベンチマークの性能を達成できなかった要因をどう分析するでしょうか。あるいは、どういう工夫をしてベンチマークの性能を達成するでしょうか。

# 参考文献

* [1] Haarnoja, T., Zhou, A., Abbeel, P., & Levine, S. (2018). Soft Actor-Critic: Off-Policy Maximum Entropy Deep Reinforcement Learning with a Stochastic Actor. ICML.
* [2] [SacAgent の実装](https://www.tensorflow.org/agents/api_docs/python/tf_agents/agents/SacAgent)