Transformer 中的 Encoder 机制

Transformer中的encoder和decoder在训练和推理过程中究竟是如何工作的 Transformer中的encoder和decoder在训练和推理过程中究竟是如何工作的苦苦冲浪,找不到答案Transformer结构(随便冲浪均可查到)Transformer推理过程Transformer训练过程 苦苦冲浪,找不到答案 之前学习transformer的时候就不是很理解encoder和decoder在训练和推理过程中是如何工作的,四处查询也没有讲的很详细,很多文章和视频都是encoder讲很多,到了decoder就一带而过了,后来在b站看了大佬讲解的transformer源码,终于明白了e 阅读详情

大家好,今天和各位分享一下 Transformer 中的 Encoder 部分涉及到的知识点:Word Embedding、Position Embedding、self_attention_Mask

本篇博文是对上一篇 《Transformer代码复现》的解析,强烈建议大家先看一下:https://blog.youkuaiyun.com/dgvv4/article/details/125491693

由于 Transformer 中涉及的知识点比较多,之后的几篇会介绍 Decoder 机制、损失计算、实战案例等。


1. Word Embedding

 Word Embedding 可以理解为让句子中的每个单词都能狗对应一个特征向量。

该部分的代码如下:

首先指定特征序列和目标序列的长度,src_len=[2, 4] 代表特征序列中包含 2 个句子,第一个句子中有 2 个单词,第二个句子中有 4 个单词。

指定序列的单词库大小为 8,即序列中所有的单词都是在 1~8 之间选取。接下来随机生成每个句子中包含的单词,得到特征序列 src_seq 和目标序列 tgt_seq。

由于每个句子的长度不一样,比如特征序列 src_seq 中第一个句子有 2 个单词,第二个句子有 4 个单词。在送入至 Word Embedding 之前,需要把所有句子的长度给统一,在第一个句子后面填充 2 个 0,使得特征序列中的两个句子等长。


   
  1. import torch
  2. from torch import nn
  3. from torch.nn import functional as F
  4. import numpy as np
  5. max_word_idx = 8 # 特征序列和目标序列的单词库由8种单词组成
  6. model_dim = 6 # wordembedding之后,每个单词用长度为6的向量来表示
  7. # ------------------------------------------------------ #
  8. #(1)构建序列,序列的字符以索引的形式表示
  9. # ------------------------------------------------------ #
  10. # 指定序列长度
  11. src_len = torch.Tensor([ 2, 4]).to(torch.int32) # 特征序列的长度为2
  12. tgt_len = torch.Tensor([ 4, 3]).to(torch.int32) # 目标序列的长度为2
  13. # 特征序列种有2个句子,第一个句子包含2个单词,第二个句子有4个单词
  14. print(src_len, tgt_len) # tensor([2, 4]) tensor([4, 3])
  15. # 创建序列,句子由八种单词构成,用1~8来表示
  16. src_seq = [ torch.randint( 1, max_word_idx, (L,)) for L in src_len ] # 创建特征序列
  17. tgt_seq = [ torch.randint( 1, max_word_idx, (L,)) for L in tgt_len ] # 创建目标序列
  18. print(src_seq, tgt_seq)
  19. # [tensor([6, 4]), tensor([6, 4, 1, 7])] # 特征序列,第一个句子有2个单词,第二个句子有4个单词
  20. # [tensor([4, 2, 1, 3]), tensor([6, 5, 1])] # 目标特征,第一个句子有4个单词,第二个句子有3个单词
  21. # 每个句子的长度都不一样,需要填充0变成相同长度
  22. new_seq = [] # 保存padding后的序列
  23. for seq in src_seq: # 遍历特征序列中的每个句子
  24. sent = F.pad(seq, pad=( 0, max(src_len)- len(seq))) # 右侧填充0保证所有句子等长
  25. sent = torch.unsqueeze(sent, dim= 0) # 变成二维张量[max_src_len]==>[1, max_src_len]
  26. new_seq.append(sent) # 保存padding后的序列
  27. for seq in tgt_seq: # 遍历目标序列中的每个句子
  28. sent = F.pad(seq, pad=( 0, max(tgt_len)- len(seq)))
  29. sent = torch.unsqueeze(sent, dim= 0) # 变成二维张量[max_tgt_len]==>[1, max_tgt_len]
  30. new_seq.append(sent) # 保存padding后的序列
  31. # 由于特征序列和目标序列都保存在list中,变成tensor类型,在axis=0维度堆叠
  32. src_seq = torch.cat(new_seq[: 2], dim= 0) # 特征序列
  33. tgt_seq = torch.cat(new_seq[ 2:], dim= 0) # 目标序列
  34. print(src_seq, src_seq.shape) # 查看特征序列 shape=[2,4], 序列中有2个句子,每个句子4个单词
  35. print(tgt_seq, tgt_seq.shape) # 目标序列同上
  36. '''
  37. src_seq = [[6, 4, 0, 0], [6, 4, 1, 7]]
  38. src_seq.shape = [2, 4]
  39. tgt_seq = [[4, 2, 1, 3], [6, 5, 1, 0]]
  40. tgt_seq.shape = [2, 4]
  41. '''
  42. # ------------------------------------------------------ #
  43. #(2)word-embadding
  44. # ------------------------------------------------------ #
  45. # 实例化embedding类, 一共8种单词,考虑到padding填充的0,因此单词表一共9种, 每种单词的特征向量长度为6
  46. src_embedding_tabel = nn.Embedding(num_embeddings=max_word_idx+ 1, embedding_dim=model_dim) # 特征序列的Embedding
  47. tgt_embedding_tabel = nn.Embedding(num_embeddings=max_word_idx+ 1, embedding_dim=model_dim) # 目标序列的Embedding
  48. print(src_embedding_tabel.weight) # shape=[9,6], 第一行是分配给padding=0,剩下的八行分类给8种单词
  49. print(tgt_embedding_tabel)
  50. # 从embedding表中获取每个单词的特征向量表示,单词0的特征向量为[-1.1004, -1.4062, 1.1152, 0.9054, 1.0759, 1.1679]
  51. src_embedding = src_embedding_tabel(src_seq) # ()代表使用该实例的前向传播方法
  52. tgt_embedding = src_embedding_tabel(tgt_seq)
  53. # 打印每个句子对应的embedding张量,每一行代表句子中每个单词对应的embedding
  54. print(src_embedding)
  55. # shape=[2,4,6] 代表目标序列由2个句子,每个句子有4个单词,每个单词用长度为6的向量表示
  56. print(src_embedding.shape)

