Почему мой Трансформер всегда выдает одинаковые ответы? - PullRequest
0 голосов
/ 26 июня 2019

Моя цель - использовать Transformer для предсказания последовательности, как и seq2seq.Но когда я декодирую последовательность, она всегда отвечает мне одними и теми же результатами, независимо от того, во что я вхожу.

Традиционно, кодировщик Transformer включает в себя модуль самообслуживания и модуль прямой связи, а декодер - самообслуживаниемодуль, модуль взаимного внимания и модуль обратной связи.И со следующими настройками:

Настройка 1: маскировка использования самоконтроля кодировщика: False;

маскировка использования самоконтроля декодера: True;

использование взаимного внимания декодерамаскирование: False.

Настройка 2: маскировка с использованием собственного внимания кодера: False;

маскировка с использованием собственного внимания декодера: True;

маскировка с использованием взаимного внимания декодера:Верно

Когда я использую настройку 1, модель всегда отвечает мне одинаковыми результатами, независимо от того, во что я вхожу.На самом деле, настройка 2 - это неправильная настройка, просто для проверки результатов.Интересно, что когда я использую параметр 2, он возвращает разные ответы для разных входных данных.Я не могу сказать, почему.

У меня довольно много кодов, поэтому я вставляю здесь только код ключа.

Часть модели:

def __get_encoder(self, input_layer):
    next_step_input, self.embedding_matrix = self.embedding_layer(input_layer)
    next_step_input = self.coordinate_embedding_layer(next_step_input, step=0)
    for i in range(self.args.transformer_depth):
        next_step_input = (
                TransformerEncoderBlock(
                    name='transformer_encoder' + str(i), num_heads=self.args.num_heads,
                    residual_dropout=self.transformer_dropout,
                    attention_dropout=self.transformer_dropout,
                    activation='relu',
                    use_masking=False,  # Allow bi-directional attention
                    vanilla_wiring=True) # use vanilla Transformer instead of Universal Transformer
                    (next_step_input))
    return next_step_input

def __get_decoder(self, input_layer, encoder_output):
    next_step_input, _ = self.embedding_layer(input_layer)
    next_step_input = self.coordinate_embedding_layer(next_step_input, step=0)
    for i in range(self.args.transformer_depth):
            next_step_input = (
                TransformerDecoderBlock(
                    name='transformer_decoder' + str(i), num_heads=self.args.num_heads,
                    residual_dropout=self.transformer_dropout,
                    attention_dropout=self.transformer_dropout,
                    activation='relu',
                    self_attention_use_masking=True,  # Forbid bi-directional attention
                    mutual_attention_use_masking=False,  
                    vanilla_wiring=True) # use vanilla Transformer instead of Universal Transformer
                    ([encoder_output, next_step_input]))
    return next_step_input

def get_model(self):
    inp_query = Input(name='query_input',
                      shape=(None, ), 
                      dtype='int32'
                     )
    inp_answer = Input(name='answer_input',
                            shape=(None, ), 
                            dtype='int32',
                           )
    encoder_output = self.__get_encoder(inp_query)
    decoder_output = self.__get_decoder(inp_answer, encoder_output)

    # build model part
    word_predictions = self.output_softmax_layer(
                self.output_layer([decoder_output, self.embedding_matrix]))
    model = Model(
                      inputs=[inp_query, inp_answer],
                      outputs=[word_predictions]
                     )
    return model

Внимание Часть ключа:

attention_heads = K.reshape(
            K.batch_dot(
                self.apply_dropout_if_needed(
                    K.softmax(
                        # mask the attention for the prediction process
                        self.mask_attention_if_needed(
                            # core scaled dot product
                            K.batch_dot( # (batch_size * num_heads, tar_seq_len, src_seq_len)
                                K.reshape(q, (-1, q_shape[-2], q_shape[-1])), # q_shape: (batch_size*num_heads, q_seq_len, d_model//heads)
                                K.reshape(k_transposed,  # k_transposed: (batch_size*num_heads, d_model//heads, k_seq_len)
                                          (-1, k_t_shape[-2], k_t_shape[-1])))
                            / sqrt_d)),
                    training=training),
                K.reshape(v, (-1, v_shape[-2], v_shape[-1]))), # shape: (batch_size * num_heads, v_seq_len, d_model//heads)
            (-1, self.num_heads, q_shape[-2], q_shape[-1]))

def mask_attention_if_needed(self, dot_product):
    if not self.use_masking:
            return dot_product

    print('in %s masking...' % self.name)
    last_dims = K.shape(dot_product)
    q_len, k_len = last_dims[-2], last_dims[-1]

    row = K.expand_dims(K.arange(0, q_len), axis=-1) 
    col = K.expand_dims(K.arange(0, k_len), axis=0) 

    low_triangle_ones = K.expand_dims(K.cast(col <= row, K.floatx()), axis=0)
    inverse_low_triangle = K.ones_like(low_triangle_ones) - low_triangle_ones
    close_to_negative_inf = K.constant(-1e9, dtype=K.floatx())

    part1 = low_triangle_ones * dot_product 
    part2 = close_to_negative_inf * inverse_low_triangle
    result = (part1 + part2)
    return result

Часть декодера

results = [[ds.start_id] for _ in range(cur_batch_size)]
for t in range(1, tar_length):
    preds = model.predict([src_input, np.asarray(results)])
    for batch_i in range(len(preds)):
        last_token_id = np.argmax(preds[batch_i][-1])
        results[batch_i].append(last_token_id)

Я ожидаю, что результаты будут отличаться в зависимости от разных входных данных, но я получаю одно и то же.Я проверил почти каждую строку кода, но не могу понять проблему.Кто-нибудь может дать некоторые подсказки о том, как проверить или подтвердить код?Большое спасибо!

...