[Algorithm] 深蓝学院第八节笔记 构建一个GPT模型

写在前面

本文为第八节学习笔记,只记录重点笔记结合网上其他信息总结而成,不放出课件和代码,推荐购买课程可以学习到很多知识
课前疑惑:
1 不同的Transformer结构 BERT GPT 区别

  • 为什么有的只有encoder 有的只有decoder
    2 如何训练调整参数
    3 贪心解码和集束解码是什么

本章训练数据处理和调试见http://t.csdnimg.cn/EtEiK

BERT GPT

BERT很好的细节讲解
在这里插入图片描述

开始以Encoder only 为主的以BERT(Bidirectional Encoder Representations from Transformers)为代表的大模型领先于Decoder Only 的GPT。后续发展反转。
Encoder only输出学习到的向量编码用于后续的学习使用
还有一系列端到端的大模型 Encoder-Decoder

在这里插入图片描述
预训练:用大量的好的文本来进行预先学习,学习有着不同的目标。

BERT:它通过双向编码方式,在无监督的情况下学习语言特征表示,即用海量的训练文本进行mark操作,遮蔽不同的部分训练,所谓双向是可以看到masked区域前后的信息

GPT:挡住后面的根据训练去生成

为什么BERT是Encoder GPT是Decoder结构

Encoder:将输入文章句子序列抽象成一个高纬的向量表示

Decoder:将高度维度的表示转换回原始表示

Bert 主要考虑上下文,从整个句子出发去理解语义,GPT是一个生成模型,给出文本预测下一个词,是训练生存任务,从左到右生成,gpt只考虑前面不考虑后面,和decoder原理类似,GPT的难度大一些。GPT的单向是通过后续掩码实现的。

基础模型 Foundation Model

在这里插入图片描述

先训练出来一个基础模型,然后根据应用去配适
数据和模型的规模化可以释放提升基础模型的潜力

GPT 结构

比transformer简单,因为去除了编码器,而可以加大Decoder的层数。

transfomer的核心:自注意力和位置编码还有并行处理的能力

GPT 用爬虫上网寻求数据,生成语料。在训练阶段使用teaching forcing:加入start标志sos使Source的文本右移一位,而Target使前面不加入start标志,输入和target形成错位。
同时在自注意力的时候使用掩码,让自注意力的时候看不见后面“未来”信息

在这里插入图片描述对比Transformer少了编码器和编码器解码器注意力,

代码解读

学习了部分BEV知识后在次回头看,感觉有必要把处理的每一步再理清以下,同时作为自我复习。

注意力

自注意力

使用线性变换后的原始文本 qkv 计算注意力,qk计算得分score然后作填充掩码和后续掩码,归一化之后可以作加权和。

在这里插入图片描述这个图太好了

Q, K, V: 输入的查询(Query)、键(Key)、值(Value)张量,具有形状 [batch_size, n_heads, len_q/k/v, dim_q=k/v]。这里 n_heads 表示注意力头的数量,len_q/k/v 表示序列长度,dim_q=k/v 表示查询、键、值的维度。

attn_mask: 注意力掩码,形状和 scores 相同,用于屏蔽不应考虑的位置。掩码中的值为1的位置会被替换为一个极小的负数。

scores: 注意力分数,通过缩放的点积得到。这里使用了 torch.matmul 进行矩阵乘法,除以 np.sqrt(d_k) 进行缩放。

scores.masked_fill_: 使用掩码将不需要考虑的位置的注意力分数替换为负无穷(-1e9)。这样根据softmax函数类型就变成了很小的值。

weights: 通过 softmax 函数对注意力分数进行归一化,得到权重。

context: 通过权重加权求和得到的上下文向量,表示了模型关注的部分。

最后,返回计算得到的上下文向量 context 和注意力分数 weights。

多头注意力:把一个向量分成不同子空间,然后通过注意力抓住不同的信息

在这里插入图片描述
init中的线性层操作只针对最后一个维度也就是features。如此通过线性变换和view操作后,就得到了多头注意力的输入,这里view-1 自动推断会的出原始qkv的长度,而目的是把多头分出来即n_heads, d_k。同时准备一个和多头数量一样的mask,其他维度与qs ks 一致。通过之前定义的点积缩放注意力,得到注意力上喜爱文权重。

contiguous是保证张量在储存空间中是连续的。在残差链接和归一化后输出
扩展

