开始构建我们自己的大语言模型:数据处理部分
关注本专栏(NLP简论:手搓大语言模型实践) 继续学习从头编写、训练自己的大语言模型。
接上集,本章我们将深入说一下大语言模型数据处理部分的细节,并直接提供本部分的完整代码。
【配套资源】
暂时的词汇表:内部配套资料-LX2中文词汇表下载
*
在后面我们会根据需求微调
1. 数据准备
首先,我们需要准备原始文本数据。这些数据可以来自各种来源,如书籍、网页、社交媒体等。在处理这些数据之前,确保它们已经被清洗过,去除了噪声和无关内容。
暂时用不到所以不提供配套资源,后面会提供。
*
2. 词汇表构建
在构建大语言模型时,我们需要将文本转换为模型可以理解的数字形式。这通常通过构建一个词汇表(即Vocabulary)来实现(上一章我们提到过),词汇表中的每个词(或字符)都对应一个唯一的数字(我们成为索引)。
参考代码:
vocab = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.,!?;'" # 示例词汇表,之后要用到的中文版大型词汇表见【配套资源】。
char2idx = {u: i for i, u in enumerate(vocab)} # 将每个字对应到数字
idx2char = np.array(vocab) # 将数字对应到每个字# 打印部分词汇表以验证
print('{')
for char, _ in zip(char2idx, range(20)):print(f' {repr(char)}: {char2idx[char]},')
print(' ...\n}')
3. 文本预处理
文本预处理是数据处理中的关键步骤,包括分词、去除停用词、词干提取等。在大语言模型中,由于我们通常在字符级别或子词级别操作,所以这些步骤可能相对简单。但是,我们仍然需要处理一些特殊字符,如换行符、制表符等。
4. 文本编码
将文本转换为模型可以处理的数字序列。这通常通过查找词汇表中每个字符的索引来实现。
5. 序列划分
由于大语言模型通常使用序列到序列(Seq2Seq)的学习方式,我们需要将长文本划分为多个较短的序列,每个序列包含一个输入部分和一个目标部分。这通常通过滑动窗口的方式实现。我们之前提到过,模型输入一段文本(序列)推理下一个token(这里是一个字)。
拓展知识(理解不了就不用理解了)
问:
为什么训练数据的X和y都是序列,按照之前说的,不应该是x是序列,y是序列的下一个token吗?
答:
在训练循环神经网络(RNN)时,我们通常使用教师强制(Teacher Forcing)技术。这意味着在每个时间步,模型的输入不仅包括来自上一时间步的隐藏状态,而且还包括来自训练数据集的真实下一个token,而不是模型自己在上一步预测的token。
*
例如,如果我们有一个训练序列 “abcd”,并且我们的目标是预测序列的下一个字符,那么目标序列将是"bcde"。在训练过程中,对于每一个时间步,我们都会给模型提供正确的下一个字符,而不是让模型基于自己的预测来做出下一步的预测。
*
具体来说,这是训练时的输入和目标是如何匹配的:
*
时间步1:输入是 “a”,目标是 “b”
时间步2:输入是 “b”,目标是 “c”
时间步3:输入是 “c”,目标是 “d”
时间步4:输入是 “d”,目标是 “e”
*
在这个过程中,模型的目标是在每个时间步预测出序列中的下一个字符。由于使用了教师强制,模型在每个时间步都得到了正确的输入,这有助于模型学习序列中的模式。但是,这种方法的一个潜在问题是,如果在推理阶段模型的预测出现错误,这个错误可能会在后续的预测中累积,因为模型现在是在用自己的预测作为输入,而不是真实的序列数据。因此,训练和预测之间的主要区别在于,训练时使用教师强制提供正确的下一个token,而在预测时模型需要依靠自己的预测来决定后续的输入。
参考函数split_input_target
:
def split_input_target(chunk):input_text = chunk[:-1] # 输入文本为当前序列除最后一个字符外的所有字符target_text = chunk[1:] # 目标文本为当前序列从第二个字符开始的所有字符return input_text, target_text
6. 数据集准备
将处理好的数据转换为TensorFlow数据集格式,以便进行高效的批处理和训练。
参考代码片段:
import tensorflow as tf# 假设 BUFFER_SIZE 和 BATCH_SIZE 已经定义
BUFFER_SIZE = 50000
BATCH_SIZE = 64# 假设 vocab_size, embedding_dim, rnn_units, window 这里就不做定义了
# vocab_size:词汇表大小(有多少个token)
# embedding_dim:编码层维度(从几个维度理解token们)
# rnn_units:RNN(上面拓展知识提到过)层的神经元数量
# window:模型上下文长度(模型基于多长的原文预测下一个token)# 加载保存的数据集
def load_dataset(path):dataset = tf.data.experimental.load(path)return dataset# 加载数据集
dataset = load_dataset(r'path_to_your_dataset')
# 具体代码见文末
7. 注意事项
- 数据清洗:确保数据干净,无噪声。
- 内存管理:处理大型数据集时,注意内存使用,避免内存溢出。
- 数据增强:如果数据量不足,可以考虑数据增强技术。
- 效率优化:优化数据处理流程,提高训练效率。
通过以上步骤,我们可以为构建大语言模型准备好干净、高效的数据集。接下来,就可以进入模型构建和训练阶段了。
本部分完整代码:
def train(mt=3,big_file=False,#是否采用大文件加载策略#微调数据集path_to_file = r'en_novel.txt',ntype_='_en',#保存为微调模型名称#设置vocab版本vtype_='_lx',#type_#fen=50,#数据量分几份fwidx=0,#第几份BATCH_SIZE = 64,loadmodel=False,pass_=-1,ste=0,):'''多出的参数不必理会,后面会用到'''global LR,param_data,p_ntypep_ntype=ntype_if ntype_[0]!='_':ntype_='_'+ntype_type_=ntype_print('path_to_file',path_to_file)print('LR',LR)import os#dataset与vocab是配对的!if not os.path.exists(r'E:\小思框架\论文\ganskchat\vocab'+vtype_+'.txt'):raise Exception("can't reading vocab from "+r'E:\小思框架\论文\ganskchat\vocab'+vtype_+'.txt')else:with open('E:\\小思框架\\论文\\ganskchat\\vocab'+vtype_+'.txt','r',encoding='utf-8') as f:vocab=eval(f.read())UNK=0unkli=[]char2idx = {u:i for i, u in enumerate(vocab)}idx2char = np.array(vocab)print('{')for char,_ in zip(char2idx, range(20)):print(' {:4s}: {:3d},'.format(repr(char), char2idx[char]))print(' ...\n}')# 设定每个输入句子长度的最大值seq_length = dic[mt][2]def split_input_target(chunk):input_text = chunk[:-1]target_text = chunk[1:]return input_text, target_textimport tensorflow as tfimport pickle# 假设 BATCH_SIZE 和 BUFFER_SIZE 已经定义好if 1:# 设定缓冲区大小,以重新排列数据集BUFFER_SIZE = 50000# 词集的长度vocab_size = len(vocab)# 嵌入的维度embedding_dim = dic[mt][0]#int(1024*2*1)# RNN 的单元数量rnn_units = dic[mt][1]#int(1024*4*2)window = dic[mt][2]# 加载保存的数据集def load_dataset(path):dataset = tf.data.experimental.load(path)return datasetif os.path.exists(r'E:\小思框架\论文\ganskchat\dataset'+ntype_+'_'+str(fwidx)):#换了batch后要重新处理数据集print('loading dataset')# 加载已经打乱过的数据集dataset = load_dataset(r'E:\小思框架\论文\ganskchat\dataset'+ntype_+'_'+str(fwidx))else:if big_file:text=[]with open(path_to_file, 'r',encoding='utf-8') as f:idxlen=0print('getting length\n')for _ in tqdm.tqdm(f):idxlen+=1st=idxlen//fen*fwidxed=idxlen//fen*(fwidx+1)with open(path_to_file, 'r',encoding='utf-8') as f:idx=0print('\n\nrunning data\n')for _ in tqdm.tqdm(f):if idx<st:continueif idx>=ed:breaktext.append(_)idx+=1text=''.join(text)else:text = open(path_to_file, 'r',encoding='utf-8').read()idxlen=len(text)st=idxlen//fen*fwidxed=idxlen//fen*(fwidx+1)text=text[st:ed]print('data size:',len(text))#text_as_int = np.array([char2idx[c] for c in text])text_as_int=[]cks=list(char2idx.keys())unk_li=set()len_=0for c in tqdm.tqdm(text):if c in cks:text_as_int.append(char2idx[c])else:c=cc.convert(c)if c in cks:#转为简体再次尝试text_as_int.append(char2idx[c])else:if not is_add:if not c in unk_li:with open('unk'+ntype_+'.txt','w',encoding='utf-8') as f:f.write(str(len_)+'\n'+str(list(unk_li)))#print('unknow:',repr(c))unk_li.add(c)len_+=1text_as_int.append(UNK)text_as_int=np.array(text_as_int)#————————————————————————————# 创建训练样本 / 目标char_dataset = tf.data.Dataset.from_tensor_slices(text_as_int)if 0:for i in char_dataset.take(5):print(i.numpy())print(idx2char[i.numpy()])sequences = char_dataset.batch(seq_length+1, drop_remainder=True)for item in sequences.take(5):print(repr(''.join(idx2char[(item.numpy())])))dataset = sequences.map(split_input_target)dataset = dataset.shuffle(BUFFER_SIZE).batch(BATCH_SIZE, drop_remainder=True)tf.data.Dataset.save(dataset,'./dataset'+ntype_+'_'+str(fwidx) )
相关文章:
开始构建我们自己的大语言模型:数据处理部分
关注本专栏(NLP简论:手搓大语言模型实践) 继续学习从头编写、训练自己的大语言模型。 接上集,本章我们将深入说一下大语言模型数据处理部分的细节,并直接提供本部分的完整代码。 【配套资源】 暂时的词汇表࿱…...
springboot系列十: 自定义转换器,处理JSON,内容协商
文章目录 自定义转换器基本介绍应用实例查看源码注意事项和细节 处理JSON需求说明应用实例 内容协商基本介绍应用实例debug源码优先返回xml注意事项和细节 ⬅️ 上一篇: springboot系列九: 接收参数相关注解 🎉 欢迎来到 springboot系列十: 自定义转换器,…...
C++(new与delete操作符)
C中的new与delete new 与 delete定位new表达式 new 与 delete 在C中需要动态申请内存空间时需要使用 new 与 delete 这两个操作符 #include <iostream> using namespace std; int main() {int* p1 new int;//开辟一块int类型大小的空间给p1int* p2 new int(1);//开辟…...
STM32智能工业自动化监控系统教程
目录 引言环境准备智能工业自动化监控系统基础代码实现:实现智能工业自动化监控系统 4.1 数据采集模块 4.2 数据处理与控制模块 4.3 通信与网络系统实现 4.4 用户界面与数据可视化应用场景:工业自动化与管理问题解决方案与优化收尾与总结 1. 引言 智能…...
WPF设置欢迎屏幕,程序启动过度动画
当主窗体加载时间过长,这时候基本都会想添加一个等待操作来响应用户点击,提高用户体验。下面我记录两个方法,一点拙见,仅供参考。 方法1:在App类中使用SplashScreen类。 protected override void OnStartup(StartupEventArgs e)…...
Flink实时开发添加水印的案例分析
在Flink中,处理时间序列数据时,通常需要考虑事件时间和水印(watermarks)的处理。以下是修改前后的代码对比分析: 修改前的代码: val systemDS unitDS.map(dp > {dp.setDeviceCode(DeviceCodeEnum.fro…...
收银系统源码-线上商城diy装修
线下线上一体化收银系统越来越受门店重视,尤其是连锁多门店,想通过线下线上相互带动,相互引流,提升门店营业额。商城商城如何装修呢? 1.收银系统开发语言 核心开发语言: PHP、HTML5、Dart后台接口: PHP7.3后合管理网…...
Linux中nohup(no hang up)不挂起,用于在系统后台不挂断地运行命令,即使退出终端也不会影响程序的运行。
nohup的英文全称是 no hang up,即“不挂起”。这个命令在Linux或Unix系统中非常有用,主要用于在系统后台不挂断地运行命令,即使退出终端也不会影响程序的运行。默认情况下(非重定向时),nohup会将输出写入一…...
【.NET全栈】ASP.NET开发Web应用——站点导航技术
文章目录 前言一、站点地图1、定义站点地图文件2、使用SiteMapPath控件3、SiteMap类4、URL地址映射 二、TreeView控件1、使用TreeView控件2、以编程的方式添加节点3、使用TreeView控件导航4、绑定到XML文件5、按需加载节点6、带复选框的TreeView控件 三、Menu控件1、使用Menu控…...
docker 容器内部UI映射host
方法有很多, 目前我总计一个我自己尝试成功的方法,通过xpra。 Xpra可以看作是screen或tmux的图形版本,支持远程X11应用程序的显示和交互。 在远程服务器上,安装Xpra: sudo apt-get install xpra启动Xpra服务器会话&…...
数仓面试题——DWS层新增维度字段需求
前言 在数据仓库开发中,数据仓库的设计和维护一直是一个备受关注的话题。随着业务需求的不断变化,数据仓库的结构也需要随之调整。 面试过程中,多次被提问:当DWS构建好后,突然来了一个新的需求,需要添加某个…...
Qt实现MDI应用程序
本文记录Qt实现MDI应用程序的相关操作实现 目录 1.MDM模式下窗口的显示两种模式 1.1TabbedView 页签化显示 1.2 SubWindowView 子窗体显示 堆叠cascadeSubWindows 平铺tileSubWindows 2.MDM模式实现记录 2.1. 窗体继承自QMainWindow 2.2.增加组件MdiArea 2.3.定义统一…...
逆向案例二十六——webpack自执行函数是完整的,但我们只需要加载器,某职业技术学校登陆密码逆向
网址:统一身份认证平台 找到登陆包,搜索找到加密位置。 找到加密位置,打上断点 分析,E就是加密结果 进入n.i函数,就是t.i,看一下这个函数,传一个值,然后不变的返回,所以没什么意义 …...
容器安全最佳实践和工具
容器安全最佳实践和工具 什么是容器安全 容器安全是指保护容器化应用程序和基础设施免受潜在威胁和攻击的措施和策略。容器化技术(如Docker、Kubernetes)使得应用程序能够在隔离的环境中运行,这既提供了灵活性,也引入了新的安全…...
牛客周赛 Round 51
目录 A.小红的同余 B.小红的三倍数 C.小红充电 D.小红的gcd E.小红走矩阵 F.小红的数组 这次周赛题目比较简单,算法题也基本上是板子题,出得很好(~ ̄▽ ̄)~ A.小红的同余 思路:签到题&am…...
【Linux】详解加锁实现线程互斥
一、多线程不加线程互斥可能会引发的问题 下面是一个抢标逻辑。抢票为什么会抢到负数:假设当票数为1时,此时四个进程的判断条件tickets都大于0,都会进入抢票操作,第一个进程抢完票以后tickets0并写回内存,第二个进程再…...
Java学习高级四
JDK8开始,接口新增了三种形式的方法 接口的多继承 内部类 成员内部类 静态内部类 局部内部类 匿名内部类 import javax.swing.*; import java.awt.event.ActionEvent;public class Test {public static void main(String[] args) {// 扩展 内部类在开发中的真实使用…...
mmc-utils 的 MMC 测试工具
MMC 工具介绍 有一个名为 mmc-utils 的 MMC 测试工具,由 Ulf Hansson 维护,您可以在以下公共 git 存储库中找到它: mmc/mmc-utils.git - Unnamed repository; edit this file description to name the repository. 功能 mmc-utils 工具可以…...
使用Python Turtle绘制圣诞树和装饰
简介(❤ ω ❤) 在这篇文章中,我们将探索如何使用Python的Turtle模块来绘制一个充满节日气氛的圣诞树,以及一些可爱的装饰品。Turtle是一个受Logo语言启发的图形库,非常适合初学者学习编程和创建图形。 码农不是吗喽(大学生版&…...
非常好的新版网盘系统,是一款PHP网盘与外链分享程序,支持文件预览
这是一款PHP网盘与外链分享程序,支持所有格式文件的上传, 可以生成文件外链、图片外链、音乐视频外链,生成外链同时自动生成相应的UBB代码和HTML代码, 还可支持文本、图片、音乐、视频在线预览,这不仅仅是一个网盘&a…...
针对【module_or_function】的单元测试,全面覆盖可能的【edge_cases】
针对【module_or_function】的单元测试,全面覆盖可能的【edge_cases】 编写单元测试是为了验证代码模块或函数的正确性和鲁棒性。对于module_or_function,首先需要确定这个模块或函数的具体功能和预期输入范围。一个好的单元测试应该包括以下几个步骤&a…...
OTA测试!
OTA测试,全称“Over-The-Air Testing”,是一种无线通信设备的性能测试方法,主要用于评估设备在无线传输环境中的性能表现。以下是关于OTA测试的详细介绍: 一、定义与目的 OTA测试着重进行整机辐射性能方面的测试,以评…...
[H最短路] lc2959. 关闭分部的可行集合数目(Floyd最短路+二进制枚举+模板题)
文章目录 1. 题目来源2. 题目解析 1. 题目来源 链接:2959. 关闭分部的可行集合数目 2. 题目解析 看了看题好像还没啥思路,结果一看数据范围,好家伙…n 最大就 10 啊,那不直接闭眼直接 Floyd枚举所有情况即可吗?&…...
pyinstaller用法详解3
本文使用创作助手。 大家好,时隔多日,我又更新了pyinstaller的用法详解! 当然,这一次要比之前更详细,十分详细。 谢谢大家的支持,我们现在开始! 一、快速开始使用pyinstaller 我之前的文章…...
养猫新手不会挑智能猫砂盆?2024最新挑选干货分享!
不得不说智能猫砂盆真的帮了我很大的忙,四年以来我陆陆续续养了很多的猫咪,但是因为需要上班,所以有时候也对铲屎的工作有些力不从心,后面听了朋友的建议,去入手了智能猫砂盆,不得不说买智能猫砂盆也非常的…...
上海理工大学24计算机考研考情分析!初复试分值比55:45,复试逆袭人数不算多!
上海理工大学(University of Shanghai for Science and Technology),位于上海市,是一所以工学为主,工学、理学、经济学、管理学、文学、法学、艺术学等多学科协调发展的应用研究型大学;是上海市属重点建设大…...
Pandas库学习之DataFrame.drop()函数
Pandas库学习之DataFrame.drop()函数 一、简介 DataFrame.drop 是 Pandas 库中一个非常实用的函数,用于删除 DataFrame 中的行或列。通过指定列名或行索引,可以灵活地从数据集中移除不需要的数据。这对于数据清洗和预处理非常有用。 二、语法和参数 D…...
WHAT - 介绍一个不太一样的 UI 组件库 shadcn/ui
目录 一、介绍主要特点核心组件示例代码社区和支持总结 二、copy/paste1. 高度可定制性2. 避免依赖锁定3. 学习和理解4. 简化调试5. 项目需求变化 官方文档:https://ui.shadcn.com/docs 一、介绍 ShadCN (ShadCN/UI) 是一个现代的 React 组件库,旨在提…...
python--实验 11 模块
目录 知识点 模块基础 模块使用方式 自定义模块示例 模块的有条件执行 Python包结构 定义和导入包 常用第三方库及安装 实例代码 第三方库自动安装脚本 Python标准库介绍 PyInstaller 小结 实验 1.(基础题)制作文本进度条。 2.(基础题) 蒙特卡罗方法计算圆周率…...
Vue3+Vite+TS+Axios整合详细教程
1. Vite 简介 Vite是新一代的前端构建工具,在尤雨溪开发Vue3.0的时候诞生。类似于Webpack Webpack-dev-server。其主要利用浏览器ESM特性导入组织代码,在服务器端按需编译返回,完全跳过了打包这个概念,服务器随起随用。生产中利用…...
株洲网站建设公司/sem培训班
DNS由两层控制,一层是系统全局的,一个是network-manager配置的dns。 解决:这是dns解析的问题。修改/etc/resolv.conf,这个修改的是全局的dns。 # 系统的 nameserver 127.0.0.53 # 全局国内 nameserver 223.5.5.5 # 全局国外 nam…...
wordpress中文tag/seo外包杭州
一、引子顾名思义,进程即正在执行的一个过程。进程是对正在运行程序的一个抽象。进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一。操作系统的其他所有内容都是围绕进程的概念展开的。所…...
备案 网站首页url/磁力岛引擎
监控对于我们来说到底有多重要? 网络监控是企业IT运维中必不可少的重要一环,传统的监控工具以监控各个服务的健康和性能为中心。而随着数字化时代的到来,我们需要一个更加全面的监控视图,能够把不同环境下所有资源间的流量信息进行…...
建设美食网站/自己怎么做网址
Git 的作用: (1)方便多人协同开发; (2)方便版本控制 Git 分布式版本控制的主要区域及命令图,下面会详细讲解: 创建项目并将切换至项目目录下 1. 创建本地仓库: git init 此命令会在根目录下创建 .git的隐藏文件,为本地的代码仓库 2. 配置个人信息 : git config user.name&…...
为什么有的公司做很多个网站/百度seo sem
我在实施以下方案时遇到问题.我的问题陈述如下:>我有3个线程. ThreadCamera用于从相机抓取帧.用于处理(获取的图像/帧的OpenCV进行一些图像处理)帧和显示图像的主GUI线程的ThreadProcess.>我不知道ThreadProcess将花费多少时间来处理图像.所以我想将图像从Thr…...
wordpress无限登录密码/百度竞价托管代运营
JVM内存模型总体架构图 程序计数器 多线程时,当线程数超过CPU数量或CPU内核数量,线程之间就要根据时间片轮询抢夺CPU时间资源。因此每个线程有要有一个独立的程序计数器,记录下一条要运行的指令。线程私有的内存区域。如果执行的是JAVA方法&a…...