使用ULMFiT和Python中的fastai库的文本分类(NLP)教程

Introduction

自然语言处理(NLP)在当今世界不需要介绍。 它是最重要的研究和研究领域之一,并且在过去十年中出现了惊人的兴趣增长。 NLP的基础知识广为人知,易于掌握。 但是当文本数据变得庞大且非结构化时,事情开始变得棘手。

这就是深度学习变得如此关键的地方。 是的,我正在谈论对NLP任务进行深入学习 - 这仍然是一个相对较少的路径。 DL已经证明了它在图像检测,分类和分割等计算机视觉任务中的实用性,但是文本生成和分类等NLP应用一直被认为适合传统的ML技术。

在这里插入图片描述
正如您将在本文中看到的那样,深度学习肯定会对NLP产生非常积极的影响。 我们将重点关注转移学习的概念,以及如何利用流行的fastai库在NLP中利用它来构建令人难以置信的精确模型。 我将在此过程中向您介绍ULMFiT框架。

Table of Contents

  • 转学习的优势
  • NLP中预先训练的模型
  • ULMFiT概述
  • 理解问题陈述
  • 系统设置:Google Colab
  • 在Python中实现
  • 下一步是什么?

The Advantage of Transfer Learning

我赞扬在介绍中深入学习,当之无愧。 然而,一切都是有代价的,深度学习也不例外。 深度学习的最大挑战是培训模型的大量数据要求。 很难找到如此巨大的数据集,而且准备这样的数据集的成本太高。 大多数组织根本不可能提出它们。

另一个障碍是运行高级深度学习算法所需的GPU成本很高。
在这里插入图片描述
值得庆幸的是,我们可以使用经过预先培训的最先进的深度学习模型,并对它们进行调整以便为我们工作。这被称为转移学习。它不像从头开始训练深度学习模型那样资源密集,即使在少量训练数据上也能产生不错的结果。当我们在相当小的数据集上实现我们的学习时,这个概念将在本文后面进行扩展。

NLP预训练模型

预先训练的模型通过提供可以利用的现有框架,帮助数据科学家开始解决新问题。您并不总是需要从头开始构建模型,尤其是当其他人已经付出了艰苦的努力和努力时!这些经过预先训练的模型已被证明在计算机视觉领域真正有效和有用查看本文 看看我们在CV中挑选的前10名预训练模型。

他们的成功普遍归功于Imagenet数据集。它有超过1400万张带标签的图像,超过100万张图像也附带边界框。该数据集于2009年首次发布,从此成为有史以来最受欢迎的图像数据集之一。它在计算机视觉的深度学习研究方面取得了一些突破,转移学习就是其中之一。
在这里插入图片描述
然而,在NLP中,转移学习并不那么成功(与计算机视觉相比,无论如何)。当然,我们有预先训练过的word嵌入,如word2vec,GloVe和fastText,但它们主要用于初始化神经网络的第一层。模型的其余部分仍需要从头开始训练,并且需要大量示例才能产生良好的性能。

在这种情况下我们真正需要什么?与前面提到的计算机视觉模型一样,我们需要一个预先训练的NLP模型,可以对其进行微调并在不同的文本数据集上使用。预训练自然语言模型的竞争者之一是用于文本分类的通用语言模型微调,或ULMFiT(Imagenet数据集[cs.CL])。

它是如何工作的?它的应用程序有多广泛?我们怎样才能让它在Python中运行?在本文的其余部分,我们将通过解决文本分类问题并检查其执行情况来对ULMFiT进行测试。

Overview of ULMFiT

由fast.ai的Jeremy Howard和NUI Galway Insight Center的Sebastian Ruder提出,ULMFiT本质上是一种为任何NLP任务实现转移学习并取得优异成果的方法。 所有这些,无需从头开始训练模型。 这引起了你的注意,不是吗?

ULMFiT使用以下新技术实现最先进的结果:

扫描二维码关注公众号,回复: 6009991 查看本文章
  • 判别性微调
  • 倾斜的三角学习率,和
  • 逐渐解冻

该方法涉及微调预训练语言模型(LM),在Wikitext 103数据集上进行训练,以一种新的数据集,它不会忘记它以前学到的东西。
在这里插入图片描述

