#python #deep-learning #reinforcement-learning #q-learning #dqn
#python #глубокое обучение #подкрепление-обучение #q-обучение #dqn
Вопрос:
У меня есть вопрос о вводе и выводе (уровне) 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)
Ответ №1:
Добавление 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
метод, который вы написали, policy(np.expand_dims(state,0))
и получить результат измерения (batch_shape, 4)
[в данном случае (1,4)
].
И вот ответы на ваши первоначальные вопросы:
- Ваш выходной уровень должен иметь 4 узла (единицы измерения).
- Ваш первый плотный слой не обязательно должен иметь 4 узла (единицы измерения). Если вы рассматриваете
Reshape
слой, понятие узлов или единиц там не подходит. Вы можете думать оReshape
слое как о заполнителе, который принимает тензор формы (None, 4, 2) и выводит измененный тензор формы (None, 8). - Теперь вы должны получить выходные данные формы (None, 4) — там 4 значения представляют q-значения 4 соответствующих действий. Здесь не нужно ничего делать
argmax
, чтобы найти q-значения.
Ответ №2:
Может иметь смысл передать DQN некоторую информацию о направлении, в котором он находится в данный момент. Вы могли бы настроить его как (текущий Pos X, текущий Pos Y, X от цели, Y от цели, направление).
Выходной слой должен быть просто (Вверх, Влево, вниз, вправо) в определенном вами порядке. Слой Argmax подходит для решения этой проблемы. Точный код зависит от того, используете ли вы TF / Pytorch.
Комментарии:
1. Спасибо за ваш ответ. Я использую TF. Я не понимаю результат, который я получаю. 4 массива из-за 4 выходных узлов и 4 возможных действий, верно? Но почему я получаю 4 значения в каждом массиве?
2. Какова форма используемой вами нейронной сети?
3. 1 Входной слой с 4 узлами, 2 плотных слоя по 128 узлов в каждом и 1 выходной слой с 4 узлами
4. К сожалению, я пытаюсь понять, почему вы получаете этот выходной уровень. В основном я использовал Pytorch.
5. Нет проблем. Обычно при 4 выходных данных, т.е. 4 действиях, я бы получил 4 q-значения, верно?