1

更新1:は、εを非常に少ない量にする前に取ったエピソードの数が非常に少ないという貪欲イプシロンポリシーを改訂しました。私はコードを更新しました。なぜ、q学習機能がopenai山岳車に収束しないのですか?

新しい問題は完全にそれがはるかに逸脱してはならない訓練の後であるが、それは間違った値をピックアップし、すぐに発散するイプシロンは小さな


になっている私は私の目標として今かなりいつかのためにopenai gymプラットフォームに取り組んできました強化学習の詳細については、スタックオーバフローユーザー@sajadの助けを借りて、経験豊富なリプレイ(PER)でダブルディープq学習(DQN)を実装しました。カートポールの問題で、注意深いハイパーパラメータチューニングで非常に良い成功率を得ました。これはこれまでのところ、私が学んだ最善のアルゴリズムですが、私が何をするにしても、報酬が常にエピソードの-200に続く山車の問題でこの仕事を得るようには見えません。私は自分のコードを見て、various tutorialsから私は私のメモリの実装が正しいと思います。

基本的なDQNからPERを持つDQNまでのアルゴリズムのどちらも機能していないようです。

私はコードやここ

を収束していない、それを引き起こしている可能性があり、他の実装の変更をデバッグするには、いくつかの助けを得るならば、それは役に立つだろうが、私の実装です:すべてのパラメータは、通常の名前

# implemented using sum_tree 

import os 
import random 

import gym 
import numpy as np 
import tensorflow as tf 
from memory import Memory 

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' 
env = gym.make("MountainCar-v0") 
env.reset() 
model_save_path = "C:/Users/sanka/codes/mountain car openai/mc_save" 


class dqn(object): 
    def __init__(self): 
     self.flag = 0 
     self.batch_size = 64 
     self.episodes = 20000 
     self.input_size = env.observation_space.sample().size 
     self.output_size = env.action_space.n 
     self.gamma = 0.99 
     self.epsilon = 1.0 
     self.step = 0 
     self.learning_rate = 0.0001 
     self.lambda1 = 0.001 
     self.initial_epsilon = self.epsilon 
     self.final_epsilon = 0.01 
     self.weights = {} 
     self.biases = {} 
     self.target_weights = {} 
     self.target_biases = {} 
     self.create_nn() 
     self.create_training_network() 
     self.max_size = 10000 
     self.memory = Memory(size=self.max_size) 
     self.sess = tf.InteractiveSession() 
     self.sess.run(tf.global_variables_initializer()) 
     self.saver = tf.train.Saver() 

    def create_nn(self): 

     s1 = {1: [self.input_size, 30], 2: [30, 100], 3: [100, 30], 4: [30, self.output_size]} 
     s2 = {1: [30], 2: [100], 3: [30], 4: [self.output_size]} 
     for i in s1: 
      self.weights[i] = tf.Variable(tf.truncated_normal(s1[i]), name='w{0}'.format(i)) 
      self.biases[i] = tf.Variable(tf.truncated_normal(s2[i]), name='b{0}'.format(i)) 
      self.target_weights[i] = tf.Variable(tf.truncated_normal(s1[i]), name='tw{0}'.format(i)) 
      self.target_biases[i] = tf.Variable(tf.truncated_normal(s2[i]), name='tb{0}'.format(i)) 

    def feed_forward(self, z): 
     q = tf.nn.relu(tf.matmul(z, self.weights[1]) + self.biases[1]) 
     for i in range(2, len(self.weights), 1): 
      q = tf.nn.relu(tf.matmul(q, self.weights[i]) + self.biases[i]) 
     q = tf.matmul(q, self.weights[len(self.weights)]) + self.biases[len(self.biases)] 
     return q 

    def feed_forward_target(self, z): 
     q = tf.nn.relu(tf.matmul(z, self.target_weights[1]) + self.target_biases[1]) 
     for i in range(2, len(self.weights), 1): 
      q = tf.nn.relu(tf.matmul(q, self.target_weights[i]) + self.target_biases[i]) 
     q = tf.matmul(q, self.target_weights[len(self.weights)]) + self.target_biases[len(self.weights)] 
     return q 

    def create_training_network(self): 
     self.x = tf.placeholder(tf.float32, [None, self.input_size]) 
     self.y = tf.placeholder(tf.float32, [None]) 
     self.a = tf.placeholder(tf.float32, [None, self.output_size]) 
     self.q_value = self.feed_forward(self.x) 
     self.q_value_target = self.feed_forward_target(self.x) 
     self.output = tf.reduce_sum(tf.multiply(self.q_value, self.a), reduction_indices=1) 
     self.action = tf.argmax(self.q_value, 1) 
     self.loss = tf.reduce_mean(tf.square(self.output - self.y)) 
     self.optimizer = tf.train.AdamOptimizer(learning_rate=self.learning_rate).minimize(self.loss) 

    def append_to_memory(self, state, action, reward, next_state, done): 
     one_hot_action = np.zeros(self.output_size) 
     one_hot_action[action] = 1.0 
     prob = (abs(reward) + .01) ** 0.6 
     self.memory.append(prob, (state, one_hot_action, reward, next_state, done)) 
     if self.memory.current_size >= self.memory.size: 
      self.step += 1 
      # self.epsilon = self.final_epsilon + (self.initial_epsilon - self.final_epsilon) * np.exp(
      # -self.lambda1 * (self.step/200)) 
      self.epsilon = max(self.initial_epsilon - (self.step/200) * self.lambda1, self.final_epsilon) 
      if (self.flag == 0): 
       print("started training") 
       self.flag = 1 
      self.train() 

    def get_reward(self, q1, q2, reward, done): 
     if done: 
      return reward 
     else: 
      return reward + self.gamma * q2[np.argmax(q1)] 

    def train(self): 
     index, sample = self.memory.sample(self.batch_size) 
     train_x = [i[0] for i in sample] 
     action = [i[1] for i in sample] 
     reward = [i[2] for i in sample] 
     next_state = [i[3] for i in sample] 
     train_y = [] 
     q = self.sess.run(self.q_value, feed_dict={self.x: np.array(train_x)}) 
     q_1 = self.sess.run(self.q_value, feed_dict={self.x: np.array(next_state)}) 
     q_next = self.sess.run(self.q_value_target, feed_dict={self.x: np.array(next_state)}) 
     for i in range(len(reward)): 
      train_y.append(self.get_reward(q_1[i], q_next[i], reward[i], sample[i][4])) 
     train_y = np.array(train_y) 
     train_x = np.array(train_x) 
     action = np.array(action) 
     self.sess.run(self.optimizer, feed_dict={self.x: train_x, self.y: train_y, self.a: action}) 
     for i in range(self.batch_size): 
      error = abs(np.max(q[i]) - train_y[i]) 
      self.memory.update(index[i], (error + 0.01) ** 0.6) 
      # return loss 

    def copy_variables(self): 
     for i in range(1, len(self.weights) + 1, 1): 
      self.sess.run(self.target_weights[i].assign(self.weights[i])) 
      self.sess.run(self.target_biases[i].assign(self.biases[i])) 

    def save(self): 
     self.saver.save(self.sess, model_save_path) 
     print("model saved") 