Q:softmax|normalizatoin|standardization 区别 (更多见我的收集https://blog.csdn.net/weixin_46479223/article/details/132784268)
A:
Softmax:
作用:Softmax 主要用于将一组数值转化为概率分布,使得所有值在0到1之间,且和为1。在深度学习中,通常用于多类别分类问题的输出层。

Normalization(归一化):
    作用:Normalization 的目的是将数据缩放到特定范围或分布,以便提高模型的稳定性和训练效果。有不同的归一化方法,例如 Batch Normalization 和 Layer Normalization。

Standardization(标准化):
    作用:标准化也是一种数据缩放的方法,将数据转换为均值为0,标准差为1的分布,有助于处理不同尺度的特征。

总结:

Softmax 用于转换数值为概率分布。
Normalization 是数据缩放的通用术语,可以包括各种方法,如 Batch Normalization 和 Layer Normalization。
Standardization 是一种特定的标准化方法,将数据转换为具有特定均值和标准差的分布。

逐位置前向传播网络

更关注每一个局部位置的作用而不使用位置关系
GPT的解读:

假设我们有一个包含5个单词的源语言句子:{“我 喜欢 学习 机器学习”}

逐位置前向传播网络的作用是对每个单词的表示进行逐位置的非线性变换。

无逐位置前向传播网络的情况:
    对于单词"学习",自注意力机制直接计算其与其他所有单词的关系,涉及到所有单词的计算。

有逐位置前向传播网络的情况:
    对于单词"学习",先通过逐位置前向传播网络进行非线性变换。这个变换可以使模型更好地捕捉到该单词的局部特征和上下文相关信息。
    然后,自注意力机制在这个变换后的表示上进行计算,关注于局部相关性,而非整个序列。

具体来说,逐位置前向传播网络是自注意力层中每个位置独立应用的前馈神经网络(Feedforward Neural Network)。其主要作用包括:

增加非线性能力:通过逐位置前向传播,每个位置的特征都会经过一个非线性激活函数,从而引入更多的非线性变换。这有助于模型学习更复杂、更抽象的特征表示。

降低计算复杂性:自注意力机制中的计算复杂度与序列长度关系较大,引入逐位置前向传播网络可以降低计算复杂性,使模型更容易扩展到处理长序列。

增强特征的局部性:逐位置前向传播网络强调了每个位置的局部信息,有助于模型更好地捕捉输入序列中的局部模式和结构。

总体而言,逐位置前向传播网络的引入是为了在保持模型表达能力的同时,更有效地处理长序列和提高计算效率。这种结构的选择往往是为了在模型性能和计算成本之间取得平衡。
在这里插入图片描述

扩展
Q:一维卷积和卷积核大小为1的话 和 线性层的区别
GPT: A:卷积核大小改为1,意味着一维卷积核在每个位置上只关注当前位置的特征,而不考虑邻近位置。这将使一维卷积层的作用类似于全连接层,因为每个位置的输出只依赖于相应位置的输入。


import torch
import torch.nn as nn


input_sequence = torch.randn(1, 3, 5)  # 假设一个 batch 大小为1,特征维度为3,序列长度为5


conv1d_layer = nn.Conv1d(in_channels=3, out_channels=6, kernel_size=1)  # 输入特征维度为3,输出特征维度为6,卷积核大小为1


output_conv1d = conv1d_layer(input_sequence)
print("Conv1d output shape with kernel size 1:", output_conv1d.shape)

在这个例子中,一维卷积核的大小被设置为1,这使得每个位置的输出只依赖于相应位置的输入。因此,output_conv1d 的形状将与输入的形状相同 (1, 6, 5),其中 (1, 6, 5) 表示 (batch_size, out_channels, sequence_length)。

这时,一维卷积层的作用类似于一个全连接层,因为它在每个位置上只执行线性变换而不考虑邻近位置。

正弦位置编码

用于在自注意力机制中为输入序列的每个位置添加位置编码。通过嵌套的循环遍历所有位置和维度,计算每个位置和维度对应的角度值。通过对偶数和奇数维度分别应用正弦和余弦函数,得到最终的正弦位置编码表,帮助模型在没有显式顺序信息的情况下理解输入序列中元素的相对位置

for pos_i in range(n_position):
        for hid_j in range(embedding_dim):
            angle = pos_i / np.power(10000, 2 * (hid_j // 2) / embedding_dim)
            sinusoid_table[pos_i, hid_j] = angle    

    sinusoid_table[:, 0::2] = np.sin(sinusoid_table[:, 0::2])  
    sinusoid_table[:, 1::2] = np.cos(sinusoid_table[:, 1::2]) 

填充位置掩码 && 后续位置掩码

Padding Mask 和 Look Ahead Mask的区别

填充掩码(Padding Mask):
    当处理可变长度的序列时,为了使这些序列能够组成一个批次进行并行计算,通常会对较短的序列进行填充(padding)以匹配批次中最长的序列长度。
    填充掩码的目的是告诉模型忽略填充部分的信息。因为填充部分通常是无关紧要的,将其考虑进去可能会干扰模型的学习。
    在自注意力机制中,填充掩码会将填充位置的注意力权重设为负无穷,从而使这些位置的信息对当前位置的输出没有影响。

在这里插入图片描述

后续位置掩码(Look-Ahead Mask):
    在序列生成任务中,模型在预测当前位置的标记时不能使用未来位置的信息,以避免信息泄漏。后续位置掩码就是用来屏蔽掉未来位置的信息。
    在自注意力机制中,后续位置掩码会将当前位置之后的位置的注意力权重设为负无穷,这样模型在计算当前位置的时候就不会考虑到未来的信息。

在这里插入图片描述

解码器层 &&解码器

利用之前的组件搭建一个解码器层类,就是图中蓝框区域
在这里插入图片描述一下是解码器整体

在这里插入图片描述以下为解码器整体
在这里插入图片描述

训练

用wikitest数据集 ,定义数据整理类,定义train类,定义train和test流程,
和之前RNN估计yawrate流程大同小异

然后定义了对结果的处理

贪心解码 集束解码

对于输出概率的解码
和图搜索类似,贪心可能局部最优,集束则考虑全局,作者的方法保留三列组合的结果
从老师结果看,不同的最后处理对于同然的神经网络的输出结果差别还挺大。

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值