Llama2-Chinese项目:2.2-大语言模型词表扩充
因为原生LLaMA对中文的支持很弱,一个中文汉子往往被切分成多个token,因此需要对其进行中文词表扩展。思路通常是在中文语料库上训练一个中文tokenizer模型,然后将中文tokenizer与LLaMA原生tokenizer进行合并,最终得到一个扩展后的tokenizer模型。国内Chinese-LLaMA-Alpaca开源项目详细说明了词表扩展[2]。
一.对LLaMA tokenizer扩充自定义的词表
原版LLaMA模型的词表大小是32K,其主要针对英语进行训练,下面对其扩充20K中文词表,如下所示:
python merge_tokenizers.py \
--llama_tokenizer_dir r'L:/20230902_Llama1/llama-7b-hf' \
--chinese_sp_model_file r'./chinese_sp.model'
- llama_tokenizer_dir:指向存放原版LLaMA tokenizer的目录
- chinese_sp_model_file:指向用sentencepiece训练的中文词表文件
说明:在中文通用语料上训练的20K中文词表下载链接参考[3],如何构建垂直领域的中文词表下次分享。
二.merge_tokenizers.py注释
1.本文环境
本文环境为Windows10,Python3.10,CUDA 11.8,GTX 3090(24G),内存24G。
2.merge_tokenizers.py代码
import os
from transformers import LlamaTokenizer
from sentencepiece import sentencepiece_model_pb2 as sp_pb2_model
import sentencepiece as spm
import argparse
os.environ["PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION"] = "python"
# parser = argparse.ArgumentParser() # 创建一个ArgumentParser对象
# parser.add_argument('--llama_tokenizer_dir', default=r'L:/20230902_Llama1/llama-7b-hf', type=str, required=True) # 添加参数
# parser.add_argument('--chinese_sp_model_file', default='./chinese_sp.model', type=str) # 添加参数
# args = parser.parse_args() # 解析参数
# llama_tokenizer_dir = args.llama_tokenizer_dir # 这里是LLaMA tokenizer的路径
# chinese_sp_model_file = args.chinese_sp_model_file # 这里是Chinese tokenizer的路径
llama_tokenizer_dir = r'L:/20230902_Llama1/llama-7b-hf' # 这里是LLaMA tokenizer的路径
chinese_sp_model_file = r'./chinese_sp.model' # 这里是Chinese tokenizer的路径
# 加载tokenizer
llama_tokenizer = LlamaTokenizer.from_pretrained(llama_tokenizer_dir) # 加载LLaMA tokenizer
chinese_sp_model = spm.SentencePieceProcessor() # 定义Chinese tokenizer
chinese_sp_model.Load(chinese_sp_model_file) # 加载Chinese tokenizer
llama_spm = sp_pb2_model.ModelProto() # 定义LLaMA tokenizer的sentencepiece model
llama_spm.ParseFromString(llama_tokenizer.sp_model.serialized_model_proto()) # 从LLaMA tokenizer中加载sentencepiece model
chinese_spm = sp_pb2_model.ModelProto() # 定义Chinese tokenizer的sentencepiece model
chinese_spm.ParseFromString(chinese_sp_model.serialized_model_proto()) # 从Chinese tokenizer中加载sentencepiece model
# 输出tokens的信息
print(len(llama_tokenizer), len(chinese_sp_model)) # 两个tokenizer的词表大小;输出为32000、20000
print(llama_tokenizer.all_special_tokens) # LLaMA tokenizer的special tokens;输出为['']
print(llama_tokenizer.all_special_ids) # LLaMA tokenizer的special tokens对应的id;输出为[0]
print(llama_tokenizer.special_tokens_map) # LLaMA tokenizer的special tokens;输出为{'bos_token': '', 'eos_token': '', 'unk_token': ''}
# 将Chinese tokenizer的词表添加到LLaMA tokenizer中(合并过程)
llama_spm_tokens_set = set(p.piece for p in llama_spm.pieces) # LLaMA tokenizer的词表
print(len(llama_spm_tokens_set)) # LLaMA tokenizer的词表大小;输出为32000
print(f"Before:{len(llama_spm_tokens_set)}") # LLaMA tokenizer的词表大小;输出为Before:32000
for p in chinese_spm.pieces: # 遍历Chinese tokenizer的词表
piece = p.piece # Chinese tokenizer的词
if piece not in llama_spm_tokens_set: # 如果Chinese tokenizer的词不在LLaMA tokenizer的词表中
new_p = sp_pb2_model.ModelProto().SentencePiece() # 创建一个新的sentencepiece
new_p.piece = piece # 设置sentencepiece的词
new_p.score = 0 # 设置sentencepiece的score
llama_spm.pieces.append(new_p) # 将sentencepiece添加到LLaMA tokenizer的词表中
print(f"New model pieces: {len(llama_spm.pieces)}") # LLaMA tokenizer的词表大小;输出为New model pieces: 49953
# 保存LLaMA tokenizer
output_sp_dir = 'merged_tokenizer_sp' # 这里是保存LLaMA tokenizer的路径
output_hf_dir = 'merged_tokenizer_hf' # 这里是保存Chinese-LLaMA tokenizer的路径
os.makedirs(output_sp_dir, exist_ok=True) # 创建保存LLaMA tokenizer的文件夹
with open(output_sp_dir + '/chinese_llama.model', 'wb') as f:
f.write(llama_spm.SerializeToString())
tokenizer = LlamaTokenizer(vocab_file=output_sp_dir + '/chinese_llama.model') # 创建LLaMA tokenizer
tokenizer.save_pretrained(output_hf_dir) # 保存Chinese-LLaMA tokenizer
print(f"Chinese-LLaMA tokenizer has been saved to {output_hf_dir}") # 保存Chinese-LLaMA tokenizer
# 测试tokenizer
llama_tokenizer = LlamaTokenizer.from_pretrained(llama_tokenizer_dir) # LLaMA tokenizer
chinese_llama_tokenizer = LlamaTokenizer.from_pretrained(output_hf_dir) # Chinese-LLaMA tokenizer
print(tokenizer.all_special_tokens) # LLaMA tokenizer的special tokens;输出为['<s>', '</s>', '<unk>']
print(tokenizer.all_special_ids) # LLaMA tokenizer的special tokens对应的id;输出为[0, 1, 2]
print(tokenizer.special_tokens_map) # LLaMA tokenizer的special tokens;输出为{'bos_token': '<s>', 'eos_token': '</s>', 'unk_token': '<unk>'}
text = '''白日依山尽,黄河入海流。欲穷千里目,更上一层楼。
The primary use of LLaMA is research on large language models, including'''
print("Test text:\n", text) # 测试文本
print(f"Tokenized by LLaMA tokenizer:{llama_tokenizer.tokenize(text)}") # 测试LLaMA tokenizer
# 输出结果
# Tokenized by LLaMA tokenizer:['▁', '白', '日', '<0xE4>', '<0xBE>', '<0x9D>', '山', '<0xE5>', '<0xB0>', '<0xBD>', ',', '黄', '河', '入', '海', '流', '。', '<0xE6>', '<0xAC>', '<0xB2>', '<0xE7>', '<0xA9>', '<0xB7>', '千', '里', '目', ',', '更', '上', '一', '<0xE5>', '<0xB1>', '<0x82>', '<0xE6>', '<0xA5>', '<0xBC>', '。', '<0x0A>', 'The', '▁primary', '▁use', '▁of', '▁L', 'La', 'MA', '▁is', '▁research', '▁on', '▁large', '▁language', '▁models', ',', '▁including']
print(f"Tokenized by Chinese-LLaMA tokenizer:{chinese_llama_tokenizer.tokenize(text)}") # 测试Chinese-LLaMA tokenizer
# 输出结果
# Tokenized by Chinese-LLaMA tokenizer:['▁白', '日', '依', '山', '尽', ',', '黄河', '入', '海', '流', '。', '欲', '穷', '千里', '目', ',', '更', '上', '一层', '楼', '。', '<0x0A>', 'The', '▁primary', '▁use', '▁of', '▁L', 'La', 'MA', '▁is', '▁research', '▁on', '▁large', '▁language', '▁models', ',', '▁including']
3.生成的目录

