Я пытаюсь обучить 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. Однако я все еще пытаюсь понять это.
Кто-нибудь знает, как это сделать? Любая помощь будет принята с благодарностью!