BERT:BidirectionalEncoderRepresentations fromTransformers代码及数据解读

news2024/11/25 2:53:31

论文地址

写在前面

由于官网给的是TensorFlow版本的,github也有pytorch版本,但是给出的pytorch的代码是需要根据实际情况进行修改的。

词表文件vocab.txt文件读取的问题

vocab.py代码的class WordVocab(Vocab)类中的def load_vocab(vocab_path)函数为:

def load_vocab(vocab_path):
	with open(vocab_path, 'rb') as f:
		return pickle.load(f)

因为在HuggingFace上下载的词表文件是vocab.txt,这里读取的话会有报错:

_pickle.UnpicklingError: invalid load key, '['

所以需要进行如下修改

@staticmethod
def convert_to_unicode(text):
	if isinstance(text, str):
		return text
	elif isinstance(text, bytes):
		return text.decode("uft-8", "ignore")
	else:
		raise ValueError("不支持的数据类型")

@staticmethod
def load_vocab(vocab):
	vocab = collections.OrderedDict()
	index = 0
	with open(vocab_path, 'rb') as f:
		while True:
			token = conver_to_unicode(f.readline())
			if not token:
				break
			token = token.strip()
			vocab[token] = index
			index += 1
	return WordVocab(vocab)

这里用递归返回,把HuggingFace的词表文件读取到WordVocab中,通过WordVocab.stoi调用,这里的词表顺序不再是vocab.txt中的顺序,会有些许差别。

数据准备

1. vocab.txt

HuggingFace的上下载的词表文件,形如下图:
在这里插入图片描述
然后再vocab.py中转换成字典,其中的顺序可能会有些许不同,可以通过如下代码调用这个转换后的字典

vocab = WordVocab("vocab.txt")
print(vocab.stoi)

输出如下:
在这里插入图片描述

2. training_dataset

数据处理部分在dataset.py中,实际上的读取为:

class BERTDataset(Dataset):
	def __init__(self, corpus_path, corpus_lines, encoding="uft-8", ...):
		with open(corpus_path, "r", encoding=encoding) as f:
			self.lines = [line[:-1].split("\t") for line in tqdm.tqdm(f, desc="Loading Dataset", total=corpus_lines)]

	def get_corpus_line(self, item):
		return self.lines[item][0], self.lines[item][1]

上面代码中的 def get_corpus_line就是实际上读取代码,这里的item就是DataLoader循环的次数,固定参数,不用管,需要注意的是后面的索引值,这也就意味着:

  • 自己的数据必须要有且有两个维度,才能保证self.lines[item][0], self.lines[item][1]
  • 如果自己数据有多个维度,一定要考虑问答在哪个维度上

举例子解释:

  • 逐维度读取的文本为:“龟甲缚如何打绳结?\t”
  • 去掉首位的操作符: “龟甲缚如何打绳结?”
  • 在vocab.stoi查询排序值,把[“龟”, “甲”, “缚”, “如”, “何”, “打”, “绳”, “结”,“?”]转换成[20993, 17510, 18361, 14965, 13865, 15804, 18336, 18312]

如何称之为Masked Language Model?

说起来就是一个很简单的事情,就是把读取的文本,进行遮罩!
具体方法为:

    def random_word(self, sentence):
        tokens = sentence.split()
        output_label = []

        for i, token in enumerate(tokens):
            prob = random.random()
            if prob < 0.15:
                # 有15%的概率执行这里
                prob /= 0.15

                # 80% randomly change token to mask token
                # 15%的执行概率中,有80%的概率执行这里,也就是12%的概率执行这里
                if prob < 0.8:
                    # 这里才是核心,就是12%的概率执行这里
                    # 也就是说,有12%的词会被遮罩(mask),这里就是把词的代号换成了self.vocab.mask_index(就是4)
                    tokens[i] = self.vocab.mask_index

                # 10% randomly change token to random token
                # 15%的执行概率中,有10%的概率执行这里,也就是1.5%的概率执行这里
                elif prob < 0.9:
                    # 也就是有1.5%的词被随机替换成任意值,可能是起始符、终止符 、遮罩符、任意文字等
                    tokens[i] = random.randrange(len(self.vocab))

                # 10% randomly change token to current token
                # 15%的执行概率中,有10%的概率执行这里,也就是1.5%的概率执行这里
                else:
                    # 也就是有1.5%的概率随机抹除这个文字,设置为未知, unknown
                    tokens[i] = self.vocab.stoi.get(token, self.vocab.unk_index)

                output_label.append(self.vocab.stoi.get(token, self.vocab.unk_index))

            else:
                # 有85%的概率执行这里

                # 在vocab.py中把句子中的词转换成了词和排序值对应的字典
                # 这里把token对应的排序值抽出来,如果没有对应的键(词语),那么就返回self.vocab.unk_index
                tokens[i] = self.vocab.stoi.get(token, self.vocab.unk_index)
                output_label.append(0)

