irpas技术客

用Bert做英法机器翻译_阿袁的小园子_bert机器翻译

网络投稿 6211

过程基本参考自BERT实战——(5)生成任务-机器翻译,结合我个人的数据集在数据处理部分做了些调整,完整代码可见translate.ipynb

一、数据处理

我的数据集是这样的: 第一列是英文,第二列是对应的法文翻译,第三列是文本来源,所以说第三列是不需要的

1.首先是读取数据,把前两列存入数组中,并把前90%的数据作为训练集,后10%的数据作为验证集

f=open("fra.txt","r",encoding="utf-8").readlines() en=[] fre=[] data=[] for l in f: line=l.strip().split("\t") tmp={} tmp["en"]=line[0] tmp["fr"]=line[1] data.append(tmp) print(len(data)) print(data[0]) train_size=int(len(data)*0.9) train_data=data[:train_size] val_data=data[train_size:]

2.把数据存入到对应的文件中

f=open("train.txt","w") for i in train_data: f.write(str(i)+"\n") f.close() f=open("val.txt","w") for i in val_data: f.write(str(i)+"\n") f.close()

3.加载分词器

# 分词,使用已经训练好的helsinki-NLP/opus-mt-en-ro来做翻译任务 from transformers import AutoTokenizer model_checkpoint="Helsinki-NLP/opus-mt-en-ro" tokenizer=AutoTokenizer.from_pretrained(model_checkpoint,use_fast=True)

4.定义预处理函数,把数据按源语言和目标语言分开,作为dataset中的input_ids和labels

from datasets import load_dataset raw_datasets=load_dataset("text",data_files={"train":"train.txt","validation":"val.txt"}) max_input_length=64 max_target_length=64 source_lang="en" target_lang="fr" def preprocess_function(examples): inputs=[eval(ex)[source_lang] for ex in examples["text"]] targets=[eval(ex)[target_lang] for ex in examples["text"]] model_inputs=tokenizer(inputs,max_length=max_input_length,truncation=True) # 为目标语言设置分词器 with tokenizer.as_target_tokenizer(): labels=tokenizer(targets,max_length=max_target_length,truncation=True) model_inputs["labels"]=labels["input_ids"] return model_inputs # 把预处理函数应用到原始的dataset中 tokenized_datasets=raw_datasets.map(preprocess_function,batched=True)

分别输出raw_datasets和tokenized_datasets的结构,可以看到后者多了三列内容,我们只需要关注input_ids和labels就行:

二、加载预训练模型,并设置参数

1.预训练模型和训练参数

# 加载预训练模型 from transformers import AutoModelForSeq2SeqLM model=AutoModelForSeq2SeqLM.from_pretrained(model_checkpoint) # 设定训练参数 from transformers import Seq2SeqTrainingArguments batch_size=8 args=Seq2SeqTrainingArguments( "test-translation", evaluation_strategy="epoch", learning_rate=2e-5, per_device_train_batch_size=batch_size, per_device_eval_batch_size=batch_size, weight_decay=0.01, save_total_limit=3, # 至多保存的模型个数 num_train_epochs=10, predict_with_generate=True, fp16=False, )

2.载入数据收集器

# 数据收集器data collator,告诉trainer如何从预处理的输入数据中构造batch,我使用数据处理器DataCollatorForSeq2Seq # 将预处理的输入分batch再次处理后喂给模型 from transformers import DataCollatorForSeq2Seq data_collator=DataCollatorForSeq2Seq(tokenizer,model=model)

3.加载评估方法

# 定义评估方法,使用bleu指标,利用metric.compute计算该指标对模型进行评估 # 定义postprocess_text函数做一些数据后处理 import numpy as np from datasets import load_metric metric=load_metric("sacrebleu") print("successfully import metric")

4.评估方法只能接收特定格式的数据,因此要把用postprocess_text方法把preds和labels处理成对应的格式

def postprocess_text(preds,labels): preds=[pred.strip() for pred in preds] labels=[[label.strip()] for label in labels] return preds,labels def compute_metrics(eval_preds): preds,labels=eval_preds if isinstance(preds,tuple): preds=preds[0] decoded_preds=tokenizer.batch_decode(preds,skip_special_tokens=True) # 如果labels=-100,说明这个label是无法编码的,应该用pad_token_id去进行填充 labels=np.where(labels!=-100,labels,tokenizer.pad_token_id) decoded_labels=tokenizer.batch_decode(labels,skip_special_tokens=True) # 把预测后的输出转成适合metric.compute输入的格式 print("type(decoded_preds)=",type(decoded_preds)) print("type(decoded_labels)=",type(decoded_labels)) decoded_preds,decoded_labels=postprocess_text(decoded_preds,decoded_labels) result=metric.compute(predictions=decoded_preds,references=decoded_labels) result={"bleu":result["score"]} prediction_lens=[np.count_nonzero(pred!=tokenizer.pad_token_id) for pred in preds] result["gen_len"]=np.mean(prediction_lens) result={k:round(v,4) for k,v in result.items()} print("result is as follow============================") print(result) return result 三、开始训练(微调模型) # 开始训练 import os os.environ['CUDA_VISIBLE_DEVICES'] = '0' from transformers import Seq2SeqTrainer trainer=Seq2SeqTrainer( model, args, train_dataset=tokenized_datasets["train"], # 这里要改成自己的训练集 eval_dataset=tokenized_datasets["validation"], # 这里要改成自己的验证集 data_collator=data_collator, tokenizer=tokenizer, compute_metrics=compute_metrics ) trainer.train()

训练结果如下: sacrebleu的评测结果是乘了100后的,所以可以看到评估出来的bleu是在44%左右。 这个实验是用A100跑的,但是跑了10个epoch竟然花了两个半小时。


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #bert机器翻译 #quotrquot