首先我们的单词库是由 1~8 组成的,后面又多了 padding 的 0 填充,因此现在单词库中一共有 9 种,通过 nn.Embedding() 为 9 种单词分别构建一个长度为 model_dim=6 的特征向量。如下面的第一个矩阵,单词 0 用向量 [-1.1004, -1.4062, 1.1152, 0.9054, 1.0759, 1.1679] 来表示。

接下来通过前向传播为序列中的每个单词编码,见下面的第二个矩阵,如:src_seq = [[6, 4, 0, 0], [6, 4, 1, 7]] 中,第一个单词 6 用向量 [-0.9194, 0.3338, 0.7215, -1.2306, 0.9512, -0.1863] 来表示。

特征序列的 shape 由原来的 [2, 4] 变成 [2, 4, 6],即特征序列中有 2 个句子,每个句子包含 4 个单词,每个单词用长度为 6 的向量来表示。


   
  1. # src_embedding_tabel.weight
  2. Parameter containing:
  3. tensor([[- 1.1004, - 1.4062, 1.1152, 0.9054, 1.0759, 1.1679],
  4. [- 0.0360, - 1.6144, 0.9804, 0.4482, 1.8510, 0.3860],
  5. [ 0.2041, 0.1746, 0.4676, - 1.3600, 0.3034, 1.7780],
  6. [ 0.5122, - 1.3473, - 0.2934, - 0.7200, 1.9156, - 1.5741],
  7. [ 0.7404, - 1.1773, 1.3077, - 0.7012, 1.9886, - 1.3895],
  8. [- 1.8221, - 0.7920, 0.9091, 0.4478, - 0.3373, - 1.5661],
  9. [- 0.9194, 0.3338, 0.7215, - 1.2306, 0.9512, - 0.1863],
  10. [- 1.3199, - 1.4841, 1.0171, 0.8665, 0.3624, 0.4318],
  11. [- 1.7603, - 0.5641, 0.3106, - 2.7896, 1.6406, 1.9038]],
  12. requires_grad= True)
  13. # src_embedding
  14. Embedding( 9, 6)
  15. tensor([[[- 0.9194, 0.3338, 0.7215, - 1.2306, 0.9512, - 0.1863],
  16. [ 0.7404, - 1.1773, 1.3077, - 0.7012, 1.9886, - 1.3895],
  17. [- 1.1004, - 1.4062, 1.1152, 0.9054, 1.0759, 1.1679],
  18. [- 1.1004, - 1.4062, 1.1152, 0.9054, 1.0759, 1.1679]],
  19. [[- 0.9194, 0.3338, 0.7215, - 1.2306, 0.9512, - 0.1863],
  20. [ 0.7404, - 1.1773, 1.3077, - 0.7012, 1.9886, - 1.3895],
  21. [- 0.0360, - 1.6144, 0.9804, 0.4482, 1.8510, 0.3860],
  22. [- 1.3199, - 1.4841, 1.0171, 0.8665, 0.3624, 0.4318]]],
  23. grad_fn=<EmbeddingBackward>)

2. Position Embedding

注意力机制更多的是关注词与词之间的重要程度,而不关心句子中词语位置的顺序关系。

例如:“从北京开往济南的列车”与“从济南开往北京的列车”,词向量表示并不能对两句话中的“北京”进行区分,其编码是一样的。但是在真实语境中,两个词语所表达的语义并不相同,第一个表示的是起始站,另一个表示的是终点站,两个词所表达的语义信息并不相同。

因此以 Attention 结构为主的大规模模型都需要位置编码来辅助学习顺序信息。

