【Tensorflow 2.0 正式版教程】词嵌入(word embedding)与GLoVe

这篇教程来讲解自然语言处理中的词嵌入,也就是word embedding,并介绍GLoVe预训练参数的加载。

简单来说,word embedding是将单词转换为向量,从而进一步参与神经网络的计算。在tensorflow 2.0中,tensorflow.keras.layers.Embedding实现了这一功能。其中embedding层计算了一个行向量乘矩阵的矩阵乘法,其中行向量是one hot形式的单词,矩阵为权重,所以本质上权重的每一行代表一个单词在语义空间的特征向量,该矩阵的行数为单词数。

下面以一个简单的文本分类实例具体讲解。数据库选用IMDB影评情感分析,该数据tensorflow提供官方下载与解析函数。

(train_sequences, train_labels), (test_sequences, test_labels) = tf.keras.datasets.imdb.load_data(num_words=word_num)
word_index = tf.keras.datasets.imdb.get_word_index()

其中sequences是序列化的结果,即以数字代替单词,num_words参数是最大单词数,特别的,0代表空白符,用于后续补位,1代表起始符,2代表未知单词,3代表未使用的单词。后续4为最高词频单词’the’,5及之后按词频排序。
word_index即单词到数字的映射关系,有个坑是这个映射表里’the’对应的是1,之后需要特殊处理。

考虑到tensorflow的数据放在了googleapis.com上,对于网络状况不好的环境,也可以先从官方下载数据:imdb.npzimdb_word_index.json,然后在上面的加载函数中指定path参数。

将sequences输入到网络之前,还需要统一长度,小于指定长度的在前面补0,大于指定长度的截取后段。

train_sequences = pad_sequences(train_sequences, maxlen=max_len)
test_sequences = pad_sequences(test_sequences, maxlen=max_len)

此时,输入到网络的文本数据尺寸应为(batch_size, max_len),经过Embedding层,得到(batch_size, max_len, embedding_dim)大小的词嵌入向量,其中embedding_dim为语义空间维数。由此可以搭建一个简单的全连接网络对文本进行分类。

def Model():
    model = tf.keras.Sequential()
    model.add(Embedding(word_num, embedding_dim))
    model.add(GlobalAveragePooling1D())
    model.add(Dense(128, activation=tf.nn.relu))
    model.add(Dense(2, activation='softmax'))
    return model

然后便可以开始训练

word_num = 10000
max_len = 256
embedding_dim = 100

# get model
model = Model()
model.summary()

# train
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(train_sequences,
          train_labels,
          batch_size=512,
          epochs=10)

# test
test_loss, test_acc = model.evaluate(test_sequences, test_labels)
print(test_acc)

此时可以达到约87.1%的准确率。

更进一步,Embedding层的权重是随机初始化的,为了取得更好的结果,需要加载预训练的权重,如word2vec、GLoVe等,这里以GLoVe为例。

GLoVe权重可以从官方下载。考虑到权重的每一行代表一个单词在语义空间的特征向量,因此可以借助word_index中的映射关系进行赋值。

def get_embedding_weight(weight_path, word_index):
    # embedding_weight = np.zeros([word_num, embedding_dim])
    embedding_weight = np.random.uniform(-0.05, 0.05, size=[word_num, embedding_dim])
    cnt = 0
    with open(weight_path, 'r') as f:
        for line in f:
            values = line.split()
            word = values[0]
            if word in word_index.keys() and word_index[word] + 3 < word_num:
                """
                In tf.keras.dataset.imdb.load_data(), there are 4 special mark.
                <pad>: 0
                <start>: 1
                <unknown>: 2
                <unused>: 3
                So word_index loaded from offical file, "mdb_word_index.json", need to +3.
                """
                weight = np.asarray(values[1:], dtype='float32')
                embedding_weight[word_index[word] + 3] = weight
                cnt += 1
    print('matched word num: {}'.format(cnt))
    return embedding_weight

然后在Embedding层实例化时指定权重
Embedding(word_num, embedding_dim, weights=[embedding_weight])
我在实验中选用GLoVe_path = '/home1/dataset/GLoVe/glove.6B.100d.txt',在测试集上可以达到88.2%的准确率。相比随机初始化的方式,加载预训练权重提升了分类准确率。

考虑到本文仅作embedding层与GLoVe加载的简单教学,最终达到的准确率较低。代码中的超参数与模型本身可进一步调整以达到更好的结果。完整的代码可以在我的github上找到。
https://github.com/Apm5/tensorflow_2.0_tutorial/blob/master/RNN/simple_example.py

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一段使用TensorFlow 2.0实现的LSTM文本分类代码,使用GloVe进行词嵌入的示例: ```python import tensorflow as tf import numpy as np # 加载GloVe词向量 glove_file = 'glove.6B.100d.txt' embedding_index = {} with open(glove_file, encoding='utf-8') as f: for line in f: values = line.split() word = values[0] coefs = np.asarray(values[1:], dtype='float32') embedding_index[word] = coefs # 构建词向量矩阵 embedding_dim = 100 max_words = 10000 embedding_matrix = np.zeros((max_words, embedding_dim)) for word, i in tokenizer.word_index.items(): if i < max_words: embedding_vector = embedding_index.get(word) if embedding_vector is not None: embedding_matrix[i] = embedding_vector # 构建模型 model = tf.keras.Sequential([ tf.keras.layers.Embedding(max_words, embedding_dim, input_length=maxlen), tf.keras.layers.LSTM(32), tf.keras.layers.Dense(1, activation='sigmoid') ]) # 编译模型 model.layers[0].set_weights([embedding_matrix]) model.layers[0].trainable = False model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc']) # 训练模型 history = model.fit(x_train, y_train, epochs=10, batch_size=32, validation_data=(x_val, y_val)) ``` 其,`glove.6B.100d.txt`是GloVe预训练的100维词向量文件,可以从GloVe官网下载。`max_words`是词汇表的大小,`maxlen`是输入序列的最大长度。在构建词向量矩阵时,只使用了词汇表前`max_words`个词的词向量,其余词的词向量均为0。在构建模型时,首先使用`Embedding`层加载词向量矩阵,然后使用`LSTM`层进行序列建模,最后使用`Dense`层输出二分类结果。在编译模型时,将词向量矩阵权重设置为不可训练,以避免过拟合。在训练模型时,使用`fit`方法进行训练,其`x_train`和`y_train`是训练集的输入和输出,`x_val`和`y_val`是验证集的输入和输出。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值