我正在尝试训练强化学习模型,以便使用keras-rl
向我回应一个点。
我的代码如下所示,使用20x20的世界形状。
import numpy as np
import rl.core as krl
class EchoEnv(krl.Env):
def __init__(self):
self.shape = np.array([20, 20])
self.desired = np.random.rand(*self.shape.shape)
def step(self, action):
action = np.clip(action, 0, 1) * self.shape
self.action = action
observation = self.desired
dx = action - (self.desired * self.shape)
distance_to_goal = np.sqrt((dx**2).sum())
done = distance_to_goal < 1
reward = -distance_to_goal
# observation, reward, done, info
return observation, reward, done, {}
def reset(self):
self.desired = np.random.rand(*self.shape.shape)
return self.desired
每次迭代,提供的observation
是当前的随机self.desired
值。 (代理应该学会立即返回此值。)done
值表示所选点是否在合理的误差范围内。提供的奖励是-distance
,因此它应该选择一个更靠近目标的点来最大化此值。
from rl.agents import DDPGAgent
from rl.memory import SequentialMemory
from rl.random import OrnsteinUhlenbeckProcess
from keras.layers import Dense, Input, concatenate, Flatten, Activation
from keras.models import Model, Sequential
from keras.optimizers import Adam
actor_n = 3
critic_n = 3
env = EchoEnv()
nb_actions = len(env.desired)
observation_shape = (nb_actions,)
actor = Sequential()
actor.add(Flatten(input_shape=(1,) + observation_shape))
for _ in range(actor_n):
actor.add(Dense(16))
actor.add(Activation("relu"))
actor.add(Dense(nb_actions))
actor.add(Activation("sigmoid"))
actor.summary()
action_input = Input(shape=observation_shape, name="action_input")
observation_input = Input(
shape=(1,) + observation_shape, name="observation_input")
flattened_observation = Flatten()(observation_input)
output = concatenate([action_input, flattened_observation])
for _ in range(critic_n):
output = Dense(32)(output)
output = Activation("relu")(output)
output = Dense(1)(output)
output = Activation("linear")(output)
critic = Model(inputs=[action_input, observation_input], outputs=[output])
critic.summary()
memory = SequentialMemory(limit=10000, window_length=1)
random_process = OrnsteinUhlenbeckProcess(
size=nb_actions, theta=.15, mu=0, sigma=.1)
agent = DDPGAgent(
nb_actions=nb_actions,
actor=actor,
critic=critic,
critic_action_input=action_input,
memory=memory,
nb_steps_warmup_critic=100,
nb_steps_warmup_actor=100,
random_process=random_process,
gamma=.99,
target_model_update=1e-3
)
agent.compile(Adam(lr=1e-2), metrics=["mae"])
agent.fit(env, nb_steps=100000, visualize=False, verbose=2)
agent.test(env, nb_episodes=10, visualize=True)
演员是Sequential
模型,从初始Flatten
图层开始。添加了具有16个节点的actor_n = 3
层的一些数字(在这种情况下为Dense
),然后激活ReLU。最后,添加Dense
层nb_actions
个节点(在本例中为2
)和sigmoid激活。
评论家从行动和观察的Input
层开始,观察是Flatten
。输出定义为concatenate
d动作和展平观察输入。添加一些具有32个节点的critic_n = 3
层的数字(在这种情况下为Dense
),然后激活ReLU。最后,添加带Dense
节点的1
图层,并添加线性激活函数。
使用的随机过程是Ornstein–Uhlenbeck process,mu = 0
,sigma = 0.1
和theta = 0.15
。
最后,使用actor,crit,random进程和其他参数(如上面的代码所示)创建实际的DDPGAgent
。它使用Adam
优化程序进行编译,学习率为0.01
,平均绝对误差指标。
理论上,这个代理人应该很快知道返回观察到的值将提供最高的回报。但是,有两个主要问题。
偶尔,随机,这将有效。它将开始返回非常接近所提供观察的行动,在[-1, 0)
范围内获得奖励,这是可能的最佳奖励。
但是,这里要注意的重要事项是“随机”。通常,它会训练数万个步骤,而不是学习这个简单的属性。偶尔,偶然,似乎有效。
如果我在找到最佳策略之前取消训练,则算法会反复猜测相同的错误值。我之前的机器学习经验让我有理由相信,即使在测试过程中,代理人也应该尝试优化策略,尽量使奖励最大化并快速结束这一集,而不是“放弃”并反复选择相同的值。
我的环境似乎没有问题。因此,问题必须在我的DDPG模型中。我的直觉告诉我,无论是演员还是评论家,它都必须是层次的东西。但是,问题很可能与任何其他参数一起,包括在随机过程或优化器中。
我怎样才能解决这些问题?