自作中のシンプルな分散強化学習フレームワークの紹介


今までいろいろな強化学習アルゴリズムを実装してきましたが、以下の問題を毎回感じていました。

1. アルゴリズム毎に環境と学習のための実装が必要  
　(gym等は環境側のインタフェースまでは提供されているが、学習を含めた実装は提供されていない)
1. アルゴリズムの学習フローがそもそも複雑になりやすい
1. 分散学習まで考えると更に大変
1. アルゴリズムと環境が分離しきれず結構依存する
   1. Atariの画像の前処理とその入力に依存したニューラルネットワークの設計
   1. アクションが離散値と連続値の場合によるアルゴリズム側の違い
   1. よくある数フレーム入力やフレームスキップ、実行できないアクション等を加味した場合の変更
   1. 学習フローの差異（AlphaZeroやモデルベース強化学習など）
1. ログや可視化等の作成

既存のフレームワークを試したりしましたが自作アルゴリズムを作ろうとした場合、フレームワークの理解から勉強が必要になりかなりハードルが高いような気がしました。
そこでなるべくハードルが低くなるようなフレームワークを自作しようと思い作成しました。

このフレームワークの特徴は以下です。

1. カスタマイズ可能な環境の提供
1. カスタマイズ可能な強化学習アルゴリズムの提供
1. 環境とアルゴリズム間のインタフェースの自動調整
1. 分散強化学習のサポート
1. 有名な強化学習アルゴリズムの提供
1. （新しいアルゴリズムへの対応）

本記事はフレームワークの説明をすると共に実装しているアルゴリズムも説明していこうかと思います。
各項目については別記事にして少しずつ作成する予定です。

# Github

https://github.com/pocokhc/simple_distributed_rl


# 目次

