tensorflow 2.0+ 基于预训练BERT模型 的文本分类

简介

基于transformers的语言模型在许多不同的自然语言处理(NLP)基准任务测试上都取得了很大进展。迁移学习与大规模的transformers语言模型训练的结合正在成为现代NLP的一个标准。在这篇文章,我们对transformers体系结构和文本分类问题做一些必要的理论介绍。然后,我们将演示预训练BERT模型在文本分类任务的微调过程,这里运用的是TensorFlow 2.0+的 Keras API。



文本分类–问题及公式

一般来说, 分类是确定新样本的类别问题。我们有数据集D,在文档中包含文本序列,如

在这里插入图片描述

这里 Xi 是每一段文本 而N 是文本的个数。

实现分类的算法称为分类器。文本分类可以根据目标性质分为不同的任务:

  • 多分类问题(multi-class classification)

  • 多标签问题(multi-label classification)

多分类也称为单标签问题,例如,我们为每个样本分配一个标签。名称中的"多"表示我们处理至少 3 个类,对于 2 个类,我们可以使用术语二进制分类(binary classification)。另一方面,多标签任务更为一般,允许我们为每个样本分配多个标签,而不仅仅是一样本一标签。



为什么选择transformers?

在这篇文章中,我们不会详细讨论transformers架构。然而了解 NLP 中的一些难点还是很有用的。NLP 中有两个相辅相成的重要概念:

transformers用于构建语言模型,而embeddings 是可以用于预训练的附属品。



基于 RNNs/LSTMs 的方法

大多数较旧的语言建模方法都基于 RNN(recurrent neural network)。简单的 RNN 存在梯度消失/梯度爆炸问题,所以无法对较长的上下文依赖关系进行建模。它们大多数被所谓的长短期记忆网络模型(LSTMs) 所取代, 该神经网络也是 RNN 的一个变种形式,但可以捕获文档中较长的上下文。然而,LSTM 只能单向处理序列,因此基于 LSTM 的最先进方法演变为双向 LSTM,此结构可以从左到右以及从右到左读取上下文。基于LSTM有非常成功的模型,如ELMO或 ULMFIT,这些模型仍然适用于现在的NLP任务。



基于transformers架构的方法

双向 LSTM 的主要限制之一是其顺序性,这使得并行训练非常困难, transformer 架构通过注意力机制(Vashvani et al. 2017) 完全取代LSTM来解决这一个问题。在注意力机制中,我们把整个序列看作一个整体, 因此并行训练要容易得多。我们可以对整个文档上下文进行建模,并使用大型数据集以无人监督学习的方式进行预训练,并微调下游任务。



最先进的transformers模型

有很多基于transformers的语言模型。最成功的是以下这些(截至2020年4月)

这些模型之间略有差异,而BERT一直被认为是许多 NLP 任务中最先进的模型。但现在看来,它已被同样来自谷歌的 XLNet 所超越。XLNet 利用置换语言建模,该模型对句子中所有可能的单词排列进行自动回归模型。我们将在本文中使用基于 BERT 的语言模型。



BERT

BERT (Bidirectional Encoder Representations from Transformers) (Devlint et al., 2018) 是一种预训练语言表示的方法。我们不会讨论太多细节,但与原始transformers (Vaswani et al., 2017) 的主要区别是, BERT没有解码器, 但在基本版本中堆叠了12个编码器,而且在更大的预训练模型中会增加编码器的数量。这种架构不同于 OpenAI 的 GPT-2,它是适合自然语言生成 (NLG) 的自回归语言模型。



Tokenizer

官方 BERT 语言模型是使用切片词汇预训练与使用, 不仅token 嵌入, 而且有区分成对序列的段嵌入, 例如问答系统。由于注意力机制在上下文评估中不考虑位置,因此需要把位置信息嵌入才能将位置感知注入 BERT 模型。

需要注意的是,BERT限制序列的最大长度为 512 个token。对于比最大允许输入短的序列,我们需要添加 [PAD],另一方面,如果序列更长,我们需要剪切序列。对于较长的文本段,您需要了解此对序列最大长度的 BERT 限制,请参阅此 GitHub issue 以了解进一步的解决方案。

非常重要的还有所谓的特殊token,例如 [CLS] token和 [SEP] token。[CLS] token将插入序列的开头,[SEP] token位于末尾。如果我们处理序列对,我们将在最后一个序列对的末尾添加额外的 [SEP] token。

在这里插入图片描述

使用transformers库时,我们首先加载要使用的模型的标记器。然后,我们将按如下方式进行:

from transformers import BertTokenizer

tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')


max_length_test = 20
test_sentence = '曝梅西已通知巴萨他想离开'

# add special tokens
test_sentence_with_special_tokens = '[CLS]' + test_sentence + '[SEP]'
tokenized = tokenizer.tokenize(test_sentence_with_special_tokens)
print('tokenized', tokenized)

# convert tokens to ids in WordPiece
input_ids = tokenizer.convert_tokens_to_ids(tokenized)
  
# precalculation of pad length, so that we can reuse it later on
padding_length = max_length_test - len(input_ids)

# map tokens to WordPiece dictionary and add pad token for those text shorter than our max length
input_ids = input_ids + ([0] * padding_length)

# attention should focus just on sequence with non padded tokens
attention_mask = [1] * len(input_ids)

# do not focus attention on padded tokens
attention_mask = attention_mask + ([0] * padding_length)

# token types, needed for example for question answering, for our purpose we will just set 0 as we have just one sequence
token_type_ids = [0] * max_length_test
bert_input = {
   
    "token_ids": input_ids,
    "token_type_ids": token_type_ids,
    "attention_mask": attention_mask
} 
print(bert_input)

