BERT训练之数据集处理(代码实现)

embedded/2024/9/30 1:55:52/

目录

1读取文件数据

 2.生成下一句预测任务的数据

 3.预测下一个句子

 4.生成遮蔽语言模型任务的数据

 5.从词元中得到遮掩的数据

 6.将文本转化为预训练数据集

7.封装函数类

8.调用


python">import os
import random
import torch
import dltools

1读取文件数据

python">def _read_wiki(data_dir):#拼接文件路径file_name = os.path.join(data_dir, 'wiki.train.tokens')#将输入参数中的两个名字拼接成一个完整的文件路径。with open(file_name, 'r', encoding='utf-8') as f:#打开文件,逐行读取内容,并将每行作为一个元素添加到列表中。lines = f.readlines()#大写字母转换为小写字母,获取分句之后的段落列表paragraphs = [line.strip().lower().split('.') for line in lines if len(line.split('.')) >= 2]random.shuffle(paragraphs)  #大陆那段落列表中的元素return paragraphs_read_wiki('./wikitext-2/')  #输出过长,不展示

 2.生成下一句预测任务的数据

python">def _get_next_sentence(sentence, next_sentence, paragraphs):if random.random() < 0.5: #若50%的概率发生时is_next = Trueelse:#否则,next_sentence就不是下一个句子,是随机抽取的其他句子#paragraphs是三重列表的嵌套#从所有列表中随机抽取一个段落,从这个段落中又随机抽取一个句子next_sentence = random.choice(random.choice(paragraphs))is_next =Falsereturn sentence, next_sentence, is_next     

 3.预测下一个句子

python">def _get_nsp_data_from_paragraph(paragraph, paragraphs, vocab, max_len):nsp_data_from_paragraph = []  #创建空列表,存放下一个句子的数据for i in range(len(paragraph) - 1):   #len(paragraph) - 1是因为索引是从0开始的,左闭右开,输出段落中的每一个句子的索引#调用函数,获取用于预测下一个句子任务的数据tokens_a, tokens_b , is_next = _get_next_sentence(paragraph[i], paragraph[i+1], paragraphs)#预测输入的两个句子结构是  -->    <cls> tokens_a  <sep> tokens_b <sep># +3表示考虑 1个<cls>  +2个<sep>if len(tokens_a) + len(tokens_b) + 3 > max_len:continue   #这种情况超出了序列的最大长度,不需要#将文本数据分割成词元(tokens)和句子分段(segments)。#这个过程通常涉及到一系列的预处理步骤,如去除标点符号、转换为小写、数字处理等,以确保输入数据的标准化和一致性‌tokens, segments = dltools.get_tokens_and_segments(tokens_a, tokens_b)nsp_data_from_paragraph.append((tokens, segments, is_next))  #三个数据以元祖的形式存放到列表中return nsp_data_from_paragraph

 4.生成遮蔽语言模型任务的数据

python">#Mask Language Modle
def _replace_mlm_tokens(tokens, candidate_pred_positions, num_mlm_preds, vocab):"""tokens:传入的词元candidate_pred_positions:等待预测的词元位置索引编号(若传入句子的序列长度为100,那么它就是0-99)num_mlm_preds:预测遮掩的数量vocab:整体词汇表"""#为遮蔽语言模型的输入创建新的词元副本, 其中输入可能包含替换的<mask>或随机词元mlm_input_tokens = [token for token in tokens]  #复制词元数据,后期的替换不修改原数据pred_positions_and_labels = []  #用于存放预测的词元位置和目标标签#打乱顺序  等待预测的词元位置索引编号random.shuffle(candidate_pred_positions)for mlm_pred_position in candidate_pred_positions:  #遍历#判断存放预测词元的个数是否已经超过了需要预测的数量if len(pred_positions_and_labels) >= num_mlm_preds:break  #若预测数量够了,就不预测了,直接退出当前for循环,  continue是退出当前if判断#否则,接着预测mask_token = None  #初始化变量:被15%抽中需要被替换的词元   为空#80%的概率, 将抽取的15%的词元,替换成<mask>词元if random.random() < 0.8:msaked_token = '<mask>'else:  #否则,将剩下的其中10%的词元保持不变      从剩下的20%中抽取50%来表示if random.random() < 0.5:mask_token = tokens[mlm_pred_position]else:  #将剩下的其中10%的词元,用随机词替换msaked_token = random.choice(vocab.idx_to_token)#将获取到的msaked_token按索引赋值替换原词元mlm_input_tokens[mlm_pred_position] = mask_token#mlm_pred_position需要被预测的词元位置索引,  tokens[mlm_pred_position]被遮掩预测的词元的标签(真实值是什么)pred_positions_and_labels.append((mlm_pred_position, tokens[mlm_pred_position]))return mlm_input_tokens, pred_positions_and_labels

 5.从词元中得到遮掩的数据