参考文献:
[1]是否有基于Llama-2的增量训练模型:https://github.com/ymcui/Chinese-LLaMA-Alpaca/issues/817
[2]https://github.com/ymcui/Chinese-LLaMA-Alpaca/blob/main/scripts/merge_tokenizer/merge_tokenizers.py
[3]https://github.com/ymcui/Chinese-LLaMA-Alpaca/tree/main/scripts/merge_tokenizer/chinese_sp.model
[4]下载Chinese-LLaMA-Alpaca:git clone https://github.com/ymcui/Chinese-LLaMA-Alpaca.git
[5]下载llama-7b-hf:git lfs clone https://huggingface.co/yahma/llama-7b-hf
Llama2-Chinese项目:2.2-大语言模型词表扩充的更多相关文章
- Golang优秀开源项目汇总, 10大流行Go语言开源项目, golang 开源项目全集(golang/go/wiki/Projects), GitHub上优秀的Go开源项目
Golang优秀开源项目汇总(持续更新...)我把这个汇总放在github上了, 后面更新也会在github上更新. https://github.com/hackstoic/golang-open- ...
- 本地推理,单机运行,MacM1芯片系统基于大语言模型C++版本LLaMA部署“本地版”的ChatGPT
OpenAI公司基于GPT模型的ChatGPT风光无两,眼看它起朱楼,眼看它宴宾客,FaceBook终于坐不住了,发布了同样基于LLM的人工智能大语言模型LLaMA,号称包含70亿.130亿.330亿 ...
- .net项目中上传大图片失败
.net项目中有时用户提出要上传大图片,一张图片有可能十几兆,本来用的第三方的上传控件,有限制图片上传大小的设置,以前设置的是2M.按照用户的要求,以为直接将限制图片上传大小的设置改下就可以了,但是当 ...
- 《深度访谈:华为开源数据格式 CarbonData 项目,实现大数据即席查询秒级响应》
深度访谈:华为开源数据格式 CarbonData 项目,实现大数据即席查询秒级响应 Tina 阅读数:146012016 年 7 月 13 日 19:00 华为宣布开源了 CarbonData ...
- Hugging News #0324: 🤖️ 黑客松结果揭晓、一键部署谷歌最新大语言模型、Gradio 新版发布,更新超多!
每一周,我们的同事都会向社区的成员们发布一些关于 Hugging Face 相关的更新,包括我们的产品和平台更新.社区活动.学习资源和内容更新.开源库和模型更新等,我们将其称之为「Hugging Ne ...
- 使用 LoRA 和 Hugging Face 高效训练大语言模型
在本文中,我们将展示如何使用 大语言模型低秩适配 (Low-Rank Adaptation of Large Language Models,LoRA) 技术在单 GPU 上微调 110 亿参数的 F ...
- pytorch在有限的资源下部署大语言模型(以ChatGLM-6B为例)
pytorch在有限的资源下部署大语言模型(以ChatGLM-6B为例) Part1知识准备 在PyTorch中加载预训练的模型时,通常的工作流程是这样的: my_model = ModelClass ...
- 保姆级教程:用GPU云主机搭建AI大语言模型并用Flask封装成API,实现用户与模型对话
导读 在当今的人工智能时代,大型AI模型已成为获得人工智能应用程序的关键.但是,这些巨大的模型需要庞大的计算资源和存储空间,因此搭建这些模型并对它们进行交互需要强大的计算能力,这通常需要使用云计算服务 ...
- python接口自动化(四十二)- 项目结构设计之大结局(超详解)
简介 这一篇主要是将前边的所有知识做一个整合,把各种各样的砖块---模块(post请求,get请求,logging,参数关联,接口封装等等)垒起来,搭建一个房子.并且有很多小伙伴对于接口项目测试的框架 ...
- 更好的在 Git 项目中保存大文件(Git LFS 的使用)
珠玉在前, 大家可以参考 Git LFS的使用 - 简书 为什么要用 Git LFS 原有的 Git 是文本层面的版本控制, 为代码这种小文件设计的, 保存大文件会导致 repo 非常臃肿, push ...
随机推荐
- Unity禁止C#自动编译
基于unity2017\2020版本 using System; using System.Linq; using System.Reflection; using UnityEditor; usin ...
- Mach-O Inside: 命令行工具集 otool objdump od 与 dwarfdump
1 otool otool 命令行工具用来查看 Mach-O 文件的结构. 1.1 查看文件头 otool -h -v 文件路径 -h选项表明查看 Mach-O 文件头. -v 选项表明将展示的内容进 ...
- JS深入之内存详解,数据结构,存储方式
理解了本文,就知道深拷贝和浅拷贝的底层,了解赋值的底层原理. 可以结合另一篇文章一起食用:深拷贝与浅拷贝的区别,实现深拷贝的方法介绍. 以下是正文: 栈数据结构 栈的结构就是后进先出(LIFO),如果 ...
- Kubernetes:kube-apiserver 之鉴权
kubernetes:kube-apiserver 系列文章: Kubernetes:kube-apiserver 之 scheme(一) Kubernetes:kube-apiserver 之 sc ...
- 【源码解读(二)】EFCORE源码解读之查询都做了什么以及如何自定义批量插入
引言 书接上回,[源码解读(一)]EFCORE源码解读之创建DBContext查询拦截,在上一篇文章中,主要讲了DBContext的构造函数,以及如何缓存查询方法提升查询性能,还有最重要的拦截查询,托 ...
- webgoat _v8.1全流程通关
1.1 (A1)SQL Injection (intro) 概念 本课程介绍了什么是结构化查询语言(SQL),以及如何操纵它以执行开发人员原始意图之外的任务. 目标 用户将对SQL的工作原理和用途有基 ...
- freeRTOS 学习
一.任务状态 任务状态可以分成 Running 和Not Running: 但实际的Not Running状态还有许多的其他状态作为细分. 包括挂起,阻塞和就绪态 挂起状态表示该任务虽然已经创建但是在 ...
- 聊聊分布式 SQL 数据库Doris(八)
稀疏索引 密集索引:文件中的每个搜索码值都对应一个索引值,就是叶子节点保存了整行. 稀疏索引:文件只为索引码的某些值建立索引项. 稀疏索引的创建过程包括将集合中的元素分段,并给每个分段中的最小元素创建 ...
- 数据驱动决策,Datainside引领可视化报告新时代
数据驱动决策已经成为当今社会中的重要趋势,而Datainside作为一家数据可视化报告平台,正引领着可视化报告的新时代.下面是关于Datainside平台的详细描述. 数据集成与连接 Datainsi ...
- windows下tomcat开机自启动
在Windows下,可以通过以下步骤将Tomcat设置为开机自启动: 1. 打开Tomcat安装目录:通常情况下,Tomcat的安装目录位于`C:\Program Files\Apache Softw ...