当前位置: 首页 > news >正文

GPT 结束语设计 以nanogpt为例

GPT 结束语设计 以nanogpt为例

目录

GPT 结束语设计 以nanogpt为例

1、简述

2、分词设计

3、结束语断点


1、简述

在手搓gpt的时候,可能会遇到一些性能问题,即关于是否需要全部输出或者怎么节约资源。

在输出语句被max_new_tokens 限制,如果出现一些输出句子比较长,就会被限制,但如果是设计时候没有设计结束语,就会出现全部输出的问题。

如果只需要一部分的语句,或者是某一些特定的场景设计,例如:

1、gpt自动化操作

2、输出美观

3、一些较小的业务场景,特定处理的业务

以上的业务场景都是设计的时候为特定模型,即小大模型,通常不需要较大的参数,所以在设计时候如果考虑到轻量化和小型化,参数1M至100M之间的小大模型。

基于成本和开发快速考虑,可以使用nanogpt用于训练和开发,然后再进一步的微调迭代,所需要的性能和效果基本可以满足部分要求,迭代速度较快,适合单人或小团队开发特定场景。


2、分词设计

以下是关于之前做过的一个开发场景:音乐生成按键的场景

分词中加入了end的作为特定的结束语,如果后续扩展可以通过end前后设计一些音乐风格的标识符,这样通过风格的标识来达到风格的统一。


# 自定义词典
word_dict = set(['\n', ' ', '+', '.', '0', '1', '2', '3', '4'
         '6', '7', '8', '9', ':', "'a'", "'b'", "'c'", "'d'",
         "'e'", "'f'", "'g'", "'h'","'j'", "'n'","'m'","'q'","'w'","'r'","'t'","'y'","'u'",
        "'s'", "'v'", "'x'", "'z'",'<96>','<97>','<98>','<99>','<100>',
        '<101>','<102>','<103>','<104>','<105>','end'])

seg_list = max_forward_matching(data, word_dict, max(len(word) for word in word_dict))
words = list(seg_list)
# 创建一个默认字典来存储词汇到ID的映射
word_to_id = defaultdict(lambda: len(word_to_id))
# 创建一个列表来存储ID到词汇的映射(可选)
id_to_word = []
# 构建词汇到ID的映射
for word in words:
    word_id = word_to_id[word]
    # ID到词汇的映射,可以这样做:
    if word_id == len(word_to_id):  # 只有当新的ID被分配时才添加到id_to_word中
        id_to_word.append(word)

