窝牛号

基于transformer一步一步训练一个多标签文本分类的BERT模型

Bert(Bidirectional Encoder Representations from Transformers)是一种基于Transformer架构的预训练语言模型,由Google在2018年提出。Bert模型在自然语言处理领域取得了重大突破,被广泛应用于各种NLP任务,如文本分类、命名实体识别、问答系统等。

Bert模型的核心思想是通过大规模无监督预训练来学习通用的语言表示,然后再通过有监督微调来适应特定任务。与传统的语言模型不同,Bert模型采用了双向Transformer编码器,能够同时利用上下文信息,从而更好地理解句子中的词语。

BERT

Bert模型的预训练过程包括两个阶段:Masked Language Model(MLM)和Next Sentence Prediction(NSP)。在MLM阶段,Bert模型会随机遮盖输入句子中的一些词语,然后通过上下文信息预测这些被遮盖的词语。在NSP阶段,Bert模型会判断两个句子是否是连续的。

屏蔽语言建模 (MLM):取一个句子,模型随机屏蔽输入中 15% 的单词,然后通过模型运行训练,并预测屏蔽的单词。 这与传统的循环神经网络 (RNN) 不同,传统的循环神经网络通常会一个接一个的输入单词,也不同于 GPT 等自回归模型。

句子预测(NSP):模型在预训练期间连接屏蔽两个句子作为输入。数据有时2个句子是相邻的句子,有时则不是,模型需要进行训练,来判断2个句子的相关性。

在微调阶段,Bert模型可以通过简单地添加一个任务特定的输出层来适应不同的NLP任务。通过微调,Bert模型可以在各种任务上取得出色的性能,而无需针对每个任务进行独立的训练。本期我们就使用transformers来从头训练一个多标签的Bert模型。

!pip install datasets !pip install accelerate -U !pip install transformers[torch] !pip install transformers==4.28.0 from transformers import TrainingArguments, Trainer from datasets import load_dataset from transformers import AutoTokenizer from transformers import AutoModelForSequenceClassification import numpy as np from sklearn.metrics import f1_score, roc_auc_score, accuracy_score from transformers import evalPrediction import torch dataset = load_dataset(&34;, &34;) Downloading builder script: 100% 6.29k/6.29k [00:00<00:00, 208kB/s] Downloading metadata: 100% 7.76k/7.76k [00:00<00:00, 387kB/s] Downloading readme: 100% 10.6k/10.6k [00:00<00:00, 152kB/s] Downloading data files: 100% 1/1 [00:02<00:00, 2.09s/it] Downloading data: 100% 5.98M/5.98M [00:00<00:00, 12.3MB/s] Extracting data files: 100% 1/1 [00:00<00:00, 2.80it/s] Generating train split: 100% 6838/6838 [00:01<00:00, 3607.10 examples/s] Generating test split: 100% 3259/3259 [00:00<00:00, 3258.22 examples/s] Generating validation split: 100% 886/886 [00:00<00:00, 4346.76 examples/s]

这里使用的是hugging face的transformers库来进行Bert模型的训练,并加载了一个dataset,运行以上代码后,模型会自动下载相关的数据集,可以看到此数据集有6838行train训练数据,3259行test数据以及886行validation验证数据。

example = dataset[&39;][0] example

当然这里可以看一下整个数据的样式,打印一下这个数据集的数据,可以看到,每行数据有一个ID,一句话以及这句话的标签组成。我们就来训练此数据集,最终模型可以接受一个输入,并反馈此句话的标签。

labels = [label for label in dataset[&39;].features.keys() if label not in [&39;, &39;]] id2label = {idx:label for idx, label in enumerate(labels)} label2id = {label:idx for idx, label in enumerate(labels)} tokenizer = AutoTokenizer.from_pretrained(&34;) def preprocess_data(examples): text = examples[&34;] encoding = tokenizer(text, padding=&34;, truncation=True, max_length=128) labels_batch = {k: examples[k] for k in examples.keys() if k in labels} labels_matrix = np.zeros((len(text), len(labels))) for idx, label in enumerate(labels): labels_matrix[:, idx] = labels_batch[label] encoding[&34;] = labels_matrix.tolist() return encoding encoded_dataset = dataset.map(preprocess_data, batched=True, remove_columns=dataset[&39;].column_names)

这里首先我们处理一下数据集,并获取数据集中的所有标签,并加载Bert预训练模型,这里使用preprocess_data函数来进行数据集的map操作。

Downloading (…)okenizer_config.json: 100% 28.0/28.0 [00:00<00:00, 1.62kB/s] Downloading (…)lve/main/config.json: 100% 570/570 [00:00<00:00, 25.3kB/s] Downloading (…)solve/main/vocab.txt: 100% 232k/232k [00:00<00:00, 8.78MB/s] Downloading (…)/main/tokenizer.json: 100% 466k/466k [00:00<00:00, 5.48MB/s] Map: 100% 6838/6838 [00:01<00:00, 7062.05 examples/s] Map: 100% 3259/3259 [00:00<00:00, 6021.69 examples/s] Map: 100% 886/886 [00:00<00:00, 5738.86 examples/s]

接下来,就可以定义一个transformer模型来训练Bert模型了。

[id2label[idx] for idx, label in enumerate(example[&39;]) if label == 1.0] encoded_dataset.set_format(&34;) model = AutoModelForSequenceClassification.from_pretrained(&34;, problem_type=&34;, num_labels=len(labels),id2label=id2label, label2id=label2id) batch_size = 834;f1&34;bert-finetuned-sem_eval-english&34;epoch&34;epoch&39;micro&39;micro&39;f1&39;roc_auc&39;accuracy&34;train&34;validation&34;I&34; encoding = tokenizer(text, return_tensors=&34;) encoding = {k: v.to(trainer.model.device) for k,v in encoding.items()} outputs = trainer.model(**encoding) logits = outputs.logits logits.shape sigmoid = torch.nn.Sigmoid() probs = sigmoid(logits.squeeze().cpu()) predictions = np.zeros(probs.shape) predictions[np.where(probs >= 0.5)] = 1 predicted_labels = [id2label[idx] for idx, label in enumerate(predictions) if label == 1.0] print(predicted_labels) [ &39;,&39;]

通过以上的代码,我们就使用了Bert模型的预训练模型训练了一个文本多标签分类任务模型,Bert模型当然也可以进行其他文本相关的任务,比如mask完形填空,预测下一个句子等等,这些模型的训练都可以基于Bert的预训练模型进行微调。而正是Bert模型无监督学习方式来进行模型的预训练,大大提高了模型的泛化能力,从而使transformer预训练成为了可能。

本站所发布的文字与图片素材为非商业目的改编或整理,版权归原作者所有,如侵权或涉及违法,请联系我们删除

窝牛号 wwww.93ysy.com   沪ICP备2021036305号-1