学习ELMo从文本中提取特征的分步NLP指南

 

目录

语言模型嵌入(ELMo)

目录

什么是ELMo?

了解ELMo的工作原理

ELMo与其他单词嵌入有何不同?

实现:用于Python中文本分类的ELMo

我们还能用ELMo做些什么?

结束笔记


 

我从事不同的自然语言处理(NLP)问题(成为数据科学家的好处!)。每个NLP问题都是以自己的方式面临的独特挑战。这只是人类语言复杂,美丽和精彩的反映。

但有一点一直是NLP从业者心中的荆棘是无法(机器)理解句子的真正含义。是的,我在谈论背景。当被要求执行基本任务时,传统的NLP技术和框架非常棒。当我们试图为这种情况添加背景时,事情很快就消失了。

NLP格局在过去18个月左右发生了重大变化。像谷歌的BERT和Zalando的Flair这样的NLP框架能够解析句子并掌握它们的编写环境。

语言模型嵌入(ELMo)

在这方面取得的最大突破之一归功于ELMo,这是AllenNLP开发的最先进的NLP框架。当你完成这篇文章的时候,你也将成为一个伟大的ELMo粉丝 - 就像我一样。

在本文中,我们将探索ELMo(嵌入语言模型)并使用它在真实数据集上使用Python构建令人兴奋的NLP模型。

注意:本文假设您熟悉不同类型的字嵌入和LSTM体系结构。您可以参考以下文章来了解有关这些主题的更多信息:

  • 对Word嵌入的直观理解
  • 深度学习要点:长期短期记忆简介

目录

  1. 什么是ELMo?
  2. 了解ELMo的工作原理
  3. ELMo与其他单词嵌入有何不同?
  4. 实现:用于Python中文本分类的ELMo
  5. 我们还能用ELMo做些什么?

什么是ELMo?

不,我们所指的ELMo不是芝麻街的角色!背景重要性的典型例子。

ELMo是一种在矢量或嵌入中表示单词的新方法。这些单词嵌入有助于在几个NLP任务中实现最先进的(SOTA)结果:

全球NLP科学家已开始将ELMo用于各种NLP任务,包括研究和行业。您必须在此处查看原始的ELMo研究论文 -  https://arxiv.org/pdf/1802.05365.pdf。我通常不会要求人们阅读研究论文,因为他们经常会遇到沉重而复杂的问题,但我正在为ELMo做例外。这是对ELMo如何设计的一个非常酷的解释。

了解ELMo的工作原理

让我们直观地了解ELMo在我们在Python中实现它之前是如何工作的。为什么这很重要?

好吧,想象一下。您已成功将GitHub中的ELMo代码复制到Python中,并设法在自定义文本数据上构建模型。您可以获得平均结果,因此您需要改进模型。如果您不了解ELMo的架构,您将如何做到这一点?如果你还没有研究过它,你会调整哪些参数?

这种思路适用于所有机器学习算法。你不需要进入他们的推导,但你应该总是知道足够的玩它们并改进你的模型。

现在,让我们回到ELMo的工作原理。

正如我之前提到的,ELMo字向量是在双层双向语言模型(biLM)之上计算的。这个biLM模型有两层堆叠在一起。每层有2次传球 - 前传和后传:

  • 上述架构使用字符级卷积神经网络(CNN)将文本串的单词表示为原始单词向量
  • 这些原始单词向量充当第一层biLM的输入
  • 前向传递包含关于某个单词的信息以及该单词之前的上下文(其他单词)
  • 向后传递包含有关该词及其后的上下文的信息
  • 来自前向和后向传递的这对信息形成中间词向量
  • 这些中间词向量被馈送到下一层biLM中
  • 最终表示(ELMo)是原始单词向量和2个中间单词向量的加权和

由于biLM的输入是根据字符而不是单词计算的,因此它捕获了单词的内部结构。例如,biLM将能够发现像美丽和美丽这样的术语在某种程度上是相关的,甚至没有看到它们经常出现的背景。听起来不可思议!

ELMo与其他单词嵌入有何不同?

与传统的单词嵌入(如word2vec和GLoVe)不同,分配给标记或单词的ELMo向量实际上是包含该单词的整个句子的函数。因此,相同的单词在不同的上下文中可以具有不同的单词向量。

我可以想象你在问 - 知道如何帮助我处理NLP问题?让我用一个例子解释一下。

假设我们有几句话:

  1. 我昨天了这本书。
  2. 你现在能看完这封信吗?

花点时间思考这两者之间的区别。第一句中的动词“read”是过去时。同一个动词在第二句中转换成现在时。这是一词多义词,其中一个词可以有多种含义或感官。

语言是如此复杂的事情。

传统的单词嵌入会在两个句子中为“read”一词提供相同的向量。因此,他们无法区分多义词。