Transformer 模型通过对输入向量额外添加位置编码来解决这个问题。Transformer 模型中采用正弦位置编码。利用正弦和余弦函数来生成位置编码信息,将位置编码信息与词嵌入的值相加,作为输入送到下一层。

计算公式如下所示,其中 pos 代表行,i 代表列,d_model 代表每个位置索引用多长的向量表示。

偶数列:PE(pos, 2i) = sin(pos/10000^{2i/d_{model}})

奇数列:PE(pos, 2i+1) = cos(pos/10000^{2i/d_{model}})

代码如下:


   
  1. import torch
  2. from torch import nn
  3. from torch.nn import functional as F
  4. import numpy as np
  5. max_word_idx = 8 # 特征序列和目标序列的单词库由8种单词组成
  6. model_dim = 6 # wordembedding之后,每个单词用长度为6的向量来表示
  7. # ------------------------------------------------------ #
  8. #(1)构建序列,序列的字符以索引的形式表示
  9. # ------------------------------------------------------ #
  10. # 指定序列长度
  11. src_len = torch.Tensor([ 2, 4]).to(torch.int32) # 特征序列的长度为2
  12. tgt_len = torch.Tensor([ 4, 3]).to(torch.int32) # 目标序列的长度为2
  13. # 特征序列种有2个句子,第一个句子包含2个单词,第二个句子有4个单词
  14. print(src_len, tgt_len) # tensor([2, 4]) tensor([4, 3])
  15. # 创建序列,句子由八种单词构成,用1~8来表示
  16. src_seq = [ torch.randint( 1, max_word_idx, (L,)) for L in src_len ] # 创建特征序列
  17. tgt_seq = [ torch.randint( 1, max_word_idx, (L,)) for L in tgt_len ] # 创建目标序列
  18. print(src_seq, tgt_seq)
  19. # [tensor([6, 4]), tensor([6, 4, 1, 7])] # 特征序列,第一个句子有2个单词,第二个句子有4个单词
  20. # [tensor([4, 2, 1, 3]), tensor([6, 5, 1])] # 目标特征,第一个句子有4个单词,第二个句子有3个单词
  21. # 每个句子的长度都不一样,需要填充0变成相同长度
  22. new_seq = [] # 保存padding后的序列
  23. for seq in src_seq: # 遍历特征序列中的每个句子
  24. sent = F.pad(seq, pad=( 0, max(src_len)- len(seq))) # 右侧填充0保证所有句子等长
  25. sent = torch.unsqueeze(sent, dim= 0) # 变成二维张量[max_src_len]==>[1, max_src_len]
  26. new_seq.append(sent) # 保存padding后的序列
  27. for seq in tgt_seq: # 遍历目标序列中的每个句子
  28. sent = F.pad(seq, pad=( 0, max(tgt_len)- len(seq)))
  29. sent = torch.unsqueeze(sent, dim= 0) # 变成二维张量[max_tgt_len]==>[1, max_tgt_len]
  30. new_seq.append(sent) # 保存padding后的序列
  31. # 由于特征序列和目标序列都保存在list中,变成tensor类型,在axis=0维度堆叠
  32. src_seq = torch.cat(new_seq[: 2], dim= 0) # 特征序列
  33. tgt_seq = torch.cat(new_seq[ 2:], dim= 0) # 目标序列
  34. print(src_seq, src_seq.shape) # 查看特征序列 shape=[2,4], 序列中有2个句子,每个句子4个单词
  35. print(tgt_seq, tgt_seq.shape) # 目标序列同上
  36. '''
  37. src_seq = [[6, 4, 0, 0], [6, 4, 1, 7]]
  38. src_seq.shape = [2, 4]
  39. tgt_seq = [[4, 2, 1, 3], [6, 5, 1, 0]]
  40. tgt_seq.shape = [2, 4]
  41. '''
  42. # ------------------------------------------------------ #
  43. #(2)position-embadding 奇数列使用cos,偶数列使用sin
  44. # 正余弦位置编码的泛化能力较强、具有对称性、每个位置的embedding是确定的
  45. # ------------------------------------------------------ #
  46. # ==1== embedding
  47. # 构造行矩阵, pos对应序列的长度, 特征序列中每个句子包含4个单词
  48. pos_mat = torch.arange( max(src_len)) # 对应句子中的每个单词的位置
  49. # 变成二维矩阵,每一行是一样的
  50. pos_mat = torch.reshape(pos_mat, shape=[- 1, 1]) # shape=[4,1]
  51. print(pos_mat)
  52. # 构造列矩阵, 对应公式中的2i/d_model
  53. # 每个单词用长度为6的向量来表示(d_model=6),而i代表特征向量中的每一列,2i代表偶数列
  54. i_mat = torch.arange( 0,model_dim, 2).reshape(shape=( 1,- 1)) / model_dim
  55. print(i_mat) # tensor([[0.0000, 0.3333, 0.6667]])
  56. # 公式中的10000的i_mat次方
  57. i_mat = torch. pow( 10000, i_mat)
  58. print(i_mat) # tensor([[ 1.0000, 21.5443, 464.1590]])
  59. # 初始化位置编码,4行6列的张量,4代表序列长度(一句话中单词个数),6代表特征列个数(一个单词用长度为6的向量表示)
  60. pe_embedding_tabel = torch.zeros(size=( max(src_len), model_dim))
  61. print(pe_embedding_tabel)
  62. # 偶数列
  63. pe_embedding_tabel[:, 0:: 2] = torch.sin(pos_mat / i_mat)
  64. print(pe_embedding_tabel)
  65. # 奇数列
  66. pe_embedding_tabel[:, 1:: 2] = torch.cos(pos_mat / i_mat)
  67. print(pe_embedding_tabel) # 完成正余弦位置编码
  68. # 实例化embedding层,对每句话中的4个单词使用长度为6的向量来编码
  69. pe_embedding = nn.Embedding(num_embeddings= max(src_len), embedding_dim=model_dim)
  70. print(pe_embedding.weight)
  71. # 改写embedding层的权重,并且训练过程中不更新权重
  72. pe_embedding.weight = nn.Parameter(pe_embedding_tabel, requires_grad= False)
  73. print(pe_embedding.weight) # shape=[4,6]
  74. # ==2== 位置索引
  75. # 构建句子中每个单词的位置索引
  76. src_pos = [torch.unsqueeze(torch.arange( max(src_len)), dim= 0) for _ in src_len]
  77. tgt_pos = [torch.unsqueeze(torch.arange( max(tgt_len)), dim= 0) for _ in tgt_len]
  78. print(src_pos, # [tensor([[0, 1, 2, 3]]), tensor([[0, 1, 2, 3]])]
  79. tgt_pos) # [tensor([[0, 1, 2, 3]]), tensor([[0, 1, 2, 3]])]
  80. # 将列表类型变成tensor类型,在axis=0维度concat
  81. src_pos = torch.cat(src_pos, dim= 0)
  82. tgt_pos = torch.cat(tgt_pos, dim= 0)
  83. print(src_pos, # tensor([[0, 1, 2, 3], [0, 1, 2, 3]])
  84. tgt_pos) # tensor([[0, 1, 2, 3], [0, 1, 2, 3]])
  85. # 位置编码, 最长的一句话中有4个单词,每个单词的位置用长度为6的向量来表示
  86. src_pe_embedding = pe_embedding(src_pos)
  87. tgt_pe_embedding = pe_embedding(tgt_pos)
  88. print(src_pe_embedding.shape) # torch.Size([2, 4, 6])
  89. print(src_pe_embedding)