+ [強化学習の基礎](https://qiita.com/pocokhc/items/953585fa60fa71651969)
+ [Windows11における機械学習+GPU環境の構築方法](https://qiita.com/pocokhc/items/f796b4b3fa54510c8d3a)
+ フレームワークの使い方
  + [オリジナル環境の作成方法](https://pocokhc.github.io/simple_distributed_rl/pages/custom_env.html)
  + [オリジナルアルゴリズムの作成方法](https://pocokhc.github.io/simple_distributed_rl/pages/custom_algorithm.html)
  + [KaggleのConnectXへの投稿方法を解説（スコア900越えコード付き）](https://qiita.com/pocokhc/items/da46d75563732cd0b4ae)
  + [クラウドサービスを利用した分散強化学習（無料編）](https://qiita.com/pocokhc/items/f7a32ee6c62cba54d6ab)
  + [クラウドサービスを利用した分散強化学習（kubernetes編）](https://qiita.com/pocokhc/items/56c930e1e401ce156141)
  + [クラウドサービスを利用した分散強化学習（GKE/有料編）](https://qiita.com/pocokhc/items/e08aab0fe56566ab9407)
  + [エミュレータ連携（Gym×BizHawk×強化学習）](https://qiita.com/pocokhc/items/031fbb3e65b0450bd2a3)
+ 技術関係
  + [分散強化学習について](https://qiita.com/pocokhc/items/ca83562fc1469b35d67b)
  + [部分観測マルコフ決定過程について](https://qiita.com/pocokhc/items/6bf5a9519440fe5bd0d5)
  + [Off-Policyにおける安全な学習方法(Retrace)](https://qiita.com/pocokhc/items/dac186f947c134c707fb)
+ 各アルゴリズム
  + 価値ベース
    + [価値ベースアルゴリズムの基礎（Q学習）](https://qiita.com/pocokhc/items/73e1141bb30f5f6aad38)
    + [DQN](https://qiita.com/pocokhc/items/bb6a47e4d1d15112469f) 
    + [Rainbow](https://qiita.com/pocokhc/items/9972a528901c15e42519)
    + [R2D2](https://qiita.com/pocokhc/items/c456f5b034498ab18ab7)
    + [Agent57](https://qiita.com/pocokhc/items/daeeeb39cd717e641e78)
  + 方策ベース
    + [方策ベースアルゴリズムの基礎（方策勾配法/REINFORCE）](https://qiita.com/pocokhc/items/d1cc041f04f8ad23156e)
    + [TRPO(過去記事、フレームワーク未実装)](https://qiita.com/pocokhc/items/746d2890d394b79f7e24)
    + [PPO](https://qiita.com/pocokhc/items/1a68dc661eaa98dcacb2)
    + [DDPG/TD3(過去記事、フレームワーク実装あり)](https://qiita.com/pocokhc/items/6746df2eb9e7840e6814)
    + [SAC(過去記事、フレームワーク実装あり)](https://qiita.com/pocokhc/items/354a2ddf4cbd742d3191)
  + Alphaシリーズ
    + [モンテカルロ木探索(MCTS)](https://qiita.com/pocokhc/items/392a7f89c79f5e1e6bca)
    + [AlphaZero](https://qiita.com/pocokhc/items/a1b5f66361f23b2aefe8)
    + [MuZero](https://qiita.com/pocokhc/items/190779b4ff2e51cbeceb)
    + [StochasticMuZero](https://qiita.com/pocokhc/items/8ac7b66c2f18cbdf8ade)
    + [EfficientZeroV2](https://qiita.com/pocokhc/items/34f2174bcde690704350)
  + WorldModelsシリーズ
    + [WorldModels](https://qiita.com/pocokhc/items/912667ef2bbd3f82aa87)
    + [PlaNet](https://qiita.com/pocokhc/items/2c5562cb51c99a29c2ee)
    + [Dreamer](https://qiita.com/pocokhc/items/9d69ab60a97ab73ae18d)
    + [DreamerV2](https://qiita.com/pocokhc/items/31050a83539665bfc799)
    + [DreamerV3](https://qiita.com/pocokhc/items/d28da501aec04ad45861)
    + [DIAMOND](https://qiita.com/pocokhc/items/9aad5402051582dc589d)
  + その他の強化学習アルゴリズム
    + [Go-Explore](https://qiita.com/pocokhc/items/e2a2c526ff30303ac488)
    + [SND](https://qiita.com/pocokhc/items/c33d62388fc5dde75a52) 
  + オリジナル
    + [SearchDynaQ（テーブルベースアルゴリズム）](https://qiita.com/pocokhc/items/e246f136c9d5d2d23678)
+ フレームワークとは関係ない機械学習関係の記事
  + [最適化アルゴリズムを実装していくぞ（概要）](https://qiita.com/pocokhc/items/07b698cc426cadb3a64e)
   + [重み付き乱択アルゴリズムをまとめて計測してみた](https://qiita.com/pocokhc/items/a8f0281d54e1de7d3a30)
  + [Softmax+多クラス分類の感覚をつかむために基礎からちゃんと調べてみた（交差エントロピー損失）](https://qiita.com/pocokhc/items/c936a326e1d4821a0c23)
  + [BitNet b1.58(BitLinear)を実装してMNISTで検証してみた(Tensorflow/Torch)](https://qiita.com/pocokhc/items/09128e92654783a5fa5b)
  + [大規模言語モデルと強化学習：強化学習にLLMを組み込んで実装してみた（ローカルLLM）](https://qiita.com/pocokhc/items/44a8643e9570efb61a48)
  + [話題のDeepSeekで使われている強化学習GRPOを調べてみた](https://qiita.com/pocokhc/items/b50a56febeab2c990bea)
+ Tensorflow/ディープラーニング関係
  + [0から理解する誤差逆伝播法（理論からコードの実装まで）](https://qiita.com/pocokhc/items/401ff11ac4090dcc2a4f)
  + [基本的な出力層の活性化関数と損失関数の組み合わせまとめ（TF2.0）](https://qiita.com/pocokhc/items/d67b63ec9ca74b453093)
  + [LSTM(RNN)で可変長な時系列と隠れ状態について調べてみた(Tensorflow2.0)](https://qiita.com/pocokhc/items/1a1c31b443c3082fe76b)
  + [乱数の固定方法(random/numpy/tensorflow/gym)](https://qiita.com/pocokhc/items/68f4d50739e4776248a6)
  + [混合密度ネットワーク（Tensorflow2.0）](https://qiita.com/pocokhc/items/4fb37b39eaaed5a66d6d) 
  + [tf.GradientTapeで正則化項が反映されているか調査してみた（過学習の公式チュートリアルを添えて）](https://qiita.com/pocokhc/items/5f1bb1795bed16050a97) 
  + [離散空間のReparameterizationTrick（GumbelMaxTrick/StraightGradients/VQ-VAE）](https://qiita.com/pocokhc/items/d438a13d4c6ef861364a) 
  + [ELBO（変分下限）を最大化するという意味をゼロから理解する（尤度、最尤推定）](https://qiita.com/pocokhc/items/45ed63c130d0652543f3)
  + [[拡散モデル入門] ゼロから理解する拡散モデルの最新理論（図解付き）](https://qiita.com/pocokhc/items/53bfd610aba13bbbacd3)
+ その他
  + [中心極限定理が本当か試してみた](https://qiita.com/pocokhc/items/195c85350aed09f87857)


# 1.インストール

インストールする一例は以下です。
詳細は[GitHub](https://github.com/pocokhc/simple_distributed_rl)を見てください。

``` python
# 基本的な機能のみをインストール
pip install srl-framework

# 主要な拡張機能や補助的なライブラリも含めてインストール（※TensorFlowやPyTorchは含まれません）
pip install srl-framework[full]
```

# 2.使い方

``` python
import numpy as np
import srl

# ---  1. 使うアルゴリズムをimport
from srl.algorithms import ql

def main():

    # --- 2. 各configを設定
    env_config = srl.EnvConfig("Grid")  # 環境config
    rl_config = ql.Config()     # アルゴリズムconfig

    # --- 3. Runnerを作成
    runner = srl.Runner(env_config, rl_config)

    # --- 4. 学習
    if True:
        # 逐次学習の場合
        runner.train(timeout=20)
    else:
        # 分散学習の場合
        runner.train_mp(timeout=20)
    
    # 評価
    rewards = runner.evaluate(max_episodes=10)
    print(f"10回テストした結果の平均報酬: {np.mean(rewards)}")

    # 可視化
    # Terminal上で1エピソードを見る
    runner.render_terminal()

    # 1エピソードをアニメーション化
    runner.animation_save_gif("_Grid.gif")

if __name__ == '__main__':
    main()

```

* アニメーション

![Grid.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396150/f55c8cec-354a-466b-87dd-4e9eac1359f7.gif)


* Terminal上での結果

``` python
10回テストした結果の平均報酬: 0.7960000045597553
### 0, action 3, rewards [0.], next 0
env   None
work0 None
......
.   G.
. . X.
.P   .
......


 ←  : 0.10151
 ↓  : 0.07913
 →  : 0.02751
*↑  : 0.36339

### 1, action 3, rewards [-0.04], next 0
env   {}
work0 {}
......
.   G.
.P. X.
.    .
......


 ←  : 0.17283
 ↓  : 0.11623
 →  : 0.17698
*↑  : 0.48977

### 2, action 2, rewards [-0.04], next 0
env   {}
work0 {}
......
.P  G.
. . X.
.    .
......


 ←  : 0.23222
 ↓  : 0.18907
*→  : 0.61112
 ↑  : 0.24942

### 3, action 2, rewards [-0.04], next 0
env   {}
work0 {}
......
. P G.
. . X.
.    .
......


 ←  : 0.25572
 ↓  : 0.31604
*→  : 0.76530
 ↑  : 0.32385

### 4, action 2, rewards [-0.04], next 0
env   {}
work0 {}
......
.  PG.
. . X.
.    .
......


 ←  : 0.32941
 ↓  : 0.26414
*→  : 0.92709
 ↑  : 0.44327

### 5, action 2, rewards [-0.04], next 0
env   {}
work0 {}
......
.  PG.
. . X.
.    .
......


 ←  : 0.32941
 ↓  : 0.26414
*→  : 0.92709
 ↑  : 0.44327

### 6, action 2, rewards [1.], done(env), next 0
env   {}
work0 {}
......
.   P.
. . X.
.    .
......

```


# おわりに

少しずつ開発しているので温かく見守っていただければ幸いです。