DQN понимание ввода и вывода (слой)

#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) ].

И вот ответы на ваши первоначальные вопросы:

  1. Ваш выходной уровень должен иметь 4 узла (единицы измерения).
  2. Ваш первый плотный слой не обязательно должен иметь 4 узла (единицы измерения). Если вы рассматриваете Reshape слой, понятие узлов или единиц там не подходит. Вы можете думать о Reshape слое как о заполнителе, который принимает тензор формы (None, 4, 2) и выводит измененный тензор формы (None, 8).
  3. Теперь вы должны получить выходные данные формы (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-значения, верно?