训练 keras 模型时维度如何工作?

How does the dimensions work when training a keras model?

获得:

    assert q_values.shape == (len(state_batch), self.nb_actions)
AssertionError
q_values.shape <class 'tuple'>: (1, 1, 10)
(len(state_batch), self.nb_actions) <class 'tuple'>: (1, 10)

来自 sarsa 代理的 keras-rl 库:

rl.agents.sarsa.SARSAAgent#compute_batch_q_values

    batch = self.process_state_batch(state_batch)
    q_values = self.model.predict_on_batch(batch)
    assert q_values.shape == (len(state_batch), self.nb_actions)

这是我的代码:

class MyEnv(Env):

    def __init__(self):
        self._reset()

    def _reset(self) -> None:
        self.i = 0

    def _get_obs(self) -> List[float]:
        return [1] * 20

    def reset(self) -> List[float]:
        self._reset()
        return self._get_obs()



    model = Sequential()
    model.add(Dense(units=20, activation='relu', input_shape=(1, 20)))
    model.add(Dense(units=10, activation='softmax'))
    logger.info(model.summary())

    policy = BoltzmannQPolicy()
    agent = SARSAAgent(model=model, nb_actions=10, policy=policy)

    optimizer = Adam(lr=1e-3)
    agent.compile(optimizer, metrics=['mae'])

    env = MyEnv()
    agent.fit(env, 1, verbose=2, visualize=True)

想知道是否有人可以向我解释应该如何设置维度以及它如何与库一起使用?我正在输入一个包含 20 个输入的列表,并希望输出 10 个。

此特定错误是由于您的输入形状为 (1, 20) 引起的。如果您使用 (20,) 的输入形状,错误将消失。

换句话说,SARSAAgent 需要一个输出二维张量的模型(batch_size、nb_actions)。您的模型正在输出 (batch_size, 1, 10) 的形状。您可以减少模型输入的维度或展平输出。

自定义环境

先搭建一个简单的玩具环境

  1. 这是一个一维迷宫:[1,1,0,1,1,0,1,1,0]
  2. 1:踏入这块迷宫将获得奖励1
  3. 0:踏入这块迷宫会死亡,奖励为0
  4. 允许的操作0:移动到下一个迷宫块,1:跳过下一个块,即跳过下一个并移动到下一个迷宫块的下一个块

要在 gym 中实现我们的环境,我们需要实现 2 个方法

  • step:采取行动并执行步骤,returns 步骤后的状态,奖励和表示游戏是否结束的 bool
  • 重置:重置游戏和return当前状态(初始状态)

环境码

class FooEnv(gym.Env):
    def __init__(self):
        self.maze = [1,1,0,1,1,0,1,1,0]
        self.curr_state = 0
        self.action_space = spaces.Discrete(2)
        self.observation_space = spaces.Discrete(1)

    def step(self, action):        
        if action == 0:
            self.curr_state += 1
        if action == 1:
            self.curr_state += 2

        if self.curr_state >= len(self.maze):
            reward = 0.
            done = True
        else:
            if self.maze[self.curr_state] == 0:
                reward = 0.
                done = True
            else:
                reward = 1.
                done = False
        return np.array(self.curr_state), reward, done, {}

    def reset(self):
        self.curr_state = 0
        return np.array(self.curr_state)

神经网络

现在给定当前状态,我们希望神经网络预测要采取的行动。

  • NN 将采用当前状态,这是一个表示我们当前所在的迷宫块的单个数字作为输入
  • NN 将 return 两个可能的操作之一 0 或 `1

NN 代码

model = Sequential()
model.add(Dense(units=16, activation='relu', input_shape=(1,)))
model.add(Dense(units=8, activation='relu'))
model.add(Dense(units=2, activation='softmax'))

放在一起

policy = BoltzmannQPolicy()
agent = SARSAAgent(model=model, nb_actions=2, policy=policy)

optimizer = Adam(lr=1e-3)
agent.compile(optimizer, metrics=['acc'])

env = FooEnv()
agent.fit(env, 10000, verbose=1, visualize=False)
# Test the trained agent using
# agent.test(env, nb_episodes=5, visualize=False)

输出

Training for 10000 steps ...
Interval 1 (0 steps performed)
10000/10000 [==============================] - 54s 5ms/step - reward: 0.6128
done, took 53.519 seconds

如果您的环境是一个网格 (2D),如果大小 n X m 那么 NN 的输入大小将是 (n,m) 如下所示,并在传递到密集层之前将其展平

model.add(Flatten(input_shape=(n,m))

检查来自 keras-rl docs

的示例