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

【Transformer框架代码实现】

Transformer

    • Transformer框架
    • 注意力机制框架
    • 导入必要的库
    • Input Embedding / Out Embedding
    • Positional Embedding
    • Transformer Embedding
    • ScaleDotProductAttention(self-attention)
    • MultiHeadAttention 多头注意力机制
    • EncoderLayer 编码层
    • Encoder多层编码块/前馈网络层
    • DecoderLayer解码层
    • Decoder多层解码块
    • MyTransformer实现完整的Transformer框架

Transformer框架

在这里插入图片描述

注意力机制框架

在这里插入图片描述

导入必要的库

from torch import nn
import torch
import math
import torch.nn.functional as F

Input Embedding / Out Embedding

词嵌入层的实现
nn.Embedding(vocab_size, embed_dim)中
vocab_size: 词典长度,必须大于输入的单词总量
embed_dim:词向量维度

class TokenEmbedding(nn.Module):def __init__(self, vocab_size, embed_dim):""":param vocab_size: 词典长度/维度/图片size(0)  必须大于输入的单词总量. batch_size=句子数量:param embed_dim: 词向量维度"""super(TokenEmbedding, self).__init__()self.embed_dim = embed_dimself.embedding = nn.Embedding(vocab_size, embed_dim)def forward(self, x):# 对原始向量进行缩放,出自论文# [batch_size, vocab_size, embed_dim]return self.embedding(x.long()) * math.sqrt(self.embed_dim)

Positional Embedding

位置编码层的实现
与RNN不同,对于给定输入input = “I am fine”,RNN中会顺序读入每个单词,而在Transformer中则是所有单词同时读入,因此失去了“有序性“,对机器来说,只收到三个单词I,am,fine,其并不知道这三个单词之间的位置关系,为此需要为每个单词附加上额外的位置信息。比如这里我们可以简单的传(I, 1),(am, 2),(fine, 3)。这样不仅传入了句子的单词,还附加上单词的位置信息。

一种好的位置编码方案需要满足以下几条要求:

  • 能为每个时间步输出一个独一无二的编码
  • 不同长度的句子之间,任何两个时间步之间的距离应该保持一致
  • 模型应该能毫不费力地泛化到更长的句子,且值是有界的
  • 必须是确定性的
class PositionEncoding(nn.Module):def __init__(self, d_model, max_len, dropout=0.1, device='cpu'):""":param max_len: 句子最大长度  default:5000:param d_model: 模型维度/embed_dim  default:512   必须为偶数:param device:"""super(PositionEncoding, self).__init__()self.dropout = nn.Dropout(dropout)pos_encoding = torch.zeros(max_len, d_model, device=device)# 2D: [max_len, d_model]pos = torch.arange(0, max_len, dtype=torch.float, device=device).unsqueeze(dim=1)# 2D: [max_len, 1]div_term = torch.exp(torch.arange(0, d_model, step=2,  device=device).float() * (-math.log(10000) / d_model))# 1D: [d_model / 2]pos_encoding[:, 0::2] = torch.sin(pos * div_term)pos_encoding[:, 1::2] = torch.cos(pos * div_term)# 2D: [max_len, d_model]pos_encoding = pos_encoding.unsqueeze(dim=0)# print(pos_encoding.shape)# 3D: [1, max_len, d_model], 扩充batch_size维度 batch_size * max_len * d_modelself.register_buffer('pos_encoding', pos_encoding)def forward(self, x):# [batch_size, max_len, d_model]x = x + self.pos_encoding[:, :x.size(1)].requires_grad_(False)return self.dropout(x)

Transformer Embedding

词嵌入层+位置编码层

class TransformerEmbedding(nn.Module):def __init__(self, vocab_size, max_len, d_model, drop, device):""":param vocab_size: 字典大小,字典中不同字符个数:param max_len::param d_model::param drop::param drop_prob::param device:"""super(TransformerEmbedding, self).__init__()self.embed = TokenEmbedding(vocab_size, d_model)self.pos = PositionEncoding(d_model, max_len, drop, device)def forward(self, x):""":param x: padding后的vectors:return: embedding + pos_encoder 后的vectors; shape: [batch_size, max_len, d_model]"""embed = self.embed(x)pos = self.pos(embed)return pos

调试例子,可以详细查看每一步运行的shape变化

