Embedding

Embedding的含义

根据tf.keras.layers.Embedding的解释python

是将正整数转换为固定长度的连续向量,它和one-hot编码的做用相似,都是对数据字符数值进行编码。网络

不一样之处是,embedding是将一个单纯的数值转换成一个长度惟一的几率分布向量,再避免one-hot编码产生的特征稀疏性问题的同时,也能增长特征的描述。函数

须要注意的是,当embedding进行神经网络构建时,embedding层必须做为第一层对输入数据进行embedding处理。其配置的参数以下post

  • input_dim: 配置字典的长度。embedding 是针对词频字典中的索引进行处理的,所以须要配置字典的长度。编码

  • output_dim: 配置神经网络层输出的维度。.net

  • embeddings_initializer: 配置embedding 矩阵的初始化code

  • embeddings_regularizer: 配置embedding 矩阵的正则化方程blog

  • embedding_constraint: 配置embedding 的约束函数索引

  • mask_zero: 配置"0"是否为Padding的值,若是配置为True, 则将全部的"0"去掉token

  • input_length: 配置输入语句的长度,将不足长度的用0填充。

    其中 input_dim 和 output_dim必须指定

当时,我看这个解释仍是比较懵逼。

举个小例子吧,下面咱们定义一个词汇表为200的嵌入层(例如从0到199的整数编码的字,包括0到199),一个32维的向量空间,其中将嵌入单词,以及输入文档,每一个单词有50个单词。

e = Embedding(input_dim=200, output_dim=32, input_length=50)

Embedding的实例

下面方法基于keras, 在tensorflow中咱们可使用 tf.keras.preprocessing.text.Tokenizer这个API库下的相关方法

咱们将定义一个小问题,咱们有10个文本文档,每一个文档都有一个学生提交的工做评论。每一个文本文档被分类为正的“1”或负的“0”。这是一个简单的情感分析问题。

首先,咱们将定义文档及其类别标签。

# define documents 定义文档
docs = ['Well done!',
		'Good work',
		'Great effort',
		'nice work',
		'Excellent!',
		'Weak',
		'Poor effort!',
		'not good',
		'poor work',
		'Could have done better.']
# define class labels 定义分类标签
labels = [1,1,1,1,1,0,0,0,0,0]

接下来,咱们来整数编码每一个文件。这意味着把输入,嵌入层将具备整数序列。咱们能够尝试其余更复杂的bag of word 模型好比计数或TF-IDF。

Keras提供one_hot()函数来建立每一个单词的散列做为一个有效的整数编码。咱们用估计50的词汇表大小,这大大减小了hash函数的冲突几率。

# integer encode the documents 独热编码
vocab_size = 50
encoded_docs = [one_hot(d, vocab_size) for d in docs]
print(encoded_docs)

[[6, 16], [42, 24], [2, 17], [42, 24], [18], [17], [22, 17], [27, 42], [22, 24], [49, 46, 16, 34]]

每一个词都能有0-49的一个索引值。例如 'well done' = [6, 16], 可是因为不一样的序列有不一样的长度,方便进行处理,所以咱们须要进行padding, 将全部的输入序列的长度填充为4.

# pad documents to a max length of 4 words 将不足长度的用0填充为长度4
max_length = 4
padded_docs = pad_sequences(encoded_docs, maxlen=max_length, padding='post')
print(padded_docs)
[[ 6 16  0  0]
 [42 24  0  0]
 [ 2 17  0  0]
 [42 24  0  0]
 [18  0  0  0]
 [17  0  0  0]
 [22 17  0  0]
 [27 42  0  0]
 [22 24  0  0]
 [49 46 16 34]]

咱们如今准备将咱们的嵌入层定义为咱们的神经网络模型的一部分。

嵌入的词汇量为50,输入长度为4,咱们将选择一个8维的嵌入空间。

该模型是一个简单的二元分类模型。重要的是,嵌入层的输出将是每一个8维的4个矢量,每一个单词一个。咱们将其平铺到一个32个元素的向量上以传递到密集输出层。

# define the model 定义模型
model = Sequential()
model.add(Embedding(vocab_size, 8, input_length=max_length))
model.add(Flatten())
model.add(Dense(1, activation='sigmoid'))
# compile the model 编译
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['acc'])
# summarize the model 打印模型信息
print(model.summary())

进行到这,咱们一直须要关注的是在进行维度的转换,本来是10x4, 可是通过Embedding以后,其实会变成10x4x8.

  1. input_dim: vocal_size = 50 字典的大小,由于咱们在进行one-hot编码时,每一个词都是由 0-49 中的某个值做为索引值, 于是字典大小为 49+1 = 50;

  2. input_length: 4, 若是输入的向量长度不足为4,就会给向量填充0,直到向量长度为4。

  3. output_dim: 8 每一个词的向量长度,在embedding以前,每一个词只有一个索引值,所以咱们须要将每一个词的索 引转变成一个长度为8的几率分布向量。(10x4x1 => 10x4x8)

    此处咱们能够明白embedding到底作了什么,举个栗子:

    ​ “公主”和“王妃” 使用One-hot编码 可能会获得: 公主 [1 0] 王妃 [0 1] 。

    ​ One-hot编码可以获得彻底独立的两个01向量,而且当若是文本集够大,那就会致使稀疏矩阵。

    ​ 因为二者彻底独立,表达关联特征的能力几乎就为0, 但王妃和公主是有关系,最基本的她们都是女性。

    ​ 而embedding会将one-hot编码(稀疏态),经过一些线性变换,让相互独立向量变成了有内在联系的关系 向量(密集态)便可能 公主 [ 1.0 0.25] 王妃 [ 0.6 0.75] 。


补充

使用tensorflow2.0中的tokenizer进行处理时。

# 定义word2vec的函数,经过统计全部训练集中的字符出现频率,构建字典,并使用字典中的码值对训练集中的语句进行替换
def tokenize(lang):
    # 使用高阶API tf.keras.preprocessing.text.Tokenize实例化一个转换器,构建字典并使用字典中的码值对训练集中的语句进行替换, oov_token: 配置不在字典中的字符的替换数字,通常使用“3”来替换。
    lang_tokenizer = tf.keras.preprocessing.text.Tokenizer(num_words=gConfig['enc_vocab_size'], oov_token=3)
    # 使用fit_on_texts方法对训练数据进行处理,构建字典
    lang_tokenizer.fit_on_texts(lang)
    # 转换器使用已经构建好的字典,将训练集的数据所有替换为字典的码值
    tensor = lang_tokenizer.texts_to_sequences(lang)
    # 为了提升计算效率,将训练语句的长度统一补全
    tensor = tf.keras.preprocessing.sequence.pad_sequences(tensor, padding='post')

    return tensor, lang_tokenizer

其实里面还有不少方法,能够参考该博客

参考

相关文章
相关标签/搜索