import os
import pickle
import requests
import numpy as np
from collections import defaultdict
# download the tiny shakespeare dataset
input_file_path = os.path.join(os.path.dirname(__file__), 'music.txt')
if not os.path.exists(input_file_path):data_url = 'https://raw.githubusercontent.com/karpathy/char-rnn/master/data/tinyshakespeare/input.txt'with open(input_file_path, 'w') as f:f.write(requests.get(data_url).text)with open(input_file_path, 'r',encoding="utf-8") as f:data = f.read()
print(f"length of dataset in characters: {len(data):,}")# get all the unique characters that occur in this text
def max_forward_matching(text, word_dict, max_len):result = []index = 0while index < len(text):found = Falsefor size in range(max_len, 0, -1):  # 从最大长度开始尝试匹配piece = text[index:index + size]if piece in word_dict:result.append(piece)index += sizefound = Truebreakif not found:  # 如果没有找到匹配的词,则按字符输出result.append(text[index])index += 1return result#自建一套
# 自定义词典
word_dict = set(['\n', ' ', '+', '.', '0', '1', '2', '3', '4''6', '7', '8', '9', ':', "'a'", "'b'", "'c'", "'d'","'e'", "'f'", "'g'", "'h'","'j'", "'n'","'m'","'q'","'w'","'r'","'t'","'y'","'u'","'s'", "'v'", "'x'", "'z'",'<96>','<97>','<98>','<99>','<100>','<101>','<102>','<103>','<104>','<105>','end'])seg_list = max_forward_matching(data, word_dict, max(len(word) for word in word_dict))
words = list(seg_list)
# 创建一个默认字典来存储词汇到ID的映射
word_to_id = defaultdict(lambda: len(word_to_id))
# 创建一个列表来存储ID到词汇的映射(可选)
id_to_word = []
# 构建词汇到ID的映射
for word in words:word_id = word_to_id[word]# ID到词汇的映射,可以这样做:if word_id == len(word_to_id):  # 只有当新的ID被分配时才添加到id_to_word中id_to_word.append(word)chars = list(word_to_id)
print(chars)
vocab_size = len(chars)print("all the unique characters:", ''.join(chars))
print(f"vocab size: {vocab_size:,}")
#Myzzb That is need about jieba to cut text
print(chars)
# create a mapping from characters to integers
stoi = { ch:i for i,ch in enumerate(chars) }
print(stoi)
itos = { i:ch for i,ch in enumerate(chars) }
print(itos)def encode(s):seg_list = max_forward_matching(data, word_dict, max(len(word) for word in word_dict))words = list(seg_list)# 创建一个默认字典来存储词汇到ID的映射word_to_id = defaultdict(lambda: len(word_to_id))# 创建一个列表来存储ID到词汇的映射id_to_word = []# 构建词汇到ID的映射for word in words:word_id = word_to_id[word]# 如果你也需要ID到词汇的映射,可以这样做:if word_id == len(word_to_id):  # 只有当新的ID被分配时才添加到id_to_word中id_to_word.append(word)return [word_to_id[word] for word in words] # encoder: take a string, output a list of integers
def decode(l):seg_list = max_forward_matching(data, word_dict, max(len(word) for word in word_dict))words = list(seg_list)# 创建一个默认字典来存储词汇到ID的映射word_to_id = defaultdict(lambda: len(word_to_id))# 创建一个列表来存储ID到词汇的映射(可选)id_to_word = []# 构建词汇到ID的映射for word in words:word_id = word_to_id[word]# 如果你也需要ID到词汇的映射,可以这样做:if word_id == len(word_to_id):  # 只有当新的ID被分配时才添加到id_to_word中id_to_word.append(word)return ''.join([word_to_id[word] for word in words]) # decoder: take a list of integers, output a string
# create the train and test splits
n = len(data)
train_data = data[:int(n*0.95)]#这里因为没写字典排序,所以训练集和测试集懒得分开
val_data = data[int(n*0.95):]
# print(val_data)
# encode both to integers
train_ids = encode(train_data)
print(train_ids)
val_ids = encode(val_data)
print(val_ids)
# print(val_ids)
print(f"train has {len(train_ids):,} tokens")
print(f"val has {len(val_ids):,} tokens")# export to bin files
train_ids = np.array(train_ids, dtype=np.uint16)
val_ids = np.array(val_ids, dtype=np.uint16)
train_ids.tofile(os.path.join(os.path.dirname(__file__), 'train.bin'))
val_ids.tofile(os.path.join(os.path.dirname(__file__), 'val.bin'))# save the meta information as well, to help us encode/decode later
meta = {'vocab_size': vocab_size,'itos': itos,'stoi': stoi,
}
with open(os.path.join(os.path.dirname(__file__), 'meta.pkl'), 'wb') as f:pickle.dump(meta, f)

3、结束语断点

通过在推理过程中检测新生成的编码是否和结束语一致,以上在设计的过程中通过字典分词,然后再分配的编码,是可以通过代码获取对应的结束语的编码。

通过在分词的时候进行对部分结束语进行输出,例子:

print(encode("\n"))
print(encode("\t"))

源码添加上,即可知道结束语的编码是多少:

