#python #tensorflow #keras #deep-learning #lstm
#python #tensorflow #keras #глубокое обучение #lstm
Вопрос:
Я создал LSTM, используя Keras с TensorFlow в качестве серверной части. Перед тем, как мини-пакет с num_step 96 будет передан в обучение, скрытое состояние LSTM устанавливается в истинные значения предыдущего временного шага.
Сначала параметры и данные:
batch_size = 10
num_steps = 96
num_input = num_output = 2
hidden_size = 8
X_train = np.array(X_train).reshape(-1, num_steps, num_input)
Y_train = np.array(Y_train).reshape(-1, num_steps, num_output)
X_test = np.array(X_test).reshape(-1, num_steps, num_input)
Y_test = np.array(Y_test).reshape(-1, num_steps, num_output)
Модель Keras состоит из двух слоев LSTM и одного слоя для обрезки вывода до num_output, который равен 2:
model = Sequential()
model.add(LSTM(hidden_size, batch_input_shape=((batch_size, num_steps, num_input)),
return_sequences=True, stateful = True)))
model.add(LSTM(hidden_size, return_sequences=True)))
model.add(Dropout(0.2))
model.add(TimeDistributed(Dense(num_output, activation='softmax')))
model.compile(loss='mean_squared_error', optimizer='adam', metrics=['accuracy'])
Генератор, а также обучение (hidden_states[x] имеет форму (2,)):
def gen_data():
x = np.zeros((batch_size, num_steps, num_input))
y = np.zeros((batch_size, num_steps, num_output))
while True:
for i in range(batch_size):
model.layers[0].states[0] = K.variable(value=hidden_states[gen_data.current_idx]) # hidden_states[x] has shape (2,)
x[i, :, :] = X_train[gen_data.current_idx]
y[i, :, :] = Y_train[gen_data.current_idx]
gen_data.current_idx = 1
yield x, y
gen_data.current_idx = 0
for epoch in range(100):
model.fit_generator(generate_data(), len(X_train)//batch_size, 1,
validation_data=None, max_queue_size=1, shuffle=False)
gen_data.current_idx = 0
Этот код не выдает мне ошибку, но у меня есть два вопроса по этому поводу:
1) Внутри генератора я устанавливаю скрытое состояние LSTM model.layers[0].states[0]
в переменную on hidden_states[gen_data.current_idx]
с формой (2,). Почему это возможно для LSTM со скрытым размером больше 2?
2) Значения в hidden_states[gen_data.current_idx]
также могут быть выводом из модели Keras. Имеет ли смысл для двухслойного LSTM устанавливать скрытое состояние таким образом?
Ответ №1:
Состояния в LSTM
LSTM состоит из элементов, которые вычисляют cell state
и hidden state
.
На рисунке верхняя стрелка, выходящая справа от LSTM, указывает на состояние ячейки ( c_t
), а нижняя стрелка — на скрытое состояние ( h_t
). Состояния ячеек являются результатом манипулирования с закрытыми настройками, а размер состояния такой же, как hidden_size
у LSTM. Каждое развертывание (с соответствующим вводом X) приводит к собственному состоянию ячейки. В случае LSTM состояние ячейки состоит из двух значений hidden_state( h_t
) из (batch_size x hidden_size) и cell_state ( c_t
) из (batch_size x hidden_size).
batch_size = 2
num_steps = 5
num_input = num_output = 1
hidden_size = 8
inputs = Input(batch_shape=(batch_size,num_steps, num_input))
lstm, state_h, state_c = LSTM(hidden_size, return_state=True, return_sequences=True)(inputs)
model = Model(inputs=inputs, outputs=[state_h, state_c])
print (model.predict(np.zeros((batch_size, num_steps, num_input))))
print (model.layers[1].cell.state_size)
Примечание: В случае GRU / RNN нет состояния ячейки, есть только скрытое состояние, поэтому состояние ячейки в случае просто h_t
размера (batch_size , hidden_size)
Ссылка:
Реализация LSTM в Keras
количество тензоров состояния равно 1 (для RNN и GRU) или 2 (для LSTM).
Иллюстрированное руководство по LSTM и GRU
Состояния подачи
В вашем примере layers[0]
относится к 1 LSTM и layers[1]
относится ко 2-му LSTM. Если вы намерены инициализировать состояние ячейки ( c_t
) n-го пакета из состояния ячейки of (n-1), т. е. предыдущего пакета, есть два варианта
-
То, что вы делаете в генераторе, но используйте,
states[1]
если хотитеc_t
иstates[0]
дляh_t
. Аналогично используйтеlayers[0]
для 1-го LSTM иlayers[1]
для второго LSTM. Но вместо этого используйтеset_value
методы. Смотрите редактирование ниже. -
Используйте keras
Stateful=True
: При значении состояния true состояния LSTM не сбрасываются после каждого пакета. Таким образом, если у вас есть пакет с 5 образцами данных (каждый с некоторой длиной последовательности), вы получите состояние ячейки для каждого из 5 образцов данных. При значении состояния true эти состояния используются для инициализации состояния ячейки следующего пакета для следующего пакета.
Редактировать:
Метод set_value
следует использовать для установки значения тензорной переменной. Код model.layers[0].states[0] = K.variable(value=hidden_states[gen_data.current_idx])
действителен, потому что то, что он делает, изменяет состояние [0], которое указывало на переменную размера (batch_size X hidden_size) на переменную размера (batch_size x 2). Это не изменяет значение тензорной переменной, а скорее указывает на новую тензорную переменную другого измерения.
Тестовый код:
print (model.layers[0].states[0], hex(id(model.layers[0].states[0])))
model.layers[0].states[0]= K.variable(np.random.randn(10,2))
print (model.layers[0].states[0], hex(id(model.layers[0].states[0])))
Вывод
<tf.Variable 'lstm_18/Variable:0' shape=(10, 8) dtype=float32_ref> 0x7f8812e6ee10
<tf.Variable 'Variable_2:0' shape=(10, 2) dtype=float32_ref> 0x7f881269afd0
Как вы можете видеть, это две разные переменные. Правильный способ сделать это
print (model.layers[0].states[0], hex(id(model.layers[0].states[0])))
K.set_value(model.layers[0].states[0], np.random.randn(10,8))
print (model.layers[0].states[0], hex(id(model.layers[0].states[0])))
Вывод
<tf.Variable 'lstm_20/Variable:0' shape=(10, 8) dtype=float32_ref> 0x7f881138eb70
<tf.Variable 'lstm_20/Variable:0' shape=(10, 8) dtype=float32_ref> 0x7f881138eb70
Если ваш код исправлен, то
K.set_value(model.layers[0].states[0], np.random.randn(10,2))
Выдаст ошибку, поскольку размер тензора и размер значения, которое вы устанавливаете, не совпадают.
Комментарии:
1. спасибо за ваш ответ, но я не вижу ответа на свои вопросы. Мои вопросы были связаны со скрытым состоянием
h_t
. Мой первый вопрос был: почему в моем примере можно установитьh_t
с помощью (batch_size x 2), когда обычно требуется ввод формы (batch_size x hidden_size)?2. @MerklT вы должны использовать метод set_value для установки значения тензора. Пожалуйста, проверьте отредактированный для получения подробной информации.