从头构建gpt2 基于Transformer

news2024/11/16 10:41:23

从头构建gpt2 基于Transformer

VX关注{晓理紫|小李子},获取技术推送信息,如感兴趣,请转发给有需要的同学,谢谢支持!!

如果你感觉对你有所帮助,请关注我。

源码获取 VX关注晓理紫并回复“chatgpt-0”

在这里插入图片描述

  • 头文件以及超参数
import torch
import torch.nn as nn
from torch.nn import functional as F
# 加入为了扩大网络进行修改 head ,注意力、前向网络添加了dropout和设置蹭数目
#超参数
batch_size = 64
block_size = 34 #块大小 现在有34个上下文字符来预测
max_iters = 5000
eval_interval = 500
learning_rate=3e-4
device = 'cuda' if torch.cuda.is_available() else 'cpu'
eval_iters = 200
n_embd = 384  #嵌入维度
n_head = 6    #有6个头,每个头有284/6维
n_layer = 6   # 6层
dropout = 0.2

torch.manual_seed(1337)
  • 数据处理

with open('input.txt','r',encoding='utf-8') as f:
    text = f.read()

chars = sorted(list(set(text)))
vocab_size = len(chars)

stoi = {ch:i for i,ch in enumerate(chars)}

itos = {i:ch for i,ch in enumerate(chars)}

encode = lambda s : [stoi[c] for c in s]
decode = lambda l: ''.join([itos[i] for i in l])

data = torch.tensor(encode(text),dtype=torch.long)

n = int(0.9*len(data))
train_data = data[:n]
val_data = data[n:]

def get_batch(split):
    data = train_data if split=="train" else val_data
    ix = torch.randint(len(data)-batch_size,(batch_size,))
    x = torch.stack([data[i:i+block_size] for i in ix])
    y = torch.stack([data[i+1:i+block_size+1] for i in ix])
    x,y = x.to(device),y.to(device)
    return x,y
  • 估计损失
@torch.no_grad()
def estimate_loos(model):
    out={}
    model.eval()
    for split in ['train','val']:
        losses = torch.zeros(eval_iters)
        for k in range(eval_iters):
            x,y = get_batch(split)
            logits,loss = model(x,y)
            losses[k] = loss.mean()
        out[split] = losses.mean()
    model.train()
    return out
  • 单头注意力
class Head(nn.Module):
    """one head of self-attention"""

    def __init__(self, head_size):
        super(Head,self).__init__()
        self.key = nn.Linear(n_embd,head_size,bias=False)
        self.query = nn.Linear(n_embd,head_size,bias=False)
        self.value= nn.Linear(n_embd,head_size,bias=False)
        self.register_buffer('tril',torch.tril(torch.ones(block_size,block_size)))
        self.dropout = nn.Dropout(dropout)
    def forward(self,x):
        B,T,C = x.shape
        k = self.key(x) #(B,T,C)
        q = self.query(x) #(B,T,C)

        wei = q@k.transpose(-2,-1)*C**-0.5  #(B,T,C) @ (B,C,T)-->(B,T,T)
        wei = wei.masked_fill(self.tril[:T,:T]==0,float('-inf'))#(B,T,T)
        wei = F.softmax(wei,dim=-1) #(B,T,T)
        wei = self.dropout(wei)
        v= self.value(x)
        out = wei@v
        return out
  • 多头注意力

在这里插入图片描述

class MultiHeadAttention(nn.Module):
    """multiple heads of self-attention in parallel"""
    def __init__(self, num_heads,head_size) -> None:
        super(MultiHeadAttention,self).__init__()
        self.heads = nn.ModuleList([Head(head_size) for _ in range(num_heads)])
        self.proj = nn.Linear(n_embd,n_embd) #投影,为了方便使用惨差跳连
        self.dropout = nn.Dropout(dropout)
    def forward(self,x):
        out = torch.cat([h(x) for h in self.heads],dim=-1)
        out = self.dropout(self.proj(out))
        return out
  • 前馈网络

在这里插入图片描述

