自然语言处理秘籍(四)
六、面向自然语言处理的深度学习
在本章中,您将实现 NLP 的深度学习。涵盖以下食谱。
-
食谱 1。使用深度学习的信息检索
-
食谱 2。使用 CNN 的文本分类,RNN,LSTM
-
食谱三。使用电子邮件 LSTM 预测下一个单词/单词序列
-
食谱 4。堆栈溢出问题推荐
深度学习简介
深度学习是受大脑功能启发的机器学习的一个子领域。就像神经元在大脑中相互连接一样,神经网络也以同样的方式工作。每个神经元接受输入,在神经元内进行一些操作,并产生更接近预期输出的输出(在标记数据的情况下)。
神经元内发生的事情是我们感兴趣的,以获得最准确的结果。它为每个输入赋予权重,并生成一个函数来累积所有这些权重,并将它们传递给下一层,最终是输出层。
该网络有三个组成部分。
-
输入层
-
隐藏层
-
输出层
基于问题或数据,函数可以是不同的类型。这些也被称为激活功能 s 。下面描述了这些类型。
-
线性激活函数:线性神经元采用加权输入的线性组合,输出可以采用负无穷大到无穷大之间的任何值。
-
非线性激活函数:这些是最常用的,它们使输出限制在某个范围内。
-
sigmoid 或 logit 激活函数通过应用对数函数在 0 和 1 之间缩小输出,使分类问题变得更容易。
-
softmax 函数类似于 sigmoid,但它计算 n 个不同类上的事件概率,这有助于确定多类分类问题中的目标。
-
双曲正切函数是–1 比 1;否则与乙状结肠相同。
-
整流线性单位激活函数将任何小于零的值转换为零。所以,范围变成了 0 到无穷大。
-
我们仍然没有讨论在神经网络中如何进行训练。让我们用卷积神经网络来做这件事。
卷积神经网络
卷积神经网络(CNN)类似于普通的神经网络,但有多个隐藏层,以及一个称为卷积层的过滤器。CNN 成功识别人脸、物体和交通标志,也用于自动驾驶汽车。
数据
算法基本上对数字数据起作用。图像和文本数据是非结构化数据,甚至在我们开始任何事情之前,它们就需要被转换成数值。
-
图像:计算机将一幅图像作为像素值的数组。根据图像的分辨率和大小,它会看到一个 X * Y * Z 的数字数组。例如,有一幅彩色图像,其大小为 480×480 像素。该数组的表示形式为 480×480×3,其中 3 是颜色的 RGB 值。这些数字中的每一个都从 0 到 255 不等,这描述了该点的像素强度/密度。这个概念是,如果给计算机和这个数组的数字,它输出的概率图像是某一类的情况下,分类问题。
-
Text :我们已经讨论过如何从文本中创建特征。您可以使用任何一种技术将文本转换为特征。RNN 和 LSTM 更适合文本相关的解决方案,我们将在下一节中讨论。
体系结构
CNN 是具有输入层、输出层和多个隐藏层的神经网络的特例。隐藏层有四个不同的程序来完成网络。每一个都有详细的解释。
盘旋
卷积层是卷积神经网络的核心,它执行大多数计算操作。该名称来源于从输入图像中提取特征的“卷积”运算符。这些也被称为滤镜(一个橙色的 33 矩阵)。通过在整个图像上滑动滤波器并计算这两个矩阵之间的点积而形成的矩阵被称为卷积特征*、激活图或特征图。例如,假设在表数据中计算不同类型的特征,例如从“出生日期”计算“年龄”直边、简单颜色和曲线是过滤器可以从图像中提取的一些特征。
在 CNN 的训练过程中,它学习过滤器中存在的数字或值,并将其用于测试数据。特征的数量越多,提取的图像特征就越多,并识别看不见的图像中的模式。
非线性(ReLU)
一个整流线性单元 ( ReLU )是 CNN 架构中卷积层之后使用的非线性函数。它用零替换矩阵中的所有负值。ReLU 的目的是在 CNN 中引入非线性以更好地执行。
联营
池化或二次采样在不丢失重要信息的情况下降低了特征的维数。这样做是为了减少全连接层的大量输入和处理模型所需的计算。它还减少了模型的过拟合。它使用一个 2×2 的窗口,在图像上滑动,并在每个区域取最大值,如图所示。这就是它降低维度的方式。
展平、完全连接和 Softmax 层
最后一层是需要特征向量作为输入的密集层。但是池层的输出不是 1D 特征向量。这个将卷积输出转换为特征向量的过程称为展平。完全连接层从展平层获取输入,并给出一个 n 维向量,其中 n 是类的数量。全连接层的功能是使用这些特征,根据训练数据集的损失函数将输入图像分类为各种类别。在最后使用 softmax 函数将这些 n 维向量转换成每个类别的概率,最终将图像分类到特定类别。
反向传播:训练神经网络
在正常的神经网络中,您进行前向传播以获得输出,并检查该输出是否正确并计算误差。在反向传播中,你通过你的网络反向寻找误差相对于每个权重的偏导数。
让我们看看它到底是如何工作的。
输入图像被输入网络。它完成前向传播,即卷积、ReLU 和池化操作,在全连接层中进行前向传播,并为每个类生成输出概率。根据前馈规则,权重被随机分配,并完成训练和输出随机概率的第一次迭代。第一步结束后,网络使用以下公式计算输出层的误差
总误差= ∑(目标概率-输出概率) 2
现在,反向传播开始计算网络中所有权重的误差梯度,并使用梯度下降来更新所有滤波器值和权重,最终使输出误差最小化。过滤器数量、过滤器尺寸和网络架构等参数在构建网络时就已确定。过滤器矩阵和连接权重在每次运行时都会更新。对整个训练集重复整个过程,直到误差最小。
循环神经网络
CNN 用于计算机视觉问题,但无法解决序列模型。序列模型是那些甚至实体的序列也很重要的模型。例如,在文章中,单词的顺序对于创造有意义的句子很重要。这就是 rnn 发挥作用的地方,它对顺序数据很有用,因为每个神经元都可以用自己的记忆来记住上一步的信息。
要理解 RNN 到底是如何运作的相当复杂。如果你看到上图,循环神经网络从隐藏层获取输出,并在给出预测之前将其发送回同一层。
训练 RNN:穿越时间的反向传播(BPTT)
你知道前馈和反向传播在 CNN 是如何工作的,所以让我们看看 RNN 是如何进行培训的。
如果我们只讨论隐藏层,它不仅从隐藏层获取输入,而且您还可以向同一个隐藏层添加另一个输入。现在反向传播就像你以前见过的任何其他训练一样发生;现在,它依赖于时间。这里,通过展开隐藏层,误差从最后一个时间戳反向传播到第一个时间戳。这允许计算每个时间戳的误差并更新权重。在隐藏单元之间具有循环连接的循环网络读取整个序列,然后产生所需的输出。
当梯度值太小时,模型需要太长时间来学习,这被称为消失梯度。LSTM 解决了这个问题。
长短期记忆(LSTM)
LSTMs 类似于 rnn,但具有更好的方程和反向传播,这使它们的性能更好。LSTMs 的工作方式类似于 rnn,但是它们可以学习很长时间间隔的东西,并且它们可以像计算机一样存储信息。
该算法通过加权方法学学习单词或字符的重要性,并决定是否存储它。为此,它使用被称为门的调节结构,可以向细胞中添加或删除信息。这些细胞有一个 sigmoid 层,决定应该传递多少信息。它有三层——输入、遗忘和输出——来执行这个过程。
对 CNN 和 RNN 工作的深入讨论超出了本书的范围。如果你有兴趣了解更多,书的末尾有参考资料。
食谱 6-1。检索信息
信息检索是自然语言处理中使用频率很高的应用之一,并且非常棘手。单词或句子的意思取决于所用的确切单词以及上下文和意思。两个句子可能是完全不同的词,但可以传达相同的意思。你应该能捕捉到。
信息检索(IR)系统允许用户基于搜索文本/查询有效地搜索文档并检索有意义的信息。
问题
使用词嵌入的信息检索。
解决办法
有多种方法可以进行信息检索。使用单词嵌入是非常有效的,因为它也考虑了上下文。我们在第三章中讨论了单词嵌入是如何构建的。预训练的 word2vec 只在这种情况下使用。
让我们举一个简单的例子,看看如何使用查询输入构建文档检索。假设数据库中有四个文档,如下所示。(这展示了它是如何工作的。现实世界的应用程序中有许多文档。)
Doc1 = ["With the Union cabinet approving the amendments to the Motor Vehicles Act, 2016, those caught for drunken driving will have to have really deep pockets, as the fine payable in court has been enhanced to Rs 10,000 for first-time offenders." ]
Doc2 = ["Natural language processing (NLP) is an area of computer science and artificial intelligence concerned with the interactions between computers and human (natural) languages, in particular how to program computers to process and analyze large amounts of natural language data."]
Doc3 = ["He points out that public transport is very good in Mumbai and New Delhi, where there is a good network of suburban and metro rail systems."]
Doc4 = ["But the man behind the wickets at the other end was watching just as keenly. With an affirmative nod from Dhoni, India captain Rohit Sharma promptly asked for a review. Sure enough, the ball would have clipped the top of middle and leg."]
假设有许多这样的文档。并且您想要检索与查询“cricket”最相关的一个让我们来看看如何建立它。
query = "cricket"
它是如何工作的
步骤 1-1。导入库
这里是图书馆。
import gensim
from gensim.models import Word2Vec
import numpy as np
import nltk
import itertools
from nltk.corpus import stopwords
from nltk.tokenize import sent_tokenize, word_tokenize
import scipy
from scipy import spatial
from nltk.tokenize.toktok import ToktokTokenizer
import re
tokenizer = ToktokTokenizer()
stopword_list = nltk.corpus.stopwords.words('english')
步骤 1-2。创建或导入文档
从网上随机抽取句子。
Doc1 = ["With the Union cabinet approving the amendments to the Motor Vehicles Act, 2016, those caught for drunken driving will have to have really deep pockets, as the fine payable in court has been enhanced to Rs 10,000 for first-time offenders." ]
Doc2 = ["Natural language processing (NLP) is an area of computer science and artificial intelligence concerned with the interactions between computers and human (natural) languages, in particular how to program computers to process and analyze large amounts of natural language data."]
Doc3 = ["He points out that public transport is very good in Mumbai and New Delhi, where there is a good network of suburban and metro rail systems."]
Doc4 = ["But the man behind the wickets at the other end was watching just as keenly. With an affirmative nod from Dhoni, India captain Rohit Sharma promptly asked for a review. Sure enough, the ball would have clipped the top of middle and leg."]
# Put all the documents in one list
fin= Doc1+Doc2+Doc3+Doc4
步骤 1-3。下载 word2vec
接下来,让我们使用单词嵌入来解决这个问题。从 https://drive.google.com/file/d/0B7XkCwpI5KDYNlNUTTlSS21pQmM/edit 下载 word2vec。
#load the model
Model= gensim.models.KeyedVectors.load_word2vec_format('/GoogleNews-vectors-negative300.bin', binary=True)
步骤 1-4。创建一个 IR 系统
现在,建立信息检索系统。
#Preprocessing
def remove_stopwords(text, is_lower_case=False):
pattern = r'[^a-zA-z0-9\s]'
text = re.sub(pattern, ", ".join(text))
tokens = tokenizer.tokenize(text)
tokens = [token.strip() for token in tokens]
if is_lower_case:
filtered_tokens = [token for token in tokens if token not in stopword_list]
else:
filtered_tokens = [token for token in tokens if token.lower() not in stopword_list]
filtered_text = ' '.join(filtered_tokens)
return filtered_text
# Function to get the embedding vector for n dimension, we have used "300"
def get_embedding(word):
if word in model.wv.vocab:
return model[x]
else:
return np.zeros(300)
对于每一个文档,我们都会得到很多基于单词数量的向量。您需要通过取所有单词向量的平均值来计算文档的平均向量。
# Getting average vector for each document
out_dict = {}
for sen in fin:
average_vector = (np.mean(np.array([get_embedding(x) for x in nltk.word_tokenize(remove_stopwords(sen))]), axis=0))
dict = { sen : (average_vector) }
out_dict.update(dict)
# Function to calculate the similarity between the query vector and document vector
def get_sim(query_embedding, average_vector_doc):
sim = [(1 - scipy.spatial.distance.cosine(query_embedding, average_vector_doc))]
return sim
# Rank all the documents based on the similarity to get relevant docs
def Ranked_documents(query):
query_words = (np.mean(np.array([get_embedding(x) for x in nltk.word_tokenize(query.lower())],dtype=float), axis=0))
rank = []
for k,v in out_dict.items():
rank.append((k, get_sim(query_words, v)))
rank = sorted(rank,key=lambda t: t[1], reverse=True)
print('Ranked Documents :')
return rank
步骤 1-5。结果和应用
让我们通过几个例子来看看我们构建的信息检索系统。
# Call the IR function with a query
Ranked_documents("cricket")
Result :
[('But the man behind the wickets at the other end was watching just as keenly. With an affirmative nod from Dhoni, India captain Rohit Sharma promptly asked for a review. Sure enough, the ball would have clipped the top of middle and leg.',
[0.44954327116871795]),
('He points out that public transport is very good in Mumbai and New Delhi, where there is a good network of suburban and metro rail systems.',
[0.23973446569030055]),
('With the Union cabinet approving the amendments to the Motor Vehicles Act, 2016, those caught for drunken driving will have to have really deep pockets, as the fine payable in court has been enhanced to Rs 10,000 for first-time offenders.',
[0.18323712012013349]),
('Natural language processing (NLP) is an area of computer science and artificial intelligence concerned with the interactions between computers and human (natural) languages, in particular how to program computers to process and analyze large amounts of natural language data.',
[0.17995060855459855])]
Doc4(在结果的顶部)与查询“cricket”最相关,尽管单词 cricket 一次也没有提到,相似度为 0.449。
让我们再举一个可能开车的例子。
Ranked_documents("driving")
[('With the Union cabinet approving the amendments to the Motor Vehicles Act, 2016, those caught for drunken driving will have to have really deep pockets, as the fine payable in court has been enhanced to Rs 10,000 for first-time offenders.',
[0.35947287723800669]),
('But the man behind the wickets at the other end was watching just as keenly. With an affirmative nod from Dhoni, India captain Rohit Sharma promptly asked for a review. Sure enough, the ball would have clipped the top of middle and leg.',
[0.19042556935316801]),
('He points out that public transport is very good in Mumbai and New Delhi, where there is a good network of suburban and metro rail systems.',
[0.17066536985237601]),
('Natural language processing (NLP) is an area of computer science and artificial intelligence concerned with the interactions between computers and human (natural) languages, in particular how to program computers to process and analyze large amounts of natural language data.',
[0.088723080005327359])]
同样,由于驾驶与运输和机动车辆法案相关联,它会将最相关的文档放在最上面。前两个文档与查询相关。
您可以使用相同的方法,并将其扩展到尽可能多的文档。为了获得更高的准确性,你可以为特定的行业构建你自己的嵌入,正如你在第三章中所学的,因为我们使用的是通用的。
这是可用于许多应用程序的基本方法,如下所示。
-
搜索引擎
-
文档检索
-
段落检索
-
问答
事实证明,当查询越长,结果越短时,结果越好。这就是为什么当搜索查询的字数较少时,你在搜索引擎中得不到很好的结果。
食谱 6-2。利用深度学习对文本进行分类
这个食谱使用深度学习方法构建了一个文本分类器。
问题
您想要使用 CNN、RNN 和 LSTM 建立一个文本分类模型。
解决办法
方法和 NLP 管道保持不变。唯一的变化是,我们不再使用机器学习算法,而是使用深度学习算法建立模型。
它是如何工作的
按照本节中的步骤,使用深度学习方法构建电子邮件分类器。
步骤 2-1。定义业务问题
电子邮件分类(垃圾邮件或垃圾邮件)。您需要根据电子邮件内容对垃圾邮件进行分类。
第 2-2 步。确定潜在的数据来源并收集
使用第四章中配方 4-6 中的相同数据。
#read file
file_content = pd.read_csv('spam.csv', encoding = "ISO-8859-1")
#check sample content in the email
file_content['v2'][1]
#output
'Ok lar... Joking wif u oni...'
第 2-3 步。预处理文本
让我们对数据进行预处理。
#Import library
from nltk.corpus import stopwords
from nltk import *
from sklearn.feature_extraction.text import TfidfVectorizer
from nltk.stem import WordNetLemmatizer
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
# Remove stop words
stop = stopwords.words('english')
file_content['v2'] = file_content['v2'].apply(lambda x: " ".join(x for x in x.split() if x not in stop))
# Delete unwanted columns
Email_Data = file_content[['v1', 'v2']]
# Rename column names
Email_Data = Email_Data.rename(columns={"v1":"Target", "v2":"Email"})
Email_Data.head()
#output
Target Email
0 ham Go jurong point, crazy.. Available bugis n gre...
1 ham Ok lar... Joking wif u oni...
2 spam Free entry 2 wkly comp win FA Cup final tkts 2...
3 ham U dun say early hor... U c already say...
4 ham Nah I think goes usf, lives around though
#Delete punctuations, convert text in lower case and delete the double space
Email_Data['Email'] = Email_Data['Email'].apply(lambda x: re.sub('[!@#$:).;,?&]', ", x.lower()))
Email_Data['Email'] = Email_Data['Email'].apply(lambda x: re.sub(' ', ' ', x))
Email_Data['Email'].head(5)
#output
0 go jurong point crazy available bugis n great ...
1 ok lar joking wif u oni
2 free entry 2 wkly comp win fa cup final tkts 2...
3 u dun say early hor u c already say
4 nah i think goes usf lives around though
Name: Email, dtype: object
#Separating text(input) and target classes
list_sentences_rawdata = Email_Data["Email"].fillna("_na_").values
list_classes = ["Target"]
target = Email_Data[list_classes].values
To_Process=Email_Data[['Email', 'Target']]
第 2-4 步。为建模准备数据
接下来,准备数据。
#Train and test split with 80:20 ratio
train, test = train_test_split(To_Process, test_size=0.2)
# Define the sequence lengths, max number of words and embedding dimensions
# Sequence length of each sentence. If more, truncate. If less, pad with zeros
MAX_SEQUENCE_LENGTH = 300 #user_transform
# Top 20000 frequently occurring words
MAX_NB_WORDS = 20000
# Get the frequently occurring words
tokenizer = Tokenizer(num_words=MAX_NB_WORDS)
tokenizer.fit_on_texts(train.Email)
train_sequences = tokenizer.texts_to_sequences(train.Email)
test_sequences = tokenizer.texts_to_sequences(test.Email)
# dictionary containing words and their index
word_index = tokenizer.word_index
# print(tokenizer.word_index)
# total words in the corpus
print('Found %s unique tokens.' % len(word_index))
# get only the top frequent words on train
train_data = pad_sequences(train_sequences, maxlen=MAX_SEQUENCE_LENGTH)
# get only the top frequent words on test
test_data = pad_sequences(test_sequences, maxlen=MAX_SEQUENCE_LENGTH)
print(train_data.shape)
print(test_data.shape)
#output
Found 8443 unique tokens.
(4457, 300)
(1115, 300)
train_labels = train['Target']
test_labels = test['Target']
#import library
from sklearn.preprocessing import LabelEncoder
# converts the character array to numeric array. Assigns levels to unique labels.
le = LabelEncoder()
le.fit(train_labels)
train_labels = le.transform(train_labels)
test_labels = le.transform(test_labels)
print(le.classes_)
print(np.unique(train_labels, return_counts=True))
print(np.unique(test_labels, return_counts=True))
#output
['ham' 'spam']
(array([0, 1]), array([3889, 568]))
(array([0, 1]), array([936, 179]))
# changing data types
labels_train = to_categorical(np.asarray(train_labels))
labels_test = to_categorical(np.asarray(test_labels))
print('Shape of data tensor:', train_data.shape)
print('Shape of label tensor:', labels_train.shape)
print('Shape of label tensor:', labels_test.shape)
#output
Shape of data tensor: (4457, 300)
Shape of label tensor: (4457, 2)
Shape of label tensor: (1115, 2)
EMBEDDING_DIM = 100
print(MAX_SEQUENCE_LENGTH)
#output
300
第 2-5 步。建模和预测
我们正在使用不同的深度学习方法构建模型,如 CNN、RNN、LSTM 和双向 LSTM,并使用不同的准确性指标比较每个模型的性能。首先,我们来定义一下 CNN 模型。
这里我们定义了一个有 128 个存储单元的隐藏层。网络使用概率为 0.5 的辍学。输出图层是使用 softmax 激活函数输出概率预测的密集图层。
# Import Libraries
import sys, os, re, csv, codecs, numpy as np, pandas as pd
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences
from keras.utils import to_categorical
from keras.layers import Dense, Input, LSTM, Embedding, Dropout, Activation
from keras.layers import Bidirectional, GlobalMaxPool1D, Conv1D, SimpleRNN
from keras.models import Model
from keras.models import Sequential
from keras import initializers, regularizers, constraints, optimizers, layers
from keras.layers import Dense, Input, Flatten, Dropout, BatchNormalization
from keras.layers import Conv1D, MaxPooling1D, Embedding
from keras.models import Sequential
print('Training CNN 1D model.')
model = Sequential()
model.add(Embedding(MAX_NB_WORDS,
EMBEDDING_DIM,
input_length=MAX_SEQUENCE_LENGTH
))
model.add(Dropout(0.5))
model.add(Conv1D(128, 5, activation="relu"))
model.add(MaxPooling1D(5))
model.add(Dropout(0.5))
model.add(BatchNormalization())
model.add(Conv1D(128, 5, activation="relu"))
model.add(MaxPooling1D(5))
model.add(Dropout(0.5))
model.add(BatchNormalization())
model.add(Flatten())
model.add(Dense(128, activation="relu"))
model.add(Dense(2, activation="softmax"))
model.compile(loss='categorical_crossentropy',
optimizer="rmsprop",
metrics=['acc'])
我们现在正在使我们的模型符合数据。有五个时期和 64 个模式的批量大小。
model.fit(train_data, labels_train,
batch_size=64,
epochs=5,
validation_data=(test_data, labels_test))
#output
#predictions on test data
predicted=model.predict(test_data)
predicted
#output
array([[0.5426713 , 0.45732868],
[0.5431667 , 0.45683333],
[0.53082496, 0.46917507],
...,
[0.53582424, 0.46417573],
[0.5305845 , 0.46941552],
[0.53102577, 0.46897423]], dtype=float32)
#model evaluation
import sklearn
from sklearn.metrics import precision_recall_fscore_support as score
precision, recall, fscore, support = score(labels_test, predicted.round())
print('precision: {}'.format(precision))
print('recall: {}'.format(recall))
print('fscore: {}'.format(fscore))
print('support: {}'.format(support))
print("############################")
print(sklearn.metrics.classification_report(labels_test, predicted.round()))
#output
我们现在可以定义我们的 RNN 模型。
#import library
from keras.layers.recurrent import SimpleRNN
#model training
print('Training SIMPLERNN model.')
model = Sequential()
model.add(Embedding(MAX_NB_WORDS,
EMBEDDING_DIM,
input_length=MAX_SEQUENCE_LENGTH
))
model.add(SimpleRNN(2, input_shape=(None,1)))
model.add(Dense(2,activation='softmax'))
model.compile(loss = 'binary_crossentropy', optimizer="adam",metrics = ['accuracy'])
model.fit(train_data, labels_train,
batch_size=16,
epochs=5,
validation_data=(test_data, labels_test))
#output
# prediction on test data
predicted_Srnn=model.predict(test_data)
predicted_Srnn
#output
array([[0.9959137 , 0.00408628],
[0.99576926, 0.00423072],
[0.99044365, 0.00955638],
...,
[0.9920791 , 0.00792089],
[0.9958105 , 0.00418955],
[0.99660563, 0.00339443]], dtype=float32)
#model evaluation
from sklearn.metrics import precision_recall_fscore_support as score
precision, recall, fscore, support = score(labels_test, predicted_Srnn.round())
print('precision: {}'.format(precision))
print('recall: {}'.format(recall))
print('fscore: {}'.format(fscore))
print('support: {}'.format(support))
print("############################")
print(sklearn.metrics.classification_report(labels_test, predicted_Srnn.round()))
#output
这是我们的长期短期记忆(LSTM)模型。
#model training
print('Training LSTM model.')
model = Sequential()
model.add(Embedding(MAX_NB_WORDS,
EMBEDDING_DIM,
input_length=MAX_SEQUENCE_LENGTH
))
model.add(LSTM(output_dim=16, activation="relu", inner_activation="hard_sigmoid",return_sequences=True))
model.add(Dropout(0.2))
model.add(BatchNormalization())
model.add(Flatten())
model.add(Dense(2,activation='softmax'))
model.compile(loss = 'binary_crossentropy', optimizer="adam",metrics = ['accuracy'])
model.fit(train_data, labels_train,
batch_size=16,
epochs=5,
validation_data=(test_data, labels_test))
#output
#prediction on text data
predicted_lstm=model.predict(test_data)
predicted_lstm
array([[1.0000000e+00, 4.0581045e-09],
[1.0000000e+00, 8.3188789e-13],
[9.9999976e-01, 1.8647323e-07],
...,
[9.9999976e-01, 1.8333606e-07],
[1.0000000e+00, 1.7347950e-09],
[9.9999988e-01, 1.3574694e-07]], dtype=float32)
#model evaluation
from sklearn.metrics import precision_recall_fscore_support as score
precision, recall, fscore, support = score(labels_test, predicted_lstm.round())
print('precision: {}'.format(precision))
print('recall: {}'.format(recall))
print('fscore: {}'.format(fscore))
print('support: {}'.format(support))
print("############################")
print(sklearn.metrics.classification_report(labels_test, predicted_lstm.round()))
#output
最后,让我们讨论双向 LSTM 并实现它。
LSTM 使用隐藏状态保存输入的信息。在双向 LSTMs 中,输入有两种方式:一种是从过去到未来,另一种是从未来到过去,帮助学习未来的表示。众所周知,双向 LSTMs 可以产生非常好的结果,因为它们可以更好地理解上下文。
#model training
print('Training Bidirectional LSTM model.')
model = Sequential()
model.add(Embedding(MAX_NB_WORDS,
EMBEDDING_DIM,
input_length=MAX_SEQUENCE_LENGTH
))
model.add(Bidirectional(LSTM(16, return_sequences=True, dropout=0.1, recurrent_dropout=0.1)))
model.add(Conv1D(16, kernel_size = 3, padding = "valid", kernel_initializer = "glorot_uniform"))
model.add(GlobalMaxPool1D())
model.add(Dense(50, activation="relu"))
model.add(Dropout(0.1))
model.add(Dense(2,activation='softmax'))
model.compile(loss = 'binary_crossentropy', optimizer="adam",metrics = ['accuracy'])
model.fit(train_data, labels_train,
batch_size=16,
epochs=3,
validation_data=(test_data, labels_test))
#output
# prediction on test data
predicted_blstm=model.predict(test_data)
predicted_blstm
#output
array([[9.9999976e-01, 2.6086647e-07],
[9.9999809e-01, 1.9633851e-06],
[9.9999833e-01, 1.6918856e-06],
...,
[9.9999273e-01, 7.2622524e-06],
[9.9999964e-01, 3.3541210e-07],
[9.9999964e-01, 3.5427794e-07]], dtype=float32)
#model evaluation
from sklearn.metrics import precision_recall_fscore_support as score
precision, recall, fscore, support = score(labels_test, predicted_blstm.round())
print('precision: {}'.format(precision))
print('recall: {}'.format(recall))
print('fscore: {}'.format(fscore))
print('support: {}'.format(support))
print("############################")
print(sklearn.metrics.classification_report(labels_test, predicted_blstm.round()))
#output
你可以看到双向 LSTM 优于其他算法。
食谱 6-3。下一个单词预测
自动填充/显示潜在的单词序列节省了大量写电子邮件的时间,并使用户乐于在任何产品中使用它。
问题
您希望使用电子邮件数据,根据前面的单词序列建立一个模型来预测/建议下一个单词。
如下图所示,语言被建议为下一个单词。
解决办法
本节构建了一个 LSTM 模型,用于从电子邮件数据中学习单词序列。这个模型预测下一个单词。
它是如何工作的
按照本节中的步骤,使用深度学习方法建立下一个单词预测模型。
步骤 3-1。定义业务问题
根据单词或句子的顺序预测下一个单词。
第 3-2 步。确定潜在的数据来源并收集
对于这个问题,让我们使用第四章中配方 4-6 的相同电子邮件数据。这里的数据要少得多,但是为了展示工作流程,我们对这些数据很满意。数据越多,准确性越好。
file_content = pd.read_csv('spam.csv', encoding = "ISO-8859-1")
# Just selecting emails and connverting it into list
Email_Data = file_content[[ 'v2']]
list_data = Email_Data.values.tolist()
list_data
#output
[['Go until jurong point, crazy.. Available only in bugis n great world la e buffet... Cine there got amore wat...'],
['Ok lar... Joking wif u oni...'],
["Free entry in 2 a wkly comp to win FA Cup final tkts 21st May 2005\. Text FA to 87121 to receive entry question(std txt rate)T&C's apply 08452810075over18's"],
['U dun say so early hor... U c already then say...'],
["Nah I don't think he goes to usf, he lives around here though"],
["FreeMsg Hey there darling it's been 3 week's now and no word back! I'd like some fun you up for it still? Tb ok! XxX std chgs to send, å£1.50 to rcv"],
['Even my brother is not like to speak with me. They treat me like aids patent.'],
["As per your request 'Melle Melle (Oru Minnaminunginte Nurungu Vettam)' has been set as your callertune for all Callers. Press *9 to copy your friends Callertune"],
['WINNER!! As a valued network customer you have been selected to receivea å£900 prize reward! To claim call 09061701461\. Claim code KL341\. Valid 12 hours only.']
,
['Had your mobile 11 months or more? U R entitled to Update to the latest colour mobiles with camera for Free! Call The Mobile Update Co FREE on 08002986030'],
第 3-3 步。导入并安装必要的库
这里是图书馆。
import numpy as np
import random
import pandas as pd
import sys
import os
import time
import codecs
import collections
import numpy
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import LSTM
from keras.callbacks import ModelCheckpoint
from keras.utils import np_utils
from nltk.tokenize import sent_tokenize, word_tokenize
import scipy
from scipy import spatial
from nltk.tokenize.toktok import ToktokTokenizer
import re
tokenizer = ToktokTokenizer()
第 3-4 步。处理数据
接下来,处理数据。
#Converting list to string
from collections import Iterable
def flatten(items):
"""Yield items from any nested iterable"""
for x in items:
if isinstance(x, Iterable) and not isinstance(x, (str, bytes)):
for sub_x in flatten(x):
yield sub_x
else:
yield x
TextData=list(flatten(list_data))
TextData = ".join(TextData)
# Remove unwanted lines and converting into lower case
TextData = TextData.replace('\n',")
TextData = TextData.lower()
pattern = r'[^a-zA-z0-9\s]'
TextData = re.sub(pattern, ", ".join(TextData))
# Tokenizing
tokens = tokenizer.tokenize(TextData)
tokens = [token.strip() for token in tokens]
# get the distinct words and sort it
word_counts = collections.Counter(tokens)
word_c = len(word_counts)
print(word_c)
distinct_words = [x[0] for x in word_counts.most_common()]
distinct_words_sorted = list(sorted(distinct_words))
# Generate indexing for all words
word_index = {x: i for i, x in enumerate(distinct_words_sorted)}
# decide on sentence length
sentence_length = 25
第 3-5 步。为建模准备数据
这一步将邮件分成固定长度为十个单词的单词序列。(您可以根据业务问题和计算能力选择任何内容。)文本由单词序列分割。当创建这些序列时,这个窗口沿着整个文档滑动,一次一个单词,允许每个单词学习前一个单词。
#prepare the dataset of input to output pairs encoded as integers
# Generate the data for the model
#input = the input sentence to the model with index
#output = output of the model with index
InputData = []
OutputData = []
for i in range(0, word_c - sentence_length, 1):
X = tokens[i:i + sentence_length]
Y = tokens[i + sentence_length]
InputData.append([word_index[char] for char in X])
OutputData.append(word_index[Y])
print (InputData[:1])
print ("\n")
print(OutputData[:1])
#output
[[5086, 12190, 6352, 9096, 3352, 1920, 8507, 5937, 2535, 7886, 5214, 12910, 6541, 4104, 2531, 2997, 11473, 5170, 1595, 12552, 6590, 6316, 12758, 12087, 8496]]
[4292]
# Generate X
X = numpy.reshape(InputData, (len(InputData), sentence_length, 1))
# One hot encode the output variable
Y = np_utils.to_categorical(OutputData)
Y
#output
array([[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
...,
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.]])
第 3-6 步。建立模型
接下来,让我们定义 LSTM 模型,一个具有 256 个存储单元的单一隐藏 LSTM 层。这个模型使用 0.2 的 dropout。输出层使用 softmax 激活函数。这里我们使用 ADAM 优化器。
# define the LSTM model
model = Sequential()
model.add(LSTM(256, input_shape=(X.shape[1], X.shape[2])))
model.add(Dropout(0.2))
model.add(Dense(Y.shape[1], activation="softmax"))
model.compile(loss='categorical_crossentropy', optimizer="adam")
#define the checkpoint
file_name_path="weights-improvement-{epoch:02d}-{loss:.4f}.hdf5"
checkpoint = ModelCheckpoint(file_name_path, monitor="loss", verbose=1, save_best_only=True, mode="min")
callbacks = [checkpoint]
现在,您可以根据数据拟合模型。这里我们使用五个时期和 128 个模式的批量大小。为了获得更好的结果,您可以使用更多的纪元,如 50 或 100。当然,你可以在更多的数据上使用它们。
#fit the model
model.fit(X, Y, epochs=5, batch_size=128, callbacks=callbacks)
Note
我们没有将数据分为训练和测试数据。我们对精确的模型不感兴趣。深度学习模型需要大量的数据进行训练,并且需要大量的时间进行训练,因此我们使用模型检查点来捕获所有的模型权重以进行归档。我们使用最佳的权重集进行预测。
#output
运行代码后,您的本地目录中就有了权重检查点文件。选择保存在工作目录中的网络权重文件。当我们运行这个示例时,我们获得了下面的检查点,它的损失最小,这是我们在五个时期内实现的。
# load the network weights
file_name = "weights-improvement-05-6.8213.hdf5"
model.load_weights(file_name)
model.compile(loss='categorical_crossentropy', optimizer="adam")
第 3-7 步。预测下一个单词
随机生成一系列单词并输入到模型中,看看它能预测什么。
# Generating random sequence
start = numpy.random.randint(0, len(InputData))
input_sent = InputData[start]
# Generate index of the next word of the email
X = numpy.reshape(input_sent, (1, len(input_sent), 1))
predict_word = model.predict(X, verbose=0)
index = numpy.argmax(predict_word)
print(input_sent)
print ("\n")
print(index)
# Output
[9122, 1920, 8187, 5905, 6828, 9818, 1791, 5567, 1597, 7092, 11606, 7466, 10198, 6105, 1837, 4752, 7092, 3928, 10347, 5849, 8816, 7092, 8574, 7092, 1831]
5849
# Convert these indexes back to words
word_index_rev = dict((i, c) for i, c in enumerate(tokens))
result = word_index_rev[index]
sent_in = [word_index_rev[value] for value in input_sent]
print(sent_in)
print ("\n")
print(result)
Result :
['us', 'came', 'use', 'respecthe', 'would', 'us', 'are', 'it', 'you', 'to', 'pray', 'because', 'you', 'do', 'me', 'out', 'youre', 'thk', 'where', 'are', 'mrng', 'minutes', 'long', '500', 'per']
shut
因此,给定 25 个输入单词,它预测单词“shut”是下一个单词。当然,这没有多大意义,因为它是在更少的数据和时期上训练的。确保你有强大的计算能力,并对大量的数据进行训练。
食谱 6-4。堆栈溢出问题推荐
Stack Overflow 是一个面向专业人士和狂热开发者的问答网站。 It 是程序员学习、分享知识和建立职业生涯的最大在线社区
问题
每天都有成千上万的问题在 Stack Overflow 社区中被提问和回答。很有可能会问相同类型的问题,这会在系统中产生不必要的重复问题。如果当用户提出新问题时,系统能够推荐一个类似的问题,这就减少了大量的重复。
解决办法
我们需要将提出的问题与现有的所有其他问题进行比较。这是一个句子对比任务。我们使用预先训练的嵌入来获得句子级的平均向量,以计算相似性得分。这些分数随后用于对问题进行排名。
让我们使用各种预先训练的模型,如伯特句子变形金刚、开放人工智能 GPT 和 GloVe 来解决这个项目和传统的 TFIDF 方法。
它是如何工作的
步骤 4-1。收集数据
如果存在堆栈溢出问题,请使用免费的源数据集。原始数据集位于 www.kaggle.com/c/predict-closed-questions-on-stack-overflow/data?select=train-sample.csv 。
下载该数据集,并将其保存在一个文件夹中以备将来使用。
第 4-2 步。将笔记本和数据导入 Google Colab
鉴于 BERT 模型很大,Google Colab 用于解决这个项目,在 Colab 中构建它更容易、更快。
去谷歌 Colab ( https://colab.research.google.com/notebooks/intro.ipynb )。
然后转到“文件”,打开一个新笔记本或使用“上传笔记本”从本地上传笔记本。跟随下面截图。
要导入数据,请转到“文件”,然后单击“上传到会话存储”选项。示例如下图所示。
第 4-3 步。导入库
让我们导入必要的库。
#importing necessary libraries
import pandas as pd
import numpy as np
import pickle
import time
import re
from bs4 import BeautifulSoup
import nltk
from nltk.tokenize import ToktokTokenizer
from nltk.stem.wordnet import WordNetLemmatizer
from string import punctuation
import matplotlib.pyplot as plt
import nltk
nltk.download('stopwords')
from nltk.corpus import stopwords
from sklearn.feature_extraction.text import TfidfVectorizer
import re
from nltk.stem.porter import PorterStemmer
from nltk.stem import WordNetLemmatizer
from sklearn.metrics.pairwise import cosine_similarity
from scipy.sparse import coo_matrix, hstack,csr_matrix
第 4-4 步。导入数据和 EDA
在解决实际问题之前,让我们导入数据并做一些快速 EDA。
#importing training data
df=pd.read_csv('train-sample.csv')
#counting all null values
df.isnull().sum()
PostId 0
PostCreationDate 0
OwnerUserId 0
OwnerCreationDate 0
ReputationAtPostCreation 0
OwnerUndeletedAnswerCountAtPostTime 0
Title 0
BodyMarkdown 0
Tag1 10
Tag2 27251
Tag3 64358
Tag4 100622
Tag5 124558
PostClosedDate 70136
OpenStatus 0
dtype: int64
#Replacing missing values with blank space
df['Tag1']=df['Tag1'].replace(np.NaN,'')
df['Tag2']=df['Tag2'].replace(np.NaN,'')
df['Tag3']=df['Tag3'].replace(np.NaN,'')
df['Tag4']=df['Tag4'].replace(np.NaN,'')
df['Tag5']=df['Tag5'].replace(np.NaN,'')
#converting column type into string
df['Title']=df['Title'].astype(str)
df['BodyMarkdown']=df['BodyMarkdown'].astype(str)
#checking top 10 most common words from the Body column
from collections import Counter
cnt = Counter()
for text in df["BodyMarkdown"].values:
for word in text.split():
cnt[word] += 1
cnt.most_common(10) #top 10 common words
# Result
[('the', 514615),
('to', 410003),
('I', 358442),
('a', 285706),
('and', 212914),
('is', 192019),
('in', 182699),
('=', 180765),
('of', 164698),
('that', 121863)]
这些是停用词,在数据清理步骤中会被删除。
第 4-5 步。清理文本数据
让我们做一些标准的数据清理过程。
#importing tokenizer for sentence tokenization
token=ToktokTokenizer()
#stop words removing function
def stopWords(text):
stop_words = set(stopwords.words("english")) #importing stopwords dictionary
#text = re.sub('[^a-zA-Z]', ' ', text)
words=token.tokenize(text) # tokenizing sentences
filtered = [w for w in words if not w in stop_words] #filtering words which are not in stopwords
return ' '.join(map(str, filtered)) #creating string combining all filtered words
#function to remove punctuations
def remove_punctuations(text):
punct = '!"#$%&\'()*+,./:;<=>?@[\\]^_`{|}~' #list of punctuation marks
for punctuation in punct:
text = text.replace(punctuation, '') #replacing punctuation mark with blank space
return text
#function to remove frequent words but they were mostly from stopwords
FREQWORDS = set([w for (w, wc) in cnt.most_common(10)])
def remove_freqwords(text):
return " ".join([word for word in str(text).split() if word not in FREQWORDS])
#cleaning the text
def clean_text(text):
text = text.lower()
text = re.sub(r"what's", "what is ", text)
text = re.sub(r"\'s", " ", text)
text = re.sub(r"n't", " not ", text)
text = re.sub(r"i'm", "i am ", text)
text = re.sub(r"\'re", " are ", text)
text = re.sub(r"\'d", " would ", text)
text = re.sub(r"\'ll", " will ", text)
text = re.sub(r"\'scuse", " excuse ", text)
text = re.sub(r"\'\n", " ", text)
text = re.sub('\s+', ' ', text)
text = re.sub(r"\'ve", " have ", text)x`
text = re.sub(r"can't", "can not ", text)
text = text.strip(' ')
return text
#URL removing function
def remove_urls(text):
url_pattern = re.compile(r'https?://\S+|www\.\S+')
return url_pattern.sub(r'', text)
#function to remove html tag and replacing with blank space
def remove_html(text):
html_pattern = re.compile('<.*?>')
return html_pattern.sub(r'', text)
让我们对数据集中的 BodyMarkdown 列使用上面创建的函数。
#Applying all preprocessing steps defined above on both Body
df['BodyMarkdown']=df['BodyMarkdown'].apply(lambda x: clean_text(x))
df['BodyMarkdown'] = df['BodyMarkdown'].apply(remove_punctuations)
df['BodyMarkdown'] = df['BodyMarkdown'].apply(remove_urls)
df['BodyMarkdown'] = df['BodyMarkdown'].apply(remove_html)
df['BodyMarkdown'] = df['BodyMarkdown'].apply(lambda x:stopWords(x))
第 4-6 步。使用 TFIDF 进行特征工程
有多种方法可以将文本转换为特征。先说 TFIDF。
#Importing TFIDF vector as tfidf_vectorizer
tfidf_vectorizer = TfidfVectorizer()
#applying tfidf on Body column
tfidf_matrix2 = tfidf_vectorizer.fit_transform(df['BodyMarkdown'])
这个矩阵稍后用于提取类似的问题。
第 4-7 步。将手套嵌入用于特征工程
让我们导入手套预训练模型。
!wget http://nlp.stanford.edu/data/glove.6B.zip
!unzip glove*.zip
!ls
!pwd
Note
提取和计算平均向量需要几个小时。
为整个数据集提取特征需要花费大量时间。首先,考虑减少开发和测试代码的样本数量。一旦一切正常,就可以考虑整个数据集来提取特征并找到类似的问题。
#creating sample data set with 100 rows for testing. Comment this line to run it on the whole dataset.
dfg=df.iloc[0:100,:]
# load the glove model
glove_model = pd.read_table("glove.6B.100d.txt", sep=" ", index_col=0, header=None, quoting=csv.QUOTE_NONE)
# getting mean vector for each sentence
def get_mean_vector(glove_model, words):
# remove out-of-vocabulary words
words = [word for word in word_tokenize(words) if word in list(glove_model.index)] #if word is in vocab
if len(words) >= 1:
return np.mean(glove_model.loc[words].values, axis=0)
else:
return np.array([0]*100)
#Defining empty list and appending array to the list
glove_embeddings=[]
for i in dfg.BodyMarkdown:
glove_embeddings.append(list(get_mean_vector(glove_model, i)))
glove_embeddings 拥有数据集中所有句子的向量。运行一次并保存向量以避免每次都运行,因为这会花费很多时间。
让我们将它导出到一个 CSV 文件中,以便您可以在需要时使用它。
# Saving vectors of each abstract in the #data frame so that we can use them directly while running code again
glove_embeddings_t=pd.DataFrame(K1).transpose()
glove_embeddings_t.to_csv('glove-vec.csv')
下面的代码导入 CSV 文件,该文件包含我们刚刚导出的向量。当新会话打开时,您需要运行代码来加载该数据集的向量。
#Loading our pre-trained vectors of each abstract
K=pd.read_csv('glove-vec.csv')
glove_embeddings_loaded=[]
#transforming data frame into a required array-#like structure as we did in the above step
for i in range(dfg.shape[0]):
glove_embeddings_loaded.append(K[str(i)].values)
glove_embeddings_loaded=np.asarray(glove_embeddings_loaded)
第 4-8 步。使用 GPT 进行特征工程
让我们安装开放人工智能的 GPT 模型。
!pip install pytorch_pretrained_bert
# importing necessary libraries for GPT
import torch
from pytorch_pretrained_bert import OpenAIGPTTokenizer, OpenAIGPTModel
tokenizer = OpenAIGPTTokenizer.from_pretrained('openai-gpt')
model = OpenAIGPTModel.from_pretrained('openai-gpt')
model.eval()
print('Model Loaded')
#function to get embedding of each token
def returnEmbedding(pSentence):
tokens = pSentence.split(' ')
hidden_states = np.zeros((1,768))
for token in tokens:
subwords = tokenizer.tokenize(token)
indexed_tokens = tokenizer.convert_tokens_to_ids(subwords)
tokens_tensor = torch.tensor([indexed_tokens])
with torch.no_grad():
try:
hidden_states += np.array(torch.mean(model(tokens_tensor),1))
except Exception as ex:
continue
hidden_states /= len(tokens)
return hidden_states
# Initialize Matrix with number of dataset records as rows and 768 columns as embedding dimension
X = np.zeros((df_gpt.shape[0], 768))
# Generate sentence level embedding by calculating average of all word embedding
for iter in range(df_gpt.shape[0]):
text = df_gpt.loc[iter,'BodyMarkdown']
#print(iter)
X[iter] = returnEmbedding(text)
embeddings_GPT = X
嵌入 _GPT 稍后用于查找前 n 个类似的问题。
步骤 4-9。使用句子-BERT 进行特征工程
# Install BERT sentence transformer for sentence encoding
!pip install sentence-transformers
#running on 100 rows only for testing. Later comment this line
df_bert=df.iloc[0:100,:]
#importing bert-base model
from sentence_transformers import SentenceTransformer
sbert_model = SentenceTransformer('bert-base-nli-mean-tokens')
#embeding on Body column
sentence_embeddings = sbert_model.encode(df['BodyMarkdown'])
print('Sample BERT embedding vector - length', len(sentence_embeddings[0]))
#output
Sample BERT embedding vector - length 768
步骤 4-10。创建获取热门问题的函数
现在我们已经为数据集中的每个问题提取了向量或嵌入,让我们创建函数来
-
寻找余弦相似性
-
返回 top n 相似问题(排名)
#defining function to derive cosine similarity
from numpy import dot
from numpy.linalg import norm
def cos_sim(a,b):
return dot(a, b)/(norm(a)*norm(b))
#Function which returns Top N similar sentence from data frame directly
def top_n(user,p,df):
#Converting cosine similarities of overall data set with input queries into LIST
x=cosine_similarity(user,p).tolist()[0]
#store list in temp file to retrieve index
tmp=list(x)
#sort the list
x.sort(reverse=True)
print( x[0:5])
#get index of top 5
L=[]
for i in x[0:5]:
L.append(tmp.index(i))
return df.iloc[L, [6,7]]
这两个函数和所有嵌入将在下一节中使用。
步骤 4-11。预处理用户输入
用户可以输入任何问题。您需要对用户输入文本进行预处理,并根据所选的一种模型提取嵌入内容。下面的函数可以做到这一点。
#function to pre-process and extract embeddings for the user input text
def user_transform(query,model):
query= clean_text(query)
query= remove_punctuations(query)
query= remove_urls(query)
query= remove_html(query)
query= stopWords(query)
print(query)
if model=='TFIDF':
k=tfidf_vectorizer.transform([str(query)])
elif model=='BERT':
k=sbert_model.encode(str(query))
elif model=='glove_model':
k=get_mean_vector(glove_model,query)
k=k.reshape(1,-1)
elif model=='GPT':
k=returnEmbedding(query)
return k
pd.set_option("display.max_colwidth", -1) #this function will display full text from each column
步骤 4-12。查找类似问题
使用 TFIDF 查找类似问题。
# Getting top 5 similar questions for user input query using TFIDF
input=user_transform('do we have any other Q&A platform like stackoverflow which is free source?','TFIDF')
top_n(input,tfidf_matrix2,df)
如果查看结果,第一个问题类似于用户输入的查询。
使用 GloVe 查找类似问题。
# Getting top 5 similar questions using Glove model
input=user_transform('do we have any other Q&A platform like stackoverflow which is free source?','glove_model') #query
top_n(input,glove_embeddings_loaded,df)
如果查看结果,第一个问题类似于用户输入的查询。
用 GPT 找出类似的问题。
#similar questions from GPT (from 100 rows)
input=user_transform('do we have any other Q&A platform like stackoverflow which is free source?','GPT') #query
top_n(input,embeddings_GPT,df)
这个输出表明 GPT 模型并不完全适合我们的用例。
使用 BERT 查找类似问题。
#similar questions from BERT
input=user_transform('do we have any other Q&A platform like stackoverflow which is free source?','BERT') #query
top_n(input,sentence_embeddings,df)
如果查看结果,第一个问题类似于用户输入的查询。
七、总结和下一代自然语言处理
本章总结了各种过去、现在和未来的自然语言处理方法和技术。本章以关于 NLP 和深度学习的优秀研究论文的信息结束。
到目前为止,您已经了解了以下内容。
-
如何收集、读取、清理和处理文本数据
-
如何将文本转换为特征
-
如何使用 NLP 技术结合机器学习和深度学习来构建应用程序
现在让我们看看 NLP 的最新进展和未来。
我们讨论以下食谱。
-
食谱 1。文本到特征或分布式表示的最新进展
-
食谱 2。面向自然语言处理的高级深度学习
-
配方 3:强化学习在 NLP 中的应用
-
食谱 4。转移学习和预培训模型
-
食谱 5。自然语言处理中的元学习
-
食谱 6。面向自然语言处理的胶囊网络
但是在开始食谱之前,让我们快速回顾一下。
到目前为止,你已经在人工智能和 NLP 的保护伞下解决了一些最有趣的项目。
您还看到了 NLP 在与机器学习和深度学习相结合时,如何帮助解决跨行业和领域的复杂业务问题。
大约 50 年前,人类首次开始使用计算方法来分析人类语言,尽管这些技术中的大多数最近都取得了成功。
NLP 是 Siri 和 Alexa 背后的声音。类似地,客户服务聊天机器人利用 NLP 的力量在电子商务、医疗保健和公用事业部门生成个性化的响应。一些最流行的 NLP 应用程序是虚拟助手、情感分析、客户服务和翻译。
随着技术的发展,NLP 的未来变得更加以用户为中心。例如,虚拟助理可以回答更复杂的问题,并评估问题的含义和字面意义。(问:今天天气怎么样?甲:下雨了。你需要一把伞。)未来,公司将能够提供各种专业的客户服务,接听电话,向真人传递问题。
NLP 的应用不仅限于解决客户问题或提供个性化建议;这主要是技术援助。目前,如果你用 NLP 问,“我的网络怎么了?”,您可以训练它提供一个错误列表。未来,NLP 将能够理解用户的真实意图。NLP 的未来令人兴奋,因为 NLP 的进步将使人类从问题转向结果。当 NLP 理解用户评论并为他们的真实意图提供更复杂的解决方案时,这将是一个巨大的飞跃。
NLP 将能够理解人类的情感。随着 NLP 技术的发展,计算机将把它们目前的处理能力扩展到对人类语言的整体理解。到目前为止,NLP 仅限于解释有限的人类情感,包括喜悦或愤怒。最终,NLP 将被编程为理解更复杂的人类语言元素,如幽默、讽刺等等。
在一个激动人心的时刻,NLP 将结合人脸和手势识别等其他技术为企业创造收入,使其更加灵活和高效。
有了 Alexa、Siri 和 Google Duplex,下一代 NLP 才刚刚开始。
NLP 对于教导机器执行复杂的自然语言任务也是有用的,例如机器翻译和对话生成。
现在,让我们通过菜谱来揭示一些最先进的下一代算法将如何在未来的 NLP 时代发挥重要作用。
配方 7-1。文本到特征或分布式表示的最新进展
本食谱讨论了文本到特征或分布式表示的最新进展。
问题
在文本到特征或分布式表示方面,有哪些超出你所学的新进展(例如,单词嵌入、GloVe、fastText 等)。)?
解决办法
分布式表示在过去已经被广泛用于研究各种 NLP 任务,但是 CBOW 和 skip-gram 模型的流行度已经增加。第三章讨论了大多数最新的嵌入技术。但是请保持警惕,因为这个领域正在快速发展。
配方 7-2。面向自然语言处理的高级深度学习
这个食谱着眼于 NLP 的一些高级深度学习技术。
问题
你想了解 NLP 深度学习技术的最新进展。
解决办法
让我们讨论循环神经网络和深度生成模型。
循环神经网络
循环神经网络的基本形式,网络函数将组件向上组合,以计算更高级句子的表示。循环神经网络用于各种应用中,如下所示。
-
从语法上分析
-
使用短语级表示的情感分析
-
语义关系的分类(例如,主题消息)
深度生成模型
变分自编码器(VAE)和生成对抗网络(GAN)等深度生成模型被应用于自然语言处理,以发现丰富的自然语言结构。众所周知,由于不受限制的潜在空间,标准句子自编码器不能生成真实的句子。VAE 执行隐藏空间的先验分布,允许模型生成适当的样本。VAE 由编码到潜在空间的编码器和生成器网络组成,然后从该空间生成样本。训练旨在最大化在生成的模型中观察到的数据的对数概率的变化下限。
配方 7-3。强化学习在自然语言处理中的应用
这个食谱讨论了强化学习在 NLP 中的应用。
问题
你想了解强化学习在 NLP 领域的作用。
解决办法
强化学习利用行为心理学,软件代理在环境中执行操作,增加代理的累积回报。该系统试图通过在模拟器环境中反复试验来理解行为随时间的变化。
我们来讨论一下强化学习方法。
勘探与开发的权衡
在这里,代理必须对文本进行分类。智能体通过不同的神经网络层来决定下一步的动作状态。探索和利用之间的权衡涉及到代理必须探索可能的行为状态的困境,这将有助于合法地对文本进行分类,并利用当前的行为状态来获得最佳结果。在 NLP 中,我们应该通过使用 softmax 函数计算置信限来解决这个问题。即使存在未知的不确定性,softmax 和更高的置信限也有助于获得最高的回报。
时间差异
时差概念涉及一种无模型的强化学习方法。它是基于时间 t + 1 的下一个行动状态可能比时间 t 的结果更好的概念,这就像蒙特卡罗方法。您可以根据结果调整权重。但是在这里,使用称为启动的概念,在结果已知之前,您根据当前输入调整结果以获得最佳结果。例如,您希望对所有未知数据进行排名。在时间 t + 1,你应该可以预测标签,同理,在 t + 2,你应该可以确定下一个动作状态。下一步是您应该能够对属于该标签的所有数据进行分类,并通过行为克隆找到所有其他类似的标签。
配方 7-4。转移学习和预培训模型
这份食谱讨论了迁移学习和预训练模型是如何改变 NLP 前景的。
问题
您希望深入了解迁移学习和 NLP 预训练模型的最新进展。
解决办法
简单来说,迁移学习就是在大规模数据集上形成一个模型,然后用这个预先训练好的模型去学习另一个下游任务(如目标任务)的过程。通过 ImageNet 数据集,迁移学习在计算机视觉领域获得了广泛的应用。在这里,我们不讨论计算机视觉。相反,让我们关注这些概念如何应用于自然语言处理领域。
迁移学习旨在使用源领域中有价值的知识来帮助模拟目标领域中的表现。
为什么需要迁移学习 NLP?
在 NLP 应用中,特别是当我们没有足够的数据集来解决任务(称为 T-target tasks )时,我们希望从其他任务中转移知识,以避免过拟合,提高 T 的性能。
将知识转移到语义相似/相同但数据集不同的任务。
NLP 中神经传递的学习很大程度上取决于源数据集和目标数据集的语义相似度。
对于 NLP 和 ML 的研究人员和爱好者来说,这些都是激动人心的时刻。最近,预训练的语言模型在广泛的 NLP 任务中获得了最新的结果,例如序列标签和句子分类。最近使用预训练语言模型的工作包括 ULMFit、ELMo、GLoMo 和 OpenAI 转换。这些语言建模系统使用分层表示或图形表示来执行整个模型的大量预训练。这个概念改变了多年来用于处理许多 NLP 任务的一元嵌套单词的使用,支持更复杂和抽象的表示。
NLP 中的前期训练是如何进行的?为什么前期培训有用?它允许模型从大规模语料库中捕捉和学习各种语言现象,如长期依赖和否定。然后使用(转移)这些知识来初始化,然后形成另一个模型来执行特定的 NLP 任务,例如情感分类。
这在 NLP 中是可行的;例如,否定是从文本信息中检测情感极性的重要属性。此外,否定也可能是有用的,例如,检测情绪或讽刺,这是最复杂和未解决的 NLP 任务之一。否定在许多 NLP 任务中是有用的,因此预训练模型具有共同的属性。
在 NLP 研究中缺少带注释的数据集或语言资源时,具有通用属性的语言模型可能是有用的。这个想法令人兴奋,因为我们正试图建立一个通用模型,并解决 NLP 研究的一些困难挑战:数据和语言资源的可用性。
到目前为止,我们知道从预先形成的语言模型(如嵌入单词的形式)中获得的知识适用于许多 NLP 任务。这里的问题是,这种潜在的知识形式的知识不够广泛或不足以正确地执行目标任务或下游任务。对此有许多解释——有些事情我们知道,有些我们不知道——但现在,我们简要介绍一种解决这些限制的最新方法。
ELMo 是一种最近流行的方法,它被描述为“使用跨神经层堆栈的深度上下文表示来预训练整个模型”,而不是简单地使用嵌套单词(一键编码特征表示)作为初始化。
伯特、埃尔莫、乌尔姆菲特。(NLP 破解迁移学习的方式)
2018 年是基于文本的机器学习模型(更准确地说,是自然语言处理或 NLP)的转折点。我们对如何最好地表达单词和短语以更好地理解潜在含义和关系的概念理解正在迅速发展。此外,NLP 社区强调,你可以免费下载所有像 BERT 这样的预训练模型,并在你自己的模板和管道(例如 ImageNet)中使用它们,这表明了类似的开发如何加速了具有令人难以置信的强大组件的机器学习的发展。
这一发展的最新里程碑之一是 BERT 的发布,它被描述为标志着 NLP 新时代的开始。BERT 是一个模型,它打破了一些记录,并确定了模型如何处理基于语言的任务。在模型文档发布后不久,该团队还开放了模型代码,将预先训练好的模型版本下载到大型数据集。这是一个突破,任何建立涉及语言处理的机器学习模型的人都可以将这个强大的工具作为现成的组件使用——节省时间和可以形成语言处理模型的精力、知识和资源。
BERT 基于 NLP 社区中出现的一些最新发展,包括半监督学习序列(Andrew Wells Dale)、ELMo (Matthew Peters 和研究人员 AI2 和 UW CSE)、ULMFiT(由创始人 Fast.ai、杰瑞米·霍华德和塞巴斯蒂安·罗德斯开发)、OpenAI transformer(研究人员 OpenAI Redford、Nara Singham 和 Salimans Sutskever)和 transformers (Vaswani 等)。).
你需要了解一些概念才能理解 BERT 是什么。因此,在查看模型本身所涉及的概念之前,让我们先看看使用 BERT 的不同方式。
BERT 是一个转换器编码器堆栈,它有两种型号。
-
BERT-Base: OpenAI 变压器
-
BERT-Large:一个非常大的模型,具有最先进的结果
两种 BERT 模型都有许多编码器层(也称为变换块):12 的基本版本和 24 的大型版本。它们还具有更高的预测网络和更多的注意力头(分别为 12 和 16),而不是基础纸上的 transformer 实现的默认配置(分别为 768 和 1024 个隐藏单元)(六层编码器、512 个隐藏单元和八个注意力头)。
嵌入的新时代
这些新的发展导致了单词编码方式的新变化。到目前为止,主流 NLP 模型如何对待语言,嵌入词一直是主力。word2vec 和 Glove 等方法已广泛用于此类任务。在指出变化之前,让我们回顾一下它们的用法。
该领域很快意识到,使用大量文本数据比形成与这种通常很小的数据集模型并行的预集成要好。因此,word2vec 或 GloVe 可以下载预训练期间生成的单词列表及其组合。
ULMFiT:自然语言处理中的迁移学习
ULMFiT 引入了一种有效利用模型在预训练期间学习的大部分内容的方法——这不仅仅是情境化的组合。ULMFiT 使用语言模型和过程来有效地使语言模型适应各种任务。
NLP 最终会找到让迁移学习成为可能的方法,就像计算机视觉一样。
变形金刚:超越 LSTM
《变形金刚》文档、代码和机器翻译的发布让一些人相信他们正在取代 LSTM。此外,《变形金刚》在管理长期依赖关系方面比 LSTM 更胜一筹。
天资
flair 框架在解决 NER (POS)、词义消歧和文本分类等自然语言处理问题方面提供了一流的性能。这个 NLP 框架直接建立在 PyTorch 之上。
当今大多数先进的方法都是基于一种叫做文本嵌入的技术。它将文本转换成大空间的数字表示。它允许文档、句子、单词、字符在这个大空间中作为向量来表达它们自己。
flair 是 NLP 的一个令人兴奋的新成员,因为 Zalando Research 最近的文章“用于序列标记的上下文字符串嵌入”( http://alanakbik.github.io/papers/coling2018.pdf )描述了一种总是比尖端解决方案更好的方法。它在 flair 中得到实现和完全支持,可以创建文本分类器。
为什么是伯特?
随着网络的大规模增长,我们有了大量的数据。并且只有一些文本数据被注释。对于像自然语言处理这样的任务,我们需要大量带注释的数据来学习有监督的或无注释的数据来进行无监督学习。各种研究人员更喜欢无监督学习。他们在网上使用大量无注释的文本(称为预训练)来突出一些常见的语言表示模型训练技术。
BERT 是谷歌开发的这些预训练模型之一,可以适应新的数据,并创建 NLP 系统,如回答问题,生成文本,排序文本,文本合成和情感分析。由于 BERT 是在大量数据的基础上形成的,它简化了语言建模过程。使用预先形成的 BERT 模型的主要优点是,与这些数据集的训练相比,精确度显著提高。
BERT 是基于在训练之前在上下文表示中的最近工作。这是先前使用纯文本语料库形成的第一个深度双向无监督语言表示。BERT 表示具有左右上下文的上下文表示。概念简单,经验丰富。BERT 优于其他方法,因为它是第一个具有域自适应特征的用于 NLP 预训练的无监督深度双向系统。从 BERT 文档中可以确定,通过适当的语言模型训练方法,基于转换器(自关注)的编码器可以潜在地用作语言模型的替代。
伯特和 RNN
RNN(理论上)给出了左边的无限上下文(目标词左边的词)。但是我们可能想要的是使用每一个左右的上下文来看看这个单词是否适合这个句子。
RNN 是一个用于翻译和顺序语言处理的网络架构。顺序性使得并行处理单元(例如 TPU)的全部功能变得困难。RNN 遇到了梯度问题,消失并爆炸。RNN 有短期记忆,因为长时间保存条目不好。
BERT 诉 LSM 案
LSTM 模型的使用限制了短期预测的能力。BERT 使用屏蔽语言建模(MLM)。MLM 目标允许左右上下文的表示,这允许预先形成深度双向变换器。
伯特 vs .OpenAI GPT(全球定位系统)
当您将精确调优方法应用于令牌级任务时(比如回答 SQuAD 的问题),将上下文集成到两个方向是很重要的。当使用 OpenAI GPT 时,它使用内置架构。从左到右,不能访问每个令牌。前一个令牌在变形金刚的焦点层。
-
GPT 使用短语分隔符([SEP])和分类标记([CLS]),它们只在特定时间输入。
-
伯特在整个预训练过程中学习 SEP、CLS 句子和句子的整合。
-
GPT 对所有的拟合实验都使用类似的 5 到 5 的学习率。BERT 在开发集上选择精确的、特定任务的和最有效的开发学习率。
以下是一些挑战。
-
因为我们有大量的训练数据,即使用一个 GPU 也很难训练;因此,可以使用谷歌 TPU。
-
推理需要的时间长。因此,我们修改了超参数,以使系统准确并尽快得到结果。它对每个超参数都有一个记录,并选择了超参数的优化组合。
配方 7-5。自然语言处理中的元学习
这个食谱讨论了自然语言处理中的元学习。
问题
你想了解自然语言处理中的元学习。
解决办法
在自然语言处理(NLP)中有一个有趣的东西,即循环神经网络(RNN),用于元学习和神经网络模型。
优化神经网络模型的元学习者的行为与循环神经网络的行为相同。作为一个 RNN,训练时模型的一系列参数和梯度作为输入序列。序列是来自计算串行输出(更新模型参数集)的输入。
我们发现元学习语言模型可以形成记忆最近条目的文章,并且是预测文章下一部分的有用起点。
配方 7-6。面向自然语言处理的胶囊网络
这个食谱着眼于 NLP 的胶囊网络。
问题
你想了解一下 NLP 的胶囊网络。
解决办法
让我们看看研究人员在将胶囊网络应用于 NLP 任务时发现了什么。
首先,你需要理解下面的层和算法。
-
n-gram 卷积层是标准的卷积层,通过各种卷积滤波器提取句子中不同位置的 n-gram 特征。
-
主胶囊层为第一胶囊层。该胶囊用矢量输出胶囊代替 CNN 标量输出特征检测器,以保留诸如单词的局部顺序和单词的语义表示等参数。
-
在卷积胶囊层中,每个胶囊仅连接到下层中的局部区域。区域中的这些胶囊乘以一个变换矩阵来学习父子关系。然后执行弦路由以在该层中创建父胶囊。胶囊层完全连接。层下面的胶囊在胶囊列表中被展平,并被引入完全连接的胶囊层。该封装通过一个转换矩阵,然后通过一个路由协议产生一个倍增的最终封装及其类别。
-
动态路由的基本思想是设计非线性映射。通过确保每个胶囊的输出被发送到下一层中适当的父节点,非线性映射被迭代地构造。对于每个潜在的父代,胶囊网络可以增加或减少与动态路由的连接,这比原始路由策略更有效,例如 CNN 中的最大累积,它检测文本中是否存在某个特征。但是,关于实体的空间信息会丢失。研究人员探索了三种策略,通过减少一些嘈杂胶囊的不便来提高路由过程的准确性。不与特定类别相关联的词有助于胶囊网络更有效地建立亲子关系模型。
研究人员已经证明了胶囊网络在文本分类中的有效性。更重要的是,胶囊网络还显示了从多类到多标签标签的文本分类的显著改进。
NLP 中的多任务处理
多任务可以在相关任务之间共享知识,并隐式增加任务中的训练数据。研究人员已经探索了文本胶囊网络的性能,并提供了一种统一、简单、高效的多任务胶囊式学习架构。
多任务处理(MTL)在自然语言处理领域取得了巨大成功。多任务和深度神经网络(DNN)通过标准化对 DNN 产生另一种协同效应。
胶囊网络可以在 MTL 中用来区分任务的特征。
要深入了解 NLP 中的多任务处理,请参考 www.aclweb.org/anthology/D18-1486 的“MCapsNet:多任务学习的文本胶囊网络”。
感谢您的阅读。我们相信你有一个伟大的学习之旅。这是我们目前所有的。下一期再见。