#python #tensorflow #machine-learning #keras #reinforcement-learning
#python #tensorflow #машинное обучение #keras #подкрепление-обучение
Вопрос:
В настоящее время я настраиваю глубоко детерминированный агент градиента политики для взаимодействия со средой криптоторговли. Код работает, когда я использую Dense
слои для аппроксиматора функций, но когда я переключаюсь на LSTM
или GRU
s, эта ошибка появляется при вызове learn
метода Agent
:
No gradients provided for any variable: ['actor_network_4/lstm/kernel:0', 'actor_network_4/lstm/recurrent_kernel:0', 'actor_network_4/lstm/bias:0', 'actor_network_4/lstm_1/kernel:0', 'actor_network_4/lstm_1/recurrent_kernel:0', 'actor_network_4/lstm_1/bias:0', 'actor_network_4/dense_8/kernel:0', 'actor_network_4/dense_8/bias:0'].
Я использую GradientTape
для записи градиентов и optimizer.apply_gradients
обновления сетей актеров и критиков. Пожалуйста, найдите фрагменты кода ниже:
#RNN version
class CriticNetwork(keras.Model):
def __init__(self, n_actions,name='critic', chkpt_dir='ddpg'):
super(CriticNetwork, self).__init__()
self.n_actions = n_actions
self.model_name = name
self.checkpoint_dir = chkpt_dir
self.checkpoint_file = os.path.join(self.checkpoint_dir, self.model_name '_ddpg.h5')
self.lstm1 = LSTM(128,return_sequences=True,unroll=False)
self.lstm2 = LSTM(128)
self.q = Dense(1, activation=None)
def call(self, state, action):
action_value = tf.concat([state, action], axis=1)
action_value = np.reshape(action_value,(32,1,44))
action_value = self.lstm1(action_value)
action_value = self.lstm2(action_value)
q = self.q(action_value)
return q
class ActorNetwork(keras.Model):
def __init__(self,n_actions=1, name='actor',chkpt_dir='ddpg'):
super(ActorNetwork, self).__init__()
self.n_actions = n_actions
self.model_name = name
self.checkpoint_dir = chkpt_dir
self.checkpoint_file = os.path.join(self.checkpoint_dir,
self.model_name '_ddpg.h5')
self.lstm1 = LSTM(128,return_sequences=True,unroll=False)
self.lstm2 = LSTM(128)
self.mu = Dense(self.n_actions, activation='tanh')
def call(self, state):
state = np.reshape(state,(32,1,43))
prob = self.lstm1(state)
prob = self.lstm2(prob)
mu = self.mu(prob)
return mu
class Agent:
def __init__(self, alpha=0.001, beta=0.002, input_dims=[33], env=None,
gamma=0.99, n_actions=1, max_size=3000000, tau=0.005,
fc1=128, fc2=128, fc3=64, batch_size=32):
self.gamma = gamma
self.tau = tau
self.memory = ReplayBuffer(max_size, input_dims, n_actions)
self.batch_size = batch_size
self.n_actions = n_actions
self.max_action = 1
self.min_action = -1
self.actor = ActorNetwork(n_actions=n_actions, name='actor')
self.critic = CriticNetwork(n_actions=n_actions, name='critic')
self.target_actor = ActorNetwork(n_actions=n_actions, name='target_actor')
self.target_critic = CriticNetwork(n_actions=n_actions, name='target_critic')
self.actor.compile(optimizer=Adam(learning_rate=alpha))
self.critic.compile(optimizer=Adam(learning_rate=beta))
self.target_actor.compile(optimizer=Adam(learning_rate=alpha))
self.target_critic.compile(optimizer=Adam(learning_rate=beta))
self.update_network_parameters(tau=1)
def update_network_parameters(self, tau=None):
if tau is None:
tau = self.tau
weights = []
targets = self.target_actor.weights
for i, weight in enumerate(self.actor.weights):
weights.append(weight * tau targets[i]*(1-tau))
self.target_actor.set_weights(weights)
weights = []
targets = self.target_critic.weights
for i, weight in enumerate(self.critic.weights):
weights.append(weight * tau targets[i]*(1-tau))
self.target_critic.set_weights(weights)
def remember(self, state, action, reward, new_state, done):
self.memory.store_transition(state, action, reward, new_state, done)
def save_models(self):
print('... saving models ...')
self.actor.save_weights(self.actor.checkpoint_file)
self.target_actor.save_weights(self.target_actor.checkpoint_file)
self.critic.save_weights(self.critic.checkpoint_file)
self.target_critic.save_weights(self.target_critic.checkpoint_file)
def load_models(self):
print('... loading models ...')
self.actor.load_weights(self.actor.checkpoint_file)
self.target_actor.load_weights(self.target_actor.checkpoint_file)
self.critic.load_weights(self.critic.checkpoint_file)
self.target_critic.load_weights(self.target_critic.checkpoint_file)
def choose_action(self, observation, evaluate=False):
state = tf.convert_to_tensor([observation], dtype=tf.float32)
actions = self.actor(state)
if not evaluate:
actions = tf.random.normal(shape=[self.n_actions],
mean=0.0, stddev=0.05)
actions = tf.clip_by_value(actions, self.min_action, self.max_action)
return actions
def learn(self):
if self.memory.mem_cntr < self.batch_size:
return
state, action, reward, new_state, done =
self.memory.sample_buffer(self.batch_size)
states = tf.convert_to_tensor(state, dtype=tf.float32)
states_ = tf.convert_to_tensor(new_state, dtype=tf.float32)
rewards = tf.convert_to_tensor(reward, dtype=tf.float32)
actions = tf.convert_to_tensor(action, dtype=tf.float32)
with tf.GradientTape() as tape:
target_actions = self.target_actor(states_)
critic_value_ = tf.squeeze(self.target_critic(
states_, target_actions), 1)
critic_value = tf.squeeze(self.critic(states, actions), 1)
target = reward self.gamma*critic_value_*(1-done)
critic_loss = keras.losses.MSE(target, critic_value)
critic_network_gradient = tape.gradient(critic_loss, self.critic.trainable_variables)
self.critic.optimizer.apply_gradients(zip(critic_network_gradient, self.critic.trainable_variables))
with tf.GradientTape() as tape:
new_policy_actions = self.actor(states)
actor_loss = -self.critic(states, new_policy_actions)
actor_loss = tf.math.reduce_mean(actor_loss)
actor_network_gradient = tape.gradient(actor_loss, self.actor.trainable_variables)
self.actor.optimizer.apply_gradients(zip(actor_network_gradient, self.actor.trainable_variables))
self.update_network_parameters()
Любые советы или помощь в отношении того, как записывать и применять градиент для LSTM, помогут.
Ответ №1:
На самом деле проблема в том, что вы используете операции Numpy для определения логики вычислений (следовательно, градиенты не могут течь с этой точки и далее); однако это должно быть сделано полностью с использованием слоев TF Ops или Keras. В частности, в call
методе CriticNetwork
, а также ActorNetwork
, вместо того, чтобы использовать np.reshape
, вы должны либо использовать tf.expand_dims
(если вы хотите добавить новую ось размера один к тензору), либо tf.reshape
, либо tf.keras.layers.Reshape
слой (для более сложной перестройки). Например, используя tf.expand_dims
:
class CriticNetwork(keras.Model):
#...
def call(self, state, action):
action_value = tf.concat([state, action], axis=1)
action_value = tf.expand_dims(action_value, axis=1)
или использование tf.reshape
:
class CriticNetwork(keras.Model):
#...
def call(self, state, action):
action_value = tf.concat([state, action], axis=1)
action_value = tf.reshape(action_value, (-1, 1, 44)) # Use `-1` for the first axis so that any batch size would be supported
или использование Reshape
layer:
class CriticNetwork(keras.Model):
def __init__(self, n_actions,name='critic', chkpt_dir='ddpg'):
# ...
self.reshape = tf.keras.layers.Reshape((1, 44))
def call(self, state, action):
action_value = tf.concat([state, action], axis=1)
action_value = self.reshape(action_value)
И вам нужно сделать то же самое для ActorNetwork
.
Примечание: я не уверен, является ли это просто демонстрационным кодом или нет, но обратите внимание, что использование слоев RNN для последовательности длиной один (т. Е. Имеющих Только один временной шаг) может оказаться не очень полезным.