class FeedFoward(nn.Module):
    """a simple linear layer followed by a non-linearity"""
    def __init__(self,n_embd):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(n_embd,4*n_embd), #从512变成2048
            nn.ReLU(),
            nn.Linear(4*n_embd,n_embd), #从2048变成512
            nn.Dropout(dropout),  #Dropout 是可以在惨差链接之前加的东西
         )
    def forward(self,x):
        out = self.net(x)
        return out

在这里插入图片描述

class Block(nn.Module):
    """Transformer block:communication followed by computation"""
    def __init__(self, n_embd,n_head) -> None:
        #n_embd 需要嵌入维度中的嵌入数量
        #n_head 头部数量
        super().__init__()
        head_size = n_embd//n_head
        self.sa = MultiHeadAttention(n_head,head_size) #通过多头注意力进行计算
        self.ffwd = FeedFoward(n_embd) # 对注意力计算的结果进行提要完成
        self.ln1 = nn.LayerNorm(n_embd) #层规范  对于优化深层网络很重要 论文Layer Normalization
        self.ln2 = nn.LayerNorm(n_embd) #层规范
    def forward(self,x):
        # 通过使用残差网络的跳连进行
        x = x + self.sa(self.ln1(x)) 
        x = x + self.ffwd(self.ln2(x))
        return x
  • 整个语言模型
class BigramLangeNodel(nn.Module):
    def __init__(self):
        super(BigramLangeNodel,self).__init__()
        self.token_embedding_table = nn.Embedding(vocab_size,n_embd) #令牌嵌入表,对标记的身份进行编码
        self.position_embedding_table = nn.Embedding(block_size,n_embd) #位置嵌入表,对标记的位置进行编码。从0到block_size大小减一的每个位置将获得自己的嵌入向量
        self.blocks = nn.Sequential(*[Block(n_embd,n_head=n_head) for _ in range(n_layer)]) #通过n_layer设置构建的曾数
        self.ln_f = nn.LayerNorm(n_embd)
        self.lm_head = nn.Linear(n_embd,vocab_size)  #进行令牌嵌入到logits的转换,这是语言头
    def forward(self,idx,targets=None):
        B,T = idx.shape
        tok_emb= self.token_embedding_table(idx) #(B,T,C) C是嵌入大小    根据idx内的令牌的身份进行编码
        pos_emb = self.position_embedding_table(torch.arange(T,device=device)) #(T,C) 从0到T减一的整数都嵌入到表中
        x = tok_emb+pos_emb #(B,T,C) 标记的身份嵌入与位置嵌入相加。x保存了身份以及身份出现的位置
        # x = self.sa_head(x)  #(B,T,C)
        x = self.blocks(x)
        x = self.ln_f(x)
        logits = self.lm_head(x) #(B,T,vocab_size)

        if targets is None:
            loss = None
        else:
            B,T,C = logits.shape
            logits = logits.view(B*T,C)
            targets = targets.view(B*T)
            loss = F.cross_entropy(logits,targets)
        
        return logits,loss
    def generate(self,idx,max_new_tokens):
        for _ in range(max_new_tokens):
            idx_cond = idx[:,-block_size] 
            logits,loss= self(idx_cond)
            logits = logits[:,-1,:]# becomes (B,C)
            probs = F.softmax(logits,dim=-1)
            idx_next = torch.multinomial(probs,num_samples=1)
            idx = torch.cat((idx,idx_next),dim=1) #(B,T+1)
        return idx
  • 训练
model = BigramLangeNodel()
m  = model.to(device)

optimizer = torch.optim.AdamW(model.parameters(),lr = learning_rate)

for iter in range(max_iters):
    if iter % eval_interval==0:
        losses = estimate_loos(model)
        print(f"step {iter}:train loss {losses['train']:.4f},val loss{losses['val']:.4f}")
    xb,yb = get_batch('train')

    logits,loss = model(xb,yb)
    optimizer.zero_grad(set_to_none=True)
    loss.backward()
    optimizer.step()

context = torch.zeros((1,1),dtype=torch.long,device=device)
print(decode(m.generate(context,max_new_tokens=500)[0].tolist()))
  • 训练损失
