DQN понимает ввод и вывод (уровень)

У меня вопрос о входе и выходе (слое) DQN.

e.g

Две точки: P1 (x1, y1) и P2 (x2, y2)

P1 должен идти в сторону P2.

У меня есть следующая информация:

  • Текущая позиция P1 (x / y)
  • Текущая позиция P2 (x / y)
  • Расстояние до P1-P2 (x / y)
  • Направление на P1-P2 (x / y)

P1 имеет 4 возможных действия:

  • Up
  • Вниз
  • Левый
  • Верно

Как мне настроить входной и выходной слой?

  • 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)

person Tailor    schedule 01.12.2020    source источник


Ответы (2)


Добавление 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 как о заполнителе, который принимает тензор формы (Нет, 4, 2) и выводит измененный тензор формы (Нет, 8).
  3. Теперь вы должны получить выходные данные формы (None, 4) - там 4 значения представляют q-значения 4 соответствующих действий. Не нужно делать здесь argmax, чтобы найти значения q.
person Falguni Das Shuvo    schedule 02.12.2020
comment
Это сработало, спасибо большое! - person Tailor; 03.12.2020

Возможно, имеет смысл передать DQN некоторую информацию о направлении, в котором он сейчас смотрит. Вы можете настроить его как (Текущая позиция X, Текущая позиция Y, X от цели, Y от цели, Направление).

Выходной слой должен быть (вверх, влево, вниз, вправо) в указанном вами порядке. Слой Argmax подходит для этой задачи. Точный код зависит от того, используете ли вы TF / Pytorch.

person AverageHomosapien    schedule 01.12.2020
comment
Спасибо за ответ. Я использую TF. Я не понимаю, что я получаю. 4 массива из-за 4 выходных узлов и 4 возможных действий, верно? Но почему я получаю по 4 значения в каждом массиве? - person Tailor; 01.12.2020
comment
Какую форму нейронной сети вы используете? - person AverageHomosapien; 01.12.2020
comment
1 входной слой с 4 узлами, 2 плотных слоя по 128 узлов каждый и 1 выходной слой с 4 узлами - person Tailor; 01.12.2020
comment
Я изо всех сил пытаюсь понять, почему вы получаете этот выходной слой, к сожалению. Я в основном использовал Pytorch. - person AverageHomosapien; 01.12.2020
comment
Без проблем. Обычно с 4 выходами или 4 действиями я бы получил 4 значения q, верно? - person Tailor; 01.12.2020
comment
Да, вы должны получить значение для каждого действия, а затем иметь возможность использовать Argmax и выбрать лучшее действие. - person AverageHomosapien; 01.12.2020
comment
Ммм, может быть, из-за моего ввода. Входные данные выглядят так: [[P1_x, P1_y], [P2_x, P2_y], [Dist_x, Dist_y], [Dir_x, Dir_y]]. - person Tailor; 01.12.2020
comment
Можете ли вы отредактировать сообщение, чтобы включить код всей сети? Я посмотрю и посмотрю. Возможно, это ввод, кажется странным так его структурировать. - person AverageHomosapien; 01.12.2020
comment
Это нормально? - person Tailor; 01.12.2020
comment
Я бы старался избегать двумерных входов, особенно в этом формате. Я бы рекомендовал сохранить как можно меньшее количество входных значений (вам не нужно выполнять 2 вычисления расстояния, и я бы сказал, что даже местоположение P2 может быть избыточным - в зависимости от задачи). Я не удивлюсь, если вы получите странные выходы bc из 2d входа. - person AverageHomosapien; 01.12.2020
comment
Хорошо, значит, такой ввод: [P1_x, P1_y, P2_x, P2_y, Dist_x, Dist_y, Dir_x, Dir_y] может решить проблему? Я попробую ! - person Tailor; 01.12.2020