Модель Keras: ошибка измерения формы ввода для агента RL - PullRequest
1 голос
/ 19 марта 2020

Моя цель - разработать DQN-агента , который будет выбирать свое действие на основе определенной стратегии / политики. Ранее я работал с спортивными средами OpenAi, но теперь я хотел создать свою собственную среду RL.

На этом этапе агент должен выбрать случайное действие или выбрать свое действие на основе предсказания, данные глубокой нейронной сетью (определены в классе DQN ).

Пока что я настроил модель neural net и мою среду . NN должен получать состояния в качестве входных данных. Эти состояния представляют 11 возможных скалярных значений в диапазоне от 9,5 до 10,5 (9,5, 9,6, ..., 10,4, 10,5). Поскольку мы имеем дело с RL, агент генерирует свои данные в процессе обучения. Выходные данные должны быть равны 0 и 1 в соответствии с рекомендуемым действием.

Теперь я хотел бы передать моему агенту скалярное значение : например, состояние выборки x = 10 и позволить ему принять решение о том, какое действие предпринять (вызывается Agent.select_action ()), я столкнулся с проблемой, связанной с формой ввода / размером ввода.

Вот код: 1. Класс DQN:

class DQN():

    def __init__(self, state_size, action_size, lr):
        self.state_size = state_size
        self.action_size = action_size
        self.lr = lr

        self.model = Sequential()
        self.model.add(Dense(128, input_dim=self.state_size, activation='relu'))
        self.model.add(Dense(128, activation='relu'))
        self.model.add(Dense(self.action_size, activation='linear'))

        self.model.compile(optimizer=Adam(lr=self.lr), loss='mse')

        self.model.summary()


    def model_info(self):
        model_description = '\n\n---Model_INFO Summary: The model was passed {} state sizes,\
            \n {} action sizes and a learning rate of {} -----'\
                            .format(self.state_size, self.action_size, self.lr)
        return model_description

    def predict(self, state):
        return self.model.predict(state)

    def train(self, state, q_values):
        self.state = state
        self.q_values = q_values
        return self.model.fit(state, q_values, verbose=0)

    def load_weights(self, path):
        self.model.load_weights(path)

    def save_weights(self, path):
        self.model.save_weights(path)

2. Класс агента:

NUM_EPISODES = 100
MAX_STEPS_PER_EPISODE = 100
EPSILON = 0.5 
EPSILON_DECAY_RATE = 0.001
EPSILON_MIN = 0.01
EPSILON_MAX = 1
DISCOUNT_FACTOR = 0.99
REPLAY_MEMORY_SIZE = 50000
BATCH_SIZE = 50
TRAIN_START = 100
ACTION_SPACE = [0, 1]
STATE_SIZE = 11 
LEARNING_RATE = 0.01

class Agent():
    def __init__(self, num_episodes, max_steps_per_episode, epsilon, epsilon_decay_rate, \
        epsilon_min, epsilon_max, discount_factor, replay_memory_size, batch_size, train_start):
        self.num_episodes = NUM_EPISODES
        self.max_steps_per_episode = MAX_STEPS_PER_EPISODE
        self.epsilon = EPSILON
        self.epsilon_decay_rate = EPSILON_DECAY_RATE
        self.epsilon_min = EPSILON_MIN
        self.epsilon_max = EPSILON_MAX
        self.discount_factor = DISCOUNT_FACTOR
        self.replay_memory_size = REPLAY_MEMORY_SIZE
        self.replay_memory = deque(maxlen=self.replay_memory_size)
        self.batch_size = BATCH_SIZE
        self.train_start = TRAIN_START
        self.action_space = ACTION_SPACE
        self.action_size = len(self.action_space)
        self.state_size = STATE_SIZE
        self.learning_rate = LEARNING_RATE
        self.model = DQN(self.state_size, self.action_size, self.learning_rate)

    def select_action(self, state):
        random_value = np.random.rand()
        if random_value < self.epsilon:
            print('random_value = ', random_value)       
            chosen_action = random.choice(self.action_space) # = EXPLORATION Strategy
            print('Agent randomly chooses the following EXPLORATION action:', chosen_action)       
        else: 
            print('random_value = {} is greater than epsilon'.format(random_value))       
            state = np.float32(state) # Transforming passed state into numpy array
            prediction_by_model = self.model.predict(state) 
            chosen_action = np.argmax(prediction_by_model[0]) # = EXPLOITATION strategy
            print('NN chooses the following EXPLOITATION action:', chosen_action)       
        return chosen_action

if __name__ == "__main__":
    agent_test = Agent(NUM_EPISODES, MAX_STEPS_PER_EPISODE, EPSILON, EPSILON_DECAY_RATE, \
        EPSILON_MIN, EPSILON_MAX, DISCOUNT_FACTOR, REPLAY_MEMORY_SIZE, BATCH_SIZE, \
            TRAIN_START)
    # Test of select_action function:
    state = 10 
    state = np.array(state)
    print(state.shape)
    print(agent_test.select_action(state))

Вот ошибка трассировки, которую я получаю при выполнении этого кода:

**ValueError**: Error when checking input: expected dense_209_input to have 2 dimensions, but got array with shape ()

Я не уверен, почему возникает ошибка, касающаяся двух измерений, так как я настроил NN в классе DQN для получения только 1 измерения.

Я уже читал подобные вопросы о стекапровороте ( Форма ввода последовательной модели Keras , Форма ввода модели Keras неправильная, Объяснение ввода Keras: input_shape, единицы, batch_size, dim, et c). Однако я еще не смог адаптировать предложения к своему варианту использования.

Есть ли у вас какие-либо предложения или советы? Спасибо за помощь!

1 Ответ

2 голосов
/ 19 марта 2020

Здесь есть несколько проблем. Во-первых, то, что вы называете state_size, на самом деле является пространством состояний, то есть набором всех возможных состояний, в которых может находиться ваш агент. Размер состояния фактически равен 1, поскольку существует только один параметр, который вы хотите передать как состояние.

Когда вы определяете свой входной слой здесь:

self.model.add(Dense(128, input_dim=self.state_size, activation='relu'))

Вы говорите, что ваше входное измерение будет равно 11, но затем, когда вы вызываете прогноз, вы передаете ему 1 число (10).

Таким образом, вам нужно либо изменить input_dim, чтобы получить только одно число, либо вы можете определить свой вектор состояния, например state = np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), каждое число соответствует возможному состоянию (от 9,5 до 10,5). Поэтому, когда состояние равно 9,5, ваш вектор состояния равен [1, 0, 0, ...0] и т. Д.

Вторая проблема заключается в том, что когда вы определяете свое состояние, вы должны ставить квадратные скобки

state = np.array([10])

, иначе массив форма (), как я уверен, вы узнали.

Надеюсь, это поможет! Дайте мне знать, если вам нужны какие-либо разъяснения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...