具体效果就是:

  • 输入文本为:[“龟”, “甲”, “缚”, “如”, “何”, “打”, “绳”, “结”,“?”] ===> [20993, 17510, 18361, 14965, 13865, 15804, 18336, 18312]
  • 12 % 12\% 12%的词汇会被替换成mask: [xxx, “甲”, “缚”, “如”, “何”, “打”, “绳”, “结”,“?”] [4, 17510, 18361, 14965, 13865, 15804, 18336, 18312]
  • 1.5 % 1.5\% 1.5%的词汇会被替换成一个词表中的随机词:[“@”, “甲”, “缚”, “如”, “何”, “打”, “绳”, “结”,“?”] ===> [21059, 17510, 18361, 14965, 13865, 15804, 18336, 18312]
  • 1.5 % 1.5\% 1.5%的词汇会被随机替换成一个未知(未知有自己的索引)[unknown, “甲”, “缚”, “如”, “何”, “打”, “绳”, “结”,“?”] ===> [1, 17510, 18361, 14965, 13865, 15804, 18336, 18312]
  • 在这句话上添加开始和结束符,[sos, “龟”, “甲”, “缚”, “如”, “何”, “打”, “绳”, “结”,“?”, eos] ===> [3, 20993, 17510, 18361, 14965, 13865, 15804, 18336, 18312, 2]
  • pad_index = 0
  • unk_index = 1
  • eos_index = 2
  • sos_index = 3
  • mask_index = 4

这里有另一个问题了,文档不似图片,尺寸是固定的,这里如何保证NLP的输入是具有固定尺寸的呢?

答案很简单,就是截断padding,就是太长了我就给他剪短,太短了我就给他补长, 最终得到一个固定长度为seq_len的数字列表。

  • seq_len=16
  • pad_index = 0
    [sos, “龟”, “甲”, “缚”, “如”, “何”, “打”, “绳”, “结”,“?”, eos] ===> [3, 20993, 17510, 18361, 14965, 13865, 15804, 18336, 18312, 2, 0, 0, 0, 0, 0, 0]

于是,我们就得到了可以直接输入嵌入层的数据[3, 20993, 17510, 18361, 14965, 13865, 15804, 18336, 18312, 2, 0, 0, 0, 0, 0, 0],其意思就是[sos, “龟”, “甲”, “缚”, “如”, “何”, “打”, “绳”, “结”,“?”, eos]

如何嵌入?

self.token = TokenEmbedding(vocab_size=vocab_size, embed_size=embed_size)
self.position = PositionalEmbedding(d_model=self.token.embedding_dim)
self.segment = SegmentEmbedding(embed_size=self.token.embedding_dim)
x = self.token(sequence) + self.position(sequence) + self.segment(segment_label)

第一个,TokenEmbedding作用就是把 [ b a t c h , v o c a b _ s i z e ] [batch, vocab\_size] [batch,vocab_size]的向量,嵌入成 [ b a t c h , v o c a b _ s i z e , e m b e d _ s i z e ] [batch, vocab\_size, embed\_size] [batch,vocab_size,embed_size]的嵌入向量,例如:

[“龟”, “甲”, “缚”, “如”, “何”, “打”, “绳”, “结”,“?”] ===> [3, 20993, 17510, 18361, 14965, 13865, 15804, 18336, 18312, 2, 0, 0, 0, 0, 0, 0] ===> [ b a t c h = 1 , 16 , e m b e d _ s i z e = 512 ] [batch=1, \quad 16, \quad embed\_size=512] [batch=1,16,embed_size=512]
意思就是把上面那16个向量,每个都用512维度的向量进行表示,构成 b a t c h × 16 × 512 batch \times16\times512 batch×16×512 的向量

