Проблема с созданием слоя LSTM с одномерным входом датчика - PullRequest
0 голосов
/ 31 октября 2019

Я пытаюсь заменить свой FFNN слоем LSTM. В качестве входных данных я получаю 360 Lidar Data Point и 4 дополнительных значения для расстояния и т. Д. Алгоритм должен научиться ориентироваться в роботе по окружающей среде. С FFNN он работает абсолютно нормально, и для LSTM я начал так:

# collected data for RL
scan_range = [] #filled with .append, length=360
state = scan_range + [heading, current_distance, obstacle_min_range, obstacle_angle]
return np.asarray(state)

На основании этих данных будет проведен некоторый анализ для следующего состояния, если цель достигнута и т. Д. Данные будутхраниться в памяти: agent.appendMemory(state, action, reward, next_state, done), что будет: self.memory.append((state, action, reward, next_state, done). Действие и награда - это обычные числа, а next_state снова массивследующее для FFNN:

    def trainModel(self, target=False):
        mini_batch = random.sample(self.memory, self.batch_size)
        X_batch = np.empty((0, self.state_size), dtype=np.float64)
        Y_batch = np.empty((0, self.action_size), dtype=np.float64)

        for i in range(self.batch_size):
            states = mini_batch[i][0]
            actions = mini_batch[i][1]
            rewards = mini_batch[i][2]
            next_states = mini_batch[i][3]
            dones = mini_batch[i][4]

            q_value = self.model.predict(states.reshape((1, len(states))))
            self.q_value = q_value

            if target:
                next_target = self.target_model.predict(next_states.reshape((1, len(next_states))))

            else:
                next_target = self.model.predict(next_states.reshape((1, len(next_states))))

            next_q_value = self.getQvalue(rewards, next_target, dones)

            X_batch = np.append(X_batch, np.array([states.copy()]), axis=0)
            Y_sample = q_value.copy()

            Y_sample[0][actions] = next_q_value
            Y_batch = np.append(Y_batch, np.array([Y_sample[0]]), axis=0)

            if dones:
                X_batch = np.append(X_batch, np.array([next_states.copy()]), axis=0)
                Y_batch = np.append(Y_batch, np.array([[rewards] * self.action_size]), axis=0)
            print X_batch.shape
            print Y_batch.shape
        self.model.fit(X_batch, Y_batch, batch_size=self.batch_size, epochs=1, verbose=0)

Когда я не изменяю код, я точно получаю ошибку измерения: expected simple_rnn_1_input to have 3 dimensions, but got array with shape (1, 364), потому что вход по-прежнему двумерный, а LSTM требуется три измерения. Затем я попытался добавить третье измерение вручную, чтобы посмотреть, все ли работает нормально:

mini_batch = random.sample(self.memory, self.batch_size)
        X_batch = np.empty((0, self.state_size), dtype=np.float64)
        Y_batch = np.empty((0, self.action_size), dtype=np.float64)
        Z_batch = np.empty((0, 1), dtype=np.float64)

        for i in range(self.batch_size):
            states = mini_batch[i][0]
            actions = mini_batch[i][1]
            rewards = mini_batch[i][2]
            next_states = mini_batch[i][3]
            dones = mini_batch[i][4]

            q_value = self.model.predict(states.reshape((1, len(states))))
            self.q_value = q_value

            if target:
                next_target = self.target_model.predict(next_states.reshape((1,1, len(next_states))))

            else:
                next_target = self.model.predict(next_states.reshape((1,1, len(next_states))))

            next_q_value = self.getQvalue(rewards, next_target, dones)

            X_batch = np.append(X_batch, np.array([states.copy()]), axis=0)
            Y_sample = q_value.copy()

            Y_sample[0][actions] = next_q_value
            Y_batch = np.append(Y_batch, np.array([Y_sample[0]]), axis=0)
            Z_batch = np.append(Z_batch, np.array([[1]]), axis=0)

            if dones:
                X_batch = np.append(X_batch, np.array([next_states.copy()]), axis=0)
                Y_batch = np.append(Y_batch, np.array([[rewards] * self.action_size]), axis=0)
                Z_batch = np.append(Z_batch, np.array([[1]]), axis=0)

        self.model.fit(X_batch, Y_batch, Z_batch, batch_size=self.batch_size, epochs=1, verbose=0)

Когда я это делаю, .fit () выдает следующую ошибку: TypeError: fit() got multiple values for keyword argument 'batch_size' Мой вопрос сейчас, если.fit () в этом случае подходит для фреймворка LSTM? В документации указаны только x и z. Z кажется бесполезным в этом случае, но все же LSTM требует 3 измерения в качестве входных данных. Кроме того, мой вопрос: если я хочу использовать структуру LSTM правильно, а не с пустышками, я должен использовать больше, чем фактическое состояние? Могу ли я тогда, то есть просто сложить вместе последние 10 состояний, чтобы states.shape = (10,1364), это хороший диапазон временного шага или он должен быть длиннее? С уважением!

1 Ответ

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

Я считаю, что ваша основная проблема заключается в том, что 3-е измерение необходимо добавить в X_batch, а не другой компонент в model.fit.

В частности, модели Keras, как правило, не определяют размерность «партия» / «образец» в слоях модели. Он автоматически выводится из формы входных данных X_batch. В вашем случае у вас есть SimpleRNN с input_shape = (1364) в качестве первого слоя. Keras интерпретирует это так, что входные данные X_batch должны иметь такую ​​форму:

(num_samples, 1, 364).

Кроме того, если вы хотите создать последовательность временных шагов,вы бы предоставили X_batch следующую форму:

(num_samples, num_timesteps, 364) или что-то подобное.

На этой странице есть хорошее обсуждение: например, https://keras.io/getting-started/sequential-model-guide/, поиск для«Сложенный LSTM для классификации последовательностей», чтобы проиллюстрировать (хотя будьте осторожны с return_sequence = True - для одного LSTM вы, вероятно, захотите return_sequence = False.)

Надеюсь, это поможет.

...