if __name__ == '__main__':Input = [[1, 2, 3, 4], [5, 6, 2], [1, 7, 8, 9, 10, 11, 12, 13, 14, 15]]# 有三个句子[['你 好 世 界'], ['我 很 好'], ['你 不 是 真 正 的 快 乐']]# 句子长度不一致进行padding处理max_len = len(Input[2])print('The most length is {} sequences '.format(max_len))src_sentence = torch.tensor([])for i in range(len(Input)):src_sen = torch.tensor([Input[i]])src_sen = F.pad(src_sen, (0, max_len-len(Input[i])), 'constant', 0)src_sentence = torch.cat([src_sentence, src_sen], dim=0)# x = src_sentence.unsqueeze(dim=0)x = src_sentenceprint(x)# token_embed = TokenEmbedding(vocab_size=18, embed_dim=32)# x = token_embed(x)# print('token的维度为:', x.shape)# pos_embed = PositionEncoding(d_model=32, max_len=max_len)# x = pos_embed(x)# print(x.shape)trans = TransformerEmbedding(vocab_size=18, max_len=10, d_model=32, drop=0.1, device='cpu')x = trans(x)print('transformer的维度为:', x.shape)

ScaleDotProductAttention(self-attention)

单头注意力机制/自注意力机制实现

  • q: query 查询,
    -代表输入序列每个位置的上下文信息,可以看做单个位置向其他位置发出询问
  • k: key 键,
    -代表输入序列中每个位置的局部信息,每个位置将自己的局部信息编码为键,可以与其他位置进行比较和交互
  • v: value 值,
    -代表序列中每个位置的具体信息,可以获得具体数据
    查询会和键进行一个相似度计算,然后根据相似度的权重对值进行加权求和
class ScaleDotProductAttention(nn.Module):def __init__(self, dim_model):"""self_attention: softmax(QKT / sqrt(d_model))V:param dim_model: 嵌入维度,default: 512"""super(ScaleDotProductAttention, self).__init__()self.q = nn.Linear(dim_model, dim_model)self.k = nn.Linear(dim_model, dim_model)self.v = nn.Linear(dim_model, dim_model)self.softmax = nn.Softmax(dim=-1)def forward(self, query, key, value, mask=None):""":param query: [batch_size, max_len, d_model]:param key::param value::param mask: [max_len, max_len]:return:"""q = self.q(query)k = self.k(key)v = self.v(value)d_k = query.size(-1)qk = self.softmax(torch.matmul(q, k.transpose(-1, -2)) / math.sqrt(d_k))if mask is not None:qk = qk.masked_fill(mask == 0, -1e9)attn_weights = self.softmax(qk)output = torch.matmul(attn_weights, v)return attn_weights, output

MultiHeadAttention 多头注意力机制

多头注意力机制实现

模型在对当前位置的信息进行编码时,会过度的将注意力集中于自身的位置, 因此作者提出了通过多头注意力机制来解决这一问题。同时,使用多头注意力机制还能够给予注意力层的输出包含有不同子空间中的编码表示信息,从而增强模型的表达能力。

