(Все ссылки на код можно найти на https://github.com/EXJUSTICE/Doom_DQN_GC/blob/master/TF2_Doom_GC_CNN.ipynb)
Фон
Я прошу прощения за длину этого поста, Я хотел, чтобы это было как можно более ясным.
Я адаптировал некоторый мой код для спортзала Atari OpenAI для работы над пакетом VizDoom для построения модели DQN в Doom с использованием изображений входных кадров 480 x640. Запустив несколько начальных демонстраций (ячейка с отметкой 8) с совершенно случайной политикой, я заметил, что модель всегда пропускает первый эпизод. Если это произойдет, вызов состояния вернет объект None. В результате я адаптировал свой исходный код, чтобы проверить, был ли выполнен эпизод, прежде чем выполнять какое-либо обучение (ячейка, помеченная как 24)
Укладка
Один из общих подходов В построении агентов для обучения подкреплению есть использование сложенных кадров. Идея здесь состоит в том, чтобы отслеживать движение, суммируя поэлементные максимумы нескольких последовательных кадров. Это показано ниже для справки:
stacked_frames = deque([np.zeros((84,84), dtype=np.int) for i in range(stack_size)], maxlen=4)
def stack_frames(stacked_frames, state, is_new_episode):
# Preprocess frame
frame = preprocess_observation(state)
if is_new_episode:
# Clear our stacked_frames
stacked_frames = deque([np.zeros((84,84), dtype=np.int) for i in range(stack_size)], maxlen=4)
# Because we're in a new episode, copy the same frame 4x, apply elementwise maxima
stacked_frames.append(frame)
stacked_frames.append(frame)
stacked_frames.append(frame)
stacked_frames.append(frame)
# Stack the frames
stacked_state = np.stack(stacked_frames, axis=2)
else:
#Since deque append adds t right, we can fetch rightmost element
#maxframe=np.maximum(stacked_frames[-1],frame)
# Append frame to deque, automatically removes the oldest frame
stacked_frames.append(frame)
# Build the stacked state (first dimension specifies different frames)
stacked_state = np.stack(stacked_frames, axis=2)
return stacked_state, stacked_frames
Проблема
Все мои попытки запустить мой агент привели к следующей ошибке:
/usr/local/lib/python3.6/dist-packages/skimage/transform/_warps.py in warp(image, inverse_map, map_args, output_shape, order, mode, cval, clip, preserve_range)
805
806 if image.size == 0:
--> 807 raise ValueError("Cannot warp empty image with dimensions", image.shape)
808
809 image = convert_to_float(image, preserve_range)
ValueError: ('Cannot warp empty image with dimensions', (0, 24))
При тщательном осмотре эта ошибка возникает из-за функции изменения формы предварительной обработки, которая вызывает преобразование scikit-image для преобразования обрезанного кадра в градациях серого во входную форму (84,84). В моем исходном коде OpenAI я вызвал функцию .reshape () вместо .transform, но я это дал мне ошибки с кадрами Vizdoom, поэтому я застрял с преобразованием.
def preprocess_observation(frame):
# Crop and resize the image into a square, as we don't need the excess information
cropped = frame[60:-60,30:-30]
normalized = cropped/255.0
img_gray = rgb2gray(normalized)
preprocessed_frame = transform.resize(img_gray, [84,84])
return preprocessed_frame
Поскольку мне показалось, что метод пытался изменить пустое изображение (я полагаю), я, естественно, проверил раздел агента done .
next_obs=np.zeros((84,84), dtype=np.int)
next_obs,stacked_frames= stack_frames(stacked_frames,next_obs,False)
exp_buffer.append([obs, action, next_obs, reward, done])
step = max_steps
history.append(episodic_reward)
print('Episode: {}'.format(len(history)),
'Total reward: {}'.format(episodic_reward))
game.new_episode()
Я полагаю, что это была проблема с укладкой, которая дала мне проблему. Поэтому я провел некоторые эксперименты, чтобы подтвердить это.
Решения предприняты
Смещение функции суммирования и попытка вызвать наблюдение из самой среды приводит к Ошибка, не относящаяся к типу, которая понятна, если учесть, что среда мертва.
Увеличение длины буфера буферной памяти позволяет увеличить время обучения (от 5 до 10 эпизодов)
3.Если удаляются все стеки из раздела done , происходит определенное обучение.
step = max_steps
history.append(episodic_reward)
print('Episode: {}'.format(len(history)),
'Total reward: {}'.format(episodic_reward))
game.new_episode()
В результате получается около 10 эпизодов обучения. до того, как мы наблюдаем серию ошибок в ячейке 24 (сокращено ниже).
ValueError Traceback (most recent call last)
ValueError: setting an array element with a sequence.
The above exception was the direct cause of the following exception:
ValueError Traceback (most recent call last)
<ipython-input-24-fa4adb5665e3> in <module>()
158
159 # merge all summaries and write to the file
--> 160 mrg_summary = merge_summary.eval(feed_dict={X:o_obs, y:np.expand_dims(y_batch, axis=-1), X_action:o_act, in_training_mode:False})
161 file_writer.add_summary(mrg_summary, global_step)
162
4 frames
/usr/local/lib/python3.6/dist-packages/numpy/core/_asarray.py in asarray(a, dtype, order)
83
84 """
---> 85 return array(a, dtype, copy=False, order=order)
86
87
ValueError: setting an array element with a sequence.
Выполнение некоторого поиска в StackOverflow приводит меня к мысли, что входной массив наблюдений, подаваемый в модель, каким-то образом не в форме процесс отбора проб. Это заставляет меня поверить, что проблема заключается в отсутствии стекирования.
Любой совет может помочь решить эту головную боль. Спасибо за ваше время!