前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >手把手教你完成句子分类,最好上手的BERT初级使用指南

手把手教你完成句子分类,最好上手的BERT初级使用指南

作者头像
大数据文摘
发布2019-12-18 15:35:46
4.2K0
发布2019-12-18 15:35:46
举报
文章被收录于专栏:大数据文摘大数据文摘

大数据文摘出品

来源:github

编译:LYLM、王转转、李雷、钱天培

过去几年里,机器学习语言处理模型的发展十分迅速,已经不再局限于实验阶段,而是可以应用于某些先进的电子产品中。

举个例子,最近谷歌官宣,称BERT模型已经成为其搜索产品背后的主要动力。谷歌认为,这一进展(即自然语言理解应用于搜索领域)是过去五年中机器学习领域的最大进步,也是搜索史上的最大进展之一。

Jay Alammar小哥最近又发了一篇新文,简要介绍了如何使用BERT模型来完成句子分类任务,作为基础性入门教程,深入地展示了相关的核心概念。

与此同时,他为本篇文章制作了ipython notebook文件,可在github上查看,或者在colab中运行。

Github:https://github.com/jalammar/jalammar.github.io/blob/master/notebooks/bert/A_Visual_Notebook_to_Using_BERT_for_the_First_Time.ipynb

Colab:

https://colab.research.google.com/github/jalammar/jalammar.github.io/blob/master/notebooks/bert/A_Visual_Notebook_to_Using_BERT_for_the_First_Time.ipynb

数据集:SST2

本示例中使用的数据集是SST2,其中包含影评及相应标签(积极为1,消极为0)。

数据集:

https://nlp.stanford.edu/sentiment/index.html

模型:句子情感分类

我们的目标是创建一个模型,该模型以句子为输入(就如上述数据集中的评论),输出为1(句子带有积极情感)或者0(句子带有消极情感)。如下图所示:

句子“视觉效果满分的爱情故事”→(输入)→影评情感分类器→(输出)→积极情感

实际上,该模型是由两个子模型组成的。

DistilBERT模型负责处理句子并将从中提取的信息传给下一个模型,这是由HuggingFace团队开发的开源知识蒸馏版BERT模型,量级更轻、运行更快,性能堪比BERT。

下一个模型是scikit-learn中一个基本的逻辑回归模型,接收DistilBERT处理的结果,并将句子分类为积极或消极(分别为1或0)。

两个模型间传递的数据是一个768维的向量。我们可以把这个向量当作用于分类的句子的嵌入(embedding)。

如果你看过我之前的文章《BERT图解》的话,这个向量就是其中提到的第一位置(以[CLS]标志为输入)的输出结果。

《BERT图解》:

https://jalammar.github.io/illustrated-bert/

模型训练

虽然我们要用到两个模型,但只需训练逻辑回归模型即可。DistillBERT模型将使用适用于英语语言处理的预训练模型。这种模型没有专门为句子分类任务进行过训练和微调,但是,基于BERT模型的通用目标,它还是具有一定的句子分类能力,尤其是第一位置(与[CLS]标志相关)的BERT输出。我认为,这是由BERT模型的次要训练目标,即下一句分类(Next sentence classification)决定的。这一目标似乎是训练模型去封装整句意思作为第一位置的输出。Transformers库包含DistilBERT模型及其预训练版本模型的实现。

教程概述

这是本教程的步骤简介。首先,使用训练后的distilBERT模型来生成数据集中2000个句子的句子嵌入。

这一步后就不再用distilBERT,剩下的都是scikit-learn的工作。依照惯例,将数据集划分为训练集和测试集。

distilBert模型(模型1)的输出数据将被分为训练集和测试集,这两个数据集将用于逻辑回归模型(模型2)的训练和评估。注意,实际上sklearn在划分训练集和测试集前会先打乱数据顺序,而非直接选择数据集的前75%作为切分点。

然后使用训练集训练逻辑回归模型。

如何计算单一预测结果?

在深入代码理解如何训练模型之前,我们先来看看一个训练好的模型是如何计算出预测结果的。

先来尝试对句子“视觉效果满分的爱情故事(a visually stunning rumination on love)”进行分类。第一步,使用BERT 分词器将英文单词转化为标准词(token)。第二步,加上句子分类所需的特殊标准词(special token,如在首位的[CLS]和句子结尾的[SEP])。

第三步,分词器会用嵌入表中的id替换每一个标准词(嵌入表是从训练好的模型中得到的),词嵌入的背景知识可参见我的《图解Word2Vec》。

《图解Word2Vec》:

https://jalammar.github.io/illustrated-word2vec/

注意,分词器完成以上步骤只需一行代码:

此时,已经将输入的句子转为合适维度的向量,可直接传入DistilBERT模型中。

如果你读过《图解BERT》这篇文章,此步骤可用下图表示:

DistilBERT模型流程

将向量输入至DistilBERT模型获得输出的过程和BERT模型如出一辙。输出结果是与输入有关的向量,其中每个向量由768个(浮点)数值组成。

因为这是一个句子分类任务,所以我们将忽略除第一个向量(与[CLS]记号相关的向量)以外的其他向量。我们将第一个向量作为逻辑回归模型的输入。

之后,逻辑回归模型的工作就是根据训练阶段所学对该向量进行分类。这个预测的过程如下所示:

我们将在下一部分中讨论模型的训练以及整个过程的代码。

代码

在本节中,我们将重点介绍用于训练此句子分类模型的代码。包含所有这些代码的ipython notebook可以在colab和github上找到。