语言建模可以被认为是NLP的Imagenet的对应物。它捕获语言的一般属性,并提供大量数据,这些数据可以提供给其他下游NLP任务。这就是选择语言建模作为ULMFiT的源任务的原因。

我强烈建议您阅读最初的ULMFiT 论文,了解更多有关它的工作原理,杰里米和塞巴斯蒂安推导它的方式,并解析其他有趣的细节。

## 问题陈述
好吧,足够的理论概念 - 让我们通过在数据集上实现ULMFiT来弄清楚,看看炒作的全部内容。

我们的目标是微调预先训练的模型,并将其用于新数据集的文本分类。我们将在此过程中实施ULMFiT。这里有趣的是这个新数据的大小非常小(<1000个标记实例)。从头开始训练的神经网络模型会过度拟合这样一个小数据集。因此,我想看看ULMFiT是否在本文中承诺的这项任务中做得很好。

数据集:我们将使用sklearn数据集中提供的20个新闻组数据集。顾名思义,它包含来自20个不同新闻组的文本文档。

系统设置:Google Colab

我们将在Google Colab上执行python实现,而不是我们的本地计算机。如果您之前从未使用过colab,那么请考虑这个奖金! Colab或Google Colaboratory是一款用于运行Python的免费云服务。关于它的最好的事情之一是它免费提供GPU和TPU,因此,它非常方便培训深度学习模型。

在这里插入图片描述

Colab的一些主要好处:

  • 完全免费
  • 配备相当不错的硬件配置
  • 已连接到您的Google云端硬盘
  • 与Github很好地集成
  • 当你玩它时,你会发现更多的功能…

因此,即使您拥有一个具有相当普通硬件规格的系统也没关系 - 只要您拥有稳定的互联网连接,您就可以开始使用了。 唯一的另一个要求是您必须拥有Google帐户。 让我们开始吧!

在Python中实现

首先,登录您的Google帐户。 然后选择“NEW PYTHON 3 NOTEBOOK”。 这款笔记本与典型的Jupyter笔记本类似,因此如果您熟悉Jupyter环境,则不会有太多麻烦。 Colab笔记本看起来像下面的截图:
在这里插入图片描述
然后转到Runtime,选择Change runtime type,然后选择GPU作为硬件加速器以免费使用GPU。

导入所需的库

大多数流行的库,如pandas,numpy,matplotlib,nltk和keras,都预装了Colab。 但是,需要手动安装2个库,PyTorch和fastai v1(我们在本练习中需要)。 那么,让我们将它们加载到我们的Colab环境中:

!pip install torch_nightly -f https://download.pytorch.org/whl/nightly/cu92/torch_nightly.html
!pip install fastai
# import libraries
import fastai
from fastai import *
from fastai.text import * 
import pandas as pd
import numpy as np
from functools import partial
import io
import os

导入我们之前下载的数据集。

from sklearn.datasets import fetch_20newsgroups
dataset = fetch_20newsgroups(shuffle=True, random_state=1, remove=('headers', 'footers', 'quotes'))
documents = dataset.data

让我们创建一个由文本文档及其相应标签(新闻组名称)组成的数据框。

df = pd.DataFrame({'label':dataset.target, 'text':dataset.data})
df.shape

(11314, 2)

我们通过仅选择数据集中存在的20个标签中的2个来将其转换为二进制分类问题。 我们将分别选择对应于’comp.graphics’和’rec.sport.hockey’的标签1和10。

df = df[df['label'].isin([1,10])]
df = df.reset_index(drop = True)

让我们快速浏览目标分布。

df['label'].value_counts()
10    600
1     584
Name: label, dtype: int64

分布看起来很均匀。 在这种情况下,准确性将是一个很好的评估指标。

数据预处理

将干净的数据提供给模型始终是一种很好的做法,尤其是当数据以非结构化文本的形式出现时。 让我们通过仅保留字母表并删除其他所有内容来清理我们的文本。

df['text'] = df['text'].str.replace("[^a-zA-Z]", " ")

