做响应式网站的常用尺寸,购物网站开发中遇到的问题,做网站备案需要哪些材料,微网站免费平台本文主要是记录学习bert的pytorch实现代码的一些心得dataset1. vocab继承关系#xff1a;TorchVocab -- Vocab -- WordVocabTorchVocab该类主要是定义了一个词典对象#xff0c;包含如下三个属性#xff1a;freqs#xff1a;是一个collections.Counter对象#xf…本文主要是记录学习bert的pytorch实现代码的一些心得dataset1. vocab继承关系TorchVocab -- Vocab -- WordVocabTorchVocab该类主要是定义了一个词典对象包含如下三个属性freqs是一个collections.Counter对象能够记录数据集中不同token所出现的次数stoi是一个collections.defaultdict对象将数据集中的token映射到不同的indexitos是一个列表保存了从index到token的映射信息代码中sort与sorted的区别sort 是应用在 list 上的方法sorted 可以对所有可迭代的对象进行排序操作。list 的 sort 方法返回的是对已经存在的列表进行操作而内建函数 sorted 方法返回的是一个新的 list而不是在原来的基础上进行的操作。sorted的语法sorted(iterable, keyNone, reverseFalse)iterable -- 可迭代对象。key -- 主要是用来进行比较的元素只有一个参数具体的函数的参数就是取自于可迭代对象中指定可迭代对象中的一个元素来进行排序。reverse -- 排序规则reverse True 降序 reverse False 升序默认。VocabVocab继承TorchVocab该类主要定义了一些特殊token的表示这里用到了一个装饰器简单地说装饰器就是修改其他函数的功能的函数。这里包含了一个序列化的操作WordVocabWordVocab继承自Vocab里面包含了两个方法to_seq和from_seq分别是将token转换成index和将index转换成token表示2. dataset主要实现了一个BERTDataset类继承自torch.utils.data.Dataset里面一些操作都是根据论文中的两种训练模型构建的masked words 和 next sentence predictmodel1. attention这里首先定义了一个单注意力的类然后通过该类叠加构造一个多头注意力的类。矩阵相乘有torch.mm和torch.matmul两个函数。其中前一个是针对二维矩阵后一个是高维。当torch.mm用于大于二维时将报错。masked_filla.masked_fill(mask 0, value) mask必须是一个 ByteTensor 而且shape必须和 a一样 并且元素只能是 0或者1 是将 mask中为1的 元素所在的索引在a中相同的的索引处替换为 value ,mask value必须同为tensor 2. embeddingbert的embedding由三个部分组成TokenEmbedding、PositionalEmbedding、SegmentEmbeddingpytorch中词嵌入使用nn.Embedding只需要调用 torch.nn.Embedding(m, n) 就可以了m 表示单词的总数目n 表示词嵌入的维度其实词嵌入就相当于是一个大矩阵矩阵的每一行表示一个单词默认是随机初始化的不过也可以使用已经训练好的词向量。不理解的话可以自己用简单的例子尝试一下即可这里的位置编码是写死的不会随着训练进行更新这是论文 attention is all you need 中的做法而bert模型的官方TensorFlow源码是将位置编码position embedding直接初始化成可训练的参数并通过训练进行学习的所以此处的实现和bert模型不同import torch.nn as nn
import torch
import mathclass PositionalEmbedding(nn.Module):def __init__(self, d_model, max_len512):super().__init__()# Compute the positional encodings once in log space.pe torch.zeros(max_len, d_model).float()pe.require_grad Falseposition torch.arange(0, max_len).float().unsqueeze(1)div_term (torch.arange(0, d_model, 2).float() * -(math.log(10000.0) / d_model)).exp()pe[:, 0::2] torch.sin(position * div_term)pe[:, 1::2] torch.cos(position * div_term)pe pe.unsqueeze(0)self.register_buffer(pe, pe)def forward(self, x):return self.pe[:, :x.size(1)]代码中对positionembedding的实现一开始看有点懵感觉和原文中的表达式不太一样后来查找资料发现是对原公式做了如下变换:$$ 1/10000^{2i/d_{model}} e^{log{10000^{-2i/d_{model}}}} e^{-2i/d_{model}log{10000}} e^{2i(-log^{10000}/d_{model})} $$这样一来便和代码中的实现一致了为什么要这么做代码注释中说这样可以使用log空间一次性计算position embedding即能够节省一定的内存开销3. utils这部分主要是实现了模型中的一些组件FNN,gelu激励函数layernorm正则化以及sublayer连接理论部分论文中都介绍得很详细可以结合论文原文学习这部分的实现应该比较好理解bert语言模型构建接下来就是bert模型的具体实现了首先是构造transformer block。然后组成bert模型这里要复习一下repeat()方法torch.Tensor有两个实例方法可以用来扩展某维的数据的尺寸分别是repeat()和expand()expand()方法返回当前张量在某维扩展更大后的张量。扩展expand张量不会分配新的内存只是在存在的张量上创建一个新的视图view一个大小size等于1的维度扩展到更大的尺寸。repeat()方法沿着特定的维度重复这个张量和expand()不同的是这个函数拷贝张量的数据而不是在原来的张量上修改。trainer主要设置了optim以及封装了训练迭代的操作