"""
Prepare the Shakespeare dataset for character-level language modeling.
So instead of encoding with GPT-2 BPE tokens, we just map characters to ints.
Will save train.bin, val.bin containing the ids, and meta.pkl containing the
encoder and decoder and some other related info.
"""
import os
import pickle
import requests
import numpy as np# download the tiny shakespeare dataset
input_file_path = os.path.join(os.path.dirname(__file__), 'say.txt')
if not os.path.exists(input_file_path):data_url = 'https://raw.githubusercontent.com/karpathy/char-rnn/master/data/tinyshakespeare/input.txt'with open(input_file_path, 'w') as f:f.write(requests.get(data_url).text)with open(input_file_path, 'r',encoding="utf-8", errors='replace') as f:data = f.read()
print(f"length of dataset in characters: {len(data):,}")# get all the unique characters that occur in this text
chars = sorted(list(set(data)))
vocab_size = len(chars)
print("all the unique characters:", ''.join(chars))
print(f"vocab size: {vocab_size:,}")# create a mapping from characters to integers
stoi = { ch:i for i,ch in enumerate(chars) }
itos = { i:ch for i,ch in enumerate(chars) }def encode(s):return [stoi[c] for c in s] # encoder: take a string, output a list of integers
def decode(l):return ''.join([itos[i] for i in l]) # decoder: take a list of integers, output a stringprint(encode("\n"))
print(encode("\t"))# create the train and test splits
n = len(data)
train_data = data[:int(n*0.9)]
val_data = data[int(n*0.9):]# encode both to integers
train_ids = encode(train_data)
val_ids = encode(val_data)
print(f"train has {len(train_ids):,} tokens")
print(f"val has {len(val_ids):,} tokens")# export to bin files
train_ids = np.array(train_ids, dtype=np.uint16)
val_ids = np.array(val_ids, dtype=np.uint16)
train_ids.tofile(os.path.join(os.path.dirname(__file__), 'train.bin'))
val_ids.tofile(os.path.join(os.path.dirname(__file__), 'val.bin'))# save the meta information as well, to help us encode/decode later
meta = {'vocab_size': vocab_size,'itos': itos,'stoi': stoi,
}
with open(os.path.join(os.path.dirname(__file__), 'meta.pkl'), 'wb') as f:pickle.dump(meta, f)# length of dataset in characters:  1115394
# all the unique characters:
#  !$&',-.3:;?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
# vocab size: 65
# train has 1003854 tokens
# val has 111540 tokens

只需要简单添加一句代码即可:

# 检查是否生成了结束语 可以获取大部分结束语的编码用于判断 也可以自拟结束语 将其处理为唯一的标识符避免干扰
if 1 in idx_next[0].tolist():break

@torch.no_grad()def generate(self, idx, max_new_tokens, temperature=1.0, top_k=None):"""Take a conditioning sequence of indices idx (LongTensor of shape (b,t)) and completethe sequence max_new_tokens times, feeding the predictions back into the model each time.Most likely you'll want to make sure to be in model.eval() mode of operation for this."""for _ in range(max_new_tokens):# if the sequence context is growing too long we must crop it at block_sizeidx_cond = idx if idx.size(1) <= self.config.block_size else idx[:, -self.config.block_size:]# forward the model to get the logits for the index in the sequencelogits, _ = self(idx_cond)# pluck the logits at the final step and scale by desired temperaturelogits = logits[:, -1, :] / temperature# optionally crop the logits to only the top k optionsif top_k is not None:v, _ = torch.topk(logits, min(top_k, logits.size(-1)))logits[logits < v[:, [-1]]] = -float('Inf')# apply softmax to convert logits to (normalized) probabilitiesprobs = F.softmax(logits, dim=-1)# sample from the distributionidx_next = torch.multinomial(probs, num_samples=1)# 检查是否生成了结束语 可以获取大部分结束语的编码用于判断 也可以自拟结束语 将其处理为唯一的标识符避免干扰if 1 in idx_next[0].tolist():break# append sampled index to the running sequence and continueidx = torch.cat((idx, idx_next), dim=1)return idx

相关文章:

GPT 结束语设计 以nanogpt为例

GPT 结束语设计 以nanogpt为例 目录 GPT 结束语设计 以nanogpt为例 1、简述 2、分词设计 3、结束语断点 1、简述 在手搓gpt的时候&#xff0c;可能会遇到一些性能问题&#xff0c;即关于是否需要全部输出或者怎么节约资源。 在输出语句被max_new_tokens 限制&#xff0c…...

FastDFS的安装及使用

分布式存储发展历程 前段时间 618 活动火热进行&#xff0c;正是购物的好时机。当我们访问这些电 商网站的时候&#xff0c;每一个商品都会有各式各样的图片展示介绍&#xff0c;这些图 片一张两张可以随便丢在服务器的某个文件夹中&#xff0c;可是电商网站如此 大体量的…...

C++ lambda表达式

目录 1.lambda表达式 1.1什么是Lambda表达式&#xff1f; 1.2Lambda表达式的语法 1.3捕捉列表 1.4函数对象与lambda表达式 1.lambda表达式 1.1什么是Lambda表达式&#xff1f; Lambda表达式是C11标准引入的一种匿名函数&#xff0c;它允许你在需要函数的地方直接编写代码…...

