【问题标题】:How to use a pre-trained embedding matrix in tensorflow 2.0 RNN as initial weights in an embedding layer?如何在 tensorflow 2.0 RNN 中使用预训练的嵌入矩阵作为嵌入层的初始权重?
【发布时间】:2019-04-20 03:33:30
【问题描述】:

我想使用预训练的 GloVe 嵌入作为 RNN 编码器/解码器中嵌入层的初始权重。代码在 TensorFlow 2.0 中。简单地将嵌入矩阵作为 weights = [embedding_matrix] 参数添加到 tf.keras.layers.Embedding 层不会这样做,因为编码器是一个对象,我现在不确定是否有效地将 embedding_matrix 传递给这个对象训练时间。

我的代码紧跟neural machine translation example in the Tensorflow 2.0 documentation。在这个例子中,我如何向编码器添加一个预训练的嵌入矩阵?编码器是一个对象。当我开始训练时,Tensorflow 图无法使用 GloVe 嵌入矩阵。我收到错误消息:

RuntimeError:无法在 Tensorflow 图形函数中获取值。

代码在训练过程中使用了 GradientTape 方法和教师强制。

我尝试修改编码器对象以在各个点包含 embedding_matrix,包括在编码器的 init、调用和 initialize_hidden_​​state 中。所有这些都失败了。关于 * 和其他地方的其他问题是针对 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)))

【问题讨论】:

    标签: tensorflow nlp recurrent-neural-network embedding glove


    【解决方案1】:

    我试图做同样的事情并得到完全相同的错误。问题是嵌入层中的权重目前已被弃用。将 weights= 更改为 embeddings_initializer= 对我有用。

    self.embedding = tf.keras.layers.Embedding(vocab_size, embedding_dim, 
    embeddings_initializer=tf.keras.initializers.Constant(embedding_matrix),
    trainable=False)
    

    【讨论】:

    • 很漂亮,但是如何加载 embedding_matrix?
    【解决方案2】:

    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-然后更新编码器类如下:

        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))
    

    注意:这适用于 tensorflow 1.13.1

    【讨论】:

    • example_input_batch 是热编码的词矩阵,对吗?
    最近更新 更多