Keras-文本序列_文本向量化(二)(利用 Embedding 层学习词嵌入)
参考:
https://blog.csdn.net/qq_30614345/article/details/98714874
****1. 利用 Embedding 层学习词嵌入
代码清单 6-5 将一个 Embedding 层实例化
代码清单 6-6 加载 IMDB 数据,准备用于 Embedding 层
在真实的词嵌入空间中,常见的有意义的几何变换的例子包括“性别”向量和“复数”向量。
例如,将 king(国王)向量加上 female(女性)向量,得到的是 queen(女王)向量。将 king(国王)向量加上 plural(复数)向量,得到的是 kings 向量。词嵌入空间通常具有几千个这种可解释的、并且可能很有用的向量。
有没有一个理想的词嵌入空间,可以完美地映射人类语言,并可用于所有自然语言处理任务?可能有,但我们尚未发现。此外,也不存在人类语言(human language)这种东西。世界上a 两个词的中文含义都是“精确的”。 ——译者注6.1 处理文本数据 153
1 2 3 4 5 6 7 8 9
有许多种不同的语言,而且它们不是同构的,因为语言是特定文化和特定环境的反射。但从更实际的角度来说,一个好的词嵌入空间在很大程度上取决于你的任务。英语电影评论情感分析模型的完美词嵌入空间,可能不同于英语法律文档分类模型的完美词嵌入空间,因为某些语义关系的重要性因任务而异
import keras
keras.__version__
# 在真实的词嵌入空间中,常见的有意义的几何变换的例子包括“性别”向量和“复数”向量。
# 例如,将 king(国王)向量加上 female(女性)向量,得到的是 queen(女王)向量。将 king(国王)
# 向量加上 plural(复数)向量,得到的是 kings 向量。词嵌入空间通常具有几千个这种可解释的、
# 并且可能很有用的向量。
# 有没有一个理想的词嵌入空间,可以完美地映射人类语言,并可用于所有自然语言处理任
# 务?可能有,但我们尚未发现。此外,也不存在人类语言(human language)这种东西。世界上
# 有许多种不同的语言,而且它们不是同构的,因为语言是特定文化和特定环境的反射。但从更
# 实际的角度来说,一个好的词嵌入空间在很大程度上取决于你的任务。英语电影评论情感分析
# 模型的完美词嵌入空间,可能不同于英语法律文档分类模型的完美词嵌入空间,因为某些语义
# 关系的重要性因任务而异。
# 因此,合理的做法是对每个新任务都学习一个新的嵌入空间。幸运的是,反向传播让这种
# 学习变得很简单,而 Keras 使其变得更简单。我们要做的就是学习一个层的权重,这个层就是
# Embedding 层。
# 代码清单 6-5 将一个 Embedding 层实例化
from keras.layers import Embedding
# The Embedding layer takes at least two arguments:
# the number of possible tokens, here 1000 (1 + maximum word index),
# and the dimensionality of the embeddings, here 64.
# Embedding 层至少需要两个参数:标记的个数(这里是 1000,即最大单词索引 +1)和嵌入的维度(这里是 64)
# Embedding 层的输入是一个二维整数张量,其形状为 (samples, sequence_length),
# 每个元素是一个整数序列。它能够嵌入长度可变的序列,例如,对于前一个例子中的
# Embedding 层,你可以输入形状为 (32, 10)(32 个长度为 10 的序列组成的批量)或 (64,
# 15)(64 个长度为 15 的序列组成的批量)的批量。不过一批数据中的所有序列必须具有相同的
# 长度(因为需要将它们打包成一个张量),所以较短的序列应该用 0 填充,较长的序列应该被截断。
# 这 个 Embedding 层 返 回 一 个 形 状 为 (samples, sequence_length, embedding_
# dimensionality) 的三维浮点数张量。然后可以用 RNN 层或一维卷积层来处理这个三维张量
# (二者都会在后面介绍)。
# 将一个 Embedding 层实例化时,它的权重(即标记向量的内部字典)最开始是随机的,与
# 其他层一样。在训练过程中,利用反向传播来逐渐调节这些词向量,改变空间结构以便下游模
# 型可以利用。一旦训练完成,嵌入空间将会展示大量结构,这种结构专门针对训练模型所要解
# 决的问题。
embedding_layer = Embedding(1000, 64)
# 将电影评论限制为前 10 000 个最常见的单词(第一次处理这个数据集时就是这么做的),
# 然后将评论长度限制为只有 20 个单词。对于这 10 000 个单词,网络将对每个词都学习一个 8
# 维嵌入,将输入的整数序列(二维整数张量)转换为嵌入序列(三维浮点数张量),然后将这个
# 张量展平为二维,最后在上面训练一个 Dense 层用于分类。
# Embedding 层至少需要两个参数:
# 标记的个数(这里是 1000,即最
# 大单词索引 +1)和嵌入的维度(这
# 里是 64)154 第 6 章 深度学习用于文本和序列
# 代码清单 6-6 加载 IMDB 数据,准备用于 Embedding 层
from keras.datasets import imdb
from keras import preprocessing
# Number of words to consider as features
# 作为特征的单词个数
max_features = 10000
# Cut texts after this number of words
# (among top max_features most common words)
# 在这么多单词后截断文本(这些单词都属于前 max_features 个最常见的单词)
maxlen = 20
# Load the data as lists of integers.
# 将整数列表转换成形状为(samples,maxlen) 的二维整数张量
(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=max_features)
# This turns our lists of integers
# into a 2D integer tensor of shape `(samples, maxlen)`
x_train = preprocessing.sequence.pad_sequences(x_train, maxlen=maxlen)
x_test = preprocessing.sequence.pad_sequences(x_test, maxlen=maxlen)
Downloading data from https://s3.amazonaws.com/text-datasets/imdb.npz
12460032/17464789 [====================>.........] - ETA: 0s
# 代码清单 6-7 在 IMDB 数据上使用 Embedding 层和分类器
from keras.models import Sequential
from keras.layers import Flatten, Dense
model = Sequential()
# We specify the maximum input length to our Embedding layer
# so we can later flatten the embedded inputs
# 指定 Embedding 层的最大输入长度,以便后面将嵌入输入展平。 Embedding 层激活的形状为 (samples, maxlen, 8)
model.add(Embedding(10000, 8, input_length=maxlen))
# After the Embedding layer,
# our activations have shape `(samples, maxlen, 8)`.
# We flatten the 3D tensor of embeddings
# into a 2D tensor of shape `(samples, maxlen * 8)`
# 将三维的嵌入张量展平成形状为 (samples, maxlen * 8) 的二维张量
model.add(Flatten())
# We add the classifier on top
# 在上面添加分类器
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc'])
model.summary()
history = model.fit(x_train, y_train,
epochs=10,
batch_size=32,
validation_split=0.2)
# 得到的验证精度约为 76%,考虑到仅查看每条评论的前 20 个单词,这个结果还是相当不错
# 的。但请注意,仅仅将嵌入序列展开并在上面训练一个 Dense 层,会导致模型对输入序列中的
# 每个单词单独处理,而没有考虑单词之间的关系和句子结构(举个例子,这个模型可能会将 this
# movie is a bomb 和 this movie is the bomb 两条都归为负面评论 a)。更好的做法是在嵌入序列上添
# 加循环层或一维卷积层,将每个序列作为整体来学习特征。这也是接下来几节的重点
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
embedding_2 (Embedding) (None, 20, 8) 80000
_________________________________________________________________
flatten_1 (Flatten) (None, 160) 0
_________________________________________________________________
dense_1 (Dense) (None, 1) 161
=================================================================
Total params: 80,161
Trainable params: 80,161
Non-trainable params: 0
_________________________________________________________________
Train on 20000 samples, validate on 5000 samples
Epoch 1/10
20000/20000 [==============================] - 2s - loss: 0.6560 - acc: 0.6482 - val_loss: 0.5906 - val_acc: 0.7146
Epoch 2/10
20000/20000 [==============================] - 2s - loss: 0.5189 - acc: 0.7595 - val_loss: 0.5117 - val_acc: 0.7364
Epoch 3/10
20000/20000 [==============================] - 2s - loss: 0.4512 - acc: 0.7933 - val_loss: 0.4949 - val_acc: 0.7470
Epoch 4/10
20000/20000 [==============================] - 2s - loss: 0.4190 - acc: 0.8069 - val_loss: 0.4905 - val_acc: 0.7538
Epoch 5/10
20000/20000 [==============================] - 2s - loss: 0.3965 - acc: 0.8198 - val_loss: 0.4914 - val_acc: 0.7572
Epoch 6/10
20000/20000 [==============================] - 2s - loss: 0.3784 - acc: 0.8311 - val_loss: 0.4953 - val_acc: 0.7594
Epoch 7/10
20000/20000 [==============================] - 2s - loss: 0.3624 - acc: 0.8419 - val_loss: 0.5004 - val_acc: 0.7574
Epoch 8/10
20000/20000 [==============================] - 2s - loss: 0.3474 - acc: 0.8484 - val_loss: 0.5058 - val_acc: 0.7572
Epoch 9/10
20000/20000 [==============================] - 2s - loss: 0.3330 - acc: 0.8582 - val_loss: 0.5122 - val_acc: 0.7528
Epoch 10/10
20000/20000 [==============================] - 2s - loss: 0.3194 - acc: 0.8669 - val_loss: 0.5183 - val_acc: 0.7554