интерпретация get_weight в модели LSTM в keras

Это мой простой воспроизводимый код:

from keras.callbacks import ModelCheckpoint
from keras.models import Model
from keras.models import load_model
import keras
import numpy as np

SEQUENCE_LEN = 45
LATENT_SIZE = 20
VOCAB_SIZE = 100

inputs = keras.layers.Input(shape=(SEQUENCE_LEN, VOCAB_SIZE), name="input")
encoded = keras.layers.Bidirectional(keras.layers.LSTM(LATENT_SIZE), merge_mode="sum", name="encoder_lstm")(inputs)
decoded = keras.layers.RepeatVector(SEQUENCE_LEN, name="repeater")(encoded)
decoded = keras.layers.Bidirectional(keras.layers.LSTM(VOCAB_SIZE, return_sequences=True), merge_mode="sum", name="decoder_lstm")(decoded)
autoencoder = keras.models.Model(inputs, decoded)
autoencoder.compile(optimizer="sgd", loss='mse')
autoencoder.summary()

x = np.random.randint(0, 90, size=(10, SEQUENCE_LEN,VOCAB_SIZE))
y = np.random.normal(size=(10, SEQUENCE_LEN, VOCAB_SIZE))
NUM_EPOCHS = 1
checkpoint = ModelCheckpoint(filepath='checkpoint/{epoch}.hdf5')
history = autoencoder.fit(x, y, epochs=NUM_EPOCHS,callbacks=[checkpoint])

и вот мой код, чтобы взглянуть на веса в слое кодировщика:

for epoch in range(1, NUM_EPOCHS + 1):
    file_name = "checkpoint/" + str(epoch) + ".hdf5"
    lstm_autoencoder = load_model(file_name)
    encoder = Model(lstm_autoencoder.input, lstm_autoencoder.get_layer('encoder_lstm').output)
    print(encoder.output_shape[1])
    weights = encoder.get_weights()[0]
    print(weights.shape)
    for idx in range(encoder.output_shape[1]):
        token_idx = np.argsort(weights[:, idx])[::-1]

здесь print(encoder.output_shape) — это (None,20), а print(weights.shape) — это (100, 80).

Я так понимаю, что get_weight напечатает переход веса после слоя.

Часть, которую я не получил на основе этой архитектуры, это 80. что это такое?

И являются ли weights здесь весом, который соединяет уровень кодировщика с декодером? Я имел в виду связь между энкодером и декодером.

Я просмотрел этот вопрос здесь. поскольку это только простые плотные слои, я не мог связать эту концепцию с моделью seq2seq.

Обновление1

В чем разница между: encoder.get_weights()[0] и encoder.get_weights()[1]? первый - (100,80), а второй - (20,80) как концептуально?

любая помощь приветствуется :)


person sariii    schedule 12.07.2019    source источник


Ответы (1)


encoder, как вы определили, является моделью и состоит из двух слоев: входного слоя и слоя 'encoder_lstm', который является двунаправленным слоем LSTM в автоэнкодере. Таким образом, его выходная форма будет выходной формой слоя 'encoder_lstm', который равен (None, 20) (потому что вы установили LATENT_SIZE = 20 и merge_mode="sum"). Таким образом, выходная форма правильная и четкая.

Однако, поскольку encoder — это модель, при запуске encoder.get_weights() он вернет веса всех слоев модели в виде списка. Двунаправленный LSTM состоит из двух отдельных слоев LSTM. Каждый из этих слоев LSTM имеет 3 веса: ядро, повторяющееся ядро ​​и смещения. Таким образом, encoder.get_weights() вернет список из 6 массивов, по 3 для каждого из слоев LSTM. Первый элемент этого списка, который вы сохранили в weights и который является предметом вашего вопроса, является ядром одного из слоев LSTM. Ядро слоя LSTM имеет форму (input_dim, 4 * lstm_units). Входной размер слоя 'encoder_lstm'VOCAB_SIZE, а количество единиц — LATENT_SIZE. Следовательно, у нас есть (VOCAB_SIZE, 4 * LATENT_SIZE) = (100, 80) как форма ядра.

