RL强化学习从小白到老鸟(二)——手撕GPT(零基础保姆级教学) 📅 发布时间:2026/9/18 13:48:39 👁 浏览次数: 标题RL强化学习从小白到老鸟(二)——手撕GPT零基础保姆级教学第三篇让贪吃蛇训练更稳定、更容易复现简介帮老师带几个研究生他们想学GPT和强化学习正好我两者都略懂正在研究结合两者优势创建一个全新的结构就先手撕GPT做个教学贴吧。我发布的所有文章均是免费的如果变成VIP了那一定是平台干的请私聊我修改设置为全部可见GPT简介学过GPT的可以直接跳过本节。GPT是基于 Transformer 架构的预训练模型它通过大规模语料库的训练能够捕捉到复杂的语言特征和模式。这使得GPT在文本生成任务中能够产生连贯且具有一定逻辑的文本。GPT 可以适用于多种文本生成任务如故事生成、自动文章写作、对话生成等。其预训练的特性使得它在微调后能够迅速适应新的文本生成任务减少了任务特定模型训练的需求。GPT 是一个自回归模型它在生成文本时会考虑到之前所有生成的内容这保证了文本的连贯性和逻辑性。它每次生成一个词或一个字符然后将其作为下一步生成的上下文的一部分这种方式很适合逐步构建整体一致的长文本。随着模型规模的增大GPT表现出了显著的性能提升。例如从GPT-2到GPT-3模型的层数和参数量大幅增加使其在各种语言任务上的表现都有显著提升。这证明了GPT架构对于规模扩展的高适应性。由于GPT的零样本zero-shot和少样本few-shot学习能力它能够在没有大量特定任务数据的情况下调整并执行多种语言任务。这是通过其在大规模数据集上的预训练实现的使其学会了广泛的语言模式和知识。架构最简GPT结构多头自注意力Multi-Head Self-Attention:在这个模块中模型可以同时处理不同子空间的信息。这允许模型在生成每个词时考虑到句子中的多个上下文关系。逐位置前馈网络Position-wise Feed-Forward Networks:这是Transformer每一层中的一个组成部分它对每一个位置的表示进行独立的变换增加了模型的表达能力。正弦位置编码Sinusoidal Positional Encoding:Transformer模型没有像循环神经网络那样的递归结构因此需要位置编码来提供序列中各元素的位置信息。GPT使用的是正弦和余弦函数的组合来编码位置。填充掩码Padding Mask:在处理不等长的句子时较短的句子需要用特殊的填充符号如pad填充填充掩码用于在自注意力层忽略这些填充符号的影响。后续掩码Look-ahead Mask 或 Causal Mask:用于确保在生成当前词时只使用之前的词这对于任何自回归模型如GPT都是必要的以防止信息的未来泄露。解码器层Decoder Layer:GPT模型实际上只使用了Transformer的解码器架构的修改版没有编码器-解码器注意力每个解码器层包括多头自注意力和前馈网络。解码器Decoder:解码器是由多个解码器层堆叠而成整个结构被训练来预测下一个可能的词。如何手搓一个麻雀级别的GPT通过前面的介绍大家应该知道了GPT的基本结构接下来就代码实操一下导入模块importtorchimporttorch.nnasnnimporttorch.optimasoptim#这段代码很简单就是将pytorch的网络模块和优化器模块导入方便后续训练使用定义模型classSimpleGPT(nn.Module):# SimpleGPT通过继承nn.Module模块(所有神经网络的基类)。def__init__(self,vocab_size,d_model,num_heads,num_layers,dropout0.1):super(SimpleGPT,self).__init__()# init初始化方法用于初始化模型的参数如词汇表大小vocab_size,模型维度d_model,d多头注意力机制的头数num_heads,Transformer的层数num_layer以及dropout比率。self.embeddingnn.Embedding(vocab_size,d_model)# 创建嵌入层将词汇表中的每个词标记(通常是整数索引)映射为一个固定大小的向量。d_model是嵌入向量的维度这个嵌入向量在训练过程会被优化。self.pos_encodernn.Parameter(torch.zeros(1,1024,d_model))# 创建位置编码是Transformer模型的一个重要部分它给每个输入的词元添加一个唯一的向量这有助于模型理解词源在序列中的位置#这里我们定义了一个参数它的大小是(1,1024, d_model),其中1024是假设的最大序列长度(num_token)d_model是每个位置编码向量的维度。# Encoder Layerslayernn.TransformerEncoderLayer(d_modeld_model,nheadnum_heads,dropoutdropout bitch_firstTrue)# 定义类一个Transformer编码器层然后使用这个层创建一个多层的Transformer编码器d_model是特征维度self.transformer_encodernn.TransformerEncoder(layer,num_layersnum_layers)# num_heads是多头注意力机制的头数dropout是在训练中随机丢弃的节点比率防止过拟合num_layers是层数self.outnn.Linear(d_model,vocab_size)# 输出是一个全连接层将编码器的输出转回词汇表大小的空间用于预测每个位置可能得下一个词标记。defforward(self,src,src_mask):定义了模型如何从输入到输出的数据流 srcself.embedding(src)self.pos_encoder[:,:src.size(1)]# 输入数据src通过嵌入层并与位置编码相加outputself.transformer_encoder(src,src_mask)# 然后传递给编码器层src_mask用来在多头注意力汇总遮盖不应该被模型看到的未来未知的信息。outputself.out(output)# 通过输出层生成预测结果returnoutputdefgenerate_square_subsequent_mask(self,sz):生成遮罩生成一个三角形矩阵用于在训练的过程中遮盖序列的未来未知保证模型在做预测时只能利用之前的信息。这是实现自回归模型(如GPT)的关键部分mask(torch.triu(torch.ones(sz,sz))1).transpose(0,1)# 生成上三角矩阵然后转置。maskmask.float().masked_fill(mask0,float(-inf)).masked_fill(mask1,float(0.0))# 将布尔矩阵转换为浮点数并填充特定值returnmask逐行注解看不懂的话建议换个赛道了 哈哈哈开个玩笑初始化模型参数# 设置参数vocab_size100# 小词库的大小d_model512# 嵌入维度num_heads8# 注意力头数num_layers2# Transformer层数dropout0.1# Dropout比率modelSimpleGPT(vocab_size,d_model,num_heads,num_layers,dropout)# 实例化模型类定义优化器和损失函数criterionnn.CrossEntropyLoss()# 创建交叉熵损失函数optimizeroptim.Adam(model.parameters(),lr0.001)# 创建Adama优化器训练模型# 这段代码展示了一个简单的训练循环用于训练之前定义的SimleGPT模型。model.train()# 将模型设置为训练模式forepochinrange(10):# 举例训练10个epoch每个epoch中模型会看到所有的训练数据一次srctorch.randint(0,vocab_size,(10,32))# 随机生成一些数据数据生成是为了用于训练这里应该替换为真实数据训练。src_maskmodel.generate_square_subsequent_mask(src.size(0))outputmodel(src,src_mask)losscriterion(output.view(-1,vocab_size),src.view(-1))optimizer.zero_grad()loss.backward()optimizer.step()print(fEpoch{epoch}Loss{loss.item()})# 打印损失值。# 这个训练循环是机器学习训练过程的典型表示涵盖了数据准备、模型调用、损失计算、反向传播和参数更新等关键步骤。这个是一个测试项目用一些随机生成的数据验证模型的运行情况。想要文本类数据项目的源码关注点赞私聊发邮箱。 前面我都是放在github,结果大家只拿代码不点赞生气气了╭(╯^╰)╮RL学习的项目源码均会放在github仓库,欢迎大家关注本文的源码也会在后面空了(看到star了)更新到github建议大家先看我的上一篇文章有助于理解本文(想要你的star)star越多更新越多都是干货真实项目面试宝典RL强化学习从小白到老鸟(一)——速通贪吃蛇游戏