构造特征序列和目标序列的方法和第一小节一样,就不赘述了。

Position Embedding 是对句子中单词的位置索引做的编码,而 Word Embedding 是对句子中的单词做编码。

首先初始化一个 4 行 6 列的矩阵,其中行代表位置索引,列代表每个位置用多少长的向量来表示。根据公式,奇数列用 cos 函数代替,偶数列用 sin 函数代替。得到正余弦编码后的张量。接下来实例化 nn.Embedding(),将随机初始化的 embedding 层的权重矩阵换成正余弦位置编码后的权重,并且在训练过程中不更新位置权重。如下面第一个矩阵所示。

然后构造特征序列中句子的每个单词的位置索引 src_pos,每个句子包含 4个单词,因此单词位置索引就是 [0,1,2,3],其中 src_pos.shape = [2, 4] 代表特征序列有 2 个句子,每个句子有 4 个单词位置索引。经过 Position Embedding 层之后,shape 变成 [2, 4, 6],代表特征序列中有 2 个句子,每个句子包含 4 个单词位置,每个单词位置由长度为 6 的特征向量来表示。如下面第二个矩阵所示。


   
  1. # pe_embedding.weight (正余弦位置编码)
  2. tensor([[ 0.0000, 1.0000, 0.0000, 1.0000, 0.0000, 1.0000],
  3. [ 0.8415, 0.5403, 0.0464, 0.9989, 0.0022, 1.0000],
  4. [ 0.9093, - 0.4161, 0.0927, 0.9957, 0.0043, 1.0000],
  5. [ 0.1411, - 0.9900, 0.1388, 0.9903, 0.0065, 1.0000]])
  6. # src_pe_embedding
  7. tensor([[[ 0.0000, 1.0000, 0.0000, 1.0000, 0.0000, 1.0000],
  8. [ 0.8415, 0.5403, 0.0464, 0.9989, 0.0022, 1.0000],
  9. [ 0.9093, - 0.4161, 0.0927, 0.9957, 0.0043, 1.0000],
  10. [ 0.1411, - 0.9900, 0.1388, 0.9903, 0.0065, 1.0000]],
  11. [[ 0.0000, 1.0000, 0.0000, 1.0000, 0.0000, 1.0000],
  12. [ 0.8415, 0.5403, 0.0464, 0.9989, 0.0022, 1.0000],
  13. [ 0.9093, - 0.4161, 0.0927, 0.9957, 0.0043, 1.0000],
  14. [ 0.1411, - 0.9900, 0.1388, 0.9903, 0.0065, 1.0000]]])

3. self_attention_Mask