person today    schedule 12.07.2019
comment
Большое спасибо за ваши подробные объяснения. У меня есть еще один вопрос по этому поводу, надеюсь, вы поможете мне его прояснить. поэтому вы упомянули, что у нас есть 3 веса. Мне нужно увидеть вес, связанный с этими 20 neurons из latent size. с вашим объяснением, я думаю, что я делаю это неправильно, и я должен посмотреть на encoder.get_weights()[1]. Я прав? - person sariii; 12.07.2019
comment
@sariii Я не уверен, что вы имеете в виду под весом, связанным с этими 20 нейронами ?! Все эти веса связаны с нейронами. На самом деле ядро ​​состоит из четырех подъядер формы (input_dim, lstm_units), и у каждого есть цель. То же самое относится и к рекуррентному ядру: четыре подъядра формы (lstm_units, lstm_units), что делает его формой (lstm_units, 4* lstm_units). Поэтому я не уверен, какой из них вас интересует. У каждого есть отдельная цель, но все они связаны с нейронами в слое LSTM. - person today; 12.07.2019
comment
Большое спасибо, очень ценю это, теперь это более ясно для меня. Я обновил вопрос еще одним вопросом, точно связанным с вашими объяснениями в комментарии. не могли бы вы взглянуть и обновить свой ответ? Кроме того, я признателен, если вы могли бы предоставить мне ссылку, которую я могу прочитать, чтобы понять их различия. Теперь единственная неясная часть - это то, в чем на самом деле их различия. - person sariii; 12.07.2019
comment
Позвольте мне поделиться своей путаницей по поводу lstm. Я знал, что у нас есть 4 ядра в ячейке lstm, однако раньше я думал, что, поскольку мы извлекаем выходные данные из последнего слоя, нас больше не интересуют веса в первом третьем слое, поэтому веса - это вес, связанный с последним выходом! - person sariii; 12.07.2019
comment
@sariii Перечитывая ваш комментарий, я думаю, вас интересуют веса ядра (то есть те, которые возвращаются .get_weights()[0]), потому что на самом деле это веса, которые напрямую связаны с нейронами LSTM. Рекуррентное ядро ​​имеет дело со скрытым состоянием. Это изображение, вероятно, поможет вам: W — это ядра, а U — это повторяющиеся ядра. . Также см. соответствующую часть в исходном коде Keras. - person today; 12.07.2019
comment
Спасибо большое, теперь я лучше вижу :) Хотя последний вопрос(заранее извините за много вопросов). У меня буквально 20 нейронов в слое кодировщика, что я имел в виду, что хочу иметь 20 векторов или 20 кластеров... как я могу интерпретировать 80 здесь с точки зрения важности?. если вы хотите, чтобы я задал новый вопрос, я могу это сделать :) - person sariii; 12.07.2019
comment
@sariii Возможно, лучше задать новый вопрос, потому что я не уверен, понимаю ли я ваш комментарий (пожалуйста, задайте его на CrossValidated или DataScience, а не StackOverflow, поскольку он предназначен только для вопросов по программированию). Вы можете просматривать эти нейроны (без учета повторения и скрытого состояния) как нейроны в плотном слое: при получении входных данных они умножают его на матрицу весов, суммируют результат по смещению, применяют функцию активации и возвращают результат. Но я не уверен, для чего и как вы хотите их использовать. - person today; 12.07.2019
comment
Звучит хорошо, позвольте мне задать новый вопрос в перекрестной проверке, и я предоставлю более подробную информацию о том, что мне нужно, и свяжу это здесь. Я надеюсь, что вы можете взглянуть на него, еще раз спасибо - person sariii; 12.07.2019
comment
@sariii Также (если вы еще не читали) эта замечательная статья может помочь вам лучше понять LSTM, поскольку это помогло многим. - person today; 12.07.2019
comment
Большое спасибо за ссылку, я на самом деле читал ее раньше, но, честно говоря, я думал, что когда мы вызываем encoder.get_weigh, мы получаем доступ только к весу, связанному с Ot, поэтому я просто представил 20 neuron с размером словарного запаса (vocab_size,latent_size), теперь идея 4* latent_size доказала, что я был совершенно неправ - person sariii; 12.07.2019
comment
Еще раз спасибо за вашу помощь, я получил ответ на вопрос, который искал здесь stackoverflow.com/questions/42861460/ . плюс первая ссылка, которую вы предложили, очень помогла. Спасибо :) - person sariii; 13.07.2019
comment
@sariii А, так ты просто хотел найти подъядра?! Я уже поделился с вами ссылкой на исходный код Keras в комментариях, и я думал, что вы просмотрели его, чтобы найти, какой слайс соответствует какому подядру! В любом случае, я рад, что вы наконец нашли ответы на свои вопросы :) - person today; 13.07.2019