python"># 
def _get_mlm_data_from_tokens(tokens, vocab):candidate_pred_positions = []# tokens是一个字符串列表for i, token in enumerate(tokens):# 在遮蔽语言模型任务中不会预测特殊词元if token in ['<cls>', '<sep>']:continuecandidate_pred_positions.append(i)# 遮蔽语言模型任务中预测15%的随机词元num_mlm_preds = max(1, round(len(tokens) * 0.15))mlm_input_tokens, pred_positions_and_labels = _replace_mlm_tokens(tokens, candidate_pred_positions, num_mlm_preds, vocab)pred_positions_and_labels = sorted(pred_positions_and_labels,key=lambda x: x[0])pred_positions = [v[0] for v in pred_positions_and_labels]mlm_pred_labels = [v[1] for v in pred_positions_and_labels]return vocab[mlm_input_tokens], pred_positions, vocab[mlm_pred_labels]

 6.将文本转化为预训练数据集

python">def _pad_bert_inputs(examples, max_len, vocab):#词源需要预测的最大数量max_num_mlm_preds = round(max_len * 0.15)all_tokens_ids, all_segments, valid_lens = [], [], []all_pred_positions, all_mlm_weights, all_mlm_labels = [], [], []nsp_labels = []for (token_ids, pred_positions, mlm_pred_label_ids, segments, is_next) in examples:#对原有的tokens(每句话有长有短,补充《pad》使长度一致)all_tokens_ids.append(torch.tensor(token_ids + [vocab['<pad>']] * (max_len - len(token_ids)), dtype=torch.long))all_segments.append(torch.tensor(segments + [0] * (max_len - len(segments)), dtype=torch.long))#valid_lens不包括<pad>计数valid_lens.append(torch.tensor(len(token_ids), dtype=torch.float32))all_pred_positions.append(torch.tensor(pred_positions + [0] * (max_num_mlm_preds - len(pred_positions)), dtype=torch.long))#填充词元的预测将通过乘以0权重在损失中过滤掉all_mlm_weights.append(torch.tensor([1.0] * len(mlm_pred_label_ids) + [0.0] * (max_num_mlm_preds - len(pred_positions)), dtype=torch.float32))all_mlm_labels.append(torch.tensor(mlm_pred_label_ids + [0] * (max_num_mlm_preds - len(mlm_pred_label_ids)), dtype=torch.long))nsp_labels.append(torch.tensor(is_next, dtype=torch.long))return (all_tokens_ids, all_segments, valid_lens, all_pred_positions, all_mlm_weights, all_mlm_labels, nsp_labels)

7.封装函数类

python">class WikiTextDataset(torch.utils.data.Dataset):def __init__(self, paragraphs, max_len):#输入paragraphs[i]是代表段落的句子字符串列表#输出paragraphs[i]是代表段落的句子列表,其中每个句子都是词元列表paragraphs = [dltools.tokenize(paragraph, token='word') for paragraph in paragraphs]#获取句子的词元列表sentences = [sentence for paragraph in paragraphs for sentence in paragraph]self.vocab = dltools.Vocab(sentences, min_freq=5, reserved_tokens=['<pad>', '<mask>', '<cls>', '<sep>'])#获取下一句子预测任务的数据examples = []for paragraph in paragraphs:examples.extend(_get_nsp_data_from_paragraph(paragraph, paragraphs, self.vocab, max_len))#获取遮蔽语言模型任务的数据examples = [(_get_mlm_data_from_tokens(tokens, self.vocab) + (segments, is_next)) for tokens, segments, is_next in examples]#填充输入(self.all_token_ids, self.all_segments, self.valid_lens, self.all_pred_positions, self.all_mlm_weights, self.all_mlm_labels, self.nsp_labels) = _pad_bert_inputs(examples, max_len, self.vocab)def __getitem__(self, idx):return (self.all_token_ids[idx], self.all_segments[idx],self.valid_lens[idx], self.all_pred_positions[idx],self.all_mlm_weights[idx], self.all_mlm_labels[idx],self.nsp_labels[idx])def __len__(self):return len(self.all_token_ids)