import torch
from torch import nn
import torch.nn.functional as F
import mathclass MultiHeadAttention(nn.Module):def __init__(self, dim_model, n_head, bias=True):""":param dim_model: 词嵌入的维度,也就是前面的d_model参数,论文中的默认值为512:param n_head: self-attention的个数  多头注意力机制中多头的数量,也就是前面的n_head参数, 论文默认值为 8:param bias: 最后对多头的注意力(组合)输出进行线性变换时,是否使用偏置"""super(MultiHeadAttention, self).__init__()self.d_model = dim_modelself.head_dim = dim_model // n_headself.k_dim = self.head_dimself.v_dim = self.head_dimself.nums_head = n_head# self.dropout = nn.Dropout(dropout)assert self.nums_head * self.head_dim == self.d_model, 'embed_dim 除以 num_heads必须为整数'self.q_weight = nn.Parameter(torch.Tensor(dim_model, dim_model))# d_model = k_dim * nums_headself.k_weight = nn.Parameter(torch.Tensor(dim_model, dim_model))self.v_weight = nn.Parameter(torch.Tensor(dim_model, dim_model))self.output_weights = nn.Parameter(torch.Tensor(dim_model, dim_model))# self.output_bias = biasself.output = nn.Linear(dim_model, dim_model, bias=bias)def forward(self, query, key, value, drop_p, training=True, attn_mask=None, key_padding_mask=None):"""在论文中,编码时query, key, value 都是同一个输入,解码时 输入的部分也都是同一个输入,解码和编码交互时 key,value指的是 memory, query指的是tgt:param drop_p: attention_weights  layer:param training:  是否开启训练模式:param query: [batch_size, tgt_len, embed_dim], tgt_len 表示目标序列的长度:param key:   [batch_size, src_len, embed_dim], src_len 表示源序列的长度:param value: [batch_size, src_len, embed_dim], src_len 表示源序列的长度:param attn_mask: [tgt_len,src_len] or [num_heads*batch_size,tgt_len, src_len]一般只在解码时使用,为了并行一次喂入所有解码部分的输入,所以要用mask来进行掩盖当前时刻之后的位置信息:param key_padding_mask: [batch_size, src_len], src_len 表示源序列的长度. 填充部分掩码操作:return:attn_output: [tgt_len, batch_size, embed_dim]attn_output_weights: # [batch_size, tgt_len, src_len]"""# 第一阶段: 计算得到Q、K、Vq = F.linear(query, self.q_weight)# F.linear(inputs, weights, bias)# query:[batch_size, src_len/tgt_len, d_model], q_weight:[d_model, d_model]k = F.linear(key, self.k_weight)v = F.linear(value, self.v_weight)# 第二阶段:缩放,以及attn_mask维度判断b_s, tgt_len, embed_dim = query.size()source_len = key.size(1)scaling = 1 / math.sqrt(self.head_dim)# q*scaling: [batch_size, query_len, k_dim*nums_head]q = q * scaling# print(tgt_len, source_len)if attn_mask is not None:# [tgt_len, src_len] or [nums_head*batch_size, tgt_len, src_len]if attn_mask.dim() == 2:attn_mask = attn_mask.unsqueeze(0)# print(attn_mask.shape)if list(attn_mask.size()) != [1, tgt_len, source_len]:raise RuntimeError('The size of the 2D attn_mask is not correct.')elif attn_mask.dim() == 3:if list(attn_mask.size()) != [b_s*self.nums_head, tgt_len, source_len]:raise RuntimeError('The size of the 3D attn_mask is not correct.')# 第三阶段: 计算得到注意力权重矩阵# [batch_size, n_head, tgt_dim, k_dim] 计算时候是[tgt_dim, k_dim]* [k_dim, tgt_dim]-># [batch_size, n_head, tgt_dim, tgt_dim] == [batch_size * n_head, tgt_dim, tgt_dim]# q = q.view(b_s, tgt_len, n_head, head_dim).transpose(1, 2)q = q.contiguous().view(b_s*self.nums_head, tgt_len, self.head_dim)# [batch_size * n_head, tgt_len, k_dim]k = k.contiguous().view(b_s*self.nums_head, -1, self.k_dim)v = v.contiguous().view(b_s*self.nums_head, -1, self.v_dim)# print(q.shape, k.shape, v.shape)attn_output_wights = torch.bmm(q, k.transpose(-1, -2))# [batch_size*nums_head, tgt_len, head_dim] * [batch_size*nums_head, k_dim, src_len]# [batch_size*nums_head, tgt_len, src_len]# 第四阶段: 进行相关掩码操作if attn_mask is not None:attn_output_wights = attn_output_wights + attn_mask# [batch_size*nums_head, tgt_len, src_len] + [batch_size*nums_head, tgt_len, src_len]if key_padding_mask is not None:attn_output_wights = attn_output_wights.view(b_s, self.nums_head, tgt_len, source_len)attn_output_wights = attn_output_wights.masked_fill(key_padding_mask.unsqueeze(1).unsqueeze(2) == 0, float('-inf'))attn_output_wights = attn_output_wights.view(b_s * self.nums_head, tgt_len, source_len)attn_output_wights = F.softmax(attn_output_wights, dim=-1)attn_output_wights = F.dropout(attn_output_wights, p=drop_p, training=training)attn_output = torch.bmm(attn_output_wights, v)# [batch_size * nums_head, tgt_len, src_len], [batch_size*nums_head, src_len, v_dim]# [batch_size * nums_head, tgt_len, v_dim]attn_output = attn_output.contiguous().view(b_s, tgt_len, self.d_model)# print(attn_output.shape)attn_output_wights = attn_output_wights.view(b_s, self.nums_head, tgt_len, source_len)Z = F.linear(attn_output, self.output.weight)return Z, attn_output, attn_output_wights.sum(dim=1) / self.nums_head
if __name__ == '__main__':inputs = 'transformer_embedding_out'src_len = 5batch_size = 2d_model = 32num_head = 1src = torch.rand(([batch_size, src_len, d_model]))mha = MultiHeadAttention(dim_model=d_model, n_head=num_head, bias=True)out, attn_out, attn_weight = mha(src, src, src, drop_p=0.1, attn_mask=None, key_padding_mask=None)print(out.shape, attn_out.shape, attn_weight.shape)# print(src, out, attn_out, attn_weight)# out = mha(inputs, inputs, inputs, drop_p=0.1, attn_mask=None, key_padding_mask=None)

EncoderLayer 编码层

单个编码层的实现

注意力机制经过残差连接后,进行层归一化后输出

