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

购物帮 做特惠的导购网站搜易网托管模式的特点

购物帮 做特惠的导购网站,搜易网托管模式的特点,微官网站怎么做,阳江市问政平台留言Transformer总体架构图 输入部分#xff1a;源文本嵌入层及其位置编码器、目标文本嵌入层及其位置编码器 编码器部分 由N个编码器层堆叠而成 每个编码器层由两个子层连接结构组成 第一个子层连接结构包括一个多头自注意力子层和规范化层以及一个残差连接 第二个子层连接结构包…Transformer总体架构图 输入部分源文本嵌入层及其位置编码器、目标文本嵌入层及其位置编码器 编码器部分 由N个编码器层堆叠而成 每个编码器层由两个子层连接结构组成 第一个子层连接结构包括一个多头自注意力子层和规范化层以及一个残差连接 第二个子层连接结构包括一个前馈全连接子层和规范化层以及一个残差连接 解码器部分 由N个解码器层堆叠而成 每个解码器层由三个子层连接结构组成 第一个子层连接结构包括一个多头自注意力子层和规范化层以及一个残差连接 第二个子层连接结构包括一个多头注意力子层和规范化层以及一个残差连接 第三个子层连接结构包括一个前馈全连接子层和规范化层以及一个残差连接 输出部分包线性层、softmax层 输入部分实现 1. 文本嵌入层 import torch # 预定义的网络层torch.nn, 工具开发者已经帮助我们开发好的一些常用层, # 比如卷积层, lstm层, embedding层等, 不需要我们再重新造轮子. import torch.nn as nn import math# torch中变量封装函数Variable. from torch.autograd import Variable# 定义Embeddings类来实现文本嵌入层这里s说明代表两个一模一样的嵌入层, 他们共享参数. # 该类继承nn.Module, 这样就有标准层的一些功能, 这里我们也可以理解为一种模式, 我们自己实现的所有层都会这样去写. class Embeddings(nn.Module):def __init__(self, d_model, vocab):类的初始化函数, 有两个参数, d_model: 指词嵌入的维度, vocab: 指词表的大小.# 接着就是使用super的方式指明继承nn.Module的初始化函数, 我们自己实现的所有层都会这样去写.super(Embeddings, self).__init__()# 之后就是调用nn中的预定义层Embedding, 获得一个词嵌入对象self.lutself.lut nn.Embedding(vocab, d_model)# 最后就是将d_model传入类中self.d_model d_modeldef forward(self, x):可以将其理解为该层的前向传播逻辑所有层中都会有此函数当传给该类的实例化对象参数时, 自动调用该类函数参数x: 因为Embedding层是首层, 所以代表输入给模型的文本通过词汇映射后的张量# 将x传给self.lut并与根号下self.d_model相乘作为结果返回# 让 embeddings vector 在增加 之后的 postion encoing 之前相对大一些的操作# 主要是为了让position encoding 相对的小这样会让原来的 embedding vector 中的信息在和 position encoding 的信息相加时不至于丢失掉# 让 embeddings vector 相对大一些return self.lut(x) * math.sqrt(self.d_model)# 词嵌入维度是512维 d_model 512# 词表大小是1000 vocab 1000# 输入x是一个使用Variable封装的长整型张量, 形状是2 x 4 x Variable(torch.LongTensor([[100,2,421,508],[491,998,1,221]]))emb Embeddings(d_model, vocab) embr emb(x) print(embr:, embr) 2. 位置编码器 因为在Transformer的编码器结构中, 并没有针对词汇位置信息的处理因此需要在Embedding层后加入位置编码器将词汇位置不同可能会产生不同语义的信息加入到词嵌入张量中, 以弥补位置信息的缺失. # 定义位置编码器类, 我们同样把它看做一个层, 因此会继承nn.Module class PositionalEncoding(nn.Module):def __init__(self, d_model, dropout, max_len5000):位置编码器类的初始化函数, 共有三个参数, 分别是d_model: 词嵌入维度, dropout: 置0比率, max_len: 每个句子的最大长度super(PositionalEncoding, self).__init__()# 实例化nn中预定义的Dropout层, 并将dropout传入其中, 获得对象self.dropoutself.dropout nn.Dropout(pdropout)# 初始化一个位置编码矩阵, 它是一个0阵矩阵的大小是max_len x d_model.pe torch.zeros(max_len, d_model)# 初始化一个绝对位置矩阵, 在我们这里词汇的绝对位置就是用它的索引去表示. # 所以我们首先使用arange方法获得一个连续自然数向量然后再使用unsqueeze方法拓展向量维度使其成为矩阵 # 又因为参数传的是1代表矩阵拓展的位置会使向量变成一个max_len x 1 的矩阵 position torch.arange(0, max_len).unsqueeze(1)# 绝对位置矩阵初始化之后接下来就是考虑如何将这些位置信息加入到位置编码矩阵中# 最简单思路就是先将max_len x 1的绝对位置矩阵 变换成max_len x d_model形状然后覆盖原来的初始位置编码矩阵即可 # 要做这种矩阵变换就需要一个1xd_model形状的变换矩阵div_term我们对这个变换矩阵的要求除了形状外# 还希望它能够将自然数的绝对位置编码缩放成足够小的数字有助于在之后的梯度下降过程中更快的收敛. 这样我们就可以开始初始化这个变换矩阵了.# 首先使用arange获得一个自然数矩阵 但是细心的同学们会发现 我们这里并没有按照预计的一样初始化一个1xd_model的矩阵 # 而是有了一个跳跃只初始化了一半即1xd_model/2 的矩阵。 为什么是一半呢其实这里并不是真正意义上的初始化了一半的矩阵# 我们可以把它看作是初始化了两次而每次初始化的变换矩阵会做不同的处理第一次初始化的变换矩阵分布在正弦波上 第二次初始化的变换矩阵分布在余弦波上 # 并把这两个矩阵分别填充在位置编码矩阵的偶数和奇数位置上组成最终的位置编码矩阵.div_term torch.exp(torch.arange(0, d_model, 2) *-(math.log(10000.0) / d_model))pe[:, 0::2] torch.sin(position * div_term)pe[:, 1::2] torch.cos(position * div_term)# 这样我们就得到了位置编码矩阵pe, pe现在还只是一个二维矩阵要想和embedding的输出一个三维张量相加# 就必须拓展一个维度所以这里使用unsqueeze拓展维度.pe pe.unsqueeze(0)# 最后把pe位置编码矩阵注册成模型的buffer什么是buffer呢# 我们把它认为是对模型效果有帮助的但是却不是模型结构中超参数或者参数不需要随着优化步骤进行更新的增益对象. # 注册之后我们就可以在模型保存后重加载时和模型结构与参数一同被加载.self.register_buffer(pe, pe)def forward(self, x):forward函数的参数是x, 表示文本序列的词嵌入表示# 在相加之前我们对pe做一些适配工作 将这个三维张量的第二维也就是句子最大长度的那一维将切片到与输入的x的第二维相同即x.size(1)# 因为我们默认max_len为5000一般来讲实在太大了很难有一条句子包含5000个词汇所以要进行与输入张量的适配. # 最后使用Variable进行封装使其与x的样式相同但是它是不需要进行梯度求解的因此把requires_grad设置成false.x x Variable(self.pe[:, :x.size(1)], requires_gradFalse)# 最后使用self.dropout对象进行丢弃操作, 并返回结果.return self.dropout(x)# 词嵌入维度是512维 d_model 512 # 置0比率为0.1 dropout 0.1 # 句子最大长度 max_len60 # 输入x是Embedding层的输出的张量, 形状是2 x 4 x 512 x embrpe PositionalEncoding(d_model, dropout, max_len) pe_result pe(x) print(pe_result:, pe_result)绘制词汇向量中特征的分布曲线 import matplotlib.pyplot as plt import numpy as np# 创建一张15 x 5大小的画布 plt.figure(figsize(15, 5))# 实例化PositionalEncoding类得到pe对象, 输入参数是20和0 pe PositionalEncoding(20, 0)# 然后向pe传入被Variable封装的tensor, 这样pe会直接执行forward函数, # 且这个tensor里的数值都是0, 被处理后相当于位置编码张量 y pe(Variable(torch.zeros(1, 100, 20)))# 然后定义画布的横纵坐标, 横坐标到100的长度, 纵坐标是某一个词汇中的某维特征在不同长度下对应的值 # 因为总共有20维之多, 我们这里只查看4567维的值. plt.plot(np.arange(100), y[0, :, 4:8].data.numpy())# 在画布上填写维度提示信息 plt.legend([dim %d%p for p in [4,5,6,7]])编码器部分实现 编码器部分: * 由N个编码器层堆叠而成 * 每个编码器层由两个子层连接结构组成 * 第一个子层连接结构包括一个多头自注意力子层和规范化层以及一个残差连接 * 第二个子层连接结构包括一个前馈全连接子层和规范化层以及一个残差连接 1. 掩码张量 掩代表遮掩码就是我们张量中的数值它的尺寸不定里面一般只有1和0的元素代表位置被遮掩或者不被遮掩至于是0位置被遮掩还是1位置被遮掩可以自定义因此它的作用就是让另外一个张量中的一些数值被遮掩也可以说被替换, 它的表现形式是一个张量. 在transformer中, 掩码张量的主要作用在应用attention(将在下一小节讲解)时有一些生成的attention张量中的值计算有可能已知了未来信息而得到的未来信息被看到是因为训练时会把整个输出结果都一次性进行Embedding但是理论上解码器的的输出却不是一次就能产生最终结果的而是一次次通过上一次结果综合得出的因此未来的信息可能被提前利用. 所以我们会进行遮掩. 生成掩码张量的代码分析 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)# 生成的掩码张量的最后两维的大小 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] # 码张量的可视化 plt.figure(figsize(5,5)) plt.imshow(subsequent_mask(20)[0])2. 注意力机制 注意力计算规则的代码分析 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_attn# 我们令输入的query, key, value都相同, 位置编码的输出 query key value pe_result attn, p_attn attention(query, key, value) # attn, p_attn attention(query, key, value, maskmask) print(attn:, attn) print(p_attn:, p_attn)3. 多头注意力机制 多头注意力的结构图中貌似这个所谓的多个头就是指多组线性变换层其实并不是我只有使用了一组线性变化层即三个变换张量对QKV分别进行线性变换这些变换不会改变原有张量的尺寸因此每个变换矩阵都是方阵得到输出结果后多头的作用才开始显现每个头开始从词义层面分割输出的张量也就是每个头都想获得一组QKV进行注意力机制的计算但是句子中的每个词的表示只获得一部分也就是只分割了最后一维的词嵌入向量. 这就是所谓的多头将每个头的获得的输入送到注意力机制中, 就形成多头注意力机制. 这种结构设计能让每个注意力机制去优化每个词汇的不同特征部分从而均衡同一种注意力机制可能产生的偏差让词义拥有来自更多元的表达实验表明可以从而提升模型效果. 多头注意力机制的代码实现 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)# 假设输入的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) 4. 前馈全连接层 在Transformer中前馈全连接层就是具有两层线性层的全连接网络. 前馈全连接层的作用考虑注意力机制可能对复杂过程的拟合程度不够, 通过增加两层网络来增强模型的能力. 前馈全连接层的代码分析 # 通过类PositionwiseFeedForward来实现前馈全连接层 class PositionwiseFeedForward(nn.Module):def __init__(self, d_model, d_ff, dropout0.1):初始化函数有三个输入参数分别是d_model, d_ff,和dropout0.1第一个是线性层的输入维度也是第二个线性层的输出维度因为我们希望输入通过前馈全连接层后输入和输出的维度不变. 第二个参数d_ff就是第二个线性层的输入维度和第一个线性层的输出维度. 最后一个是dropout置0比率.super(PositionwiseFeedForward, self).__init__()# 首先按照我们预期使用nn实例化了两个线性层对象self.w1和self.w2# 它们的参数分别是d_model, d_ff和d_ff, d_modelself.w1 nn.Linear(d_model, d_ff)self.w2 nn.Linear(d_ff, d_model)# 然后使用nn的Dropout实例化了对象self.dropoutself.dropout nn.Dropout(dropout)def forward(self, x):输入参数为x代表来自上一层的输出# 首先经过第一个线性层然后使用Funtional中relu函数进行激活,# 之后再使用dropout进行随机置0最后通过第二个线性层w2返回最终结果.return self.w2(self.dropout(F.relu(self.w1(x)))) d_model 512 # 线性变化的维度 d_ff 64 dropout 0.2 # 输入参数x可以是多头注意力机制的输出 x mha_result ff PositionwiseFeedForward(d_model, d_ff, dropout) ff_result ff(x) print(ff_result)5. 规范化层 它是所有深层网络模型都需要的标准网络层因为随着网络层数的增加通过多层的计算后参数可能开始出现过大或过小的情况这样可能会导致学习过程出现异常模型可能收敛非常的慢. 因此都会在一定层数后接规范化层进行数值的规范化使其特征数值在合理范围内. 规范化层的代码实现 # 通过LayerNorm实现规范化层的类 class LayerNorm(nn.Module):def __init__(self, features, eps1e-6):初始化函数有两个参数, 一个是features, 表示词嵌入的维度,另一个是eps它是一个足够小的数, 在规范化公式的分母中出现,防止分母为0.默认是1e-6.super(LayerNorm, self).__init__()# 根据features的形状初始化两个参数张量a2和b2第一个初始化为1张量# 也就是里面的元素都是1第二个初始化为0张量也就是里面的元素都是0这两个张量就是规范化层的参数# 因为直接对上一层得到的结果做规范化公式计算将改变结果的正常表征因此就需要有参数作为调节因子# 使其即能满足规范化要求又能不改变针对目标的表征.最后使用nn.parameter封装代表他们是模型的参数。self.a2 nn.Parameter(torch.ones(features))self.b2 nn.Parameter(torch.zeros(features))# 把eps传到类中self.eps epsdef forward(self, x):输入参数x代表来自上一层的输出# 在函数中首先对输入变量x求其最后一个维度的均值并保持输出维度与输入维度一致.# 接着再求最后一个维度的标准差然后就是根据规范化公式用x减去均值除以标准差获得规范化的结果# 最后对结果乘以我们的缩放参数即a2*号代表同型点乘即对应位置进行乘法操作加上位移参数b2.返回即可.mean x.mean(-1, keepdimTrue)std x.std(-1, keepdimTrue)return self.a2 * (x - mean) / (std self.eps) self.b2 features d_model 512 eps 1e-6 # 输入x来自前馈全连接层的输出 x ff_result ln LayerNorm(features, eps) ln_result ln(x) print(ln_result) 6. 子层连接结构 如图所示输入到每个子层以及规范化层的过程中还使用了残差链接跳跃连接因此我们把这一部分结构整体叫做子层连接代表子层及其链接结构在每个编码器层中都有两个子层这两个子层加上周围的链接结构就形成了两个子层连接结构. 子层连接结构的代码分析 # 使用SublayerConnection来实现子层连接结构的类 class SublayerConnection(nn.Module):def __init__(self, size, dropout0.1):它输入参数有两个, size以及dropout size一般是都是词嵌入维度的大小 dropout本身是对模型结构中的节点数进行随机抑制的比率 又因为节点被抑制等效就是该节点的输出都是0因此也可以把dropout看作是对输出矩阵的随机置0的比率.super(SublayerConnection, self).__init__()# 实例化了规范化对象self.normself.norm LayerNorm(size)# 又使用nn中预定义的droupout实例化一个self.dropout对象.self.dropout nn.Dropout(pdropout)def forward(self, x, sublayer):前向逻辑函数中, 接收上一个层或者子层的输入作为第一个参数将该子层连接中的子层函数作为第二个参数# 我们首先对输出进行规范化然后将结果传给子层处理之后再对子层进行dropout操作# 随机停止一些网络中神经元的作用来防止过拟合. 最后还有一个add操作 # 因为存在跳跃连接所以是将输入x与dropout后的子层输出结果相加作为最终的子层连接输出.return x self.dropout(sublayer(self.norm(x))) size 512 dropout 0.2 head 8 d_model 512 # 令x为位置编码器的输出 x pe_result mask Variable(torch.zeros(8, 4, 4))# 假设子层中装的是多头注意力层, 实例化这个类 self_attn MultiHeadedAttention(head, d_model)# 使用lambda获得一个函数类型的子层 sublayer lambda x: self_attn(x, x, x, mask) sc SublayerConnection(size, dropout) sc_result sc(x, sublayer) print(sc_result) print(sc_result.shape)7. 编码器层 作为编码器的组成单元, 每个编码器层完成一次对输入的特征提取过程, 即编码过程. # 使用EncoderLayer类实现编码器层 class EncoderLayer(nn.Module):def __init__(self, size, self_attn, feed_forward, dropout):它的初始化函数参数有四个分别是size其实就是我们词嵌入维度的大小它也将作为我们编码器层的大小, 第二个self_attn之后我们将传入多头自注意力子层实例化对象, 并且是自注意力机制, 第三个是feed_froward, 之后我们将传入前馈全连接层实例化对象, 最后一个是置0比率dropout.super(EncoderLayer, self).__init__()# 首先将self_attn和feed_forward传入其中.self.self_attn self_attnself.feed_forward feed_forward# 如图所示, 编码器层中有两个子层连接结构, 所以使用clones函数进行克隆self.sublayer clones(SublayerConnection(size, dropout), 2)# 把size传入其中self.size sizedef forward(self, x, mask):forward函数中有两个输入参数x和mask分别代表上一层的输出和掩码张量mask.# 里面就是按照结构图左侧的流程. 首先通过第一个子层连接结构其中包含多头自注意力子层# 然后通过第二个子层连接结构其中包含前馈全连接子层. 最后返回结果.x self.sublayer[0](x, lambda x: self.self_attn(x, x, x, mask))return self.sublayer[1](x, self.feed_forward) size 512 head 8 d_model 512 d_ff 64 x pe_result dropout 0.2 self_attn MultiHeadedAttention(head, d_model) ff PositionwiseFeedForward(d_model, d_ff, dropout) mask Variable(torch.zeros(8, 4, 4)) el EncoderLayer(size, self_attn, ff, dropout) el_result el(x, mask) print(el_result) print(el_result.shape) 8. 编码器 编码器用于对输入进行指定的特征提取过程, 也称为编码, 由N个编码器层堆叠而成. 编码器的代码分析 # 使用Encoder类来实现编码器 class Encoder(nn.Module):def __init__(self, layer, N):初始化函数的两个参数分别代表编码器层和编码器层的个数super(Encoder, self).__init__()# 首先使用clones函数克隆N个编码器层放在self.layers中self.layers clones(layer, N)# 再初始化一个规范化层, 它将用在编码器的最后面.self.norm LayerNorm(layer.size)def forward(self, x, mask):forward函数的输入和编码器层相同, x代表上一层的输出, mask代表掩码张量# 首先就是对我们克隆的编码器层进行循环每次都会得到一个新的x# 这个循环的过程就相当于输出的x经过了N个编码器层的处理. # 最后再通过规范化层的对象self.norm进行处理最后返回结果. for layer in self.layers:x layer(x, mask)return self.norm(x)# 第一个实例化参数layer, 它是一个编码器层的实例化对象, 因此需要传入编码器层的参数 # 又因为编码器层中的子层是不共享的, 因此需要使用深度拷贝各个对象. size 512 head 8 d_model 512 d_ff 64 c copy.deepcopy attn MultiHeadedAttention(head, d_model) ff PositionwiseFeedForward(d_model, d_ff, dropout) dropout 0.2 layer EncoderLayer(size, c(attn), c(ff), dropout)# 编码器中编码器层的个数N N 8 mask Variable(torch.zeros(8, 4, 4)) en Encoder(layer, N) en_result en(x, mask) print(en_result) print(en_result.shape)解码器部分实现 输出部分实现
http://www.w-s-a.com/news/375307/

