Более эффективный способ для многомерного разбиения пространства состояний-действий, чем с np.meshgrid? - PullRequest
1 голос
/ 03 октября 2019

Прежде всего, это для практики и сравнения, я знаю, что есть более эффективные способы разбиения пространства состояний, чем с помощью линейной сетки.

Чтобы запустить некоторый алгоритм обучения с подкреплением, я бы хотел выложить своипространство состояний и действий линейное. В результате я хочу иметь каждую пару пространства-действия в виде массива. Проблема в том, что существуют разные (тренажерные) среды с разными размерами состояния и пространства действия. Поэтому я не люблю иметь жестко закодированные переменные или размеры. Поэтому мне нужно вычислить каждую пару состояния-действия, учитывая только минимальное и максимальное значения для каждого.

Я в основном решил простые задачи, но ни одно из решений не является "симпатичным".

Сначала давайте вычислим состояние и пространство действия. Плитка области с linspace от мин до макс. Я дал переменные для одной случайной тестовой среды.

import numpy as np
NOF_ACTION_SPACE_TILES = 20
NOF_STATE_SPACE_TILES = 10
action_low = np.array([-2])
state_low = np.array([-1, -1, -8])

action_space = np.vstack([*[x.flatten() for x in (np.meshgrid(*(np.linspace(action_low, action_high, NOF_ACTION_SPACE_TILES).T)))]]).T

state_space = np.vstack([*[x.flatten() for x in (np.meshgrid(*(np.linspace(state_low, state_high, NOF_STATE_SPACE_TILES).T)))]]).T

Это работает как задумано и дает все возможные комбинации для состояний и действий самостоятельно. Любой способ сделать это более прямо вперед? Мне нужно было использовать * [] два раза, потому что np.meshgrid возвращал несколько матриц и пытался сгладить векторы.

Теперь к забавной части ...

В конце яхочу иметь каждую возможную пару состояние-действие. Каждое государство с каждым действием. Это довольно быстро закодировано для циклов for, но ... цикл и for не являются быстрыми друзьями. Вот мой обходной путь, который работает для одномерного пространства действий:

s_s, a_s = np.meshgrid(state_space, action_space)

state_action_space = np.concatenate((
   s_s.reshape(-1, state_space.shape[1]),
   a_s.reshape(state_space.shape[1], action_space.shape[1], -1)[0].T), axis=1)

С state_space.shape[1], когда не хватает единственного состояния / действия.

Одна проблема, которая возвращается np.meshgrida_s для каждого из 3 измерений пространства состояний, и изменение его формы, как указано выше, не работает, потому что нам нужно изменить состояние на 3xn, а действие на 1xn.

Это даже хуже, чем приведенный выше код, но пока работает. У кого-нибудь есть предложения, как правильно и быстро использовать meshgrid или sth?

В конце, для второго шага, это просто комбинация каждой строки из двух матриц. Должен быть лучший способ ...

1 Ответ

0 голосов
/ 03 октября 2019

Благодаря обоим ответам выше, вот мои окончательные результаты. Мне по-прежнему приходилось использовать * (), чтобы разобрать linspace для meshgrid, но теперь он выглядит более читабельным. Большая проблема с кодом действия состояния раньше заключалась в том, что я пытался его слишком усложнить. Это просто копирование массивов друг на друга. Поэтому просто копируйте (или мозаику в данном случае) массив пространства состояний так часто, как вы выполняете различные действия в пространстве действий. Это то же самое, что и ACTION_SPACE_SIZE^(action-dims).

    action_space = np.stack(np.meshgrid(*(np.linspace(env.action_space.low, env.action_space.high, ACTION_SPACE_SIZE)).T), -1).reshape(-1, env.action_space.shape[0])

    state_space = np.stack(np.meshgrid(*(np.linspace(env.observation_space.low, env.observation_space.high, STATE_SPACE_SIZE)).T), -1).reshape(-1, env.observation_space.shape[0])

    state_action_space = np.concatenate((
        np.tile(state_space, (action_space.shape[0])).reshape(-1, state_space.shape[1])
        np.tile(action_space, (state_space.shape[0], 1))
        ), axis=1)
...