class EncoderLayer(nn.Module):def __init__(self, embed_dim, n_head, feedforward_dim, drop_fc=None, drop_attn=None, drop_feed=None):"""单个的编码层,论文中6个:param embed_dim: 嵌入维度,词向量和位置编码的嵌入维度,论文中:512:param n_head:   多头注意力机制个数,论文中:8个, 512//64=8,batch_size=64:param drop_attn: 注意力机制层输出的随机丢弃:param drop_feed: 前馈网络层输出的随机丢弃"""super(EncoderLayer, self).__init__()# TransformerEmbedding(vocab_size=2048, d_model=512, drop=0.1, drop_prob=0.1, max_len=None, device='cpu')# 注意力机制层  [batch_size, max_len, d_model]self.attn_encoder = MultiHeadAttention(dim_model=embed_dim, n_head=n_head, bias=True)# 注意力机制输出进行dropself.drop_out1 = nn.Dropout(drop_attn)self.norm1 = nn.LayerNorm(embed_dim)# 前馈网络层self.feedforward = PositionWiseFeedForward(dim_model=embed_dim, drop_fc=drop_fc, dim_feedforward=feedforward_dim)# 前馈网络输出进行dropself.drop_out2 = nn.Dropout(drop_feed)self.norm2 = nn.LayerNorm(embed_dim)self.activation = nn.ReLU()def forward(self, src_sentence, drop=None, training=True, attn_mask=None, src_key_padding_mask=None):"""填充后的句子输入,经过词向量+位置编码/注意力机制层/残差连接/前馈传播层/残差连接/输出:param src_key_padding_mask: 输入句子的填充部分做掩盖处理:param attn_mask: 注意力的掩码,一般在解码部分为了掩盖后续position需要使用:param training: 是否训练模式:param drop: 注意力层weights输出的drop:param src_sentence: 填充后的原始句子:return: 编码层的输出, 解码层的部分输入"""# input_embedding = self.input_embedding(src_sentence)input_embedding = src_sentenceattn_encoder = self.attn_encoder(input_embedding, input_embedding, input_embedding, drop_p=drop,training=training, attn_mask=attn_mask, key_padding_mask=src_key_padding_mask)[0]# add & norm 残差连接后归一化处理,归一化防止数值过大后续训练时候造成梯度丢失或爆炸embedding_attn = input_embedding + self.drop_out1(attn_encoder)attn_out = self.norm1(embedding_attn)attn_out = self.activation(attn_out)# 前馈连接,Feed_Forward层feed_forward = self.feedforward(attn_out)# Feed_Forward层后的残差连接+归一化attn_feed = attn_encoder + self.drop_out2(feed_forward)encoder_layer_out = self.norm2(attn_feed)return encoder_layer_out

Encoder多层编码块/前馈网络层

多个编码层的实现

class Encoder(nn.Module):def __init__(self, embed_dim, n_head, feedforward_dim, drop_fc, drop_attn, drop_feed, n_layers):super(Encoder, self).__init__()self.layers = nn.ModuleList([EncoderLayer(embed_dim=embed_dim, n_head=n_head, feedforward_dim=feedforward_dim,drop_fc=drop_fc, drop_attn=drop_attn, drop_feed=drop_feed)for _ in range(n_layers)])def forward(self, src_sentence, drop, training=True, src_mask=None, src_key_padding_mask=None):""":param drop::param training::param src_sentence: 嵌入向量的输入:param src_mask:   一般只在解码时使用,为了并行一次喂入所有解码部分的输入,所以要用mask来进行掩盖当前时刻之后的位置信息:param src_key_padding_mask: 编码部分输入的padding情况,形状为 [batch_size, src_len]:return:"""encoder_out = src_sentencefor layer in self.layers:encoder_out = layer(src_sentence, training=training, drop=drop, attn_mask=src_mask,src_key_padding_mask=src_key_padding_mask)return encoder_outclass PositionWiseFeedForward(nn.Module):def __init__(self, drop_fc=None, dim_model=512, dim_feedforward=2048):super(PositionWiseFeedForward, self).__init__()self.fc1 = nn.Linear(dim_model, dim_feedforward)self.fc2 = nn.Linear(dim_feedforward, dim_model)self.relu = nn.ReLU()self.drop = nn.Dropout(drop_fc)def forward(self, x):x = self.fc1(x)x = self.relu(x)x = self.drop(x)x = self.fc2(x)return x

DecoderLayer解码层

单个解码层的实现
需要与Encoder层进行交互
在这里插入图片描述