相关文章:

  • 微信公众号微网站建设专业网站建设出售
  • 怎么用wordpress建立自己的网站加强校园网站建设
  • 用什么做网站后台的织梦网站怎么上传
  • 怎么获取网站数据做统计百度快照推广有效果吗
  • 淘宝领卷网站什么做制造网站开发
  • 如何做com的网站网站建设投标书模板
  • 郑州网络营销网站优化网站技术方案怎么写
  • 济南市住房和城乡建设局网站wordpress mnews主题
  • ios开发网站app网站建设企业有哪些方面
  • 网站主页 优帮云深圳代做网站后台
  • app 与网站网站建设要做什么
  • 厦门国外网站建设公司郑州核酸点推vip服务
  • 免费网线seo外链怎么做
  • 宽带技术网网站wordpress widget hook
  • 山西省住房和城乡建设厅网站报名wordpress添加标签插件
  • 网站怎么自己做外贸网站案例
  • 做网站的优势公司网站怎么做站外链接
  • 海城网站制作建设精准营销的营销方式
  • 北京短视频拍摄公司重庆网站seo推广公司
  • 广州免费推广网站建设4399网页游戏大全
  • 网站的构架与组成建站公司兴田德润
  • php网站部署步骤邯郸哪有做网站的
  • 做设计什么设计比较好的网站南充市住房和城乡建设局考试网站
  • 郑州做系统集成的公司网站龙岩
  • 厦门SEO_厦门网站建设网络营销课程视频
  • vs 2015 网站开发开网店在线咨询
  • 前端如何优化网站性能大学学校类网站设计
  • 中国铁路建设投资公司网站熊学军中国it外包公司排名前50
  • 房产网站的建设广州推广排名
  • 湟源县网站建设wordpress删除未分类