ELMo字向量成功解决了这个问题。ELMo单词表示将整个输入句子转换为计算单词嵌入的等式。因此,术语“读取”在不同的上下文中将具有不同的ELMo向量。

实现:用于Python中文本分类的ELMo

现在你等待的那一刻 - 用Python实现ELMo!让我们一步一步来。

1.理解问题陈述

处理任何数据科学挑战的第一步是定义问题陈述。它构成了我们未来行动的基础。

对于本文,我们已经掌握了问题陈述:

情感分析仍然是自然语言处理(NLP)广泛应用的关键问题之一。这一次,鉴于客户关于制造和销售手机,电脑,笔记本电脑等各种技术公司的推文,我们的任务是确定这些推文是否对这些公司或产品产生负面情绪。

它显然是一个二进制文本分类任务,其中我们必须从提取的推文中预测情绪。

2.关于数据集

这是我们所拥有的数据集的细分:

  • 列车集包含7,920条推文
  • 测试集包含1,953条推文

您可以从此页面下载数据集。 请注意,您必须注册或登录才能这样做。

警告:推文中大多数亵渎和粗俗的术语已被“$&@ *#”取代。但请注意,数据集可能仍包含可能被视为亵渎,粗俗或冒犯的文本。

好吧,让我们开启我们最喜欢的Python IDE并进行编码!

3.导入库

导入我们将在整个笔记本中使用的库:

4.阅读并检查数据

 
#read data train = pd.read_csv(“train_2kmZucJ.csv”)
test = pd.read_csv(“test_oJQbWVk.csv”)
train.shape,test.shape

输出:((7920,3),(1953,2))

火车组有7,920条推文,而测试组只有1,953条。现在让我们检查火车组中的班级分布:

train ['label']。value_counts(normalize = True)

输出:

0 0.744192

1 0.255808

名称:label,dtype:float64

这里,1表示负推文,而0表示非负推文。

让我们快速浏览一下火车组的前5行:

train.head()

我们有三列可供使用。列'tweet'是独立变量,而列'label'是目标变量。

5.文本清理和预处理

我们将拥有一个干净,结构化的数据集,可以在理想的世界中使用。但是NLP中的事情并不那么简单(尚)。

我们需要花费大量时间来清理数据,以便为模型构建阶段做好准备。从文本中提取特征变得容易,甚至特征包含更多信息。您会发现模型性能有了显着改善,数据质量会越好。

所以,让我们清理我们给出的文本并进行探索。

推文中似乎有很多URL链接。他们没有告诉我们很多(如果有的话)关于推文的情绪,所以让我们删除它们。

我们使用正则表达式(或RegEx)删除了URL。

注意: 您可以在本文中了解有关Regex的更多信息。

我们现在就开始做一些常规的文本清理工作。

我还想标准化文本,也就是说,执行文本规范化。这有助于将单词缩减为其基本形式。例如,“生产”,“生产”和“生产”等词的基本形式是“产品”。经常发生的是,同一个单词的多种形式并不那么重要,我们只需要知道该单词的基本形式。

我们将利用流行的spaCy库对文本进行引理(标准化)。

列车和测试集中的推文:

train['clean_tweet'] = lemmatization(train['clean_tweet'])

 test['clean_tweet'] = lemmatization(test['clean_tweet'])

让我们快速浏览原始推文与我们清理过的推文:

train.sample(10)

仔细查看上面的列。'clean_tweet'列中的推文似乎比原始推文更易读。

但是,我觉得还有很多空间来清理文本。我鼓励您尽可能多地探索数据,并在文本中找到更多的见解或不正确之处。

6. TensorFlow Hub简介

等等,TensorFlow与我们的教程有什么关系?

TensorFlow Hub是一个库,通过允许使用许多机器学习模型来完成不同的任务,从而实现传输学习。ELMo就是这样一个例子。这就是我们在实现中通过TensorFlow Hub访问ELMo的原因。

在我们做任何其他事情之前,我们需要安装TensorFlow Hub。您必须安装或升级TensorFlow软件包至少1.7才能使用TensorFlow Hub:

$ pip install“tensorflow> = 1.7.0”
$ pip install tensorflow-hub

7.准备ELMo向量

我们现在将导入预训练的ELMo模型。请注意 - 该型号的尺寸超过350 mb,因此下载此版本可能需要一段时间。

import tensorflow_hub as hub
import tensorflow as tf
elmo = hub.Module("https://tfhub.dev/google/elmo/2", trainable=True)

我将首先向您展示如何为句子获取ELMo向量。您所要做的就是在对象elmo中传递一个字符串列表。

# just a random sentence

x = ["Roasted ants are a popular snack in Columbia"]

# Extract ELMo features

embeddings = elmo(x, signature="default", as_dict=True)["elmo"]

embeddings.shape

输出: TensorShape([尺寸(1),尺寸(8),尺寸(1024)])