class DecoderLayer(nn.Module):def __init__(self, embed_dim, feedforward_dim, n_head, drop_fc, drop_mask_attn, drop_attn, drop_feed, bias=True):"""解码层:输入嵌入+位置编码-->带掩码的多头注意力-->与编码交互的多头注意力-->前馈网络:param embed_dim: 嵌入维度:512:param feedforward_dim: 前馈网络的隐层维度:2048:param n_head:   多头注意力头数:8  512//64=8    d_model//batch_size=n_head:param drop_fc: 前馈网络中隐层输出的随机丢弃比例:param drop_mask_attn: 带掩码的多头注意力层输出:param drop_attn:    与编码交互的多头注意力层输出:param drop_feed:    前馈网络层输出:param bias:       多头注意力层线性输出时候是否加偏置"""super(DecoderLayer, self).__init__()# self.out_embedding =# TransformerEmbedding(vocab_size=2048, d_model=512, drop=0.1, drop_prob=0.1, max_len=None, device='cpu')self.attn = MultiHeadAttention(dim_model=embed_dim, n_head=n_head, bias=bias)self.mask_attn = MultiHeadAttention(dim_model=embed_dim, n_head=n_head, bias=bias)self.fc = PositionWiseFeedForward(dim_model=embed_dim, drop_fc=drop_fc, dim_feedforward=feedforward_dim)# mask_attention层self.drop1 = nn.Dropout(drop_mask_attn)# encoder_decoder_attention层self.drop2 = nn.Dropout(drop_attn)# 前馈网络层self.drop3 = nn.Dropout(drop_feed)self.norm1 = nn.LayerNorm(embed_dim)self.norm2 = nn.LayerNorm(embed_dim)self.norm3 = nn.LayerNorm(embed_dim)self.activation = nn.ReLU()def forward(self, tgt, memory, drop=None, tgt_mask=None, memory_mask=None,tgt_key_padding_mask=None, memory_key_padding_mask=None):""":param drop::param memory_mask: 编码器-解码器交互时的注意力掩码,一般为None:param tgt_mask: 注意力机制中的掩码矩阵,用于掩盖当前position之后的信息, [tgt_len, tgt_len]:param memory: 编码部分的输出(memory), [src_len,batch_size,embed_dim]:param tgt: 解码部分的输入,形状为 [tgt_len,batch_size, embed_dim]:param tgt_key_padding_mask:解码部分输入的padding情况,形状为 [batch_size, tgt_len],填充词的掩码:param memory_key_padding_mask: 编码部分输入的padding情况,形状为 [batch_size, src_len]:return:"""# out_embedding = self.out_embedding(tgt_sentence)# out_embedding = tgt_sentence# MultiHeadAttention返回: attn_out_linear, attn_concat, attn_weightsmask_attn = self.mask_attn(tgt, tgt, tgt, drop_p=drop, training=True,attn_mask=tgt_mask, key_padding_mask=tgt_key_padding_mask)[0]mask_out = self.norm1(tgt + self.drop1(mask_attn))self_attn = self.attn(tgt, key=memory, value=memory, drop_p=drop, training=True,attn_mask=memory_mask, key_padding_mask=memory_key_padding_mask)[0]attn_out = self.norm2(mask_out + self.drop2(self_attn))attn_out = self.activation(attn_out)feed_forward = self.fc(attn_out)decoder_out = self.norm3(attn_out+self.drop3(feed_forward))return decoder_out

Decoder多层解码块

多个解码层的实现

class Decoder(nn.Module):def __init__(self, n_layers, embed_dim, feedforward_dim, n_head, drop_fc,drop_mask_attn, drop_attn, drop_feed, bias=True):super(Decoder, self).__init__()self.layers = nn.ModuleList([DecoderLayer(embed_dim=embed_dim, feedforward_dim=feedforward_dim, n_head=n_head,drop_fc=drop_fc, drop_mask_attn=drop_mask_attn, drop_attn=drop_attn,drop_feed=drop_feed, bias=bias) for _ in range(n_layers)])def forward(self, tgt_sentence, memory, drop, tgt_mask=None, memory_mask=None, tgt_key_padding_mask=None,memory_key_padding_mask=None):decoder_out = tgt_sentencefor layer in self.layers:decoder_out = layer(tgt_sentence, memory, drop=drop, tgt_mask=tgt_mask,tgt_key_padding_mask=tgt_key_padding_mask,memory_key_padding_mask=memory_key_padding_mask, memory_mask=None)return decoder_out
if __name__ == '__main__':src_len = 5batch_size = 2d_model = 32num_head = 1n_layer = 6src = torch.rand(([batch_size, src_len, d_model]))encoder = Decoder(n_layers=n_layer, embed_dim=d_model, feedforward_dim=2048, n_head=num_head, drop_fc=0.1,drop_mask_attn=0.1, drop_attn=0.1, drop_feed=0.1, bias=True)print(encoder)