第二个,PositionalEmbedding位置向量,可以参考
Transformer之位置编码的通俗理解

Bert代码结构?

Bert的核心在上面的红色标题:如何称之为Masked Language Model?,具体的网络结构和代码结构没有难点,就一个12层Transformer,毫无画图的必要

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2045746.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

看看人家都用树莓派5做了什么产品?

文章作者&#xff1a; Aleksandar Dakić 原文地址&#xff1a; https://magazinmehatronika.com/edatec-ed-hmi3020-070c-hmi-recenzija/ Aleksandar Dakić《机电一体化》的杂志主编&#xff0c;同时Aleksandar 也是《机电一体化》杂志的创始人。拥有电气工程背景&#x…

MySQL的安装及配置远程链接(WindowsLinux下安装)

一.Windows下安装 在Windows下安装MySQL需要先去官网下载一下安装包 1. 官网下载地址&#xff1a;www.mysql.com 2、选择下载 往下滑选择MySQL 社区 &#xff08;GPL&#xff09; 下载 3、选择社区版适配Windows系统 MySQL Installer for Windows 4、选择本地安装版本 my…

十五年以来 — 战略性云平台服务的演进路径之全面呈现(含亚马逊、微软和谷歌)

Gartner每年都发布对全球IaaS平台进行评估的魔力象限报告。2023年底&#xff0c;Gartner将此项评估的名称改为“战略性云平台服务”&#xff08;Strategic cloud platform services&#xff09;&#xff0c;尽管其核心仍为IaaS&#xff0c;但是&#xff0c;毫无疑问&#xff0c…

算法工程师必知必会的数学基础之微积分下篇

系列文章&#xff1a; 第一篇&#xff1a;算法工程师必知必会的数学基础之线性代数第二篇&#xff1a;算法工程师必知必会的数学基础之微积分上篇第三篇&#xff1a;算法工程师必知必会的数学基础之微积分下篇&#xff08;本文&#xff09; 文章目录 2. 微积分2.7 泰勒级数&am…

【大模型从入门到精通24】开源库框架LangChain Embedding的力量1

这里写目录标题 嵌入的力量什么是嵌入&#xff1f;创建嵌入的详细过程嵌入在语义搜索中的应用向量存储&#xff1a;相似向量的有效检索关键特性与操作选择向量存储的标准示例&#xff1a;Chroma 适用于快速原型开发和小型数据集结论 嵌入的力量 什么是嵌入&#xff1f; 嵌入是…

通过CLIP引导解码减轻大型视觉-语言模型中的幻觉问题

人工智能咨询培训老师叶梓 转载标明出处 大型视觉-语言模型&#xff08;LVLMs&#xff09;因其在视觉推理方面的能力而备受瞩目&#xff0c;被视为实现自主操作智能体的重要里程碑。但它在生成文本时容易出现对象幻觉问题&#xff0c;即描述中包含不存在的对象&#xff0c;这严…

一文带你入门大模型微调

大模型相关目录 大模型&#xff0c;包括部署微调prompt/Agent应用开发、知识库增强、数据库增强、知识图谱增强、自然语言处理、多模态等大模型应用开发内容 从0起步&#xff0c;扬帆起航。 swift与Internvl下的多模态大模型分布式微调指南&#xff08;附代码和数据&#xff…

MTK 相机功耗拆解方法

和你一起终身学习&#xff0c;这里是程序员Android 经典好文推荐&#xff0c;通过阅读本文&#xff0c;您将收获以下知识点: 一、硬件功耗二、相机软件功耗三、参考文档 一、硬件功耗 1.1 硬件信息 以下硬件信息最好提前获取到 模块备注平台MTK or Qcom or sprdCPU频率大中小核…

【Qt开发】事件与信号/事件过滤器

事件与信号/事件过滤器 事件一、事件的产生二、事件的派发三、事件类和事件类型四、事件的处理 事件与信号事件过滤器 事件 Qt系统的图形化窗口是由事件驱动的。&#xff0c;点击鼠标、按键&#xff0c;改变窗口大小、最小化窗口、关闭窗口等都会产生相应的事件。 QWidget类的所…

shuashuashua

CVE-2023-2130 靶标介绍&#xff1a; 在SourceCodester采购订单管理系统1.0中发现了一项被分类为关键的漏洞。受影响的是组件GET参数处理器的文件/admin/suppliers/view_details.php中的一个未知函数。对参数id的操纵导致了SQL注入。可以远程发起攻击。 通过标靶介绍可以知道…

