赞
踩
词嵌入提供了词的密集表示及其相对含义。最简单的理解就是:将词进行向量化表示,实体的抽象成了数学描述,就可以进行建模了。它们是对较简单的单词模型表示中使用的稀疏表示的改进。
词嵌入可以从文本数据中学习,并在项目之间重用。它们也可以作为在文本数据上拟合神经网络的一部分。用于学习词嵌入的两种最常见的技术分别是全局向量单词表示(Glove)和单词到向量表示(Word2vec)
Keras提供了一个嵌入层,可用于处理文本数据的神经网络。它要求输入数据进行整数编码,以便每个单词都由唯一的整数表示。该数据准备步骤可以使用提供有Keras的Tokenizer API来执行。
在没有预训练词嵌入的Keras API中,嵌入层会使用随机权重进行初始化。它是一个灵活的层,可以以各种方式使用。
1.它可以单独使用来学习一个字嵌入,以后可以在另一个模型中使用。
2.它可以用作深度学习模型的一部分,其中嵌入与模型本身一起被学习。
3.它可以用于加载预训练的词嵌入模型,一种迁移学习。
嵌入层被定义为网络的第一个隐藏层。它必须指定3个参数:
它必须指定3个参数:
1.input_dim:这是文本数据中词汇的大小。如果你的数据是整数编码为0-10之间的值,则词表的大小将为11个字。
2.output_dim:这是嵌入单词的向量空间的大小。它为每个单词定义了该层的输出向量的大小。它可以是32或100甚至更大,根据你的问题来定。
3.input_length:这是输入序列的长度,正如你为Keras模型的任何输入层定义的那样。如果你的所有输入文档包含1000个单词,则为1000。
我们定义一个小问题,我们有10个文本文档,每个文本文档都有一个关于学生作品的评论。这是一个简单的情绪分析问题,每个文本分类为正面“1”或负面“0”。
首先,我们将定义文档及其类标签。
# without embeddings import numpy as np from keras.preprocessing.text import one_hot from keras.preprocessing.sequence import pad_sequences from keras.models import Sequential from keras.layers import Dense,Flatten from keras.layers.embeddings import Embedding # define documents documents = [ 'Well done!', 'Good work', 'Great effort', 'nice work', 'Excellent!', 'Weak', 'Poor effort!', 'not good', 'poor work', 'Could have done better.'] # define class labels labels = np.array([1,1,1,1,1,0,0,0,0,0])
使用Keras文本处理API对每个文档进行one_hot编码,通常将文档表示为整数值序列,文档中的每个单词都表示为单个整数。
vocab_size = 50
encodeDocuments = [one_hot(doc,vocab_size) for doc in documents]
序列具有不同的长度,我们可以通过Keras库中的pad_sequences()来进行填充,我们将所有输入序列的长度设为4。
# 将文本填充到最大长度
max_length = 4
paddedDocuments = pad_sequences(encodeDocuments,maxlen=max_length,padding='post')
paddedDocuments
现在将我们的嵌入层定义为神经网络模型的一部分。嵌入词汇的大小为50,输入长度为4,选择8维的嵌入空间。这里的模型是二元分类器,而且嵌入层的输出为4个向量,每个向量8个维度,一个维度一个单词。
输出层的大小,计算方式很简单。假如输入尺寸为(batch_size, sequence_length)
的2D张量,输出尺寸就为(batch_size, sequence_length, output_dim)
3D张量。这里,batch_size为样本大小,所以输出尺寸中等于输入尺寸。而在嵌入层中我们会定义output_dim,词向量的维度。其实就一个矩阵乘法:
s
e
q
u
e
n
c
e
_
l
e
n
g
t
h
×
M
=
o
u
t
p
u
t
_
d
i
m
sequence\_length \times M =output\_dim
sequence_length×M=output_dim,M大小为(sequence_length, output_dim),所以输出尺寸为(batch_size, sequence_length, output_dim)
model = Sequential(name="without embeddings")
model.add(Embedding(vocab_size, 8, input_length=max_length,name="Embedding"))
model.add(Flatten(name='Flatten'))
model.add(Dense(1,activation='sigmoid',name='output'))
model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['acc'])
print(model.summary())
model.fit(paddedDocuments, labels, epochs=50, verbose=1)
model.save('./data/without_embeddings.h5')
model.save_weights('./data/without_embeddings_weights.h5')
loss, accuracy = model.evaluate(paddedDocuments, labels, verbose=0)
print('Accuracy: %f' % (accuracy*100))
模型结构:
现在使用Keras的预训练的词嵌入,代码大致与上文相同。我们将整个Glove词嵌入文件作为词嵌入数组的字典加载到内存中。在这里,我们使用60亿词和100维的数据训练的Glove,即glove.6B.100d.txt。
import numpy as np from keras.preprocessing.text import one_hot,Tokenizer from keras.preprocessing.sequence import pad_sequences from keras.models import Sequential from keras.layers.embeddings import Embedding from keras.layers import Dense,Flatten # define documents documents = [ 'Well done!', 'Good work', 'Great effort', 'nice work', 'Excellent!', 'Weak', 'Poor effort!', 'not good', 'poor work', 'Could have done better.'] # define class labels labels = np.array([1,1,1,1,1,0,0,0,0,0]) # use tokenizer and pad tokenizer = Tokenizer() tokenizer.fit_on_texts(documents) vocab_size = len(tokenizer.word_index)+1 # print(tokenizer.word_counts) encodeDocuments = tokenizer.texts_to_sequences(documents) # print("encodeDocuments:\n",encodeDocuments) max_length = 4 paddedDocuments = pad_sequences(encodeDocuments, maxlen=max_length, padding='post') # print("paddedDocuments:\n",paddedDocuments)
接下来,我们将整个GloVe字嵌入文件作为字嵌入数组的字典加载到内存中。并且为训练数据集中的每个单词创建一个嵌入矩阵。我们可以通过枚举Tokenizer.word_index中的所有唯一的字,并从加载的GloVe嵌入中定位嵌入权重向量。
# load glove model inMemoryGlove = dict() with open('/mnt/f/py/数据集/词向量/glove.6B/glove.6B.100d.txt') as fp: for line in fp: values = line.split() word = values[0] cofficients = np.asarray(values[1:],dtype='float32') inMemoryGlove[word] = cofficients # print(len(inMemoryGlove)) # create coefficient matrix for training data trainingToEmbeddings = np.zeros((vocab_size,100)) for word, i in tokenizer.word_index.items(): gloveVector = inMemoryGlove.get(word) if gloveVector is not None: trainingToEmbeddings[i] = gloveVector
定义模型,训练与评估
model = Sequential()
model.add(Embedding(vocab_size,100,weights=[trainingToEmbeddings],input_length=max_length,trainable=False))
model.add(Flatten())
model.add(Dense(1,activation='sigmoid'))
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['acc'])
print(model.summary())
model.fit(paddedDocuments,labels,epochs=50,verbose=0)
loss, accuracy = model.evaluate(paddedDocuments, labels, verbose=0)
print('Accuracy: %f' % (accuracy * 100))
模型结构图:
情感分析基本上是用于识别并分类一段文本或语料库中所表达的情感的一种方法,为了确定他人对特定主题、产品等的态度是积极的、消极的还是中立的,使用NLP对应地文档分类为正面、中性或负面。
数据来自Crowdflower’s data for everyone数据库
import re import numpy as np import pandas as pd from keras.preprocessing.text import one_hot, Tokenizer from keras.preprocessing.sequence import pad_sequences from keras.models import Sequential from keras.layers import Dense, Flatten from keras.layers.embeddings import Embedding from sklearn.model_selection import train_test_split # 读取数据 X = pd.read_csv(r'./data/Sentiment.csv') X = X[['text', 'sentiment']] X = X[X.sentiment != 'Neutral'] # 放弃中性情感 # 对推文过滤,只保留有效的文本和单词 X['text'] = X['text'].apply(lambda x: x.lower()) X['text'] = X['text'].apply((lambda x: re.sub('[^a-zA-z0-9\s]', '', x))) # X = X['text'].apply((lambda x:x.replace('rt',' '))) # print(X) for idx, row in X.iterrows(): row[0] = row[0].replace('rt', ' ') print(type(X)) # use tokenizer and pad maxFeatures = 2000 tokenizer = Tokenizer(num_words=maxFeatures, split=' ') tokenizer.fit_on_texts(X['text'].values) # 生成token词典 encodeDocuments = tokenizer.texts_to_sequences(X['text'].values) # print(encodeDocuments) # print(max([len(row) for row in encodeDocuments])) max_length = 29 paddedDocuments = pad_sequences(encodeDocuments, maxlen=max_length, padding='post') # load glove model inMemoryGlove = dict() with open('/mnt/f/py/数据集/词向量/glove.6B/glove.6B.100d.txt') as fp: for line in fp: values = line.split() word = values[0] cofficients = np.asarray(values[1:],dtype='float32') inMemoryGlove[word] = cofficients print(len(inMemoryGlove)) # split data labels = [] for i in X['sentiment']: if i == 'Positive': labels.append(1) else: labels.append(0) labels = array(labels) # print(len(labels)) X_train, X_test, Y_train, Y_test = train_test_split(paddedDocuments,labels, test_size = 0.33, random_state = 42) print(X_train.shape, Y_train.shape) print(X_test.shape, Y_test.shape) # create coefficient matrix for training data trainingToEmbeddings = np.zeros((maxFeatures, 100)) for word, i in tokenizer.word_index.items(): # i从1开始增加 if i <= maxFeatures: gloveVector = inMemoryGlove.get(word) if gloveVector is not None: trainingToEmbeddings[i] = gloveVector # print(trainingToEmbeddings) model = Sequential(name='情感分析') model.add(Embedding(maxFeatures,100,weights=[trainingToEmbeddings],input_length=max_length,trainable=False,name='Embedding')) model.add(Flatten(name='Flatten')) model.add(Dense(1,activation='sigmoid',name='output')) model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['acc']) print(model.summary()) batch_size = 32 model.fit(X_train, Y_train, epochs=50, batch_size=batch_size, verbose=0) loss, accuracy = model.evaluate(X_test, Y_test, verbose=0) print('Accuracy: %f' % (accuracy * 100))
结果图:
参考资料:
Keras深度学习实战
Keras嵌入层API
在Keras模型中使用预训练的词嵌入
GloVe
词向量与Embedding究竟是怎么回事?
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。