PyTorch笔记 - Attention Is All You Need

Posted SpikeKing

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PyTorch笔记 - Attention Is All You Need相关的知识,希望对你有一定的参考价值。

Transformer:

  • 模型结构:
    • Encoder:
      • Position Embedding:引入位置信息,DNN结构,默认没有考虑位置信息
      • Multi-head Self-attention:模型中计算量最大的部分,Head(头)的数量是8,任意两两字符之间,计算相关性。
      • LayerNorm & Residual:层归一化,和残差连接
      • Feedforward Nenual Network:Self-attention位置混合,FFN通道混合,类似通道分离卷积(空间混合)和1x1卷积(通道混合),第1层2028,第2层512
    • Decoder:Teacher Forcing
      • Casual(因果) Multi-head Self-attention,下三角矩阵
      • Memory-base Multi-head Cross-attention,Decoder是Query,Encoder是Key和Value,Key是转置
  • 使用类型:
    • Encoder only:BERT、分类任务、非流式任务
    • Decoder only:**GPT(Generative Pre-trained Transformer)**系列、语言建模、自回归生成任务、流式任务
    • Encoder-Decoder:机器翻译、语音识别
  • 特定:
    • 无先验假设,例如局部关联性、有序建模
    • 核心在于自注意力机制,平方复杂度
    • 数据量的要求与先验假设的程度成反比

先验假设(归纳偏置)数据(样本)量,成反比:

  • 归纳偏置(Inductive Bias):在学习算法中,当学习器去预测其未遇到过的输入结果时,所做的一些假设的集合。
  • Transformer计算量以序列长度的平方成正比。
  • 基于先验假设,优化模型,例如降低计算量,要注入先验假设。
  • Transformer长时建模性长,并行计算,对比与RNN或LSTM

Transformer的Loss函数

交叉熵:torch.nn.CrossEntropyLoss

PyTorch中,CrossEntropy的输入,期望Class放在第2维,Batch放在第1维,可以是类别索引(Class indices),也可以是类别的概率(Probabilities for each class)。

reduction默认是mean,例如6个单词的平均交叉熵。reduction是none,默认交叉熵:先做softmax,再做-ln(prob)

参考:CLIP算法的Loss详解 和 交叉熵CrossEntropy实现

# 定义softmax函数
def softmax(x):
    return np.exp(x) / np.sum(np.exp(x))

# 利用numpy计算
def cross_entropy_np(x, y):
    x_softmax = [softmax(x[i]) for i in range(len(x))]
    x_log = [np.log(x_softmax[i][y[i]]) for i in range(len(y))]
    loss = - np.sum(x_log) / len(y)
    return loss

# 测试逻辑
x = [[1.9269, 1.4873, 0.9007, -2.1055]]
y = [[2]]
v1 = cross_entropy_np(x, y)
print(f"v1: v1")

x = torch.unsqueeze(torch.Tensor(x), dim=0)
x = x.transpose(1, 2)  # CrossEntropy输入期望: Class放在第2维,Batch放在第1维

y = torch.Tensor(y)
y = y.to(torch.long)  # label的类型为long

v2 = F.cross_entropy(x, y, reduction="none")
print(f"v2: v2")

随机种子:torch.manual_seed(42),每个rand之前,都需要添加

构建序列建模的Mask,如下:

import torch
import torch.nn as nn
import torch.nn.functional as F

import random
import numpy as np

# batch_size=2, seqlen=3, vocab_size=4
torch.manual_seed(42)
logits = torch.randn(2, 3, 4)
logits = logits.transpose(1, 2)
print(f'[Info] logits.shape: logits.shape')
print(f'[Info] logits: \\nlogits')

# logits_softmax = F.softmax(logits, dim=1)
# print(f'[Info] logits_softmax: \\nlogits_softmax')

# batch_size=2, vocab_size=4
torch.manual_seed(42)
label = torch.randint(0, 4, (2, 3))
print(f'[Info] label.shape: label.shape')
print(f'[Info] label: \\nlabel')
# loss: torch.nn.CrossEntropyLoss -> F.cross_entropy
# (2x4x3) + (2x3) = (2x3)
val = F.cross_entropy(logits, label, reduction="none")
print(f"[Info] val.shape: val.shape")
print(f"[Info] val: \\nval")

# 在loss中, 增加mask, 与ignore_index参数功能类似,默认值是-100
tgt_len = torch.Tensor([2,3]).to(torch.int32)
mask = [F.pad(torch.ones(L), (0, max(tgt_len)-L)) for L in tgt_len]
mask = torch.stack(mask)
print(f"[Info] mask: \\nmask")
val = F.cross_entropy(logits, label, reduction="none") * mask
print(f"[Info] val.shape: val.shape")
print(f"[Info] val: \\nval")

# 与ignore_index参数功能类似,默认值是-100
label[0, 2] = -100
val = F.cross_entropy(logits, label, reduction="none")
print(f"[Info] val.shape: val.shape")
print(f"[Info] val: \\nval")

以上是关于PyTorch笔记 - Attention Is All You Need的主要内容,如果未能解决你的问题,请参考以下文章

PyTorch笔记 - Attention Is All You Need

PyTorch笔记 - Attention Is All You Need

PyTorch笔记 - Attention Is All You Need

PyTorch笔记 - Seq2Seq + Attention 算法

PyTorch笔记 - Seq2Seq + Attention 算法

PyTorch笔记 - Seq2Seq + Attention 源码