MyTransformer实现完整的Transformer框架

import torch
import torch.nn as nn
import torch.nn.functional as F
from TransformerEmbedding import TransformerEmbedding
from EncoderLayer import Encoder
from DecoderLayer import Decoderclass MyTransformer(nn.Module):def __init__(self, src_vocab_size, src_max_len, tgt_vocab_size, tgt_max_len, embed_dim, feedforward_dim, n_head,drop_prob, n_layers):super(MyTransformer, self).__init__()self.src_embedding = TransformerEmbedding(vocab_size=src_vocab_size, max_len=src_max_len, d_model=embed_dim,drop=drop_prob, device='cpu')self.tgt_embedding = TransformerEmbedding(vocab_size=tgt_vocab_size, max_len=tgt_max_len, d_model=embed_dim,drop=drop_prob, device='cpu')self.encoder = Encoder(embed_dim=embed_dim, n_head=n_head, feedforward_dim=feedforward_dim, n_layers=n_layers,drop_fc=drop_prob, drop_attn=drop_prob, drop_feed=drop_prob)self.decoder = Decoder(embed_dim=embed_dim, feedforward_dim=feedforward_dim, n_head=n_head, n_layers=n_layers,drop_fc=drop_prob, drop_mask_attn=drop_prob, drop_attn=drop_prob, drop_feed=drop_prob)# self.fc = nn.Linear(drop_prob)def forward(self, src, tgt, drop_prob, training=True, src_mask=None, tgt_mask=None,src_key_padding_mask=None, tgt_key_padding_mask=None):src_embedding = self.src_embedding(src)tgt_embedding = self.tgt_embedding(tgt)memory = self.encoder(src_embedding, drop=drop_prob, training=training,src_key_padding_mask=src_key_padding_mask)# print(src_embedding.shape, tgt_embedding.shape, memory.shape)print('编码完成------------------------------')decoder = self.decoder(tgt_embedding, memory, drop=drop_prob, tgt_mask=tgt_mask,tgt_key_padding_mask=tgt_key_padding_mask, memory_key_padding_mask=src_key_padding_mask)print('解码完成')return decoderdef init_parameters(self):for p in self.parameters():if p.dim() > 1:nn.init.xavier_uniform_(p)def generate_square_subsequent_mask(self, s_z):mask = torch.tril(torch.ones(s_z, s_z)).transpose(0, 1)mask = mask.float().masked_fill(mask == 0.0, float('-inf')).masked_fill(mask == 1.0, float('-inf'))return mask
if __name__ == '__main__':Input = [[1, 2, 3, 4], [5, 6, 2], [1, 7, 8, 9, 10, 11, 12, 13, 14, 15]]output = [[1, 1, 2, 3, 4], [5, 5, 6, 2], [1, 7, 7, 8, 9, 10, 11, 12, 13, 14, 15]]# 有三个句子[['你 好 世 界'], ['我 很 好'], ['你 不 是 真 正 的 快 乐']]# 句子长度不一致进行padding处理src_sentence = torch.tensor([])for i in range(len(Input)):src_sen = torch.tensor([Input[i]])src_sen = F.pad(src_sen, (0, len(Input[2]) - len(Input[i])), 'constant', 0)src_sentence = torch.cat([src_sentence, src_sen], dim=0)# x = src_sentence.unsqueeze(dim=0)tgt_sentence = torch.tensor([])for i in range(len(output)):src_sen = torch.tensor([output[i]])src_sen = F.pad(src_sen, (0, len(output[2]) - len(output[i])), 'constant', 0)tgt_sentence = torch.cat([tgt_sentence, src_sen], dim=0)src_len = 10batch_size = 3dmodel = 32tgt_len = 11num_head = 8# src = torch.rand((src_len, batch_size, dmodel))  # shape: [src_len, batch_size, embed_dim]# src_key_padding_mask = torch.tensor([[True, True, True, False, False],#                                      [True, True, True, True, False]])  # shape: [batch_size, src_len]## tgt = torch.rand((tgt_len, batch_size, dmodel))  # shape: [tgt_len, batch_size, embed_dim]# tgt_key_padding_mask = torch.tensor([[True, True, True, False, False, False],#                                      [True, True, True, True, False, False]])  # shape: [batch_size, tgt_len]my_transformer = MyTransformer(src_vocab_size=5000, src_max_len=10, tgt_vocab_size=5000, tgt_max_len=11, embed_dim=32,feedforward_dim=2048, n_head=8, drop_prob=0.1, n_layers=6)tgt_mask = my_transformer.generate_square_subsequent_mask(tgt_len)out = my_transformer(src=src_sentence, tgt=tgt_sentence, drop_prob=0.1, tgt_mask=tgt_mask,src_key_padding_mask=src_sentence,tgt_key_padding_mask=tgt_sentence)print(out.shape)# torch.Size([3, 11, 32])