这里介绍 Encoder 中 Muti_head_attention 中的 mask 方法

由于每个特征句子的长度不同,经过 padding 之后每个句子的长度一致。在特征序列中,第一个句子只包含 2 个单词,用 1 来表示,后两个填充的位置用 0 值来表示。因此将特征序列表示为 [[1, 1, 0, 0], [1, 1, 1, 1]],其 shape=[2, 4]

接下来构建邻接矩阵 shape=[2, 4, 4],其中有 4 行和 4 列的单词,邻接矩阵中每个元素代表两两单词之间的对应关系,若为 1 则代表有效单词,若为 0 则代表无效单词,是通过 padding 得到的。

接下来只要将邻接矩阵中所有元素为 0 的区域都打上掩码,将该位置的元素值变得非常小。

代码如下:


   
  1. import torch
  2. from torch.nn import functional as F
  3. # ------------------------------------------------------ #
  4. # 构造一个mask shape=[batch, max_src_len, max_src_len], 值为1或负无穷
  5. # ------------------------------------------------------ #
  6. # 指定序列长度
  7. src_len = torch.Tensor([ 2, 4]).to(torch.int32) # 特征序列的长度为2
  8. # 特征序列有2个句子,第一个句子的长度为2,第二个句子的长度为4
  9. print(src_len) # tensor([2, 4])
  10. # 构建有效编码器的位置, 如:第一句话只包含2个单词,那么只有前2个元素的值为1
  11. valid_encoder_pos = [torch.ones(L) for L in src_len]
  12. print(valid_encoder_pos) # [tensor([1., 1.]), tensor([1., 1., 1., 1.])]
  13. # 由于在训练时要求每个句子包含的单词数量相同,因此通过padding将所有特征句子的长度都变成最大有效句子长度
  14. new_encoder_pos = [] # 保存padding后的句子
  15. for sent in valid_encoder_pos: # 遍历每个句子
  16. sent = F.pad(sent, pad=( 0, max(src_len)- len(sent))) # 右侧填充0保持序列长为4
  17. sent = torch.unsqueeze(sent, dim= 0) # 变成二维张量[max_src_len]==>[1, max_src_len]
  18. new_encoder_pos.append(sent) # 保存padding后的序列
  19. valid_encoder_pos = torch.cat(new_encoder_pos, dim= 0)
  20. print(valid_encoder_pos) # tensor([[1., 1., 0., 0.],[1., 1., 1., 1.]])
  21. # [2,4] ==> [2,4,1]
  22. valid_encoder_pos = torch.unsqueeze(valid_encoder_pos, dim=- 1)
  23. # 邻接矩阵得到矩阵之间的对应关系 [2,4,1]@[2,1,4]==>[2,4,4]
  24. valid_encoder_pos_matrix = torch.bmm(valid_encoder_pos, valid_encoder_pos.transpose( 1, 2))
  25. print(valid_encoder_pos_matrix) # 第一个句子只有两个有效单词,后面两个单词都是padding,
  26. # 得到无效矩阵, 为1的位置都是padding得到的, 是无效的
  27. invalid_encoder_pos_matrix = 1 - valid_encoder_pos_matrix
  28. # 变成布尔类型, True代表无效区域,需要mask
  29. mask_encoder_self_attention = invalid_encoder_pos_matrix.to(torch. bool)
  30. print(mask_encoder_self_attention)
  31. # 构造输入特征,2个句子,每个句子4个单词,每个单词用长度为4的向量表示
  32. score = torch.randn( 2, 4, 4)
  33. # 对mask中为True的地方,对应score中的元素都变成很小的负数
  34. masked_score = score.masked_fill(mask_encoder_self_attention, - 1e10)
  35. print(score)
  36. print(masked_score)

下面的第一个矩阵是经过 padding 后的特征序列的邻接矩阵;第二个矩阵是随机生成的输入序列;第三个矩阵是经过掩码后的序列,将 mask 的元素值变得非常小,这样在计算交叉熵损失时,经过 softmax 函数后这些做过 padding 的元素变得非常小,在反向传播过程中对模型的整体影响较小。


   
  1. # 邻接矩阵,0代表是是经过padding后的区域
  2. tensor([[[ 1., 1., 0., 0.],
  3. [ 1., 1., 0., 0.],
  4. [ 0., 0., 0., 0.],
  5. [ 0., 0., 0., 0.]],
  6. [[ 1., 1., 1., 1.],
  7. [ 1., 1., 1., 1.],
  8. [ 1., 1., 1., 1.],
  9. [ 1., 1., 1., 1.]]])
  10. # 随机构造的输入特征score, shape=[2,4,4]
  11. tensor([[[- 0.1509, - 0.2514, - 0.5393, 2.0241],
  12. [- 0.1525, - 1.9199, 0.6847, - 1.8795],
  13. [ 1.0322, 0.0772, 0.9992, - 0.1082],
  14. [ 1.4347, 1.4084, - 0.6897, - 0.2518]],
  15. [[- 0.0109, 0.0328, 1.5458, 0.9872],
  16. [ 0.0314, - 1.3659, - 0.6441, - 1.6444],
  17. [- 0.0487, 0.0438, 0.0576, - 1.1691],
  18. [ 0.3475, - 0.1329, - 1.0455, - 0.9671]]])
  19. # 打上 mask 之后的 score
  20. tensor([[[- 1.5094e-01, - 2.5137e-01, - 1.0000e+10, - 1.0000e+10],
  21. [- 1.5255e-01, - 1.9199e+00, - 1.0000e+10, - 1.0000e+10],
  22. [- 1.0000e+10, - 1.0000e+10, - 1.0000e+10, - 1.0000e+10],
  23. [- 1.0000e+10, - 1.0000e+10, - 1.0000e+10, - 1.0000e+10]],
  24. [[- 1.0883e-02, 3.2843e-02, 1.5458e+00, 9.8725e-01],
  25. [ 3.1395e-02, - 1.3659e+00, - 6.4410e-01, - 1.6444e+00],
  26. [- 4.8689e-02, 4.3825e-02, 5.7644e-02, - 1.1691e+00],
  27. [ 3.4751e-01, - 1.3290e-01, - 1.0455e+00, - 9.6713e-01]]])
