函数逼近器和 q 学习
Function approximator and q-learning
我正在尝试使用动作值近似函数实现 q 学习。我正在使用 openai-gym 和 "MountainCar-v0" 环境来测试我的算法。我的问题是,它根本没有收敛或找到目标。
基本上,逼近器的工作原理如下,您输入 2 个特征:位置和速度以及单热编码中的 3 个动作之一:0 -> [1,0,0], 1 -> [0,1,0] 和 2 -> [0,0,1]。输出是一个特定动作的动作值近似值 Q_approx(s,a)。
我知道通常输入是状态(2 个特征),输出层包含每个动作的 1 个输出。我看到的最大区别是我有 运行 前馈传递 3 次(每个动作一次)并取最大值,而在标准实现中你 运行 它一次并取最大值输出。
也许我的实现是完全错误的,我的想法是错误的。将代码粘贴在这里,它是一团糟,但我只是在试验一下:
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()))
提前致谢!
作为网络输入或网络不同输出的动作之间应该没有太大区别。例如,如果您的状态是图像,那确实会有很大的不同。因为 Conv 网络非常适合处理图像,并且没有明显的方法可以将动作集成到输入中。
你试过cartpole平衡环境吗?最好测试一下你的模型是否正常工作。
爬山很辛苦。在您到达顶峰之前没有奖励,而这通常根本不会发生。一旦你到达顶峰一次,该模型只会开始学习一些有用的东西。如果您永远无法登顶,您可能应该增加探索的时间。换句话说,采取更多随机行动,更多...
我正在尝试使用动作值近似函数实现 q 学习。我正在使用 openai-gym 和 "MountainCar-v0" 环境来测试我的算法。我的问题是,它根本没有收敛或找到目标。
基本上,逼近器的工作原理如下,您输入 2 个特征:位置和速度以及单热编码中的 3 个动作之一:0 -> [1,0,0], 1 -> [0,1,0] 和 2 -> [0,0,1]。输出是一个特定动作的动作值近似值 Q_approx(s,a)。
我知道通常输入是状态(2 个特征),输出层包含每个动作的 1 个输出。我看到的最大区别是我有 运行 前馈传递 3 次(每个动作一次)并取最大值,而在标准实现中你 运行 它一次并取最大值输出。
也许我的实现是完全错误的,我的想法是错误的。将代码粘贴在这里,它是一团糟,但我只是在试验一下:
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()))
提前致谢!
作为网络输入或网络不同输出的动作之间应该没有太大区别。例如,如果您的状态是图像,那确实会有很大的不同。因为 Conv 网络非常适合处理图像,并且没有明显的方法可以将动作集成到输入中。
你试过cartpole平衡环境吗?最好测试一下你的模型是否正常工作。
爬山很辛苦。在您到达顶峰之前没有奖励,而这通常根本不会发生。一旦你到达顶峰一次,该模型只会开始学习一些有用的东西。如果您永远无法登顶,您可能应该增加探索的时间。换句话说,采取更多随机行动,更多...