OUTPUT:

tokenized ['[CLS]', '曝', '梅', '西', '已', '通', '知', '巴', '萨', '他', '想', '离', '开', '[SEP]']
{
   'token_ids': [101, 3284, 3449, 6205
  • 14
    点赞
  • 97
    收藏
    觉得还不错? 一键收藏
  • 20
    评论
### 文本分类 #### 数据预处理 要求训练集和测试集分开存储,对于中文的数据必须先分词,对分词后的词用空格符分开,并且将标签连接到每条数据的尾部,标签和句子用分隔符\分开。具体的如下: * 今天 的 天气 真好\积极 #### 文件结构介绍 * config文件:配置各种模型的配置参数 * data:存放训练集和测试集 * ckpt_model:存放checkpoint模型文件 * data_helpers:提供数据处理的方法 * pb_model:存放pb模型文件 * outputs:存放vocab,word_to_index, label_to_index, 处理后的数据 * models:存放模型代码 * trainers:存放训练代码 * predictors:存放预测代码 #### 训练模型 * python train.py --config_path="config/textcnn_config.json" #### 预测模型 * 预测代码都在predictors/predict.py中,初始化Predictor对象,调用predict方法即可。 #### 模型的配置参数详述 ##### textcnn:基于textcnn的文本分类 * model_name:模型名称 * epochs:全样本迭代次数 * checkpoint_every:迭代多少步保存一次模型文件 * eval_every:迭代多少步验证一次模型 * learning_rate:学习速率 * optimization:优化算法 * embedding_size:embedding层大小 * num_filters:卷积核的数量 * filter_sizes:卷积核的尺寸 * batch_size:批样本大小 * sequence_length:序列长度 * vocab_size:词汇表大小 * num_classes:样本的类别数,二分类时置为1,多分类时置为实际类别数 * keep_prob:保留神经元的比例 * l2_reg_lambda:L2正则化的系数,主要对全连接层的参数正则化 * max_grad_norm:梯度阶段临界值 * train_data:训练数据的存储路径 * eval_data:验证数据的存储路径 * stop_word:停用词表的存储路径 * output_path:输出路径,用来存储vocab,处理后的训练数据,验证数据 * word_vectors_path:词向量的路径 * ckpt_model_path:checkpoint 模型的存储路径 * pb_model_path:pb 模型的存储路径 ##### bilstm:基于bilstm的文本分类 * model_name:模型名称 * epochs:全样本迭代次数 * checkpoint_every:迭代多少步保存一次模型文件 * eval_every:迭代多少步验证一次模型 * learning_rate:学习速率 * optimization:优化算法 * embedding_size:embedding层大小 * hidden_sizes:lstm的隐层大小,列表对象,支持多层lstm,只要在列表中添加相应的层对应的隐层大小 * batch_size:批样本大小 * sequence_length:序列长度 * vocab_size:词汇表大小 * num_classes:样本的类别数,二分类时置为1,多分类时置为实际类别数 * keep_prob:保留神经元的比例 * l2_reg_lambda:L2正则化的系数,主要对全连接层的参数正则化 * max_grad_norm:梯度阶段临界值 * train_data:训练数据的存储路径 * eval_data:验证数据的存储路径 * stop_word:停用词表的存储路径 * output_path:输出路径,用来存储vocab,处理后的训练数据,验证数据 * word_vectors_path:词向量的路径 * ckpt_model_path:checkpoint 模型的存储路径 * pb_model_path:pb 模型的存储路径 ##### bilstm atten:基于bilstm + attention 的文本分类 * model_name:模型名称 * epochs:全样本迭代次数 * checkpoint_every:迭代多少步保存一次模型文件 * eval_every:迭代多少步验证一次模型 * learning_rate:学习速率 * optimization:优化算法 * embedding_size:embedding层大小 * hidd
以下是一个使用BERT模型对新闻文本进行分类的示例,基于TensorFlow 2.0: ```python import tensorflow as tf import tensorflow_hub as hub from tensorflow.keras.models import Model from tensorflow.keras.layers import Input, Dense, Dropout # 加载BERT模型 bert_layer = hub.KerasLayer("https://tfhub.dev/tensorflow/bert_en_uncased_L-12_H-768_A-12/2", trainable=True) # 构建模型 input_word_ids = Input(shape=(128,), dtype=tf.int32, name="input_word_ids") input_mask = Input(shape=(128,), dtype=tf.int32, name="input_mask") segment_ids = Input(shape=(128,), dtype=tf.int32, name="segment_ids") pooled_output, sequence_output = bert_layer([input_word_ids, input_mask, segment_ids]) x = Dense(256, activation='relu')(pooled_output) x = Dropout(0.2)(x) output = Dense(10, activation='softmax')(x) model = Model(inputs=[input_word_ids, input_mask, segment_ids], outputs=output) # 编译模型 optimizer = tf.keras.optimizers.Adam(lr=2e-5) loss = tf.keras.losses.CategoricalCrossentropy() metric = tf.keras.metrics.CategoricalAccuracy('accuracy') model.compile(optimizer=optimizer, loss=loss, metrics=[metric]) # 训练模型 history = model.fit(train_dataset, epochs=5, validation_data=val_dataset) ``` 在这个示例中,我们使用了BERT模型对新闻文本进行分类。我们首先加载了BERT模型,然后构建了一个包含一个Dense层和一个Dropout层的分类器。我们使用了CategoricalCrossentropy作为损失函数,使用Adam优化器进行优化,并使用CategoricalAccuracy作为评估指标。最后,我们训练了模型并记录了训练历史。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值