step 0:train loss 4.3975,val loss4.3983
step 500:train loss 1.8497,val loss1.9600
step 1000:train loss 1.6500,val loss1.8210
step 1500:train loss 1.5530,val loss1.7376
step 2000:train loss 1.5034,val loss1.6891
step 2500:train loss 1.4665,val loss1.6638
step 3000:train loss 1.4431,val loss1.6457
step 3500:train loss 1.4156,val loss1.6209
step 4000:train loss 1.3958,val loss1.6025
step 4500:train loss 1.3855,val loss1.5988

简单实现自注意力

VX 关注{晓理紫|小李子},获取技术推送信息,如感兴趣,请转发给有需要的同学,谢谢支持!!

如果你感觉对你有所帮助,请关注我。

源码获取 VX关注晓理紫并回复“chatgpt-0”
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1485908.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unreal触屏和鼠标控制旋转冲突问题

Unreal触屏和鼠标控制旋转冲突问题 鼠标控制摄像机旋转添加Input轴计算旋转角度通过轴事件控制旋转 问题和原因问题原因 解决办法增加触摸控制旋转代码触屏操作下屏蔽鼠标轴响应事件 鼠标控制摄像机旋转 通过Mouse X和Mouse Y控制摄像机旋转。 添加Input轴 计算旋转角度 通过…

10 计算机结构

冯诺依曼体系结构 冯诺依曼体系结构,也被称为普林斯顿结构,是一种计算机架构,其核心特点包括将程序指令存储和数据存储合并在一起的存储器结构,程序指令和数据的宽度相同,通常都是16位或32位 我们常见的计算机,笔记本…

Android 性能优化--APK加固(1)混淆

文章目录 为什么要开启混淆如何开启代码混淆如何开启资源压缩代码混淆配置代码混淆后,Crash 问题定位结尾 本文首发地址:https://h89.cn/archives/211.html 最新更新地址:https://gitee.com/chenjim/chenjimblog 为什么要开启混淆 先上一个 …

计算机二级Python刷题笔记------基本操作题11、14、17、21、30(考察列表)

文章目录 第十一题(列表遍历)第十四题(len)第十七题(len、insert)第二十一题(append)第三十题(二维列表) 第十一题(列表遍历) 题目&a…

【RT-Thread应用笔记】英飞凌PSoC 62 + CYW43012 WiFi延迟和带宽测试

文章目录 一、安装SDK二、创建项目三、编译下载3.1 编译代码3.2 下载程序 四、WiFi测试4.1 扫描测试4.2 连接测试 五、延迟测试5.1 ping百度5.2 ping路由器 六、带宽测试6.1 添加netutils软件包6.2 iperf命令参数6.3 PC端的iperf6.4 iperf测试准备工作6.5 进行iperf带宽测试6.6…

力扣日记3.3-【回溯算法篇】332. 重新安排行程

力扣日记:【回溯算法篇】332. 重新安排行程 日期:2023.3.3 参考:代码随想录、力扣 ps:因为是困难题,望而却步了一星期。。。T^T 332. 重新安排行程 题目描述 难度:困难 给你一份航线列表 tickets &#xf…

NLP-词向量、Word2vec

