当前位置: 首页 > news >正文

临潼区建设局网站工程建设信息网站

临潼区建设局网站,工程建设信息网站,正能量网站入口不用下载,帮别人做网站必须要开公司目录 #x1f354; 编码器介绍 #x1f354; 掩码张量 2.1 掩码张量介绍 2.2 掩码张量的作用 2.3 生成掩码张量的代码分析 2.4 掩码张量的可视化 2.5 掩码张量总结 #x1f354; 注意力机制 3.1 注意力计算规则的代码分析 3.2 带有mask的输入参数#xff1a; 3.…  目录 编码器介绍 掩码张量 2.1 掩码张量介绍 2.2 掩码张量的作用 2.3 生成掩码张量的代码分析 2.4 掩码张量的可视化 2.5 掩码张量总结 注意力机制 3.1 注意力计算规则的代码分析 3.2 带有mask的输入参数 3.3 注意力机制总结 多头注意力机制 4.1 多头注意力机制概念 4.2 多头注意力机制结构图 4.3 多头注意力机制的作用 4.4 多头注意力机制的代码实现 4.5 多头注意力机制总结 学习目标 了解编码器中各个组成部分的作用. 掌握编码器中各个组成部分的实现过程. 编码器介绍 编码器部分: * 由N个编码器层堆叠而成 * 每个编码器层由两个子层连接结构组成 * 第一个子层连接结构包括一个多头自注意力子层和规范化层以及一个残差连接 * 第二个子层连接结构包括一个前馈全连接子层和规范化层以及一个残差连接 掩码张量 2.1 掩码张量介绍 掩代表遮掩码就是我们张量中的数值它的尺寸不定里面一般只有1和0的元素代表位置被遮掩或者不被遮掩至于是0位置被遮掩还是1位置被遮掩可以自定义因此它的作用就是让另外一个张量中的一些数值被遮掩也可以说被替换, 它的表现形式是一个张量. 2.2 掩码张量的作用 在transformer中, 掩码张量的主要作用在应用attention(将在下一小节讲解)时有一些生成的attention张量中的值计算有可能已知了未来信息而得到的未来信息被看到是因为训练时会把整个输出结果都一次性进行Embedding但是理论上解码器的的输出却不是一次就能产生最终结果的而是一次次通过上一次结果综合得出的因此未来的信息可能被提前利用. 所以我们会进行遮掩. 关于解码器的有关知识将在后面的章节中讲解. 2.3 生成掩码张量的代码分析 def subsequent_mask(size):生成向后遮掩的掩码张量, 参数size是掩码张量最后两个维度的大小, 它的最后两维形成一个方阵# 在函数中, 首先定义掩码张量的形状attn_shape (1, size, size)# 然后使用np.ones方法向这个形状中添加1元素,形成上三角阵, 最后为了节约空间, # 再使其中的数据类型变为无符号8位整形unit8 subsequent_mask np.triu(np.ones(attn_shape), k1).astype(uint8)# 最后将numpy类型转化为torch中的tensor, 内部做一个1 - 的操作, # 在这个其实是做了一个三角阵的反转, subsequent_mask中的每个元素都会被1减, # 如果是0, subsequent_mask中的该位置由0变成1# 如果是1, subsequent_mask中的该位置由1变成0 return torch.from_numpy(1 - subsequent_mask)np.triu演示: np.triu([[1,2,3],[4,5,6],[7,8,9],[10,11,12]], k-1) array([[ 1, 2, 3],[ 4, 5, 6],[ 0, 8, 9],[ 0, 0, 12]]) np.triu([[1,2,3],[4,5,6],[7,8,9],[10,11,12]], k0) array([[ 1, 2, 3],[ 0, 5, 6],[ 0, 0, 9],[ 0, 0, 0]]) np.triu([[1,2,3],[4,5,6],[7,8,9],[10,11,12]], k1) array([[ 0, 2, 3],[ 0, 0, 6],[ 0, 0, 0],[ 0, 0, 0]])输入实例: # 生成的掩码张量的最后两维的大小 size 5调用: sm subsequent_mask(size) print(sm:, sm)输出效果: # 最后两维形成一个下三角阵 sm: (0 ,.,.) 1 0 0 0 01 1 0 0 01 1 1 0 01 1 1 1 01 1 1 1 1 [torch.ByteTensor of size 1x5x5]2.4 掩码张量的可视化 plt.figure(figsize(5,5)) plt.imshow(subsequent_mask(20)[0])输出效果: 效果分析:通过观察可视化方阵, 黄色是1的部分, 这里代表被遮掩, 紫色代表没有被遮掩的信息, 横坐标代表目标词汇的位置, 纵坐标代表可查看的位置;我们看到, 在0的位置我们一看望过去都是黄色的, 都被遮住了1的位置一眼望过去还是黄色, 说明第一次词还没有产生, 从第二个位置看过去, 就能看到位置1的词, 其他位置看不到, 以此类推. 2.5 掩码张量总结 学习了什么是掩码张量: 掩代表遮掩码就是我们张量中的数值它的尺寸不定里面一般只有1和0的元素代表位置被遮掩或者不被遮掩至于是0位置被遮掩还是1位置被遮掩可以自定义因此它的作用就是让另外一个张量中的一些数值被遮掩, 也可以说被替换, 它的表现形式是一个张量. 学习了掩码张量的作用: 在transformer中, 掩码张量的主要作用在应用attention(将在下一小节讲解)时有一些生成的attetion张量中的值计算有可能已知量未来信息而得到的未来信息被看到是因为训练时会把整个输出结果都一次性进行Embedding但是理论上解码器的的输出却不是一次就能产生最终结果的而是一次次通过上一次结果综合得出的因此未来的信息可能被提前利用. 所以我们会进行遮掩. 关于解码器的有关知识将在后面的章节中讲解. 学习并实现了生成向后遮掩的掩码张量函数: subsequent_mask 它的输入是size, 代表掩码张量的大小.它的输出是一个最后两维形成1方阵的下三角阵.最后对生成的掩码张量进行了可视化分析, 更深一步理解了它的用途. 注意力机制 我们这里使用的注意力的计算规则: 3.1 注意力计算规则的代码分析 import torch.nn.functional as Fdef attention(query, key, value, maskNone, dropoutNone):注意力机制的实现, 输入分别是query, key, value, mask: 掩码张量, dropout是nn.Dropout层的实例化对象, 默认为None# 在函数中, 首先取query的最后一维的大小, 一般情况下就等同于我们的词嵌入维度, 命名为d_kd_k query.size(-1)# 按照注意力公式, 将query与key的转置相乘, 这里面key是将最后两个维度进行转置, 再除以缩放系数根号下d_k, 这种计算方法也称为缩放点积注意力计算.# 得到注意力得分张量scoresscores torch.matmul(query, key.transpose(-2, -1)) / math.sqrt(d_k)# 接着判断是否使用掩码张量if mask is not None:# 使用tensor的masked_fill方法, 将掩码张量和scores张量每个位置一一比较, 如果掩码张量处为0# 则对应的scores张量用-1e9这个值来替换, 如下演示scores scores.masked_fill(mask 0, -1e9)# 对scores的最后一维进行softmax操作, 使用F.softmax方法, 第一个参数是softmax对象, 第二个是目标维度.# 这样获得最终的注意力张量p_attn F.softmax(scores, dim -1)# 之后判断是否使用dropout进行随机置0if dropout is not None:# 将p_attn传入dropout对象中进行丢弃处理p_attn dropout(p_attn)# 最后, 根据公式将p_attn与value张量相乘获得最终的query注意力表示, 同时返回注意力张量return torch.matmul(p_attn, value), p_attntensor.masked_fill演示: input Variable(torch.randn(5, 5))input Variable containing:2.0344 -0.5450 0.3365 -0.1888 -2.18031.5221 -0.3823 0.8414 0.7836 -0.8481 -0.0345 -0.8643 0.6476 -0.2713 1.56450.8788 -2.2142 0.4022 0.1997 0.14742.9109 0.6006 -0.6745 -1.7262 0.6977 [torch.FloatTensor of size 5x5] mask Variable(torch.zeros(5, 5))mask Variable containing:0 0 0 0 00 0 0 0 00 0 0 0 00 0 0 0 00 0 0 0 0 [torch.FloatTensor of size 5x5] input.masked_fill(mask 0, -1e9) Variable containing: -1.0000e09 -1.0000e09 -1.0000e09 -1.0000e09 -1.0000e09 -1.0000e09 -1.0000e09 -1.0000e09 -1.0000e09 -1.0000e09 -1.0000e09 -1.0000e09 -1.0000e09 -1.0000e09 -1.0000e09 -1.0000e09 -1.0000e09 -1.0000e09 -1.0000e09 -1.0000e09 -1.0000e09 -1.0000e09 -1.0000e09 -1.0000e09 -1.0000e09 [torch.FloatTensor of size 5x5]输入参数: # 我们令输入的query, key, value都相同, 位置编码的输出 query key value pe_result Variable containing: ( 0 ,.,.) 46.5196 16.2057 -41.5581 ... -16.0242 -17.8929 -43.0405-32.6040 16.1096 -29.5228 ... 4.2721 20.6034 -1.2747-18.6235 14.5076 -2.0105 ... 15.6462 -24.6081 -30.33910.0000 -66.1486 -11.5123 ... 20.1519 -4.6823 0.4916( 1 ,.,.) -24.8681 7.5495 -5.0765 ... -7.5992 -26.6630 40.951713.1581 -3.1918 -30.9001 ... 25.1187 -26.4621 2.9542-49.7690 -42.5019 8.0198 ... -5.4809 25.9403 -27.4931-52.2775 10.4006 0.0000 ... -1.9985 7.0106 -0.5189 [torch.FloatTensor of size 2x4x512]调用: attn, p_attn attention(query, key, value) print(attn:, attn) print(p_attn:, p_attn)输出效果: # 将得到两个结果 # query的注意力表示: attn: Variable containing: ( 0 ,.,.) 12.8269 7.7403 41.2225 ... 1.4603 27.8559 -12.260012.4904 0.0000 24.1575 ... 0.0000 2.5838 18.0647-32.5959 -4.6252 -29.1050 ... 0.0000 -22.6409 -11.83418.9921 -33.0114 -0.7393 ... 4.7871 -5.7735 8.3374( 1 ,.,.) -25.6705 -4.0860 -36.8226 ... 37.2346 -27.3576 2.5497-16.6674 73.9788 -33.3296 ... 28.5028 -5.5488 -13.75640.0000 -29.9039 -3.0405 ... 0.0000 14.4408 14.857930.7819 0.0000 21.3908 ... -29.0746 0.0000 -5.8475 [torch.FloatTensor of size 2x4x512]# 注意力张量: p_attn: Variable containing: (0 ,.,.) 1 0 0 00 1 0 00 0 1 00 0 0 1(1 ,.,.) 1 0 0 00 1 0 00 0 1 00 0 0 1 [torch.FloatTensor of size 2x4x4]3.2 带有mask的输入参数 query key value pe_result# 令mask为一个2x4x4的零张量 mask Variable(torch.zeros(2, 4, 4))调用: attn, p_attn attention(query, key, value, maskmask) print(attn:, attn) print(p_attn:, p_attn)带有mask的输出效果: # query的注意力表示: attn: Variable containing: ( 0 ,.,.) 0.4284 -7.4741 8.8839 ... 1.5618 0.5063 0.57700.4284 -7.4741 8.8839 ... 1.5618 0.5063 0.57700.4284 -7.4741 8.8839 ... 1.5618 0.5063 0.57700.4284 -7.4741 8.8839 ... 1.5618 0.5063 0.5770( 1 ,.,.) -2.8890 9.9972 -12.9505 ... 9.1657 -4.6164 -0.5491-2.8890 9.9972 -12.9505 ... 9.1657 -4.6164 -0.5491-2.8890 9.9972 -12.9505 ... 9.1657 -4.6164 -0.5491-2.8890 9.9972 -12.9505 ... 9.1657 -4.6164 -0.5491 [torch.FloatTensor of size 2x4x512]# 注意力张量: p_attn: Variable containing: (0 ,.,.) 0.2500 0.2500 0.2500 0.25000.2500 0.2500 0.2500 0.25000.2500 0.2500 0.2500 0.25000.2500 0.2500 0.2500 0.2500(1 ,.,.) 0.2500 0.2500 0.2500 0.25000.2500 0.2500 0.2500 0.25000.2500 0.2500 0.2500 0.25000.2500 0.2500 0.2500 0.2500 [torch.FloatTensor of size 2x4x4]3.3 注意力机制总结 学习并实现了注意力计算规则的函数: attention 它的输入就是QKV以及mask和dropout, mask用于掩码, dropout用于随机置0.它的输出有两个, query的注意力表示以及注意力张量. 多头注意力机制 4.1 多头注意力机制概念 从多头注意力的结构图中貌似这个所谓的多个头就是指多组线性变换层其实并不是我只有使用了一组线性变化层即三个变换张量对QKV分别进行线性变换这些变换不会改变原有张量的尺寸因此每个变换矩阵都是方阵得到输出结果后多头的作用才开始显现每个头开始从词义层面分割输出的张量也就是每个头都想获得一组QKV进行注意力机制的计算但是句子中的每个词的表示只获得一部分也就是只分割了最后一维的词嵌入向量. 这就是所谓的多头将每个头的获得的输入送到注意力机制中, 就形成多头注意力机制. 4.2 多头注意力机制结构图 4.3 多头注意力机制的作用 这种结构设计能让每个注意力机制去优化每个词汇的不同特征部分从而均衡同一种注意力机制可能产生的偏差让词义拥有来自更多元的表达实验表明可以从而提升模型效果. 4.4 多头注意力机制的代码实现 # 用于深度拷贝的copy工具包 import copy# 首先需要定义克隆函数, 因为在多头注意力机制的实现中, 用到多个结构相同的线性层. # 我们将使用clone函数将他们一同初始化在一个网络层列表对象中. 之后的结构中也会用到该函数. def clones(module, N):用于生成相同网络层的克隆函数, 它的参数module表示要克隆的目标网络层, N代表需要克隆的数量# 在函数中, 我们通过for循环对module进行N次深度拷贝, 使其每个module成为独立的层,# 然后将其放在nn.ModuleList类型的列表中存放.return nn.ModuleList([copy.deepcopy(module) for _ in range(N)])# 我们使用一个类来实现多头注意力机制的处理 class MultiHeadedAttention(nn.Module):def __init__(self, head, embedding_dim, dropout0.1):在类的初始化时, 会传入三个参数head代表头数embedding_dim代表词嵌入的维度 dropout代表进行dropout操作时置0比率默认是0.1.super(MultiHeadedAttention, self).__init__()# 在函数中首先使用了一个测试中常用的assert语句判断h是否能被d_model整除# 这是因为我们之后要给每个头分配等量的词特征.也就是embedding_dim/head个.assert embedding_dim % head 0# 得到每个头获得的分割词向量维度d_kself.d_k embedding_dim // head# 传入头数hself.head head# 然后获得线性层对象通过nn的Linear实例化它的内部变换矩阵是embedding_dim x embedding_dim然后使用clones函数克隆四个# 为什么是四个呢这是因为在多头注意力中QKV各需要一个最后拼接的矩阵还需要一个因此一共是四个.self.linears clones(nn.Linear(embedding_dim, embedding_dim), 4)# self.attn为None它代表最后得到的注意力张量现在还没有结果所以为None.self.attn None# 最后就是一个self.dropout对象它通过nn中的Dropout实例化而来置0比率为传进来的参数dropout.self.dropout nn.Dropout(pdropout)def forward(self, query, key, value, maskNone):前向逻辑函数, 它的输入参数有四个前三个就是注意力机制需要的Q, K, V最后一个是注意力机制中可能需要的mask掩码张量默认是None. # 如果存在掩码张量maskif mask is not None:# 使用unsqueeze拓展维度mask mask.unsqueeze(0)# 接着我们获得一个batch_size的变量他是query尺寸的第1个数字代表有多少条样本.batch_size query.size(0)# 之后就进入多头处理环节# 首先利用zip将输入QKV与三个线性层组到一起然后使用for循环将输入QKV分别传到线性层中# 做完线性变换后开始为每个头分割输入这里使用view方法对线性变换的结果进行维度重塑多加了一个维度h代表头数# 这样就意味着每个头可以获得一部分词特征组成的句子其中的-1代表自适应维度# 计算机会根据这种变换自动计算这里的值.然后对第二维和第三维进行转置操作# 为了让代表句子长度维度和词向量维度能够相邻这样注意力机制才能找到词义与句子位置的关系# 从attention函数中可以看到利用的是原始输入的倒数第一和第二维.这样我们就得到了每个头的输入.query, key, value \[model(x).view(batch_size, -1, self.head, self.d_k).transpose(1, 2)for model, x in zip(self.linears, (query, key, value))]# 得到每个头的输入后接下来就是将他们传入到attention中# 这里直接调用我们之前实现的attention函数.同时也将mask和dropout传入其中.x, self.attn attention(query, key, value, maskmask, dropoutself.dropout)# 通过多头注意力计算后我们就得到了每个头计算结果组成的4维张量我们需要将其转换为输入的形状以方便后续的计算# 因此这里开始进行第一步处理环节的逆操作先对第二和第三维进行转置然后使用contiguous方法# 这个方法的作用就是能够让转置后的张量应用view方法否则将无法直接使用# 所以下一步就是使用view重塑形状变成和输入形状相同.x x.transpose(1, 2).contiguous().view(batch_size, -1, self.head * self.d_k)# 最后使用线性层列表中的最后一个线性层对输入进行线性变换得到最终的多头注意力结构的输出.return self.linears[-1](x)tensor.view演示: x torch.randn(4, 4)x.size() torch.Size([4, 4])y x.view(16)y.size() torch.Size([16])z x.view(-1, 8) # the size -1 is inferred from other dimensionsz.size() torch.Size([2, 8]) a torch.randn(1, 2, 3, 4)a.size() torch.Size([1, 2, 3, 4])b a.transpose(1, 2) # Swaps 2nd and 3rd dimensionb.size() torch.Size([1, 3, 2, 4])c a.view(1, 3, 2, 4) # Does not change tensor layout in memoryc.size() torch.Size([1, 3, 2, 4])torch.equal(b, c) Falsetorch.transpose演示: x torch.randn(2, 3)x tensor([[ 1.0028, -0.9893, 0.5809],[-0.1669, 0.7299, 0.4942]])torch.transpose(x, 0, 1) tensor([[ 1.0028, -0.1669],[-0.9893, 0.7299],[ 0.5809, 0.4942]])实例化参数: # 头数head head 8# 词嵌入维度embedding_dim embedding_dim 512# 置零比率dropout dropout 0.2输入参数: # 假设输入的QKV仍然相等 query value key pe_result# 输入的掩码张量mask mask Variable(torch.zeros(8, 4, 4))调用: mha MultiHeadedAttention(head, embedding_dim, dropout) mha_result mha(query, key, value, mask) print(mha_result)输出效果: tensor([[[-0.3075, 1.5687, -2.5693, ..., -1.1098, 0.0878, -3.3609],[ 3.8065, -2.4538, -0.3708, ..., -1.5205, -1.1488, -1.3984],[ 2.4190, 0.5376, -2.8475, ..., 1.4218, -0.4488, -0.2984],[ 2.9356, 0.3620, -3.8722, ..., -0.7996, 0.1468, 1.0345]],[[ 1.1423, 0.6038, 0.0954, ..., 2.2679, -5.7749, 1.4132],[ 2.4066, -0.2777, 2.8102, ..., 0.1137, -3.9517, -2.9246],[ 5.8201, 1.1534, -1.9191, ..., 0.1410, -7.6110, 1.0046],[ 3.1209, 1.0008, -0.5317, ..., 2.8619, -6.3204, -1.3435]]],grad_fnAddBackward0) torch.Size([2, 4, 512])4.5 多头注意力机制总结 学习了什么是多头注意力机制: 每个头开始从词义层面分割输出的张量也就是每个头都想获得一组QKV进行注意力机制的计算但是句子中的每个词的表示只获得一部分也就是只分割了最后一维的词嵌入向量. 这就是所谓的多头.将每个头的获得的输入送到注意力机制中, 就形成了多头注意力机制. 学习了多头注意力机制的作用: 这种结构设计能让每个注意力机制去优化每个词汇的不同特征部分从而均衡同一种注意力机制可能产生的偏差让词义拥有来自更多元的表达实验表明可以从而提升模型效果. 学习并实现了多头注意力机制的类: MultiHeadedAttention 因为多头注意力机制中需要使用多个相同的线性层, 首先实现了克隆函数clones.clones函数的输入是moduleN分别代表克隆的目标层和克隆个数.clones函数的输出是装有N个克隆层的Module列表.接着实现MultiHeadedAttention类, 它的初始化函数输入是h, d_model, dropout分别代表头数词嵌入维度和置零比率.它的实例化对象输入是Q, K, V以及掩码张量mask.它的实例化对象输出是通过多头注意力机制处理的Q的注意力表示.
http://www.ho-use.cn/article/10820794.html

