Created
July 30, 2017 23:27
-
-
Save yashpatel5400/85025ecf0db2f14f50907a7267e1321e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
solving pendulum using actor-critic model | |
""" | |
import gym | |
import numpy as np | |
from keras.models import Sequential, Model | |
from keras.layers import Dense, Dropout, Input | |
from keras.layers.merge import Add, Multiply | |
from keras.optimizers import Adam | |
import keras.backend as K | |
import tensorflow as tf | |
import random | |
from collections import deque | |
# determines how to assign values to each state, i.e. takes the state | |
# and action (two-input model) and determines the corresponding value | |
class ActorCritic: | |
def __init__(self, env, sess): | |
self.env = env | |
self.sess = sess | |
self.learning_rate = 0.001 | |
self.epsilon = 1.0 | |
self.epsilon_decay = .995 | |
self.gamma = .95 | |
self.tau = .125 | |
# ===================================================================== # | |
# Actor Model # | |
# Chain rule: find the gradient of chaging the actor network params in # | |
# getting closest to the final value network predictions, i.e. de/dA # | |
# Calculate de/dA as = de/dC * dC/dA, where e is error, C critic, A act # | |
# ===================================================================== # | |
self.memory = deque(maxlen=2000) | |
self.actor_state_input, self.actor_model = self.create_actor_model() | |
_, self.target_actor_model = self.create_actor_model() | |
self.actor_critic_grad = tf.placeholder(tf.float32, | |
[None, self.env.action_space.shape[0]]) # where we will feed de/dC (from critic) | |
actor_model_weights = self.actor_model.trainable_weights | |
self.actor_grads = tf.gradients(self.actor_model.output, | |
actor_model_weights, -self.actor_critic_grad) # dC/dA (from actor) | |
grads = zip(self.actor_grads, actor_model_weights) | |
self.optimize = tf.train.AdamOptimizer(self.learning_rate).apply_gradients(grads) | |
# ===================================================================== # | |
# Critic Model # | |
# ===================================================================== # | |
self.critic_state_input, self.critic_action_input, \ | |
self.critic_model = self.create_critic_model() | |
_, _, self.target_critic_model = self.create_critic_model() | |
self.critic_grads = tf.gradients(self.critic_model.output, | |
self.critic_action_input) # where we calcaulte de/dC for feeding above | |
# Initialize for later gradient calculations | |
self.sess.run(tf.initialize_all_variables()) | |
# ========================================================================= # | |
# Model Definitions # | |
# ========================================================================= # | |
def create_actor_model(self): | |
state_input = Input(shape=self.env.observation_space.shape) | |
h1 = Dense(24, activation='relu')(state_input) | |
h2 = Dense(48, activation='relu')(h1) | |
h3 = Dense(24, activation='relu')(h2) | |
output = Dense(self.env.action_space.shape[0], activation='relu')(h3) | |
model = Model(input=state_input, output=output) | |
adam = Adam(lr=0.001) | |
model.compile(loss="mse", optimizer=adam) | |
return state_input, model | |
def create_critic_model(self): | |
state_input = Input(shape=self.env.observation_space.shape) | |
state_h1 = Dense(24, activation='relu')(state_input) | |
state_h2 = Dense(48)(state_h1) | |
action_input = Input(shape=self.env.action_space.shape) | |
action_h1 = Dense(48)(action_input) | |
merged = Add()([state_h2, action_h1]) | |
merged_h1 = Dense(24, activation='relu')(merged) | |
output = Dense(1, activation='relu')(merged_h1) | |
model = Model(input=[state_input,action_input], output=output) | |
adam = Adam(lr=0.001) | |
model.compile(loss="mse", optimizer=adam) | |
return state_input, action_input, model | |
# ========================================================================= # | |
# Model Training # | |
# ========================================================================= # | |
def remember(self, cur_state, action, reward, new_state, done): | |
self.memory.append([cur_state, action, reward, new_state, done]) | |
def _train_actor(self, samples): | |
for sample in samples: | |
cur_state, action, reward, new_state, _ = sample | |
predicted_action = self.actor_model.predict(cur_state) | |
grads = self.sess.run(self.critic_grads, feed_dict={ | |
self.critic_state_input: cur_state, | |
self.critic_action_input: predicted_action | |
})[0] | |
self.sess.run(self.optimize, feed_dict={ | |
self.actor_state_input: cur_state, | |
self.actor_critic_grad: grads | |
}) | |
def _train_critic(self, samples): | |
for sample in samples: | |
cur_state, action, reward, new_state, done = sample | |
if not done: | |
target_action = self.target_actor_model.predict(new_state) | |
future_reward = self.target_critic_model.predict( | |
[new_state, target_action])[0][0] | |
reward += self.gamma * future_reward | |
self.critic_model.fit([cur_state, action], reward, verbose=0) | |
def train(self): | |
batch_size = 32 | |
if len(self.memory) < batch_size: | |
return | |
rewards = [] | |
samples = random.sample(self.memory, batch_size) | |
self._train_critic(samples) | |
self._train_actor(samples) | |
# ========================================================================= # | |
# Target Model Updating # | |
# ========================================================================= # | |
def _update_actor_target(self): | |
actor_model_weights = self.actor_model.get_weights() | |
actor_target_weights = self.target_critic_model.get_weights() | |
for i in range(len(actor_target_weights)): | |
actor_target_weights[i] = actor_model_weights[i] | |
self.target_critic_model.set_weights(actor_target_weights) | |
def _update_critic_target(self): | |
critic_model_weights = self.critic_model.get_weights() | |
critic_target_weights = self.critic_target_model.get_weights() | |
for i in range(len(critic_target_weights)): | |
critic_target_weights[i] = critic_model_weights[i] | |
self.critic_target_model.set_weights(critic_target_weights) | |
def update_target(self): | |
self._update_actor_target() | |
self._update_critic_target() | |
# ========================================================================= # | |
# Model Predictions # | |
# ========================================================================= # | |
def act(self, cur_state): | |
self.epsilon *= self.epsilon_decay | |
if np.random.random() < self.epsilon: | |
return self.env.action_space.sample() | |
return self.actor_model.predict(cur_state) | |
def main(): | |
sess = tf.Session() | |
K.set_session(sess) | |
env = gym.make("Pendulum-v0") | |
actor_critic = ActorCritic(env, sess) | |
num_trials = 10000 | |
trial_len = 500 | |
cur_state = env.reset() | |
action = env.action_space.sample() | |
while True: | |
env.render() | |
cur_state = cur_state.reshape((1, env.observation_space.shape[0])) | |
action = actor_critic.act(cur_state) | |
action = action.reshape((1, env.action_space.shape[0])) | |
new_state, reward, done, _ = env.step(action) | |
new_state = new_state.reshape((1, env.observation_space.shape[0])) | |
actor_critic.remember(cur_state, action, reward, new_state, done) | |
actor_critic.train() | |
cur_state = new_state | |
if __name__ == "__main__": | |
main() |
Thanks Nikunj !
…----- Mail original -----
De: "Nikunj" <[email protected]>
À: "yashpatel5400" <[email protected]>
Cc: "Alex Boulangé" <[email protected]>, "Manual" <[email protected]>
Envoyé: Jeudi 23 Mai 2019 15:35:11
Objet: Re: yashpatel5400/actor_critic.py
Yes, Alex, the script is running for me. The update functions (both) are actually unutilized in the script, so not posing an issue.
The results, however, can be improved considerably by some modifications to the code, for example, using the update actor and critic functions and maybe by playing a bit with the hyperparameters (number of layers in the actor/critic model, etc.). Also, the script runs forever right now (while True: ) though there is mention of num_trials and trial_len . Try using these variables to break the learning at your desired behaviour of policy.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub , or mute the thread .
Hi Nikunj, finaly imo this is not a mistake
( I'm working on a fork, I'll share it soon, with tau implementation)
Why isn't update_target(in line 159) executed in the main function? I think that if this is not done, the target isn't updated.
I'm glad if you tell me the reason.
Why the target is not updated at the end, also the training main loop seems to be wrong.I think there should be a double for loop for the training step. Also, I think the tau value is not used for target.
The _update_actor_target() and _update_critic_target() function has not been called anyhow in the main loop. Is is an error ?? Please review the code.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I think there is a mistake in line 153.
Instead of self.critic_target_model.get_weights() it should be self.target_critic_model.get_weights()