Transformer详解encoder 最近刚好梳理了下transformer,今天就来讲讲它~Transformer是谷歌大脑2017年在论文attention is all you need中提出来的seq2seq模型,它的本质就是由编码器和解码器组成,今天的主角则是其中的编码器(在BERT预训练模型中也只用到了编码器部分)如下图所示,这个模块的输入为 𝑋 (每一行代表一个句子,batchsize有多大就有多少行),我们将从输入到隐藏层按照从1到4的顺序逐层来看一下各个维度的变化。 阅读详情

相关推荐

Transformer Encoder 详解

位置编码是 Transformer 模型的关键组件,用于向模型注入序列的位置信息(因自注意力机制本身是位置无关的)。其中 (\text{head}_i = \text{Attention}(Q W_i^Q, K W_i^K, V W_i^V))。通过位置编码,Transformer 能够明确感知序列中元素的顺序,这是其成功替代 RNN 的关键设计之一。维度保持为 (d_{\text{model}}),无需额外变换。Transformer Encoder 由。

m0_59156726的博客 1394

Transformer简介

transformer模型简介,包括编码器(encoder)、解码器(decoder)、训练以及模型训练中的tips。

qq_44733706的博客 9844

对于Transformer的Mask机制的再思考——Encoder部分

Mask机制 虽然Mask机制在NLP领域是一个十分常见的操作,但是过去并没有仔细思考它的意义。最近参加了阿里天池的一个关于医学影像报告异常检测的数据竞赛。本质上是一个关于文本的多标签分类任务。在这个任务中,我尝试使用Transformer的Encoder结构作为基础来构建分类模型。为了巩固以及加深理解,没有使用PyTorch自带的Transformer模型,而是选择手动搭建。 Encoder中的Mask 在Encoder部分,涉及到的mask主要指self-attention过程中,在计算每个token的

weixin_44607838的博客 4385

2. Transformer基础学习--encoder模块

encoder基本模块的介绍,有多头自注意力,FFN,残差和归一化

cs_SZHS的博客 3166

【深度解析】Transformer中Encoder与Decoder的交互机制及其在NLP任务中的应用

本文深度解析了Transformer模型中Encoder与Decoder的交互机制,重点探讨了注意力机制在两者协作中的关键作用。通过机器翻译、文本摘要等NLP任务的实际案例,展示了这种交互机制如何动态捕捉输入输出的关联,提升模型性能。文章还分享了注意力头专业化、交互效率优化等高级技巧,为开发者提供实用参考。

weixin_29250403的博客 610

Transformer模型结构分析:Encoder、Decoder以及注意力机制详解

Transformer模型由论文[1]提出,其基本思想是使用注意力机制代替循环神经网络(RNN)或卷积神经网络(CNN),是一种基于序列到序列(Seq2seq)的机器翻译、文本摘要、对话系统等任务的成功范例。Transformer模型使用全连接层代替RNN和CNN的门控结构,并用多头注意力机制进行了改进,能够在捕捉全局上下文信息的同时,还保持输入输出序列之间的独立性。本文将从原理上和代码实现两个角度出发,详细解析Transformer模型的编码器、解码器及注意力机制的设计原理和具体操作步骤。

AI天才研究院 2581

Transformer架构中Encoder与Decoder的核心差异与协作机制

自注意力机制是Transformer模型的核心技术,通过计算序列元素间的关联权重实现上下文建模。其工程价值体现在并行计算能力和长距离依赖捕捉上,广泛应用于机器翻译、文本生成等序列转换任务。Transformer采用Encoder-Decoder双模块架构,其中Encoder通过多头自注意力实现双向编码,Decoder则结合掩码注意力和跨模态注意力完成自回归生成。在BERT、GPT等预训练模型中,这种分工协作模式展现出强大的特征提取和序列生成能力。关键技术实现包含位置编码、残差连接等设计,有效解决了传统RNN

weixin_30765505的博客 391

[nlp] transformer中的mask机制(encoder:mask pad=inf,decoder:mask下三角矩阵为true)