相关文章:

  • 新乡市做网站免费精准客源
  • 网站正在建设中 英语翻译婚纱网站开发背景
  • 高手优化网站网站中备案与不备案的区别
  • 湖北营销型网站建设价格暴雪代理最新消息
  • 国家外管局网站怎么做收汇电脑设计培训学校推荐
  • 河南商务学校网站建设外贸企业网站源码下载
  • 网站建设明细报价vs2013网站开发教程
  • 手机网站根目录河南建筑网站
  • 上海网站优化上网站建设规划书3000字
  • 做爰 网站贵阳城乡和住房建设厅网站
  • 菏泽网站建设服务wordpress调用媒体图片不同尺寸
  • 男做女爱网站做网站和自媒体哪个好
  • 用vs2010做免费网站模板下载地址网站移动端是什么问题吗
  • 金麦建站官网wordpress seo模板
  • 广西网站建设策划昭阳区住房和城乡建设管理局网站
  • 网站开发文档范例微网站建设包含哪些内容
  • 广元市建设银行网站c2c代表网站
  • 广州机械网站建设外包北京定制网站价格
  • 网站广告怎么放如何优化关键词排名到首页
  • 如何创建博客网站莱芜一中贴吧
  • 网站建设系统 开源商城版网站制作
  • 算卦网站开发网站开发飞沐
  • 无锡企业网站的建设电力公司在哪个网站做推广最好
  • 赣县城乡规划建设局网站wordpress菜单.html
  • wordpress全站模板外贸营销俱乐部
  • 怎么才能提高网站点击量 免费wordpress get_category_parents
  • 花都五屏网站建设php做网站多少钱
  • 网站手机端做app开发公司网站开发 建设
  • 昆明公司网站开发工作室怎么开
  • 网站制作网站建设单位东营网站建设服务电话