DQN理解输入输出(层)
DQN understanding input and output (layer)
我对 DQN 的输入和输出(层)有疑问。
例如
两点:P1(x1, y1) 和 P2(x2, y2)
P1 必须走向 P2
我有以下信息:
- 当前位置 P1 (x/y)
- 当前位置 P2 (x/y)
- 到 P1-P2 的距离(x/y)
- P1-P2方向(x/y)
P1 有 4 个可能的动作:
- 向上
- 向下
- 左
- 右
如何设置输入和输出层?
- 4个输入节点
- 4个输出节点
对吗?
我与输出有什么关系?
我有 4 个数组,每个数组有 4 个值作为输出。
对输出执行 argmax 是否正确?
编辑:
输入/状态:
# Current position P1
state_pos = [x_POS, y_POS]
state_pos = np.asarray(state_pos, dtype=np.float32)
# Current position P2
state_wp = [wp_x, wp_y]
state_wp = np.asarray(state_wp, dtype=np.float32)
# Distance P1 - P2
state_dist_wp = [wp_x - x_POS, wp_y - y_POS]
state_dist_wp = np.asarray(state_dist_wp, dtype=np.float32)
# Direction P1 - P2
distance = [wp_x - x_POS, wp_y - y_POS]
norm = math.sqrt(distance[0] ** 2 + distance[1] ** 2)
state_direction_wp = [distance[0] / norm, distance[1] / norm]
state_direction_wp = np.asarray(state_direction_wp, dtype=np.float32)
state = [state_pos, state_wp, state_dist_wp, state_direction_wp]
state = np.array(state)
网络:
def __init__(self):
self.q_net = self._build_dqn_model()
self.epsilon = 1
def _build_dqn_model(self):
q_net = Sequential()
q_net.add(Dense(4, input_shape=(4,2), activation='relu', kernel_initializer='he_uniform'))
q_net.add(Dense(128, activation='relu', kernel_initializer='he_uniform'))
q_net.add(Dense(128, activation='relu', kernel_initializer='he_uniform'))
q_net.add(Dense(4, activation='linear', kernel_initializer='he_uniform'))
rms = tf.optimizers.RMSprop(lr = 1e-4)
q_net.compile(optimizer=rms, loss='mse')
return q_net
def random_policy(self, state):
return np.random.randint(0, 4)
def collect_policy(self, state):
if np.random.random() < self.epsilon:
return self.random_policy(state)
return self.policy(state)
def policy(self, state):
# Here I get 4 arrays with 4 values each as output
action_q = self.q_net(state)
向 DQN 提供一些关于它当前面向的方向的信息也是有意义的。您可以将其设置为(当前位置 X、当前位置 Y、目标 X、目标 Y、方向)。
输出层应该按照您确定的顺序(上、左、下、右)排列。 Argmax 层适用于该问题。确切的代码取决于您是否使用 TF / Pytorch。
在第一个 Dense 层中添加 input_shape=(4,2)
导致输出形状为 (None, 4, 4)
。
通过以下方式定义 q_net 即可解决:
q_net = Sequential()
q_net.add(Reshape(target_shape=(8,), input_shape=(4,2)))
q_net.add(Dense(128, activation='relu', kernel_initializer='he_uniform'))
q_net.add(Dense(128, activation='relu', kernel_initializer='he_uniform'))
q_net.add(Dense(128, activation='relu', kernel_initializer='he_uniform'))
q_net.add(Dense(4, activation='linear', kernel_initializer='he_uniform'))
rms = tf.optimizers.RMSprop(lr = 1e-4)
q_net.compile(optimizer=rms, loss='mse')
return q_net
此处,q_net.add(Reshape(target_shape=(8,), input_shape=(4,2)))
将 (None, 4, 2) 输入重塑为 (None, 8) [此处,None 表示批量形状]。
为了验证,打印 q_net.output_shape
它应该是 (None, 4)
[而在之前的例子中它是 (None, 4, 4)
]。
你还需要做一件事。回想一下 input_shape
没有考虑批处理形状。我的意思是,input_shape=(4,2)
期望形状为 (batch_shape, 4, 2) 的输入。通过打印 q_net.input_shape
来验证它,它应该输出 (None, 4, 2)
。现在,您要做的是 - 为您的输入添加一个批次维度。您只需执行以下操作:
state_with_batch_dim = np.expand_dims(state,0)
并将state_with_batch_dim
作为输入传递给q_net。例如,您可以像 policy(np.expand_dims(state,0))
一样调用您编写的 policy
方法并获得维度 (batch_shape, 4)
的输出 [在本例中为 (1,4)
].
以下是您最初问题的答案:
- 你的输出层应该有 4 个节点(单元)。
- 你的第一个密集层不一定要有 4 个节点(单元)。如果您考虑
Reshape
层,节点或单元的概念不适合那里。您可以将 Reshape
层视为占位符,它采用形状为 (None, 4, 2) 的张量并输出形状为 (None, 8) 的重塑张量。
- 现在,您应该得到形状为 (None, 4) 的输出 - 在那里,4 个值代表 4 个对应动作的 q 值。无需在此处执行
argmax
即可找到 q 值。
我对 DQN 的输入和输出(层)有疑问。
例如
两点:P1(x1, y1) 和 P2(x2, y2)
P1 必须走向 P2
我有以下信息:
- 当前位置 P1 (x/y)
- 当前位置 P2 (x/y)
- 到 P1-P2 的距离(x/y)
- P1-P2方向(x/y)
P1 有 4 个可能的动作:
- 向上
- 向下
- 左
- 右
如何设置输入和输出层?
- 4个输入节点
- 4个输出节点
对吗? 我与输出有什么关系? 我有 4 个数组,每个数组有 4 个值作为输出。 对输出执行 argmax 是否正确?
编辑:
输入/状态:
# Current position P1
state_pos = [x_POS, y_POS]
state_pos = np.asarray(state_pos, dtype=np.float32)
# Current position P2
state_wp = [wp_x, wp_y]
state_wp = np.asarray(state_wp, dtype=np.float32)
# Distance P1 - P2
state_dist_wp = [wp_x - x_POS, wp_y - y_POS]
state_dist_wp = np.asarray(state_dist_wp, dtype=np.float32)
# Direction P1 - P2
distance = [wp_x - x_POS, wp_y - y_POS]
norm = math.sqrt(distance[0] ** 2 + distance[1] ** 2)
state_direction_wp = [distance[0] / norm, distance[1] / norm]
state_direction_wp = np.asarray(state_direction_wp, dtype=np.float32)
state = [state_pos, state_wp, state_dist_wp, state_direction_wp]
state = np.array(state)
网络:
def __init__(self):
self.q_net = self._build_dqn_model()
self.epsilon = 1
def _build_dqn_model(self):
q_net = Sequential()
q_net.add(Dense(4, input_shape=(4,2), activation='relu', kernel_initializer='he_uniform'))
q_net.add(Dense(128, activation='relu', kernel_initializer='he_uniform'))
q_net.add(Dense(128, activation='relu', kernel_initializer='he_uniform'))
q_net.add(Dense(4, activation='linear', kernel_initializer='he_uniform'))
rms = tf.optimizers.RMSprop(lr = 1e-4)
q_net.compile(optimizer=rms, loss='mse')
return q_net
def random_policy(self, state):
return np.random.randint(0, 4)
def collect_policy(self, state):
if np.random.random() < self.epsilon:
return self.random_policy(state)
return self.policy(state)
def policy(self, state):
# Here I get 4 arrays with 4 values each as output
action_q = self.q_net(state)
向 DQN 提供一些关于它当前面向的方向的信息也是有意义的。您可以将其设置为(当前位置 X、当前位置 Y、目标 X、目标 Y、方向)。
输出层应该按照您确定的顺序(上、左、下、右)排列。 Argmax 层适用于该问题。确切的代码取决于您是否使用 TF / Pytorch。
在第一个 Dense 层中添加 input_shape=(4,2)
导致输出形状为 (None, 4, 4)
。
通过以下方式定义 q_net 即可解决:
q_net = Sequential()
q_net.add(Reshape(target_shape=(8,), input_shape=(4,2)))
q_net.add(Dense(128, activation='relu', kernel_initializer='he_uniform'))
q_net.add(Dense(128, activation='relu', kernel_initializer='he_uniform'))
q_net.add(Dense(128, activation='relu', kernel_initializer='he_uniform'))
q_net.add(Dense(4, activation='linear', kernel_initializer='he_uniform'))
rms = tf.optimizers.RMSprop(lr = 1e-4)
q_net.compile(optimizer=rms, loss='mse')
return q_net
此处,q_net.add(Reshape(target_shape=(8,), input_shape=(4,2)))
将 (None, 4, 2) 输入重塑为 (None, 8) [此处,None 表示批量形状]。
为了验证,打印 q_net.output_shape
它应该是 (None, 4)
[而在之前的例子中它是 (None, 4, 4)
]。
你还需要做一件事。回想一下 input_shape
没有考虑批处理形状。我的意思是,input_shape=(4,2)
期望形状为 (batch_shape, 4, 2) 的输入。通过打印 q_net.input_shape
来验证它,它应该输出 (None, 4, 2)
。现在,您要做的是 - 为您的输入添加一个批次维度。您只需执行以下操作:
state_with_batch_dim = np.expand_dims(state,0)
并将state_with_batch_dim
作为输入传递给q_net。例如,您可以像 policy(np.expand_dims(state,0))
一样调用您编写的 policy
方法并获得维度 (batch_shape, 4)
的输出 [在本例中为 (1,4)
].
以下是您最初问题的答案:
- 你的输出层应该有 4 个节点(单元)。
- 你的第一个密集层不一定要有 4 个节点(单元)。如果您考虑
Reshape
层,节点或单元的概念不适合那里。您可以将Reshape
层视为占位符,它采用形状为 (None, 4, 2) 的张量并输出形状为 (None, 8) 的重塑张量。 - 现在,您应该得到形状为 (None, 4) 的输出 - 在那里,4 个值代表 4 个对应动作的 q 值。无需在此处执行
argmax
即可找到 q 值。