根据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)
下面方法基于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.
input_dim: vocal_size = 50 字典的大小,由于咱们在进行one-hot编码时,每一个词都是由 0-49 中的某个值做为索引值, 于是字典大小为 49+1 = 50;
input_length: 4, 若是输入的向量长度不足为4,就会给向量填充0,直到向量长度为4。
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
其实里面还有不少方法,能够参考该博客。