通过域名和HTTPS上线MSF

使用受信任证书的Meterpreter载荷 现在大多数安全解决方案还会通过分析进出目标机器的流量来进行网络入侵检测。在这种情况下&#xff0c;很可能即使使用编码器绕过了防病毒软件&#xff0c;但有效载荷也会在尝试连接到我们的侦听器时被捕获和拦截。 # 准备工作 首先需要准备…

FPGA开发——UART回环实现之接收模块的设计

一、简介 因为我们本次进行串口回环的实验的对象是FPGA开发板和PC端&#xff0c;所以在接收和发送模块中先编写接收模块&#xff0c;这样可以在后面更好的进行发送模块的验证。&#xff08;其实这里先编写哪个模块&#xff09;都不影响&#xff0c;这里看自己心情&#xff0c;反…

大语言模型微调框架Unsloth:简化模型微调流程,提升模型性能

Unsloth 将 Llama-3、Mistral、Phi-3 和 Gemma 等大型语言模型的微调速度提高了 2 倍&#xff0c;内存使用量减少了 70%&#xff0c;而且准确性不会降低&#xff01; 特点 通过手动派生所有计算繁重的数学步骤和手写 GPU 内核&#xff0c;unsloth 可以在不更改任何硬件的情况…

IMU助力跑步参数评估

近期&#xff0c;中国研究团队开发了一种创新的跑步参数评估方法&#xff0c;巧妙结合了IMU和多模态神经网络技术&#xff0c;旨在深入研究并有效评估跑步时的步态参数。 科研团队采用IMU传感器&#xff0c;将其固定在跑者的脚踝处&#xff0c;以实时监测并记录跑步时脚踝的加速…

如何利用RPA自动化流程机器人优化企业财务流程

随着企业规模的扩大和业务的复杂性增加&#xff0c;财务流程管理成了一个关键而复杂的任务。传统的财务流程往往涉及大量的重复性、繁琐的工作&#xff0c;不仅效率低下&#xff0c;而且容易出错。为了解决这些问题&#xff0c;越来越多的企业开始引入RPA机器人流程自动化来优化…

JAVA集中学习第五周学习记录(二)

系列文章目录 第一章 JAVA集中学习第一周学习记录(一) 第二章 JAVA集中学习第一周项目实践 第三章 JAVA集中学习第一周学习记录(二) 第四章 JAVA集中学习第一周课后习题 第五章 JAVA集中学习第二周学习记录(一) 第六章 JAVA集中学习第二周项目实践 第七章 JAVA集中学习第二周学…

打开Office(word、excel、ppt)显示操作系统当前的配置不能运行此应用程序最全解决方案!

我以前用过分区助手把office从c盘挪到d盘了&#xff0c;从那以后office就用不了了&#xff0c;然后我就删了&#xff08;貌似没删干净&#xff09;。 最近由于有使用word的需求&#xff0c;所以我从学校官网找到正版软件的安装包&#xff0c;按照步骤重新卸载电脑中office残留…

基于Java的民宿管理系统

TOC springboot306基于Java的民宿管理系统 第1章 绪论 1.1选题动因 当前的网络技术&#xff0c;软件技术等都具备成熟的理论基础&#xff0c;市场上也出现各种技术开发的软件&#xff0c;这些软件都被用于各个领域&#xff0c;包括生活和工作的领域。随着电脑和笔记本的广泛…

【Mac】Downie 打开提示试用的解决办法?

前情 我们在使用 Downie 的时候&#xff0c;可能遇到提示试用的问题&#xff0c;如下图所示。 原因 旧版本的 Downie 没有卸载干净导致的。 解决办法 先使用 AppCleaner 卸载掉电脑上的 Downie 旧版本软件&#xff0c;必须使用 AppCleaner 卸载。重新安装 Downie 即可。

DNN代码实战

DNN的原理 神经网络通过学习大量样本的输入与输出特征之间的关系&#xff0c;以拟合出输入与输出之间的方程&#xff0c;学习完成后&#xff0c;只给它输入特征&#xff0c;它便会可以给出输出特征。神经网络可以分为这么几步&#xff1a;划分数据集、训练网络、测试网络、使用…