对于Transformer中的mask理解_weixin_44729115的博客-优快云博客 transformer中的mask操作,可以分成encoder端和decoder端 Enocoder中的mask mask的size 是 batch_size*seq_length 对于小于最大长度的句子进行补0操作,对于大于最大长度的句子进行截断操作。 将mask中的0变成负无穷,与计算的注意力矩阵相加,原来有单词的注意力不变,没有单词的位置变换成负无穷,进行softmax运算时exp()的结果变为0。

心宝的博客 1516

3DETR进阶技巧:Masked Transformer Encoder与查询机制调优策略

3DETR作为端到端的3D目标检测Transformer模型,其核心优势在于通过Transformer架构直接处理点云数据并输出检测结果。本文将深入探讨两个关键进阶优化方向:Masked Transformer Encoder的高效实现与查询机制(Query Mechanism)的调优策略,帮助开发者提升模型性能与推理效率。 ## Masked Transformer Encoder:动态注意力

gitblog_01139的博客 835

主板USB接口全部失效解决方案(通用串行总线USB控制器有黄色叹号)保姆级教程亲测有效

通用串行总线控制器总是有叹号解决办法 办公室的崩腾时代老电脑,疫情期间没人用,来了开机之后发现鼠标键盘都用不了,本以为是主机放时间长出了问题,后来想起来就百度了“鼠标键盘都失效”的标题,结果发现了“串行总线控制器总是感叹号”的关联问题。正好办公室电脑都装有teamviwer常用来远程办公(在家偷懒)。所以通过远程发现电脑室可以运行的。并在控制面板发现:通用串行总线控制器总是感叹号,插入外设时USB无反应。如图:​ 并且右键选中其中一个,点击最后一个选项:“属性” 可以发现“设备状态”中会提示“由...

xiao_bai_0_0的博客 2万+

绕过ROS2!在RDK X5上直接用Python调用海康相机C++ SDK的避坑指南

本文详细介绍了在RDK X5上绕过ROS2,直接使用Python调用海康相机C++ SDK的轻量化方案。通过Cython构建Python绑定,提取海康相机SDK核心组件,实现高效图像采集。文章涵盖环境准备、Cython接口设计、编译系统配置及性能优化技巧,特别适合ARM64平台开发者。

weixin_33712987的博客 249

【深度学习】(3) Transformer 中的 Encoder 机制,附Pytorch完整代码

大家好,今天和各位分享一下 Transformer 中的 Encoder 部分涉及到的知识点:Word Embedding、Position Embedding、self_attention_Mask本篇博文是对上一篇 《Transformer代码复现》的解析,强烈建议大家先看一下:https://blog.youkuaiyun.com/dgvv4/article/details/125491693由于 Transformer 中涉及的知识点比较多,之后的几篇会介绍 Decoder 机制、损失计算、实战案例等。 Wor

博观而约取,厚积而薄发 3120

双有源桥DC-DC变换器:原理、软开关与移相控制深度解析

隔离型DC-DC变换器是电力电子系统的核心部件,通过高频变压器实现电气隔离与电压匹配,保障系统安全与灵活适配。其工作原理基于功率半导体器件的开关动作,通过调制策略控制能量传输。该技术的核心价值在于实现高效、高功率密度的电能转换,并支持双向能量流动,这对于提升系统整体能效和运行灵活性至关重要。在新能源储能、电动汽车V2G及数据中心供电等场景中,双向能量流成为刚性需求,推动了如双有源桥等先进拓扑的应用。本文聚焦于双有源桥这一实现高效双向隔离变换的“明星”方案,深入剖析其利用移相控制实现软开关的机理。通过分析谐振

weixin_34195142的博客 379

深入解析BERT模型:从Attention机制到Transformer Encoder的实战应用

本文深入解析了BERT模型的核心原理与实战应用。通过剖析其基于Transformer Encoder的架构,重点阐述了Attention机制如何让模型学会关注上下文重点,并详细介绍了其预训练任务(MLM和NSP)的设计思想。文章还以文本分类为例,提供了完整的BERT微调实战代码与避坑指南,帮助开发者快速上手这一强大的NLP模型。

weixin_29192211的博客 224

我每天如何使用 ChatGPT

我偶尔会用这个功能作为开始。我本人非常喜欢阅读,让 ChatGPT 来概括所有文章,感觉就像身处于但丁描述的地狱的某个层次那样痛苦。然而,有时一些文章实在是太啰嗦、无聊,或者写得让人不愉快(比如一个无趣记者对一个让人讨厌的人进行的漫无焦点的采访)。我需要获取这些文章中的一些信息,以便保持信息的更新和了解。在晚期资本主义的广告经济下,很多文章只在一个段落里提供新信息,其余都是无聊的填充内容,只是为了展示糟糕的广告,这实在是对人们的时间和生命的一种浪费。我有几次利用 ChatGPT 来。

KevinDai007的博客 3784

从零搭建A股量化交易系统:开源框架选型与实战部署指南