def main(): 
    obj = dqn() 
    for e in range(obj.episodes): 
     p = env.reset() 
     for i in range(500): 
      # obj.step += 1 
      ac = obj.sess.run(obj.action, feed_dict={obj.x: np.array([p])})[0] 
      if np.random.rand() < obj.epsilon: 
       ac = random.randint(0, obj.output_size - 1) 

      obs, rew, done, _ = env.step(ac) 
      obj.append_to_memory(p, ac, rew, obs, done) 
      p = obs 
      if done: 
       break 
      if obj.step % 1000 == 0 and obj.flag == 1: 
       obj.copy_variables() 
     # print("episode {0} completed with loss: {1}".format(e, total_loss)) 

     if e % 100 == 0: 
      print("episodes {0} completed".format(e),) 
      av = [] 
      for f in range(10): 
       p = env.reset() 
       r = 0 
       for i in range(200): 
        ac = obj.sess.run(obj.action, feed_dict={obj.x: np.array([p])})[0] 
        p, rew, done, _ = env.step(ac) 
        r += rew 
        if done: 
         break 
       av.append(r) 
      print("average score is {0}".format(np.average(np.array(av)))) 
      obj.save() 


if __name__ == '__main__': 
    main() 
を持っていますここで参考のため

は別個のモジュールとして実装メモリの実装である:予め

import numpy as np 
import random 


class Memory(object): 
    def __init__(self, size): 
     self.size = size 
     self.data = np.zeros(size, dtype=object) 
     self.tree = np.zeros(2 * size - 1, dtype=np.float32) 
     self.current_size = 0 
     self.last = 0 

    def append(self, p, data): 
     self.current_size = min(self.current_size + 1, self.size) 
     cur = self.last + self.size - 1 
     self.update_at_index(cur, p - self.tree[cur]) 
     self.data[self.last] = data 
     self.last += 1 
     if self.last >= self.size: 
      self.last = 0 

    def update(self, index, p): 
     self.update_at_index(index, p - self.tree[index]) 

    def update_at_index(self, index, change): 
     while (index >= 0): 
      self.tree[index] += change 
      index = (index - 1) // 2 

    def get(self, index, s): 
     left = index * 2 + 1 
     if (left >= self.size): 
      return (index, self.data[index + 1 - self.size]) 
     if (self.tree[left] >= s): 
      return self.get(left, s) 
     else: 
      right = left + 1 
      return self.get(right, s - self.tree[left]) 

    def sample(self, n): 
     av_sum = self.tree[0]/n 
     l = [] 
     m = [] 
     for i in range(n): 
      min_sum = av_sum * i 
      max_sum = av_sum * (i + 1) 
      s = random.uniform(min_sum, max_sum) 
      x = self.get(0, s) 
      l.append(x[0]) 
      m.append(x[1]) 
     return l, m 

おかげ

答えて

1

私はmontain car(現在はopenaiジムにあるもの)の連続バージョンで作業し、DDPGで解決しました。実験中にいくつかの最初のエピソードで報酬が得られなかった場合、何もしない。ここでは探検の問題です。多分、あなたはいくつかのエピソードのためにランダムな行動をしてから、勉強を始めることができます。 または探検に報酬を与える方法を見つけます。 (例えば、私が見たことがないと報酬を与えたとき、それは私のためにうまくいった)。

+0

はい私は最初の50回のエピソード(私の記憶が10000であるため)を完全に探索し、その後は指数関数的な速度でイプシロンを減少させ始め、学習を開始しました。無作為抽出の私の最初の試みの間に少し収束しましたが、再びトラップに落ちます。 PERとは4000エピソードでさえ収束しません。私はまた、イプシロンが減少する減少率を試しました。しかし、私はそれが動作するかどうかを見てあなたの報酬の方法を試します –

+0

あなたは正しい、それは探査の問題だった。私はランダムな値を使用していた回数を更新しました。だから収束し始めますが、私のイプシロンが非常に少なくなった後、再び発散するようになります。これに対する解決策を見つけることができませんでした –

関連する問題