输出是三维张量的形状(1,8,1024):

  • 该张量的第一维表示训练样本的数量。在我们的案例中,这是1
  • 第二个维度表示输入字符串列表中最长字符串的最大长度。由于我们的输入列表中只有1个字符串,因此第二个维度的大小等于字符串的长度--8
  • 第三维等于ELMo向量的长度

因此,输入句子中的每个单词都有一个大小为1024的ELMo向量。

让我们继续为列车和测试数据集中已清理的推文提取ELMo向量。但是,为了得到整个推文的向量表示,我们将采用构成术语或推文标记的ELMo向量的均值。

让我们定义一个执行此操作的函数:

def elmo_vectors(x):

  embeddings = elmo(x.tolist(), signature="default", as_dict=True)["elmo"]

  with tf.Session() as sess:

    sess.run(tf.global_variables_initializer())

    sess.run(tf.tables_initializer())

    # return average of ELMo features

    return sess.run(tf.reduce_mean(embeddings,1))

如果使用上述函数一次性提取推文的嵌入,则可能会耗尽计算资源(内存)。作为一种解决方法,将列车和测试装置分成每批100个样品。然后,将这些批次顺序传递给函数elmo_vectors()

我会将这些批次保存在列表中:

list_train = [train [i:i + 100] for i in range(0,train.shape [0],100)] list_test = [test [i:i + 100] for i in range(0,test.shape [ 0],100)]

现在,我们将遍历这些批次并提取ELMo向量。让我警告你,这需要很长时间。

# Extract ELMo embeddings 
elmo_train = [elmo_vectors(x['clean_tweet']) for x in list_train] elmo_test = [elmo_vectors(x['clean_tweet']) for x in list_test]

一旦我们拥有了所有向量,我们就可以将它们连接回一个数组:

elmo_train_new = np.concatenate(elmo_train,axis = 0)
elmo_test_new = np.concatenate(elmo_test,axis = 0)

我会建议你保存这些数组,因为我们花了很长时间才得到它们的ELMo向量。我们将它们保存为pickle文件:

# save elmo_train_new

pickle_out = open("elmo_train_03032019.pickle","wb")

pickle.dump(elmo_train_new, pickle_out)

pickle_out.close()

# save elmo_test_new

pickle_out = open("elmo_test_03032019.pickle","wb")

pickle.dump(elmo_test_new, pickle_out)

pickle_out.close()

使用以下代码加载它们:

# load elmo_train_new

pickle_in = open("elmo_train_03032019.pickle", "rb")

elmo_train_new = pickle.load(pickle_in)

 

# load elmo_train_new

pickle_in = open("elmo_test_03032019.pickle", "rb")

elmo_test_new = pickle.load(pickle_in)

8.模型构建和评估

让我们用ELMo构建我们的NLP模型!

我们将使用训练数据集的ELMo向量来构建分类模型。然后,我们将使用该模型对测试集进行预测。但在此之前,将elmo_train_new拆分为训练和验证集,以便在测试阶段之前评估我们的模型。

from sklearn.model_selection import train_test_split

xtrain, xvalid, ytrain, yvalid = train_test_split(elmo_train_new,train['label'],random_state=42,test_size=0.2)

由于我们的目标是设置基线分数,我们将使用ELMo向量作为特征构建一个简单的逻辑回归模型:

from sklearn.linear_model import LogisticRegression

from sklearn.metrics import f1_score

lreg = LogisticRegression()

lreg.fit(xtrain, ytrain)

预测时间!首先,在验证集上:

preds_valid = lreg.predict(xvalid)

我们将根据F1得分指标评估我们的模型,因为这是比赛的官方评估指标。

f1_score(yvalid,preds_valid)

输出: 0.789976

验证集上的F1分数非常令人印象深刻。现在让我们继续并对测试集进行预测:
# make predictions on test set 
preds_test = lreg.predict(elmo_test_new)

准备我们将在比赛页面上传的提交文件:

这些预测让我们在公共排行榜上得分为0.875672。鉴于我们只进行了相当基本的文本预处理并使用了一个非常简单的模型,这是非常令人印象深刻的。想象一下,使用更先进的技术可以得分。在你的最后尝试,让我知道结果!

我们还能用ELMo做些什么?

我们刚刚看到了ELMo对文本分类的有效性。如果再加上更复杂的模型,它肯定会提供更好的性能。ELMo的应用不仅限于文本分类的任务。只要您需要对文本数据进行矢量化,就可以使用它。

以下是我们可以使用ELMo的一些NLP任务:

  • 机器翻译
  • 语言建模
  • 文本摘要
  • 命名实体识别
  • 问答系统

结束笔记

ELMo无疑是NLP的重大进步,并且将继续存在。鉴于NLP研究的进展速度非常快,最近几个月还出现了其他新的最先进的词汇嵌入,如Google BERT和Falando's Flair。NLP从业者的激动人心的时刻!

 

你可能感兴趣的:(NLP,NLU,NLI)