相关文章:

【Transformer框架代码实现】

Transformer Transformer框架注意力机制框架导入必要的库Input Embedding / Out EmbeddingPositional EmbeddingTransformer EmbeddingScaleDotProductAttention(self-attention)MultiHeadAttention 多头注意力机制EncoderLayer 编码层Encoder多层编码块/前馈网络层…...

Apache ShenYu 网关JWT认证绕过漏洞 CVE-2021-37580

Apache ShenYu 网关JWT认证绕过漏洞 CVE-2021-37580 已亲自复现 漏洞名称漏洞描述影响版本 漏洞复现环境搭建漏洞利用 修复建议总结 Apache ShenYu 网关JWT认证绕过漏洞 CVE-2021-37580 已亲自复现) 漏洞名称 漏洞描述 Apache ShenYu是一个异步的,高性能的&#x…...

锐捷配置重发布RIP进OSPF中

一、实验拓扑 二、实验目的 使用两种动态路由协议,并使两种协议间的路由可以传递 三、实验配置 第一步:配置全网基本IP R1 Ruijie>enable Ruijie#configure terminal Ruijie(config)#interface gigabitEthernet 0/0 Ruijie(config-if-GigabitEthe…...

Android R修改wifi热点默认为隐藏热点以及禁止自动关闭热点

前言 Android R系统中WLAN 热点设置里面默认是没有wifi热点的隐藏设置选项的,如果默认wifi热点为隐藏热点可以修改代码实现。另外wifi热点设置选项里面有个自动关闭热点,这个选项默认是打开的,有些机器里面配置wifi热点后默认是需要关闭掉的,以免自动关闭后要手动打开。 …...

智能优化算法应用:基于人工大猩猩部队算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用:基于人工大猩猩部队算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于人工大猩猩部队算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.人工大猩猩部队算法4.实验参…...

[JS设计模式]Flyweight Pattern

Flyweight pattern 享元模式是一种结构化的设计模式,主要用于产生大量类似对象而内存又有限的场景。享元模式能节省内存。 假设一个国际化特大城市SZ;它有5个区,分别为nanshan、futian、luohu、baoan、longgang;每个区都有多个图…...

【.Net8教程】(一)读取配置文件全面总结

环境:.net8.0 1. 准备条件 先在appsettings.Development.json或appsettings.json添加配置 添加一个DbOption {"DbOption": {"Conn": "foolishsundaycsdn"} }2.直接读取json配置节点的几种写法 在Main函数中读取json配置 方式一 …...

亚信安慧AntDB:支撑中国广电5G业务的数据库之力

自2019年6月获得5G牌照以来,中国广电积极利用700MHz频谱资源,迅速崛起为第四大运营商,标志着其在数字通信领域取得的巨大成就。通过与中国移动紧密合作,共建共享基站已超过400万座,为实现自主运营和差异化竞争提供了坚…...

C++哈希表的实现

C哈希表的实现 一.unordered系列容器的介绍二.哈希介绍1.哈希概念2.哈希函数的常见设计3.哈希冲突4.哈希函数的设计原则 三.解决哈希冲突1.闭散列(开放定址法)1.线性探测1.动图演示2.注意事项3.代码的注意事项4.代码实现 2.开散列(哈希桶,拉链法)1.概念2.动图演示3.增容问题1.拉…...

[Angular] 笔记 6:ngStyle

ngStyle 指令: 用于更新 HTML 元素的样式。设置一个或多个样式属性&#xff0c;用以冒号分隔的键值对指定。键是样式名称&#xff0c;带有可选的 .<unit> 后缀&#xff08;如 ‘top.px’、‘font-style.em’&#xff09;&#xff0c;值为待求值的表达式&#xff0c;得到…...

Linux环境下使用logrotate工具实现nginx日志切割

本文已同步到专业技术网站 www.sufaith.com, 该网站专注于前后端开发技术与经验分享, 包含Web开发、Nodejs、Python、Linux、IT资讯等板块. 一. 前提背景及需求 nginx运行日志默认保存在nginx安装目录下的 /usr/local/nginx/logs 文件夹, 包含access.log和error.log两个文件.…...

数字信号的理解

1 数字信号处理简介 数字信号处理 digital signal processing&#xff08;DSP&#xff09;经常与实际的数字系统相混淆。这两个术语都暗示了不同的概念。数字信号处理在本质上比实际的数字系统稍微抽象一些。数字系统是涉及的硬件、二进制代码或数字域。这两个术语之间的普遍混…...

