Как использовать предварительно обученную матрицу встраивания в тензорном потоке 2.0 RNN в качестве начальных весов в слое встраивания? - PullRequest
2 голосов
/ 20 апреля 2019

Я хотел бы использовать предварительно обученное внедрение GloVe в качестве начальных весов для уровня внедрения в кодере / декодере RNN. Код находится в Tensorflow 2.0. Простое добавление матрицы внедрения в качестве параметра weights = [embedding_matrix] к слою tf.keras.layers.Embedding не будет делать этого, потому что кодировщик является объектом, и я не уверен, что сейчас эффективно передать embedding_matrix этому объекту в время тренировки.

Мой код точно соответствует примеру нейронного машинного перевода в документации Tensorflow 2.0 . Как бы я добавил предварительно обученную матрицу встраивания в кодировщик в этом примере? Кодировщик - это объект. Когда я приступаю к обучению, матрица вложения GloVe недоступна для графика Tensorflow. Я получаю сообщение об ошибке:

RuntimeError: Невозможно получить значение внутри функции графа Tensorflow.

Код использует метод GradientTape и принуждение учителя в процессе обучения.

Я попытался изменить объект кодировщика, чтобы он включал матрицу embedding_matrix в различных точках, в том числе в init кодировщика, call и initialize_hidden_state. Все это терпит неудачу. Другие вопросы по stackoverflow и в других местах относятся к Keras или более ранним версиям Tensorflow, а не Tensorflow 2.0.

class Encoder(tf.keras.Model):
    def __init__(self, vocab_size, embedding_dim, enc_units, batch_sz):
        super(Encoder, self).__init__()
        self.batch_sz = batch_sz
        self.enc_units = enc_units
        self.embedding = tf.keras.layers.Embedding(vocab_size, embedding_dim, weights=[embedding_matrix])
        self.gru = tf.keras.layers.GRU(self.enc_units,
                                       return_sequences=True,
                                       return_state=True,
                                       recurrent_initializer='glorot_uniform')

    def call(self, x, hidden):
        x = self.embedding(x)
        output, state = self.gru(x, initial_state = hidden)
        return output, state

    def initialize_hidden_state(self):
        return tf.zeros((self.batch_sz, self.enc_units))

encoder = Encoder(vocab_inp_size, embedding_dim, units, BATCH_SIZE)

# sample input
sample_hidden = encoder.initialize_hidden_state()
sample_output, sample_hidden = encoder(example_input_batch, sample_hidden)
print ('Encoder output shape: (batch size, sequence length, units) {}'.format(sample_output.shape))
print ('Encoder Hidden state shape: (batch size, units) {}'.format(sample_hidden.shape))

# ... Bahdanau Attention, Decoder layers, and train_step defined, see link to full tensorflow code above ...

# Relevant training code

EPOCHS = 10

training_record = pd.DataFrame(columns = ['epoch', 'training_loss', 'validation_loss', 'epoch_time'])


for epoch in range(EPOCHS):
    template = 'Epoch {}/{}'
    print(template.format(epoch +1,
                 EPOCHS))
    start = time.time()

    enc_hidden = encoder.initialize_hidden_state()
    total_loss = 0
    total_val_loss = 0

    for (batch, (inp, targ)) in enumerate(dataset.take(steps_per_epoch)):
        batch_loss = train_step(inp, targ, enc_hidden)
        total_loss += batch_loss

        if batch % 100 == 0:
            template = 'batch {} ============== train_loss: {}'
            print(template.format(batch +1,
                            round(batch_loss.numpy(),4)))

1 Ответ

1 голос
/ 29 июня 2019

firslty: загрузить предварительно встроенную матрицу внедрения, используя

      def pretrained_embeddings(file_path, EMBEDDING_DIM, VOCAB_SIZE, word2idx):
          # 1.load in pre-trained word vectors     #feature vector for each word
          print("graph in function",tf.get_default_graph())   
          print('Loading word vectors...')
          word2vec = {}
          with open(os.path.join(file_path+'.%sd.txt' % EMBEDDING_DIM),  errors='ignore', encoding='utf8') as f:
          # is just a space-separated text file in the format:
          # word vec[0] vec[1] vec[2] ...
          for line in f:
             values = line.split()
             word = values[0]
             vec = np.asarray(values[1:], dtype='float32')
             word2vec[word] = vec

          print('Found %s word vectors.' % len(word2vec))

          # 2.prepare embedding matrix
          print('Filling pre-trained embeddings...')
          num_words = VOCAB_SIZE
          # initialization by zeros
          embedding_matrix = np.zeros((num_words, EMBEDDING_DIM))
          for word, i in word2idx.items():
            if i < VOCAB_SIZE:
                embedding_vector = word2vec.get(word)
                if embedding_vector is not None:
                  # words not found in embedding index will be all zeros.
                  embedding_matrix[i] = embedding_vector

          return embedding_matrix

2, затем обновите класс Encoder следующим образом:

    class Encoder(tf.keras.Model):
       def __init__(self, vocab_size, embedding_dim, enc_units, batch_sz,embedding_matrix):
          super(Encoder, self).__init__()
          self.batch_sz = batch_sz
          self.enc_units = enc_units
          self.embedding = tf.keras.layers.Embedding(vocab_size, embedding_dim, weights=[embedding_matrix])
          self.gru = tf.keras.layers.GRU(self.enc_units,
                                   return_sequences=True,
                                   return_state=True,
                                   recurrent_initializer='glorot_uniform')

       def call(self, x, hidden):
           x = self.embedding(x)
           output, state = self.gru(x, initial_state = hidden)
           return output, state

       def initialize_hidden_state(self):
           return tf.zeros((self.batch_sz, self.enc_units))

3 вызывающая функция, которая загружает предварительно обученное вложение, чтобы получить вложениематрица

    embedding_matrix = pretrained_embeddings(file_path, EMBEDDING_DIM,vocab_size, word2idx) 
    encoder = Encoder(vocab_inp_size, embedding_dim, units, BATCH_SIZE,embedding_matrix)

    # sample input
    sample_hidden = encoder.initialize_hidden_state()
    sample_output, sample_hidden = encoder(example_input_batch, sample_hidden)
    print ('Encoder output shape: (batch size, sequence length, units) {}'.format(sample_output.shape))
    print ('Encoder Hidden state shape: (batch size, units) {}'.format(sample_hidden.shape))

Примечание: это работает на скважине tenorflow 1.13.1

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...