【TF2.0-NLP】词嵌入(Word Embeddings)

  在TF2.0-NLP Helloworld中讲了单词向量化,其主要目的是说明用数字来编码文本的概念。Helloworld中的所有例子都是用一个整个来编码一个单词,但实事证明用多维小数来编码单词更利于机器学习。这种用多维小数来编码单词的方式即是传说中的Word Embeddings。

Word Embeddings的第一个好处是意思相近的单词在多维空间中所处的位置是靠近的,比如“美丽”和“漂亮”会靠得很近。第二个好处是,你可以找到很多开源的已经预训练好的编码。

用IMDB训练词向量

【例1】


import tensorflow_datasets as tfds
imdb, info = tfds.load('imdb_reviews', with_info=True, as_supervised=True)

import numpy as np

train_data, test_data = imdb['train'], imdb['test']

training_sentences = []
training_labels = []

testing_sentences = []
testing_labels = []

# str(s.tonumpy()) is needed in Python3 instead of just s.numpy()
for s, l in train_data:
    training_sentences.append(str(s.tonumpy()))
    training_labels.append(l.numpy())

for s, l in test_data:
    testing_sentences.append(str(s.tonumpy()))
    testing_labels.append(l.numpy())

training_labels_final = np.array(training_labels)
testing_labels_final = np.array(testing_labels)

vocab_size = 10000
embedding_dim = 16
max_length = 120
trunc_type = 'post'
oov_tok = "<OOV>"

from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences

tokenizer = Tokenizer(num_words = vocab_size, oov_token=oov_tok)
tokenizer.fit_on_texts(training_sentences)
word_index = tokenizer.word_index
sequences = tokenizer.texts_to_sequences(training_sentences)
padded = pad_sequences(sequences, maxlen=max_length, truncating=trunc_type)

testing_seqences = tokenizer.texts_to_sequences(testing_sentences)
testing_padded = pad_sequences(testing_seqences, maxlen=max_length)

import tensorflow as tf

model = tf.keras.Sequential([
    tf.keras.layers.Embedding(vocab_size, embedding_dim, input_length=max_length),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(6, activation='relue'),
    tf.keras.layers.Dense(1, activation='sigmoid')
])

model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['accuracy'])
model.summary()

num_epochs = 10
model.fit(padded, training_labels_final, epochs=num_epochs, validation_data=(testing_padded, testing_labels_final))


e = model.layers[0]
weights = e.get_weights()[0]
print(weights.shape) # shape: (vocab_size, embedding_dim)


out_v = open('D:/tmp/vecs_.tsv', 'w', encoding='utf-8')
out_m = open('D:/tmp/meta_.tsv', 'w', encoding='utf-8')
for word_num in range(1, vocab_size):
  word = reverse_word_index[word_num]
  embeddings = weights[word_num]
  out_m.write(word + "\n")
  out_v.write('\t'.join([str(x) for x in embeddings]) + "\n")
out_v.close()
out_m.close()

【重点1】模型

model = tf.keras.Sequential([
    tf.keras.layers.Embedding(vocab_size, embedding_dim, input_length=max_length),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(6, activation='relu'),
    tf.keras.layers.Dense(1, activation='sigmoid')
])

有vocab_size=1000个词,每个词用embedding_dim=16维来编码。

【重点2】权重作词向量

e = model.layers[0]
weights = e.get_weights()[0]

注意e即为最终的词向量,它取的是第0层的权重。单词原来编码的整数成为了新的向量表的所引。

生成两个文件:vecs_.tsv/meta_.tsv。

词向量可视化

上一步得到的两个文件:

    meta_.tsv: 词汇表

    vecs_.tsv:向量表

  这两个文件的每一行有一一映射关系:vecs_.tsv的第10行的所表示的向量对应meta_.tsv中的第10行单词'it'。vecs_.tsv中第一行是16个小数,表示这是一个16维向量。之所以是每行16个数字因为我们设置的embedding_dim=16。

【可视化】 

按以下步骤可以看到词向量的3D效果

1. 用浏览器打开https://projector.tensorflow.org/

2.点击Load,然后根据提示分别导入前面生成的meta_.tsv和vecs_.tsv

3.勾选Sphereize data

4.允许3D label模式

发布了90 篇原创文章 · 获赞 24 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/menghaocheng/article/details/102797247
今日推荐