【计算机网络】TCP心跳机制、TCP粘包问题

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; 更多计算机网络知识专栏&#xff1a;计算机网络&#x1f525; 给大家跳段…...

【Linux驱动】字符设备驱动程序框架 | LED驱动

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《RTOS学习》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 目录 &#x1f3c0;Hello驱动程序⚽驱动程序框架⚽编程 &#x1f3c0;LED驱动⚽配置GPIO⚽编程驱动…...

关于编程网站变成了地方这件事

洛谷&#xff1a; 首页 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) csdn CSDN - 专业开发者社区 力扣 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 常州市力扣紧固件有限公司 常州市 力扣 紧固件 有限公司 博客园 博客园 - 开发…...

stable diffusion工作原理

目录 序言stable diffusion能做什么扩散模型正向扩散逆向扩散 如何训练逆向扩散 Stable Diffusion模型潜在扩散模型变分自动编码器图像分辨率图像放大为什么潜在空间可能存在&#xff1f;在潜在空间中的逆向扩散什么是 VAE 文件&#xff1f; 条件化(conditioning)文本条件化&am…...

华清远见嵌入式学习——ARM——作业2

目录 作业要求&#xff1a; 现象&#xff1a; 代码&#xff1a; 思维导图&#xff1a; 模拟面试题&#xff1a; 作业要求&#xff1a; GPIO实验——3颗LED灯的流水灯实现 现象&#xff1a; 代码&#xff1a; .text .global _start _start: 设置GPIOEF时钟使能 0X50000…...

R语言中使用ggplot2绘制散点图箱线图,附加显著性检验

散点图可以直观反映数据的分布&#xff0c;箱线图可以展示均值等关键统计量&#xff0c;二者结合能够清晰呈现数据蕴含的信息。 本篇笔记主要内容&#xff1a;介绍R语言中绘制箱线图和散点图的方法&#xff0c;以及二者结合展示教程&#xff0c;添加差异比较显著性分析&#xf…...

51单片机的羽毛球计分器系统【含proteus仿真+程序+报告+原理图】

1、主要功能 该系统由AT89C51单片机LCD1602显示模块按键等模块构成。适用于羽毛球计分、乒乓球计分、篮球计分等相似项目。 可实现基本功能: 1、LCD1602液晶屏实时显示比赛信息 2、按键控制比赛的开始、暂停和结束&#xff0c;以及两位选手分数的加减。 本项目同时包含器件清…...

设计模式之-责任链模式,快速掌握责任链模式,通俗易懂的讲解责任链模式以及它的使用场景

系列文章目录 设计模式之-6大设计原则简单易懂的理解以及它们的适用场景和代码示列 设计模式之-单列设计模式&#xff0c;5种单例设计模式使用场景以及它们的优缺点 设计模式之-3种常见的工厂模式简单工厂模式、工厂方法模式和抽象工厂模式&#xff0c;每一种模式的概念、使用…...

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0&#xff1a;开发环境同步测试 cookie 至 localhost&#xff0c;便于本地请求服务携带 cookie 参考地址&#xff1a;https://juejin.cn/post/7139354571712757767 里面有源码下载下来&#xff0c;加在到扩展即可使用FeHelp…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

20个超级好用的 CSS 动画库

分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码&#xff0c;而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库&#xff0c;可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画&#xff0c;可以包含在你的网页或应用项目中。 3.An…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧

上周三&#xff0c;HubSpot宣布已构建与ChatGPT的深度集成&#xff0c;这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋&#xff0c;但同时也存在一些关于数据安全的担忧。 许多网络声音声称&#xff0c;这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...

Ubuntu系统复制(U盘-电脑硬盘)

所需环境 电脑自带硬盘&#xff1a;1块 (1T) U盘1&#xff1a;Ubuntu系统引导盘&#xff08;用于“U盘2”复制到“电脑自带硬盘”&#xff09; U盘2&#xff1a;Ubuntu系统盘&#xff08;1T&#xff0c;用于被复制&#xff09; &#xff01;&#xff01;&#xff01;建议“电脑…...

Ubuntu系统多网卡多相机IP设置方法

目录 1、硬件情况 2、如何设置网卡和相机IP 2.1 万兆网卡连接交换机&#xff0c;交换机再连相机 2.1.1 网卡设置 2.1.2 相机设置 2.3 万兆网卡直连相机 1、硬件情况 2个网卡n个相机 电脑系统信息&#xff0c;系统版本&#xff1a;Ubuntu22.04.5 LTS&#xff1b;内核版本…...