8.调用

python">def load_data_wiki(batch_size, max_len):"""加载WikiText-2数据集"""num_workers = dltools.get_dataloader_workers()  #快速获取或设置最佳的工作线程数data_dir = './wikitext-2/'paragraphs = _read_wiki(data_dir)train_set = WikiTextDataset(paragraphs, max_len)train_iter = torch.utils.data.DataLoader(train_set, batch_size, shuffle=True, num_workers=num_workers)return train_iter, train_set.vocab
python">batch_size, max_len = 512, 64
train_iter, vocab = load_data_wiki(batch_size, max_len)for (tokens_X, segments_X, valid_lens_x, pred_positions_X, mlm_weights_X,mlm_Y, nsp_y) in train_iter:print(tokens_X.shape, segments_X.shape, valid_lens_x.shape,pred_positions_X.shape, mlm_weights_X.shape, mlm_Y.shape,nsp_y.shape)break
torch.Size([512, 64]) torch.Size([512, 64]) torch.Size([512]) torch.Size([512, 10]) torch.Size([512, 10]) torch.Size([512, 10]) torch.Size([512])
python">len(vocab)

 20228

 


http://www.ppmy.cn/embedded/119666.html

相关文章

如何借助Java批量操作Excel文件?

最新技术资源&#xff08;建议收藏&#xff09; https://www.grapecity.com.cn/resources/ 前言 | 问题背景 在操作Excel的场景中&#xff0c;通常会有一些针对Excel的批量操作&#xff0c;批量的意思一般有两种&#xff1a; 对批量的Excel文件进行操作。如导入多个Excel文件…

JavaScript爬虫:数据抓取的艺术与实践

在当今数据驱动的世界中&#xff0c;JavaScript作为一种广泛使用的编程语言&#xff0c;不仅在前端开发中占据重要地位&#xff0c;也可以用于编写爬虫程序&#xff0c;从互联网上抓取有价值的数据。本文将介绍如何使用JavaScript编写爬虫程序&#xff0c;并探讨其在数据抓取中…

面经 | ES6

ES6 ES6Promise对象创建Promise三个状态resolve/reject 和微任务的关系awaitset vs weakSetmap vs weakMapES6 Promise对象 new Promise(excutor);excutor是一个函数,会立刻执行;then里的回调函数,会进入微任务队列;then会返回一个新的promise对象await等到的是一定是一个已…

基于ECC簇内分组密钥管理算法的无线传感器网络matlab性能仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于ECC簇内分组密钥管理算法的无线传感器网络matlab性能仿真&#xff0c;对比网络通信开销&#xff0c;存活节点数量&#xff0c;网络能耗以及数据通信量四个指标…

springboot项目使用cxf框架开发webservice接口,常用注解

在 Spring Boot 项目中使用 Apache CXF 框架开发 WebService 接口时&#xff0c;常用的注解主要有以下几种&#xff1a; WebService&#xff1a;用于标注一个类为 WebService 接口。通常用于定义服务端接口。 import javax.jws.WebService;WebService public interface MyWebSe…

近万字深入讲解iOS常见锁及线程安全

什么是锁&#xff1f; 在程序中&#xff0c;当多个任务&#xff08;或线程&#xff09;同时访问同一个资源时&#xff0c;比如多个操作同时修改一份数据&#xff0c;可能会导致数据不一致。这时候&#xff0c;我们需要“锁”来确保同一时间只有一个任务能够操作这个数据&#…

“避开死锁泥潭:开发者必知的技巧与工具“

“欲买桂花同载酒&#xff0c;终不似、少年游。” 在之前的有一期中&#xff0c;我谈到了关于“线程安全的问题”&#xff0c;那么在线程安全问题中&#xff0c;讲到了 synchronized 关键字&#xff0c;对于 synchronized 关键字的使用&#xff0c;是一定要特别注意的。因为如果…

开源 AI 智能名片与 S2B2C 商城小程序:嫁接权威实现信任与增长

摘要&#xff1a;本文探讨了嫁接权威在产品营销中的重要性&#xff0c;并结合开源 AI 智能名片与 S2B2C 商城小程序&#xff0c;阐述了如何通过与权威关联来建立客户信任&#xff0c;提升产品竞争力。强调了在当今商业环境中&#xff0c;巧妙运用嫁接权威的方法&#xff0c;能够…