react页面定时器调用一组多个接口,如果接口请求返回令牌失效,清除定时器不再触发这一组请求

为了实现一个React页面使用定时器调用一组多个接口&#xff0c;并在任意一个接口请求返回令牌失效时清除定时器且不再触发这一组请求&#xff0c;可以遵循以下步骤&#xff1a; 1. 定义API调用函数&#xff1a;创建一个函数来处理一组API调用。每个API调用都应该检查响应状态以…...

Python的泛型(Generic)与协变(Covariant)

今天咱们聊聊Python类型标注中的泛型(Generic),与协变(Covariant)。 不了解类型标注的小伙伴,可以先看一看我的上一篇文章 “Python类型检查” Python 类型检查-CSDN博客 例子 这次我开个宠物商店。看下面代码。 class Animal:passclass Dog(Animal):passclass Cat(A…...

Python Typing: 实战应用指南

文章目录 1. 什么是 Python Typing&#xff1f;2. 实战案例&#xff1a;构建一个用户管理系统2.1 项目描述2.2 代码实现 3. 类型检查工具&#xff1a;MyPy4. 常见的 typing 用法5. 总结 在 Python 中&#xff0c;静态类型检查越来越受到开发者的重视。typing 模块提供了一种方式…...

OpenEuler学习笔记(六):OpenEuler与其他Linux服务器的区别是什么?

OpenEuler是一款基于Linux内核的开源服务器操作系统&#xff0c;与其他Linux服务器操作系统&#xff08;如CentOS、Ubuntu Server等&#xff09;存在多方面的区别&#xff0c;主要体现在以下几个方面&#xff1a; 一、社区与支持 OpenEuler&#xff1a;由华为发起并开源&…...

如何使用CRM数据分析和洞察来支持业务决策和市场营销?

如何使用CRM数据分析和洞察来支持业务决策和市场营销&#xff1f; 大家好&#xff01;今天咱们聊聊一个特别重要的话题——如何利用客户关系管理&#xff08;CRM&#xff09;系统中的数据进行分析与洞察能够帮助我们做出更好的业务决策以及提升市场营销效果。其实啊&#xff0…...

MyBatis和JPA区别详解

文章目录 MyBatis和JPA区别详解一、引言二、设计理念与使用方式1、MyBatis&#xff1a;半自动化的ORM框架1.1、代码示例 2、JPA&#xff1a;全自动的ORM框架2.1、代码示例 三、性能优化与适用场景1、MyBatis&#xff1a;灵活的SQL控制1.1、适用场景 2、JPA&#xff1a;开发效率…...

SVN客户端使用手册

目录 一、简介 二、SVN的安装与卸载 1. 安装&#xff08;公司内部一般会提供安装包和汉化包&#xff0c;直接到公司内部网盘下载即可&#xff0c;如果找不到可以看下面的教程&#xff09; 2. 查看SVN版本 ​编辑 3. SVN卸载 三、SVN的基本操作 1. 检出 2. 清除认证数据 3. 提交…...

VsCode安装文档

一、下载 进入VS Code官网&#xff1a;Visual Studio Code - Code Editing. Redefined&#xff0c;点击 DownLoad for Windows下载windows版本 当然也可以点击旁边的箭头&#xff0c;下载Windows版本 或 Mac OS 版本 备注&#xff1a; Stable&#xff1a;稳定版Insiders&#…...

豆包MarsCode 蛇年编程大作战 | 高效开发“蛇年运势预测系统”

&#x1f31f; 嗨&#xff0c;我是LucianaiB&#xff01; &#x1f30d; 总有人间一两风&#xff0c;填我十万八千梦。 &#x1f680; 路漫漫其修远兮&#xff0c;吾将上下而求索。 豆包MarsCode 蛇年编程大作战 | &#x1f40d; 蛇年运势预测 在线体验地址&#xff1a;蛇年…...

【动态规划】--- 斐波那契数模型

Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏&#xff1a; 算法Journey &#x1f3e0; 第N个泰波那契数模型 &#x1f4cc; 题目解析 第N个泰波那契数 题目要求的是泰波那契数&#xff0c;并非斐波那契数。 &…...

生信软件管家——conda vs pip

pip vs conda&#xff1a; 安装过python包的人自然两种管理软件都用过&#xff0c; Pip install和Conda install在Python环境中用于安装第三方库和软件包&#xff0c;但它们在多个方面存在显著的区别 总的来说&#xff1a; pip是包管理软件&#xff0c;conda既是包管理软件&…...

代码随想录——串

文章目录 反转字符串反转字符串Ⅱ路径加密反转字符串中的单词动态口令字符串匹配重复的子字符串 反转字符串 344. 反转字符串 //前后对应交换 //0<->sSize-1 //1<->sSize-2 //... //i<->sSize-1-i,i0,1,...,(sSize-1)/2 void reverseString(char* s, int s…...

詳細講一下RN(React Native)中的列表組件FlatList和SectionList

1. FlatList 基礎使用 import React from react; import { View, Text, FlatList, StyleSheet } from react-native;export const SimpleListDemo: React.FC () > {// 1. 準備數據const data [{ id: 1, title: 項目 1 },{ id: 2, title: 項目 2 },{ id: 3, title: 項目 3…...

TDengine 与上海电气工业互联网平台完成兼容性认证

在工业数字化转型和智能化升级的浪潮中&#xff0c;企业对高效、可靠的数据管理解决方案的需求日益增长。特别是在风电智能运维、火电远程运维、机床售后服务等复杂多样的工业场景下&#xff0c;如何实现海量设备和时序数据的高效管理&#xff0c;已经成为推动行业升级的关键。…...

随机矩阵投影长度保持引理及其证明

原论文中的引理 2 \textbf{2} 2 1. \textbf{1. } 1. 引理 1 \textbf{1} 1(前提之一) 1.1. \textbf{1.1. } 1.1. 引理 1 \textbf{1} 1的内容 &#x1f449;前提&#xff1a; X ∼ N ( 0 , σ ) X\sim{}N(0,\sigma) X∼N(0,σ)即 f ( x ) 1 2 π σ e – x 2 2 σ 2 f(x)\text{}…...

深度学习利用数据加载、预处理和增强数据提高模型的性能

深度学习数据预处理是一个关键步骤&#xff0c;旨在提高模型的性能和准确性。 通过数据加载、预处理和增强&#xff0c;可以显著提高深度学习模型的性能和准确性。在实际应用中&#xff0c;需要根据具体的数据和任务来选择合适的预处理和增强技术。 以下将详细论述并举例说明如…...

ESP32服务器和PC客户端的Wi-Fi通信

ESP32客户端-服务器Wi-Fi通信 本指南将向您展示如何设置ESP32板作为服务端&#xff0c;PC作为客户端&#xff0c;通过HTTP通信&#xff0c;以通过Wi-Fi&#xff08;无需路由器或互联网连接&#xff09;交换数据。简而言之&#xff0c;您将学习如何使用HTTP请求将一个板的数据发…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

【单片机期末】单片机系统设计

主要内容&#xff1a;系统状态机&#xff0c;系统时基&#xff0c;系统需求分析&#xff0c;系统构建&#xff0c;系统状态流图 一、题目要求 二、绘制系统状态流图 题目&#xff1a;根据上述描述绘制系统状态流图&#xff0c;注明状态转移条件及方向。 三、利用定时器产生时…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

selenium学习实战【Python爬虫】

selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

Rapidio门铃消息FIFO溢出机制

关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系&#xff0c;以下是深入解析&#xff1a; 门铃FIFO溢出的本质 在RapidIO系统中&#xff0c;门铃消息FIFO是硬件控制器内部的缓冲区&#xff0c;用于临时存储接收到的门铃消息&#xff08;Doorbell Message&#xff09;。…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)

前言&#xff1a; 双亲委派机制对于面试这块来说非常重要&#xff0c;在实际开发中也是经常遇见需要打破双亲委派的需求&#xff0c;今天我们一起来探索一下什么是双亲委派机制&#xff0c;在此之前我们先介绍一下类的加载器。 目录 ​编辑 前言&#xff1a; 类加载器 1. …...

安卓基础(Java 和 Gradle 版本)

1. 设置项目的 JDK 版本 方法1&#xff1a;通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分&#xff0c;设置 Gradle JDK 方法2&#xff1a;通过 Settings File → Settings... (或 CtrlAltS)…...