本文详细介绍了从零搭建A股量化交易系统的完整流程,重点分析了开源框架VNPY和QMT的选型与实战部署。内容涵盖系统架构设计、策略开发、性能优化及实盘过渡方案,为开发者提供了一套完整的A股实盘量化交易解决方案,助力高效构建稳定可靠的量化交易系统。

sugar的博客 1271

Qwen-Image模型结构详解:Text Encoder与Transformer模块协作机制

Qwen-Image作为通义千问系列的图像生成基础模型,其核心优势在于复杂文本渲染和精准图像编辑能力。本文将深入剖析模型的两大核心模块——Text Encoder与Transformer的内部结构及协作机制,揭示文本到图像的转化奥秘。 ## Text Encoder模块架构解析 Text Encoder承担着将文本描述转化为机器可理解的向量表示的关键任务。从[text_encoder/conf

gitblog_00976的博客 1198

三种 绘制奈奎斯特曲线 的方法

如何绘制Nyquist曲线 提供三种绘制方法,其中使用最广泛的是概略图绘制方法 ①解析法绘制 ②概略图法绘制 ③MATLAB绘制

weixin_46664967的博客 6万+

8.1 LLM 原理:Transformer、注意力机制、Encoder/Decoder

文章摘要: 本文用直观类比解析Transformer架构的核心原理,避开复杂数学公式。传统RNN因顺序处理和长程依赖问题效率低下,Transformer通过自注意力机制实现全局并行计算,让每个词动态关注其他词(如通过Q/K/V向量建模关系)。多头注意力进一步捕捉多维度语义,位置编码解决词序问题(RoPE支持长文本)。Encoder(BERT)擅长理解任务,Decoder(GPT)主导生成领域,后者因预训练简单和生成能力成为主流。尽管Transformer存在O(n²)计算复杂度等问题,其设计思想仍是现代大模

慢慢 358

TMS320F28335调试跟踪的问题:DSP从上电复位,一直到执行main()的第一条语句之间,都干了些什么,以及CCS调试时程序查找的问题

🏆 本文收录于《全栈Bug调优(实战版)》专栏,致力于分享我在项目实战过程中遇到的各类Bug及其原因,并提供切实有效的解决方案。无论你是初学者还是经验丰富的开发者,本文将为你指引出一条更高效的Bug修复之路,助你早日登顶,迈向财富自由的梦想🚀!同时,欢迎大家关注、收藏、订阅本专栏,更多精彩内容正在持续更新中。让我们一起进步,Up!Up!Up!    备注: 部分问题/难题源自互联网,经过精心筛选和整理,结合数位十多年大厂实战经验资深大佬经验总结所得,数条可行方案供所需之人参考。

**My Coding Family** 1213

IEEE Journal of Biomedical and Health Informatics(JBHI)投稿经验分享

《IEEE Journal of Biomedical and Health Informatics投稿经验分享》详细记录了在影响因子6.7的中科院一区期刊JBHI的投稿历程(2025.1-5月,历时4个月)。文章重点分析:1)审稿特色:4位审稿人差异显著,领域专家意见专业但要求严苛;2)修改要点:需重视大修(补充实验/原理阐述),并注意将回复内容同步至正文;3)期刊特点:送审率高但审稿严格,常规投稿周期约4-5个月;4)实用建议:建议首次大修全力以赴,善用AI工具辅助写作,避免拖延。

LiRongLu_的博客 5078

【技术解析】Transformer架构中Encoder与Decoder的“对话”机制:从注意力连接到信息流

本文深入解析了Transformer架构中Encoder与Decoder的核心交互机制。重点剖析了Encoder-Decoder Attention层如何作为动态“翻译官”,使解码器在生成每个词时都能精准检索并融合编码器输出的全部上下文信息,从而实现从注意力连接到信息流的有效“对话”。这一机制是Transformer在机器翻译、文本摘要等序列任务上取得卓越性能的关键。

plant的博客 165

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Transformer深度解析:Encoder与Decoder的结构差异与协作机制

注意力机制是现代深度学习模型的核心基础,它通过动态分配权重让模型聚焦关键信息。Transformer架构基于自注意力(Self-Attention)实现了序列建模的突破,其中Encoder和Decoder承担不同职责:Encoder通过双向注意力编码完整上下文,Decoder则通过带掩码的单向注意力实现自回归生成,并通过交叉注意力(Cross-Attention)与Encoder协作。理解二者的结构差异、Mask机制及训练推理阶段的信息流动,是掌握BERT、GPT等大模型的关键。在实际应用中,Encoder

weixin_29081101的博客 233

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Transformers快速入门代码解析(五):注意力机制——Transformer Encoder:Positional Embeddings

理解的基础上为代码添加了注释!

xzs1210652636的博客 548

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

【PytorchLearning】NLP入门笔记之手写Transformer Encoder内部机制

本文主要从Transformer Encoder中Word embedding生成、Position embedding机制和self-attention中的mask机制三个方面的源码及原理进行解读

日拱一卒,功不唐捐 841
上一篇: Transformer 中的 Decoder 机制
下一篇: OpenCV图像处理常用算法
onnx
博客等级 码龄5年 1万+粉丝 416原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值