Word2vec Skip-gram算法的核心部分 我们做什么来计算一个词在中心词的上下文中出现的概率? 似然函数 词已知,它的上下文单词的概率 相乘。 然后所有中心词的这个相乘数 再全部相乘,希望得到最大。 目标函数(代价函数&#xff0…

C语言数组全面解析:从初学到精通

数组 1. 前言2. 一维数组的创建和初始化3. 一维数组的使用4. 一维数组在内存中的存储5. 二维数组的创建和初始化6. 二维数组的使用7. 二维数组在内存中的存储8. 数组越界9. 数组作为函数参数10. 综合练习10.1 用函数初始化,逆置,打印整型数组10.2 交换两…

[计算机网络]--I/O多路转接之poll和epoll

前言 作者:小蜗牛向前冲 名言:我可以接受失败,但我不能接受放弃 如果觉的博主的文章还不错的话,还请点赞,收藏,关注👀支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 目录 一、poll函…

python复盘(1)

1、变量名的命名规则 #3、变量名的命名规则:可以用中文作为变量名;其他和go语言一样 # 变量名可以用数字、字母、下划线组成,但是数字不能作为开头 # 变量名不能使用空格,不能使用函数名或关键字 # 变量名最好能表示出他的作用2、…

【PyQt】16-剪切板的使用

文章目录 前言一、代码疑惑快捷键 二、现象2.1 复制粘贴文本复制粘贴 2.2 复制粘贴图片复制粘贴 2.3 复制粘贴网页 总结 前言 1、剪切板的使用 2、pycharm的编译快捷键 3、类的属性和普通变量的关系 4、pyqt应该养成的编程习惯-体现在代码里了,自己看看。 一、代码…

springboot+vue学生信息管理系统学籍 成绩 选课 奖惩,奖学金缴费idea maven mysql

技术栈 ide工具:IDEA 或者eclipse 编程语言: java 数据库: mysql5.7 框架:ssmspringboot都有 前端:vue.jsElementUI 详细技术:springbootSSMvueMYSQLMAVEN 数据库工具:Navicat/SQLyog都可以学生信息管理系统主要实现角…

源码视角,vue3为什么推荐用ref,而不是reactive

ref 和 reactive 是 Vue3 中实现响应式数据的核心 API。ref 用于包装基本数据类型,而 reactive 用于处理对象和数组。尽管 reactive 似乎更适合处理对象,但 Vue3 官方文档更推荐使用 ref。 我的想法,ref就是比reactive好用,官方也…

JAVA读取局域网电脑文件全流程

JAVA读取局域网电脑文件全流程 需求设计实现1、创建非微软用户(1)win11 不可达电脑开启网络共享2、设置文件夹共享3、高级共享设置打开文件夹与打印机共享3、java编码 需求 需要读取内网一台电脑中的文件并解析数据,但机器不可接入办公网&am…

京东云硬钢阿里云:承诺再低10%

关注卢松松,会经常给你分享一些我的经验和观点。 阿里云刚刚宣布史上最大规模的全线产品降价20%,这热度还没过,京东云当晚就喊话:“随便降、比到底!,全网比价,击穿低价,再低10%”,并…

贪心(基础算法)--- 区间选点

905. 区间选点 思路 (贪心)O(nlogn) 根据右端点排序 将区间按右端点排序 遍历区间,如果当前区间左端点不包含在前一个区间中,则选取新区间,所选点个数加1,更新当前区间右端点。如果包含,则跳…

蓝桥OJ 2942数字王国之军训排队 DFS剪枝

蓝桥OJ 2942数字王国之军训排队 #include<bits/stdc.h> using namespace std;const int N 15;//最多10队 int a[N], n; vector<int>v[N];//二维数组 v[i]记录队伍i中所有人的编号bool dfs(int cnt, int dep) {if (dep n1){//判断合法性for (int i 1; i < n; …

OpenAI划时代大模型——文本生成视频模型Sora作品欣赏(十三)

Sora介绍 Sora是一个能以文本描述生成视频的人工智能模型&#xff0c;由美国人工智能研究机构OpenAI开发。 Sora这一名称源于日文“空”&#xff08;そら sora&#xff09;&#xff0c;即天空之意&#xff0c;以示其无限的创造潜力。其背后的技术是在OpenAI的文本到图像生成模…

docker 转为docker-compose(composerize 命令)

可以使用Composerize将Docker命令转换为Docker Compose文件。 例如&#xff1a;将docker run命令转换为Docker Compose格式&#xff0c;只需用Composerize运行它&#xff0c;如下所示&#xff1a; composerize docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/…

Kubernetes: 本地部署dashboard

本篇文章主要是介绍如何在本地部署kubernetes dashboard, 部署环境是mac m2 下载dashboard.yaml 官网release地址: kubernetes/dashboard/releases 本篇文章下载的是kubernetes-dashboard-v2.7.0的版本&#xff0c;通过wget命令下载到本地: wget https://raw.githubusercont…