导入需要使用的工具包

代码语言:javascript
复制
import numpy as np
import pandas as pd
import torch
import transformers as ppb # pytorch transformers
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import train_test_split

我们所用的数据集文件可以在GitHub上找到,所以我们直接在pandas框架下导入它。

代码语言:javascript
复制
df = pd.read_csv('https://github.com/clairett/pytorch-sentiment-classification/raw/master/data/SST2/train.tsv', delimiter='\t', header=None)

我们可以使用df.head()查看数据集的前五行,看看数据长啥样。

代码语言:javascript
复制
df.head()

Which outputs:

输出如下:

导入预训练的DistilBERT模型和分词器

代码语言:javascript
复制
model_class, tokenizer_class, pretrained_weights = (ppb.DistilBertModel, ppb.DistilBertTokenizer, 'distilbert-base-uncased')



## Want BERT instead of distilBERT? Uncomment the following line:

#model_class, tokenizer_class, pretrained_weights = (ppb.BertModel, ppb.BertTokenizer, 'bert-base-uncased')



# Load pretrained model/tokenizer

tokenizer = tokenizer_class.from_pretrained(pretrained_weights)

model = model_class.from_pretrained(pretrained_weights)

现在我们可以对数据集进行分词。请注意,此处的操作与上面的示例有些不同。上面的示例仅进行了一个句子的分词。在这里,我们将分批处理所有句子的分词(考虑到资源问题,ipython notebook文件中只处理了一小部分数据,约2000个)。

分词

代码语言:javascript
复制
tokenized = df[0].apply((lambda x: tokenizer.encode(x, add_special_tokens=True)))

This turns every sentence into the list of ids.

上述指令将每个句子转化为一个id列表。

数据集是列表的列表(或pandas的Series/DataFrame)。在DistilBERT将此作为输入处理之前,我们需要令所有向量的长度相同,因而需要将较短句子的向量填充词标记为零。填充步骤可以参考notebook,是基本的python字符串和数组操作。

填充后,我们可以将矩阵/张量输入至BERT模型:

使用DistilBERT模型进行处理

现在,我们需要从填充好的标记词矩阵中获得一个张量,作为DistilBERT的输入。

代码语言:javascript
复制
input_ids = torch.tensor(np.array(padded))

with torch.no_grad():

   last_hidden_states = model(input_ids)

运行此步骤后,last_hidden_states保存DistilBERT的输出。它是一个具有多维度的元组(示例个数,序列中的最大符号的个数,DistilBERT模型中的隐藏单元数)。在我们的例子中是2000(因为我们自行限制为2000个示例),66(这是2000个示例中最长序列中的词数量),768(DistilBERT模型中的隐藏单位数量)。

解析BERT输出张量

让我们解析这个3维输出张量,先看其维度:

句子的处理流程

数据集中的每一个句子就是一行,下图概括了第一个句子的处理过程:

重要部分切片

对于句子分类问题,我们仅对[CLS]标记的BERT输出感兴趣,因此我们只选择该三维数据集的一个切片。

下面的代码是如何对三维张量进行切片以获取我们感兴趣的二维张量:

代码语言:javascript
复制
# Slice the output for the first position for all the sequences, take all hidden unit outputs

features = last_hidden_states[0][:,0,:].numpy()

现在我们获得了features这个二维numpy数组,它包含数据集中所有句子的句子嵌入。

Logistic回归数据集

现在我们有了BERT的输出,已经具备训练逻辑回归模型所需的完整数据集。768列数据是特征集,而标签可以从初始数据集中获得。

我们用来训练Logistic回归的标记数据集。其中,特征是上图中切片得到的[CLS]标记(位置0)的BERT输出向量。每行对应于我们数据集中的一个句子,每列对应于Bert / DistilBERT模型顶部转换器(transformer)中前馈神经网络的隐藏单元的输出。

在完成传统的机器学习训练集、测试集划分之后,我们得到了最终的逻辑回归模型并可以对数据集进行训练了。

代码语言:javascript
复制
labels = df[1]

train_features, test_features, train_labels, test_labels = train_test_split(features, labels)

训练集、测试集划分:

下一步,用训练集训练逻辑回归模型。

代码语言:javascript
复制
lr_clf = LogisticRegression()

lr_clf.fit(train_features, train_labels)

得到训练后的模型,进行测试评估:

代码语言:javascript
复制
lr_clf.score(test_features, test_labels)

模型的准确率在81%左右。

得分基准

作为参考,该数据集的最高准确性得分目前为96.8。可以对DistilBERT进行训练以提高其在此任务上的分数,这个过程称为微调,会更新BERT的权重,以提高其在句子分类(我们称为下游任务)中的性能。经过微调的DistilBERT准确性得分可达90.7,标准版的BERT模型可以达到94.9。

Ipython notebook

github上的Ipython notebook文件可以在colab上直接运行。

好了,BERT模型的初级体验完美结束。下一步可以去跑一下notebook文件,并尝试进行微调。你也可以回到开头用BERT代替distilBERT重新试一下,了解其工作原理。

原文链接:

https://jalammar.github.io/a-visual-guide-to-using-bert-for-the-first-time/

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-12-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 大数据文摘 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
日志服务
日志服务(Cloud Log Service,CLS)是腾讯云提供的一站式日志服务平台,提供了从日志采集、日志存储到日志检索,图表分析、监控告警、日志投递等多项服务,协助用户通过日志来解决业务运维、服务监控、日志审计等场景问题。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档