现在,我们将从文本数据中删除停用词。 如果您之前从未使用过停用词,那么您必须从nltk包下载它们,如下所示:

import nltk
nltk.download('stopwords')

from nltk.corpus import stopwords 
stop_words = stopwords.words('english')
# tokenization 
tokenized_doc = df['text'].apply(lambda x: x.split())

# remove stop-words 
tokenized_doc = tokenized_doc.apply(lambda x: [item for item in x if item not in stop_words])

# de-tokenization 
detokenized_doc = [] 
for i in range(len(df)): 
    t = ' '.join(tokenized_doc[i]) 
    detokenized_doc.append(t) 

df['text'] = detokenized_doc

现在让我们将清理后的数据集以60:40的比例分成训练和验证集。

from sklearn.model_selection import train_test_split

# split data into training and validation set
df_trn, df_val = train_test_split(df, stratify = df['label'], test_size = 0.4, random_state = 12)
df_trn.shape, df_val.shape

((710, 2), (474, 2))

完美!

在继续之前,我们需要分别为语言模型和分类模型准备数据。 好消息? 使用fastai库可以非常轻松地完成此操作:

# Language model data
data_lm = TextLMDataBunch.from_df(train_df = df_trn, valid_df = df_val, path = "")

# Classifier model data
data_clas = TextClasDataBunch.from_df(path = "", train_df = df_trn, valid_df = df_val, vocab=data_lm.train_ds.vocab, bs=32)

微调预训练模型并进行预测

我们可以使用我们之前创建的data_lm对象来微调预训练的语言模型。 我们可以创建一个学习者对象,“学习”,直接创建模型,下载预先训练的权重,并准备好进行微调:

learn = language_model_learner(data_lm, pretrained_model=URLs.WT103, drop_mult=0.7)

一个周期和循环动量允许模型在更高的学习速率下训练并更快地收敛。 一周期政策提供某种形式的正规化。 我们不会深入探讨其工作原理,因为本文是关于学习实现的。 但是,如果您想了解更多关于一个周期政策的信息,请随时参考Leslie Smith撰写的这篇优秀论文 – “A disciplined approach to neural network hyper-parameters: Part 1 — learning rate, batch size, momentum, and weight decay”.

# train the learner object with learning rate = 1e-2
learn.fit_one_cycle(1, 1e-2)

在这里插入图片描述
我们将保存此编码器,以便稍后用于分类。

learn.save_encoder('ft_enc')

现在让我们使用我们之前创建的data_clas对象来构建一个带有微调编码器的分类器。

learn = text_classifier_learner(data_clas, drop_mult=0.7)
learn.load_encoder('ft_enc')

我们将再次尝试适合我们的模型。

learn.fit_one_cycle(1, 1e-2)

在这里插入图片描述
哇! 我们的准确度有了惊人的提高,甚至验证损失也远低于训练损失。 它在小型数据集上表现非常出色。 您甚至可以使用以下代码获取学习者对象的验证集的预测:

# get predictions
preds, targets = learn.get_preds()

predictions = np.argmax(preds, axis = 1)
pd.crosstab(predictions, targets)

在这里插入图片描述

What’s Next?

随着ULMFiT等方法的出现,我们正在向更广泛的NLP系统发展。 这些模型可以同时执行多个任务。 此外,这些模型不仅限于英语,还包括全球其他几种语言。

我们还有即将出现的技术,如ELMo,一种新的词嵌入技术,以及BERT,一种新的语言表示模型,旨在通过联合调节所有层中的左右上下文来预先训练深度双向表示。 这些技术已经在许多NLP任务上实现了最先进的结果。 因此,NLP的黄金时期刚刚到来,它将继续存在。

End Notes

我希望你发现这篇文章很有帮助。 然而,在ULMFiT中使用fastai库还有很多东西要探索,我鼓励大家去看看。 如果您有任何建议/建议,请随时在下面的评论部分告诉我。 此外,尝试在您选择的不同问题和域上使用ULMFiT,并查看结果如何成功。

代码:您可以找到完整的代码这里

感谢阅读和快乐学习!

猜你喜欢

转载自blog.csdn.net/weixin_41697507/article/details/89441762