第十章 如何在Keras中学习和加载词嵌入
词嵌入提供了单词及其对应的密集向量,这是对稀疏向量的一种改进。我们可以单独地从文本中训练词嵌入,并在多个项目中使用,作为预训练模型与具体任务一起训练。接下来我们将了解如何在Keras框架中使用词嵌入,我们将其分为三个步骤:
- 关于词嵌入和Keras的Emdedding层
- 如何在神经网络中训练词嵌入模型
- 如何在神经网络中使用预训练词嵌入模型
10.1 概述
本节分为以下几个部分:
- 词嵌入
- Keras的嵌入层Embedding
- 学习词嵌入
- 使用预训练Glove嵌入
- 训练词嵌入模型清洗文本的提示
10.2 词嵌入
词嵌入是使用密集向量来表示词语在空间(高维)的位置,是对传统词袋模型编码方案的改进,对比词袋结构词嵌入结构具有节省计算机资源,表达更准确的特点。词嵌入的向量表示单词和单词在空间上的位置,而向量中的数值是通过机器学习的反向传播学习到的,并且每个词的位置都是由其在文本中的伴生词来决定的。我们接下来将会讲解Word2Vec和Glove两种词嵌入模型,至于其他的不在我们的讨论范围之内。
除了这些精心设计的方法之外,还可以把学习单词嵌入模型作为深度学习模型的一部分。这可能会比较耗时,但可以根据特定的训练数据集定制自己合适的词嵌入模型
10.3 Keras嵌入层
Keras提供一个Embedding层,可用于神经网络出了文本数据,它要求输入数据是整数编码,因此每个单词由唯一的一个向量表示。可以使用Keras提供的Tokenizer API来执行该数据准备步骤。
使用随机权重初始化Embedding层,并将学习训练数据集中所有单词嵌入。Embedding层非常灵活,可以以多种方式使用。例如:
- Input_dim:这是文本数据中词汇表的大小。例如我的数据整数编码为0-10之间的值,那么词汇表的大小将为11个单词
- Output_dim:这是将词嵌入的向量空间的大小。他为每一个单词定义了该层的输出向量的大小。例如。它可以是32或者64甚至更大。最好在实际问题中测试不同的值。
- Input_length:这是输入序列的长度。例如如果所有输入文档都包括1000个单词,则为1000、
下面我们用例子来说明一下,例如我们定义一个词汇表为200的嵌入层(从0-199的整数编码)即每一个单词是用一个200维的向量表示,一个32维的向量空间,其中将嵌入单词,输入文档,每个有50个单词
e = Embrdding(200,32,input_length = 50)
Embrdding层的权重必须被训练,如果将训练好的文件保存到文件,则将包括Embedding层权重。嵌入层的输出是2D矢量,在输入的单词序列中都会有一个向量对应。如果想要把Embedding的输出给到Dense层的输入中,则需要使用Flatten层将Embedding的2D矢量全展开,将二维的变成一维。下面我们来看看如何在实践中使用Embedding层。
10.4 学习嵌入的示例
首先我们将在神经网络的文本分类问题中训练和使用词嵌入模型,先定义文档及其标签
docs = [
'Well done',
'good work',
'Great effort',
'nice work',
'Excellent',
'Weak',
'not good',
'poor work',
'could have done better'
]
labels = ny.array([1,1,1,1,0,0,0,0])
接下来我们使用整数编码每个文档,这意味着Embedding层的输入是整数序列。我们可以尝试其他更复杂的单词模型编码:计数或TF-IDF。Keras提供了one_hot函数将每个单词的哈希值作为其有效的整数编码。我们设定词汇量大小为50,这远远大于问题所需,目的是减少哈希函数冲突概率。
import numpy as ny
import tensorflow as tf
labels = ny.array([1,1,1,1,0,0,0,0])
vocab_size = 50
encoded_docs = [tf.keras.preprocessing.text.one_hot(d,vocab_size) for d in docs]
print(encoded_docs)
print(encoded_docs)的结果为:
[[20, 48], [26, 30], [16, 17], [32, 30], [33], [34], [47, 26], [20, 30], [46, 13, 48, 19]]
可以看到每个短句的长度不都一样,而Keras的Embedding层更喜欢相同长度的输入,这里我们需要将其填充
import numpy as ny
from tensorflow.python.keras.preprocessing.sequence import pad_sequences
from tensorflow.python.keras.preprocessing.text import one_hot
#定义文档
docs = [
'Well done',
'good work',
'Great effort',
'nice work',
'Excellent',
'Weak',
'not good',
'poor work',
'could have done better'
]
labels = ny.array([1,1,1,1,0,0,0,0])
vocab_size = 50
encoded_docs = [one_hot(d,vocab_size) for d in docs]
print(encoded_docs)
max_len = max([len(v.split())for v in docs])
padded_docs = pad_sequences(encoded_docs,maxlen=max_len,padding='post')
print(padded_docs)
现在得到的结果为:
[[48, 24], [5, 9], [32, 8], [18, 9], [36], [7], [41, 5], [31, 9], [21, 31, 24, 4]]
[[48 24 0 0]
[ 5 9 0 0]
[32 8 0 0]
[18 9 0 0]
[