我有一个关于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)
在第一个密集层中添加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(的重塑张量 - 现在,您应该得到shape(None,4(的输出——在那里,4个值表示4个相应动作的q值。无需在此处执行
argmax
来查找q值
向DQN提供一些关于其当前面临的方向的信息也是有意义的。您可以将其设置为(当前位置X、当前位置Y、X来自目标、Y来自目标、方向(。
输出层应该按照您确定的顺序(向上、向左、向下、向右(。Argmax层适用于该问题。确切的代码取决于您是否使用TF/Pythorch。