活动地址:CSDN21天学习挑战赛
学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。
自然语言处理(NLP)是人工智能(AI)的一种类型,它使得机器能够分析和理解人类语言。目前,NLP正在开发能够生成和理解自然语言的软件,以便用户能够与自己的计算机进行自然对话。NLP将AI与计算机语言学、计算机科学相结合,以处理人类语言或对话。
NLP的例子有很多,包括情感分析、聊天机器人、文档分类、单词聚类、机器翻译等,除了很多NLP实例外,涉及NLP的场景数量更多。
词嵌入是一种使用密集向量表示单词或文档的NLP技术,与使用大型稀疏向量的词袋技术相比,词嵌入通过将数字向量链接到字典中的每个单词,使得单词的语义含义投射到几何空间中,既而通过任何两个向量之间的距离捕获两个相关单词之间的语义关系,由这些向量形成的几何空间被称为嵌入空间。
用于学习词嵌入的两种最常见的技术分别是全局向量单词表示(GloVe)和单词到向量表示(Word2vec)。
from numpy import array, asarray, zeros
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
from keras.layers import 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.']
Keras提供了用于准备文本的tokenizer API,可用于准备多个文本文档。构造一个分词器,然后馈入文本文档或整数编码的文本文档。这里,单词被称为令牌,将文本划分为令牌的方法被描述为令牌化。Keras中的text_to_word_sequence API可将文本拆分为单词列表,如下所示:
# use tokenizer and pad
tokenizer = Tokenizer()
tokenizer.fit_on_texts(documents)
vocab_size = len(tokenizer.word_index) + 1
encodeDocuments = tokenizer.texts_to_sequences(documents)
print(encodeDocuments)
Well Done!和Good Work文档分别用向量[6,2]和[3,1]表示,而Could have done better文档由四个整数[12,13,2,14]表示。
与之前的独热编码相比,Keras的tokenizer文本API更精细,更适用于生产实际。
如下所示将文档填充到最大长度为4,Keras库中的pad_sequences()函数可用于填充可变长度序列。默认填充值为0.0,也可以通过value参数指定首选值来进行填充。
填充可以在序列的开头或结尾使用,体现为pre-或post-序列填充,如下所示:
max_length = 4
paddedDocuments = pad_sequences(encodeDocuments, maxlen=max_length, padding='post')
print(paddedDocuments)
利用预装的GloVe进行词嵌入。GloVe提供了一套预训练的词嵌入流程,我们会使用60亿词和100维的数据训练的GloVe,即glove.6B.100d.txt。如果查看文件,我们可以在每一行上看到一个令牌(单词),后面跟着权重(100个数字)。
在上述步骤中,我们将整个GloVe词嵌入文件作为词嵌入数组的字典加载到内存中。
inMemoryGlove = dict()
f = open('/Users/manpreet.singh/git/deeplearning/deeplearning-keras/ch08/embeddings/glove.6B.100d.txt')
for line in f:
values = line.split()
word = values[0]
coefficients = asarray(values[1:], dtype='float32')
inMemoryGlove[word] = coefficients
f.close()
print(len(inMemoryGlove))
现在,为训练数据集中的每个单词创建一个嵌入矩阵。通过迭代Tokenizer.word_index中所有单词,并从加载的GloVe嵌入中定位嵌入权重向量来完成。
输出是仅针对训练集中单词的权重矩阵,代码如下:
trainingToEmbeddings = zeros((vocab_size, 100))
for word, i in tokenizer.word_index.items():
gloveVector = inMemoryGlove.get(word)
if gloveVector is not None:
trainingToEmbeddings[i] = gloveVector
如前所述,Keras模型是一系列层。通过创建一个新的序贯模型并通过添加层来创建网络拓扑,模型定义后,将模型后端配置为TensorFlow。后端将选择最佳方式来表示网络,从而使得训练过程和预测过程在给定硬件上以最佳方式运行,代码如下:
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())
对于给定的分类问题使用相应的对数损失函数,该函数利用Keras中的binary_crossentropy实现,使用梯度下降算法Adam进行优化。
现在开始拟合模型。在给定数据集或文档上执行模型,训练过程运行固定的迭代次数,除此之外还可以设置网络权重更新时的评估实例数,即批量大小,利用batch_size参数进行设置,代码如下:
model.fit(paddedDocuments, labels, epochs=50, verbose=0)
最后,在给定文档中对神经网络的性能进行评估,从而获得在训练数据本身的训练准确率。同样,在本章的后一部分,我们将使用训练数据集和测试数据集来评估模型的性能,如下所示:
loss, accuracy = model.evaluate(paddedDocuments, labels, verbose=0)
print('Accuracy: %f' % (accuracy * 100))
最后输出:
100.000000