使用Keras BERT的简单文本多分类任务
BERT是一个非常强大的语言表示模型,它已成为NLP领域的一个重要里程碑。它极大地提高了我们在NLP中进行转学的能力。它有望解决各种各样的NLP任务。到本文结尾,您肯定会学到很多知识,请继续阅读。我相信您会在BERT应用程序上获得良好的动手经验。 在深入研究实际代码之前,让我们了解BERT。
什么是BERT?
BERT是一种可以表示文本的模式l。您给它一些序列作为输入,然后向左和向右看几次,并为每个单词生成向量表示作为输出。2018年底,谷歌AI语言的研究人员开源了一种称为BERT(来自变压器的双向编码器表示形式)的自然语言处理(NLP)新技术。一项重大突破使得
深度学习社区受到了轰动,因为它的性能令人赞叹。
为什么需要BERT?
NLP的最大挑战之一是缺乏足够的培训数据。总体而言,有大量文本数据可用,但是如果我们要创建特定于任务的数据集,则需要将该堆拆分为许多不同的字段。而当我们这样做时,我们最终仅得到数千或数十万个人标记的培训示例。不幸的是,为了表现良好,基于深度学习的NLP模型需要大量数据-在数百万或数十亿的带注释的训练示例上进行训练时,它们会看到重大改进。
为了帮助弥合数据鸿沟,研究人员开发了多种技术,可在网络上使用大量无注释的文本来训练通用语言表示模型(这称为预训练)。然后,可以在较小的特定于任务的数据集上微调这些通用的预训练模型,例如,在处理诸如问题回答和情感分析之类的问题时。
与从头开始对较小的特定于任务的数据集进行训练相比,此方法可显着提高准确性。BERT是这些技术中用于NLP预训练的最新功能。它在深度学习社区引起了轰动,因为它在各种NLP任务(例如问题解答)中都提供了最新的结果。
它是如何工作的?
BERT依赖于Transformer(一种学习文本中单词之间的上下文关系的注意力机制)。一个基本的Transformer由一个读取文本输入的编码器和一个对任务进行预测的解码器组成。由于BERT的目标是生成语言表示模型,因此只需要编码器部分即可。BERT编码器的输入是一系列令牌,这些令牌首先被转换为矢量,然后在
神经网络中进行处理。但是在开始处理之前,BERT需要对输入进行按摩并用一些额外的元数据修饰:
令牌嵌入:在第一个句子的开头将[CLS]令牌添加到输入的单词令牌中,并在每个句子的末尾插入[SEP]令牌。
段嵌入:将指示句子A或句子B的标记添加到每个标记。这允许编码器区分句子。
位置嵌入:将位置嵌入添加到每个标记,以指示其在句子中的位置。
伯特
让我们开始BERT的应用程序:
步骤1:加载所需的程序包
import numpy as np
import pandas as pd
import tensorflow as tf
import tensorflow_hub as hub
import logging
logging.basicConfig(level = logging.INFO)
我们将需要一个BERT令牌化 类
!wget --quiet
https://raw.githubusercontent.co ... ert/tokenization.py
建立一个BERT层
导入tensorflow_hub作为中心
导入令牌化
module_url ='https://tfhub.dev/tensorflow/bert_en_uncased_L-12_H-768_A-12/2'
bert_layer = hub.KerasLayer(module_url,trainable = True)
步骤2:了解问题陈述并导入数据集
我正在使用Git中心错误预测数据集,它可在MachineHack平台中使用。我们的目标是根据GitHub标题和文本正文预测错误,功能和问题。
train = pd.read_json(“ embold_train.json”)。reset_index(drop = True)
test = pd.read_json(“ embold_test.json”)。reset_index(drop = True)
数据集描述:
train.json – 150000行x 3列(包括标签Column作为Target变量)
test.json – 30000行x 2列
Train.json一瞥
一窥test.json
属性说明:
标题– GitHub Bug,功能,问题的标题
正文– GitHub Bug,功能,问题的正文
标签–代表各种类别的标签
错误– 0
功能– 1
问题2
预处理:合并标题和正文列
train ['Review'] =(train ['title']。map(str)+''+ train ['body'])。apply(lambda row:row.strip())
test ['Review'] =(test ['title']。map(str)+''+ test ['body'])。apply(lambda row:row.strip())
第三步:对原始文本进行编码
令牌化是获取原始文本并将其拆分为令牌的过程,令牌是表示单词的数字数据。
正式的BERT语言模型已使用WordPiece词汇进行了预训练,并且不仅使用标记嵌入,而且使用段嵌入来区分成对的序列之间的序列,例如,问答题示例。由于注意机制在上下文评估中不考虑位置,因此需要位置嵌入以将位置意识注入BERT模型。
要注意的BERT的重要限制是BERT的序列的最大长度为512个令牌。对于比最大允许输入大小短的序列输入,我们需要添加填充令牌[PAD]。另一方面,如果序列较长,则需要剪切序列。对于较长的文本段,需要注意序列最大长度上的BERT限制。
所谓的特殊令牌也很重要,例如[CLS]令牌和[SEP]令牌。[CLS]令牌将插入序列的开头,[SEP]令牌位于末尾。如果我们处理序列对,我们将在最后一个末尾添加其他[SEP]令牌。
vocab_file = bert_layer。resolve_object。voc ab_file。asset_path。numpy()
do_lower_case = bert_layer。resolve_object。DO_ LOWER_CASE。numpy()
tokenizer =标记化。FullTokenizer(voc ab_file,do_lower_case)
def b ert_encode(texts,tokenizer,max_len = 512):
一个ll_tokens = []
一个ll_masks = []
一个ll_segments = []
对于T EXT在文本:
t ext =标记生成器。标记化(文字)
t ext =文字[:max_len -2]
我nput_sequence = [“ [CLS]”] +文字+ [“ [SEP]”]
p ad_len = max_len - len(input_sequence)
吨okens =标记生成器。convert_tokens_to_ IDS(input_sequence)+ [0] * pad_len
p ad_masks = [1] * LEN(input_sequence)+ [0] * pad_len
小号egment_ids = [0] * MAX_LEN
al l_tokens .append(令牌)
一个ll_masks .append(pad_masks)
一个ll_segments .append(segment_ IDS)
返回n p。数组(all_tokens),np。array(all_masks),np。数组(all_segments)
步骤4:建立模型
定义b uild_model(bert_layer,max_len = 512):
我nput_word_ids = tf。喀拉斯邦。输入(形状=(MAX_LEN,),D型细胞= TF。INT32,名字= “input_word_ids”)
我nput_mask = tf。喀拉斯邦。输入(形状=(MAX_LEN,),D型细胞= TF。INT32,名字= “input_mask”)
小号egment_ids = TF。喀拉斯邦。输入(形状=(MAX_LEN,),D型细胞= TF。INT32,名字= “segment_ids”)
p ooled_output,sequence_output = bert_layer([ input_word_ids,input_mask,segment_ids ])
c lf_output = sequence_output [:,0 ,: ]
n et = tf。喀拉斯邦。层。密集(64,activation ='relu')(clf_output)
n et = tf。喀拉斯邦。层。辍学(0.2)(n et)
n et = tf。喀拉斯邦。层。密集(32,激活='relu')(净)
n et = tf。喀拉斯邦。层。辍学(0.2)(n et)
o ut = tf。喀拉斯邦。层。密集(5,激活='softmax')(净)
m odel = tf。喀拉斯邦。型号。模型(inputs = [ input_word_ids,input_mask,segment_ids ],outputs = out)
米Odel等。编译(TF。keras。optimiz ERS。亚当(LR = 1E-5),损耗= 'categorical_ crossentropy',度量= [ '准确性'])
回报米奥德尔
ReLu:整流线性单元是深度学习模型中最常用的激活函数。如果函数接收到任何负输入,则该函数将返回0,但是对于任何正值,它将返回该值。
伯特
Softmax:此功能非常适合分类问题,尤其是当我们要处理多类分类问题时,该功能将报告每个类的“置信度”。由于我们在这里处理概率,因此softmax函数返回的分数加起来为1。
我们仅检查每个评论的前150个字符。
您也可以增加此长度,但是运行时间也会增加
类别数= 3(错误,功能,问题)
MAX_LEN = 150
train_input = bert_encode(火车。综述。值,标记生成器,MAX_LEN = MAX_LEN)
test_input = bert_encode(试验。综述。值,标记生成器,MAX_LEN = MAX_LEN)
train_labels = TF .onclick =“parent.postMessage({ '所指' :'。tensorflow.keras'},'*')“> keras。实用程序。to_categorical(火车,标签,值,num_classes = 3)
模型= build_model(bert_layer,max_len = max_len)
模型。摘要()
步骤5:运行模型
伯特
每个时期大约需要1个小时(即使使用GPU加速)。毕竟,我们有一个庞大的数据集。
checkpoint = tf.keras.callbacks.ModelCheckpoint('model.h5',monitor ='val_accuracy',save_best_only = True,verbose = 1)
earlystopping = tf.keras.callbacks.EarlyStopping(monitor ='val_accuracy',耐心= 5,冗长= 1)
train_history = model.fit(
train_input,train_labels,
validation_split = 0.2,
纪元= 3,
callbacks = [检查点,提早停止],
batch_size = 32,
verbose = 1
测试数据的预测:
model.load_weights('model.h5')
test_pred = model.predict(测试输入)
结论:
打开kaggle Kernal,然后按照上述步骤尝试这种方法。肯定会得到更好的结果。通过这种方法,我在MachineHack(GitHub错误预测)中排名16。
每个时代模型都使用检查点保存结果,而无需再次运行。每次保存模型。
我希望这篇文章对您有所帮助,并非常感谢Analytics Vidhya提供了这一难得的机会。
题库