LLM理论到实践

绪论

对于语言模型的介绍

语言模型的目标就是建模自然语言的概率分布

词汇表 V 上的语言模型,由函数 P(w1w2...wm) 表示,可以形式化 地构建为词序列 w1w2...wm 的概率分布,表示词序列 w1w2...wm 作为一个句子出现的可能性大小。 由于联合概率 P(w1w2...wm) 的参数量十分巨大,直接计算 P(w1w2...wm) 非常困难。

 所以我们要考虑P的存储与计算

为了减少 P(w1w2...wm) 模型的参数空间,可以利用句子序列通常情况下从左至右的生成过 程进行分解,使用链式法则得到:

P(w1w2...wm) = P(w1)P(w2|w1)P(w3|w1w2)· · · P(wm|w1w2...wm−1) = Ym i=1 P(wi |w1w2 · · · wi−1) 

由此,w1w2...wm 的生成过程可以看作单词逐个生成的过程。首先生成 w1,之后根据 w1 生成 w2, 再根据 w1 和 w2 生成 w3,以此类推,根据前 m − 1 个单词生成最后一个单词 wm。例如:对于句 子 “把努力变成一种习惯”的概率计算,使用公式可以转化为:

P(把 努力 变成 一种 习惯) =P(把) × P(努力|把) × P(变成|把 努力)× P(一种|把 努力 变成) × P(习惯|把 努力 变成 一种)

回想隐马尔可夫定理,我们还可以将这个式子进一步简化,就简化成假设任意单词w_i出现的几率只跟过去的n-1个词有关,这样的表示方法也叫作n元语法 

尽管 n 元语言模型能缓解句子概率为 0 的问题,但语言是由人和时代创造的,具备无穷的可 能性,再庞大的训练语料也无法覆盖所有的 n-gram,而训练语料中的零频率并不代表零概率。因 此,需要使用平滑技术(Smoothing)来解决这一问题,对所有可能出现的字符串都分配一个非零 的概率值,从而避免零概率问题。平滑是指为了产生更合理的概率,对最大似然估计进行调整的 一类方法,也称为数据平滑(Data Smoothing)。平滑处理的基本思想是提高低概率,降低高概率, 使整体的概率分布趋于均匀。这类方法通常称为统计语言模型

大语言模型基础

现在的大语言模型一般都使用transformer架构

由于之前的笔记中提到过,现在就对于其拆解进行研究

嵌入层

首先是嵌入层,嵌入层将每个单词转化为其对应的向量表示,transformer架构没有使用基于循环的方式建模文本输入,所以并没有位置信息。

所以我们一个非常重要的操作就是使用位置编码

我们使用之前提到过的位置编码加入到词嵌入中

pytorch代码如下

class PositionalEncoder(nn.Module):
def __init__(self, d_model, max_seq_len = 80):
super().__init__()
self.d_model = d_model
# 根据 pos 和 i 创建一个常量 PE 矩阵
pe = torch.zeros(max_seq_len, d_model)
for pos in range(max_seq_len):
for i in range(0, d_model, 2):
pe[pos, i] = math.sin(pos / (10000 ** ((2 * i)/d_model)))
pe[pos, i + 1] = math.cos(pos / (10000 ** ((2 * (i + 1))/d_model)))
pe = pe.unsqueeze(0)
self.register_buffer('pe', pe)
def forward(self, x):
# 使得单词嵌入表示相对大一些
x = x * math.sqrt(self.d_model)
# 增加位置常量到单词嵌入表示中
seq_len = x.size(1)
x = x + Variable(self.pe[:,:seq_len], requires_grad=False).cuda()

我们可以看到,d_model是一个设定好的超参,在嵌入层中将每个单词映射到n维的空间

然后我们使用设定好的位置编码方式进行位置编码

pe = pe.unsqueeze(0) 表示对 pe 进行维度扩展,将原本形状为 (seq_len, d_model) 的张量 pe 在第0个维度上添加一个大小为1的维度,得到形状为 (1, seq_len, d_model) 的新张量 pe。这一操作通常是为了满足模型的输入要求,例如在 Transformer 模型中,位置编码器需要和输入嵌入拼接在一起,而输入嵌入的形状为 (batch_size, seq_len, d_model),因此需要在位置编码器的形状上加上一个大小为1的维度以适应输入嵌入的形状。

self.register_buffer('pe', pe) 是 pytorch 中用于注册模型参数的方法。它将 pe 张量注册为模型的一个缓冲区,并分配给模型一个名称 'pe'。缓冲区是模型状态的一部分,但缓冲区的值不会被反向传播更新,也不会被torch.optim优化器进行优化。在模型训练过程中,缓冲区的值保持不变。通常,使用缓冲区来保存一些与模型状态相关的信息,例如位置编码器中的位置编码矩阵就是通过这种方式保存的。

我们对forward中的x进行放缩是为了让他更匹配位置编码

  • 21
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值