Объединение двух входов различного измерения по определенному индексу в последовательности в Керасе - PullRequest
1 голос
/ 15 мая 2019

Я пытаюсь обучить LSTM, используя два типа встраиваемых слоев. Допустим, мое токенизированное предложение следующее:

tokenized_sentence = ['I', 'am', 'trying', 'to', 'TARGET_TOKEN', 'my', 'way', 'home']

Теперь для слов, окружающих "TARGET_TOKEN", у меня есть слой внедрения, который (vocab_size x 128), в то время как для токена 'TARGET_TOKEN' с индексом 4 у меня есть слой внедрения, который является (vocab_size x 512). Поэтому мне нужно преобразовать вложение TARGET_TOKEN из 512 в 128, а затем вставить этот вектор измерения 128 в индекс 4 (этот индекс будет меняться в зависимости от функции) выходных данных из слоя внедрения окружающих слов перед подачей этого составного списка (тензора) в LSTM. В моей ситуации расположение слов / токенов очень важно, и поэтому я не хочу терять положение, в котором находится токен TARGET_TOKEN в предложении.

Первоначально я искал, как уменьшить размер 512 вложений, и обнаружил, что с помощью numpy я могу взять среднее значение для каждых 4 смежных векторов, и, таким образом, я получаю от 512 измерений до 128 измерений. Однако, насколько я понимаю, это может больше не представлять векторы в правильном направлении.

Давайте назовем токен «TARGET_TOKEN» как «target_token», а остальные слова как «context_tokens». Поэтому вместо дальнейшего чтения я подумал, что могу взять выходные данные слоя внедрения target_token и пропустить его через слой Dense со 128 единицами (таким образом, уменьшив его размер до 128). После этого я объединю выходные данные плотного слоя с выходными данными уровня внедрения context_tokens. Пока я знаю, как это сделать. Моя проблема в том, что позиционирование важно, и важно, чтобы мой LSTM изучил вложение target_token относительно окружающего его контекста. Так коротко, мне нужно объединить в индексе 4 (возможно, я смотрю на это неправильно, но я так понимаю).

Тем не менее, слой сцепления в Keras не имеет такого параметра, и я могу только объединить два слоя без учета расположения.

Моя модель будет принимать три входа:

input1 = target_token
input2 = context_tokens
input3 = target_token_index

и один выход (как последовательность).

Мой код выглядит так:

target_token_input = Input((1,))
sentence_input = Input((None,))
index_input = Input((1,), dtype="int32")

target_token_embedding_layer = Embedding(500, 512, weights=[], trainable=False)(target_token_input)

target_token_dense_layer = Dense(128, activation="relu")(target_token_embedding_layer)

context_embedding_layer = Embedding(self.vocab_size, 128, weights=[self.weight_matrix],
                                                trainable=False)(sentence_input)

concatenation_layer = Concatenate()([target_token_dense_layer, context_embedding_layer])

bidirectional = Bidirectional(LSTM(64, return_sequences=self.return_sequences, dropout=0.2, recurrent_dropout=0.2))(concatenation_layer)

normalization_layer = BatchNormalization()(bidirectional)

output_layer = TimeDistributed(Dense(self.output_size, activation=self.activation))(normalization_layer)

model = Model([target_token_input, sentence_input, index_input],[output_layer]) 

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

original_tokens = ['I', 'am', 'trying', 'to', 'eng-12345', 'my', 'way', 'home']
vector_original_tokens = [128, 128, 128, 128, 512, 128, 128, 128]
post_concatenation_tokens = [128, 128, 128, 128, 128, 128, 128, 128]

Обратите внимание, что в индексе 4 вложение изменилось с 512 до 128. Я изучаю возможность преобразования тензора в список, вставляя выходные данные target_token_embedding_layer в этот список по желаемому индексу и затем преобразовывая список обратно в тензор и используя этот тензор в качестве входных данных для LSTM. Однако я все еще пытаюсь понять это.

Кто-нибудь знает, как это сделать? Любая помощь будет принята с благодарностью!

1 Ответ

0 голосов
/ 15 мая 2019

Хм, краткий ответ: ты не можешь.Вы можете сделать это программно, где все будет выглядеть так, как вы хотите, чтобы они выглядели, но Keras LSTM этого не поймет.Keras LSTM должен понимать связь между токенами.Когда вы получаете список вложений из одной «вселенной» и пытаетесь объединить его с вложениями из другой «вселенной», все просто не работает.

Вам придется токенизировать / встраивать все слова втакие же размеры, чтобы он работал.Я предполагаю, что TARGET_TOKEN имеет различные вложения (512) по сравнению с остальной частью словаря?Вы можете создать новое вложение (128 + 512).Однако, поскольку вы упомянули, что вы сократили исходные 512 вложений до 128, я предлагаю вам вернуться к 512 вложениям.

Обратите внимание, как я упоминаю Keras LSTM: что я запястье в ответ на общееХорошо известен слой LSTM со стандартными 4 затворами.Если вы пишете свой собственный вариант слоя LSTM с нуля (скажем, в Tensorflow или numpy), все ставки сняты.

Я предполагаю, что вы пытаетесь построить какую-то сеть, которая заполняетзаготовки?По какой причине вы переключились с 512 вложений на 128?Экономия памяти?

...