J'essaie de mettre en œuvre q-learning avec une fonction d'approximation de valeur d'action. J'utilise openai-gym et l'environnement "MountainCar-v0" pour tester mon algorithme. Mon problème est, il ne converge pas ou ne trouve pas l'objectif du tout.Approximateur de fonction et q-learning
Fondamentalement l'approximateur fonctionne comme suit, vous alimentez dans les 2 caractéristiques: position et vitesse et l'une des 3 actions dans un codage à chaud: 0 -> [1,0,0], 1 -> [ 0,1,0] et 2 -> [0,0,1]. La sortie est l'approximation de la valeur d'action Q_approx (s, a), pour une action spécifique.
Je sais que généralement, l'entrée est l'état (2 caractéristiques) et la couche de sortie contient 1 sortie pour chaque action. La grande différence que je vois est que j'ai couru la passe d'avance 3 fois (un pour chaque action) et prenons le maximum, tandis que dans l'implémentation standard vous l'exécutez une fois et prenez le maximum sur la sortie.
Peut-être que ma mise en œuvre est complètement fausse et je me trompe. Je vais coller le code ici, c'est un bordel mais j'expérimente juste un peu:
import gym
import numpy as np
from keras.models import Sequential
from keras.layers import Dense, Activation
env = gym.make('MountainCar-v0')
# The mean reward over 20 episodes
mean_rewards = np.zeros(20)
# Feature numpy holder
features = np.zeros(5)
# Q_a value holder
qa_vals = np.zeros(3)
one_hot = {
0 : np.asarray([1,0,0]),
1 : np.asarray([0,1,0]),
2 : np.asarray([0,0,1])
}
model = Sequential()
model.add(Dense(20, activation="relu",input_dim=(5)))
model.add(Dense(10,activation="relu"))
model.add(Dense(1))
model.compile(optimizer='rmsprop',
loss='mse',
metrics=['accuracy'])
epsilon_greedy = 0.1
discount = 0.9
batch_size = 16
# Experience replay containing features and target
experience = np.ones((10*300,5+1))
# Ring buffer
def add_exp(features,target,index):
if index % experience.shape[0] == 0:
index = 0
global filled_once
filled_once = True
experience[index,0:5] = features
experience[index,5] = target
index += 1
return index
for e in range(0,100000):
obs = env.reset()
old_obs = None
new_obs = obs
rewards = 0
loss = 0
for i in range(0,300):
if old_obs is not None:
# Find q_a max for s_(t+1)
features[0:2] = new_obs
for i,pa in enumerate([0,1,2]):
features[2:5] = one_hot[pa]
qa_vals[i] = model.predict(features.reshape(-1,5))
rewards += reward
target = reward + discount*np.max(qa_vals)
features[0:2] = old_obs
features[2:5] = one_hot[a]
fill_index = add_exp(features,target,fill_index)
# Find new action
if np.random.random() < epsilon_greedy:
a = env.action_space.sample()
else:
a = np.argmax(qa_vals)
else:
a = env.action_space.sample()
obs, reward, done, info = env.step(a)
old_obs = new_obs
new_obs = obs
if done:
break
if filled_once:
samples_ids = np.random.choice(experience.shape[0],batch_size)
loss += model.train_on_batch(experience[samples_ids,0:5],experience[samples_ids,5].reshape(-1))[0]
mean_rewards[e%20] = rewards
print("e = {} and loss = {}".format(e,loss))
if e % 50 == 0:
print("e = {} and mean = {}".format(e,mean_rewards.mean()))
Merci d'avance!
J'ai entendu parler d'utiliser les actions comme des fonctionnalités avant, mais je n'ai pas entendu parler de cela fonctionne bien. Je pense que vous êtes mieux d'aller avec la tradition à ce sujet et d'utiliser des actions comme sorties. Mathématiquement, ces deux réseaux seront très différents. – Andnp