DDPG by gymnasium 4日目

前回はリプレイバッファを作りました。

今回はいよいよ、ニューラルネットワークの核心、学習部分を作っていきます。

12.メインスクリプトのagent.remember()直下にagent.learn()を作ります。

13.AgentDDPGクラス内にlearn()メソドを新規作成します。

14.バッチサイズ分のトランジションが集まるまでは何も実行しない。
        if self.memory.memory_count< self.batch_size:
            return
15.メモリバッファからデータを抜き出す sample_buffer()
        obs, action, reward, new_state, done = self.memory.sample_buffer(self.batch_size)
16.ReplayBufferのメソドとしてsample_bufferメソドを追加する。
    def sample_buffer(self, batch_size):
        # indexが最大メモリに到達していない場合を想定する。
        max_index = min(self.max_memory_size, self.memory_count)
        choosed_index = np.random.choice(max.index, batch_size)
        observations = self.state_memory[choosed_index]
        actions = self.action_memory[choosed_index]
        rewards = self.reward_memory[choosed_index]
        next_states = self.next_state_memory[choosed_index]
        terminals = self.terminal[choosed_index]
        return observations, actions, rewards, next_states, terminals
17.抜き出したデータをpytorchで微分可能なようにtorch.tensor化する。torch.tensor( obs, dtype=float)
        obs = T.tensor(obs, dtype=float)
        action = T.tensor(action, dtype=float)
        reward = T.tensor(reward, dtype=float)
        new_state = T.tensor(new_state, dtype=float)
        done = T.tensor(done, dtype=float)
18.ターゲットアクターネットワークインスタンスtarget_actorに
         次の状態next_satesを入れて、ターゲットアクションtarget_actionsとして取り出す。
        target_actions = self.target_actor.forward(next_states)
19.AgentDDPGクラスにターゲットアクターネットワークインスタンスtarget_actorを作成する。actorとtarget_actorのネットワークは同じActorNN構造で良い
        self.target_actor = ActorNN(input_dim=self.input_dim, output_dim=self.output_dim)
20.ターゲットクリティックネットワークインスタンスtareget_criticに
        # 次の状態next_statesと上記より算出したターゲットアクションの2つを入力して
        # 価値関数の推定値ターゲットバリューを出力する。
        # TDターゲット:r + γ*V(w)[s_t+1] の部分のこと。
        # ターゲットクリティックバリューはターゲットアクターネットワークを使う
        target_critic_values = self.target_critic.forward(next_states, target_actions)
21.AgentDDPGクラスにターゲットクリティックネットワークインスタンスtareget_criticを作成する
        self.target_critic = CriticNN(input_dim=self.input_dim, output_dim=self.output_dim)

Contents

問題発生

2.エージェントクラスのインスタンスを生成するところで
agent = AgentDDPG(input_dim=17, output_dim=6)
としていますが、これだけの引数ではDDPGを表現できないことに気が付きました。
ActorNNは入力obsと出力actionだけなので17と6だけの情報で良かったのですが、CriticNNは入力がactionと obsの2つ、また出力が状態価値state_valueの1つあるので、ニューラルネットワークに必要な入出力の数が異なります。
よって、入力の形、学習率、ニューラルネットワークの各層とノード数など、アクターとクリティックで異なるであろう部分はエージェントクラスから含めるように修正していきます。
以下のようにエージェントクラスの引数をたくさん増やしました。
agent = AgentDDPGalpha=0.000025, beta=0.00025, gamma=0.99, tau=0.001, n_obs_space=17 , n_action_space=6, layer1_size=64, layer2_size=64, batch_size=64)
またアクターニューラルネットワーククラスへ受け渡す引数を修正しました。
self.actor = ActorNN(alpha=0.000025, n_obs_space=17, n_action_space=6, layer1_size=64, layer2_size=64, batch_size=64)

さらなる問題

“””エラーメッセージ

このエラーメッセージは、行列の乗算に問題があることを示しています。具体的には、1×64の行列と17×64の行列を乗算しようとしていますが、この操作は許容されません。なぜなら、最初の行列の列数(64)が2番目の行列の行数(17)と異なるためです。

この問題を解決するには、乗算しようとしている行列の次元を確認し、行列乗算に対して互換性のある次元になるように調整する必要があります。あるいは、行列の次元に合わせて、適切な演算や変換を使用することも検討してみてください。

“””
バッファメモリーへ保存した観測情報obsを
observations = self.state_memory[choosed_index]
によって64個のバッチサイズで抜き出して、ニューラルネットワークへ入力した時点でエラーが発生しました。
流れを今一度おさらいします。
ひとつの観測情報obsをActorNNへ入力することによって、1つ行動actionが生成されます。
このobsの形は1×17なので、バッチ64個分をバッファから抜き出すと 64×17のはずです。しかし、エラーでは1×64となっているので根本的に間違っています。
患部リプレイバッファーの初期化部分でした。
self.state_memory = np.zeros((self.max_memory_size, self.n_obs_space))
これで、観測データ1000000 x 観測空間17 を確保するつもりが、
self.state_memory = np.zeros(self.max_memory_size)
となっており、観測空間17のメモリーしか確保されていませんでした。
さらに悪いことに保存データが
self.state_memory[index] = obs.detach().numpy().flatten()[0]
となっており、観測空間17個のうち先頭の1個しか保存されないという間違いがありました。
self.state_memory[index] = obs.detach().numpy().flatten()に修正しました。
ほかにも
self.new_state_memory[index]がありますので同様に修正が必要です。
ここまでの修正スクリプト
リプレイバッファが64データ蓄積されるまでは動きます。
学習learn()メソドが始まるとエラーが出る状態です。
次回はここを解消していきます。
 

pytorchで謎の部分は下記のサイトを参考にさせていただきました。

https://qiita.com/tatsuya11bbs/items/86141fe3ca35bdae7338