LLaMA模型之中文词表的蜕变

news2024/12/24 2:16:19

在目前的开源模型中,LLaMA模型无疑是一颗闪亮的⭐️,但是相对于ChatGLM、BaiChuan等国产大模型,其对于中文的支持能力不是很理想。原版LLaMA模型的词表大小是32K,中文所占token是几百个左右,这将会导致中文的编解码效率低。

在将LLaMA系列模型用于中文语言时需要进行中文词表扩充,基于sentencepiece工具训练,产生新的词表,然后与原始词表合并得到一个新词表。

本文将LLaMA模型中文词表扩充分为以下步骤:训练数据准备、词表训练、词表合并、词表测试。

训练数据准备

这里使用MedicalGPT中的天龙八部小说作为训练文本。

数据是txt文件,一行文本作为一条数据。

词表训练代码

import sentencepiece as spm

spm.SentencePieceTrainer.train(
    input='tianlongbabu.txt',
    model_prefix='bpe_llama',
    shuffle_input_sentence=False,
    train_extremely_large_corpus=True,
    max_sentence_length=2048,
    pad_id=3,
    model_type='BPE',
    vocab_size=5000,
    split_digits=True,
    split_by_unicode_script=True,
    byte_fallback=True,
    allow_whitespace_only_pieces=True,
    remove_extra_whitespaces=False,
    normalization_rule_name="nfkc",
)

print('训练完成')

sentencepiece训练参数:
Usage: …/build/src/spm_train [options] files

  • –input(逗号分隔的输入句子列表) 类型:字符串 默认值:“”
  • –input_format(输入格式。支持的格式为texttsv。) 类型:字符串 默认值:“”
  • –model_prefix(输出模型前缀) 类型:字符串 默认值:“”
  • –model_type(模型算法:unigram、bpe、word或char) 类型:字符串 默认值:“unigram”
  • –vocab_size(词汇表大小) 类型:int32 默认值:8000
  • –accept_language(此模型可以接受的语言的逗号分隔列表) 类型:字符串 默认值:“”
  • –self_test_sample_size(自测样本的大小) 类型:int32 默认值:0
  • –character_coverage(用于确定最小符号的字符覆盖率) 类型:double 默认值:0.9995
  • –input_sentence_size(训练器加载的句子的最大大小) 类型:uint64_t 默认值:0
  • –shuffle_input_sentence(提前随机抽样输入句子。当–input_sentence_size > 0时有效) 类型:bool 默认值:true
  • –seed_sentencepiece_size(seed sentencepieces的大小) 类型:int32 默认值:1000000
  • –shrinking_factor(与损失相关的保留顶部shrinking_factor片段) 类型:double 默认值:0.75
  • –num_threads(训练时的线程数) 类型:int32 默认值:16
  • –num_sub_iterations(EM子迭代的数量) 类型:int32 默认值:2
  • –max_sentencepiece_length(sentence piece的最大长度) 类型:int32 默认值:16
  • –max_sentence_length(句子的最大长度(字节)) 类型:int32 默认值:4192
  • –split_by_unicode_script(使用Unicode脚本拆分句子片段) 类型:bool 默认值:true
  • –split_by_number(通过数字(0-9)拆分标记) 类型:bool 默认值:true
  • –split_by_whitespace(使用空格拆分句子片段) 类型:bool 默认值:true
  • –split_digits(将所有数字(0-9)拆分为单独的片段) 类型:bool 默认值:false
  • –treat_whitespace_as_suffix(将空格标记视为后缀而不是前缀。) 类型:bool 默认值:false
  • –allow_whitespace_only_pieces(允许只包含(连续的)空格标记的片段) 类型:bool 默认值:false
  • –control_symbols(控制符号的逗号分隔列表) 类型:字符串 默认值:“”
  • –control_symbols_file(从文件加载控制符号。) 类型:字符串 默认值:“”
  • –user_defined_symbols(用户定义符号的逗号分隔列表) 类型:字符串 默认值:“”
  • –user_defined_symbols_file(从文件加载user_defined_symbols。) 类型:字符串 默认值:“”
  • –required_chars(UTF8字符,无论character_coverage如何,始终在字符集中使用) 类型:字符串 默认值:“”
  • –required_chars_file(从文件加载required_chars。) 类型:字符串 默认值:“”
  • –byte_fallback(将未知片段分解为UTF-8字节片段) 类型:bool 默认值:false
  • –vocabulary_output_piece_score(在vocab文件中定义分数) 类型:bool 默认值:true
  • –normalization_rule_name(规范化规则名称。从nfkc或identity中选择) 类型:字符串 默认值:“nmt_nfkc”
  • –normalization_rule_tsv(规范化规则TSV文件。) 类型:字符串 默认值:“”
  • –denormalization_rule_tsv(反规范化规则TSV文件。) 类型:字符串 默认值:“”
  • –add_dummy_prefix(在文本开头添加虚拟空格) 类型:bool 默认值:true
  • –remove_extra_whitespaces(删除前导、尾随和重复的内部空格) 类型:bool 默认值:true
  • –hard_vocab_limit(如果设置为false,则–vocab_size被视为软限制。) 类型:bool 默认值:true
  • –use_all_vocab(如果设置为true,则使用所有标记作为vocab。对于word/char模型有效。) 类型:bool 默认值:false
  • –unk_id(覆盖UNK(<unk>)id。) 类型:int32 默认值:0
  • –bos_id(覆盖BOS(<s>)id。将-1设置为禁用BOS。) 类型:int32 默认值:1
  • –eos_id(覆盖EOS(</s>)id。将-1设置为禁用EOS。) 类型:int32 默认值:2
  • –pad_id(覆盖PAD(<pad>)id。将-1设置为禁用PAD。) 类型:int32 默认值:-1
  • –unk_piece(覆盖UNK(<unk>)片段。) 类型:字符串 默认值:“<unk>”
  • –bos_piece(覆盖BOS(<s>)片段。) 类型:字符串 默认值:“<s>”
  • –eos_piece(覆盖EOS(</s>)片段。) 类型:字符串 默认值:“</s>”
  • –pad_piece(覆盖PAD(<pad>)片段。) 类型:字符串 默认值:“<pad>”
  • –unk_surface(<unk>的虚拟表面字符串。在解码中,<unk>被解码为unk_surface。) 类型:字符串 默认值:“ ⁇ ”
  • –train_extremely_large_corpus(增加unigram标记化的位深度。) 类型:bool 默认值:false
  • –random_seed(随机生成器的种子值。) 类型:uint32 默认值:4294967295
  • –enable_differential_privacy(是否在训练时添加差分隐私。目前仅UNIGRAM模型支持。) 类型:bool 默认值:false
  • –differential_privacy_noise_level(DP时添加的噪声量) 类型:float 默认值:0
  • –differential_privacy_clipping_threshold(DP时剪切计数的阈值) 类型:uint64_t 默认值:0
  • –help(显示帮助) 类型:bool 默认值:false
  • –version(显示版本) 类型:bool 默认值:false
  • –minloglevel(低于此级别的消息实际上不会被记录在任何地方) 类型:int 默认值:0
  1. 测试
import sentencepiece as spm

sp = spm.SentencePieceProcessor()
sp.load("bpe_llama.model")

print(sp.encode_as_pieces("这老者姓左,名叫子穆,是“无量剑”东宗的掌门。那道姑姓辛,道号双清,是“无量剑”西宗掌门。"))
print(sp.encode_as_ids("这老者姓左,名叫子穆,是“无量剑”东宗的掌门。那道姑姓辛,道号双清,是“无量剑”西宗掌门。"))

词表合并代码

import os
os.environ["PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION"]="python"

from transformers import LlamaTokenizer
from sentencepiece import sentencepiece_model_pb2 as sp_pb2_model
import sentencepiece as spm

llama_tokenizer_dir = 'llama-2-7b-bin'
chinese_sp_model_file = 'bpe_llama.model'

# 分词器加载
llama_tokenizer = LlamaTokenizer.from_pretrained(llama_tokenizer_dir)
chinese_sp_model = spm.SentencePieceProcessor()
chinese_sp_model.Load(chinese_sp_model_file)

# 解析
llama_spm = sp_pb2_model.ModelProto()
llama_spm.ParseFromString(llama_tokenizer.sp_model.serialized_model_proto())
chinese_spm = sp_pb2_model.ModelProto()
chinese_spm.ParseFromString(chinese_sp_model.serialized_model_proto())

# 词表长度
print(len(llama_tokenizer),len(chinese_sp_model))

# 添加新token到llama词表
llama_spm_tokens_set=set(p.piece for p in llama_spm.pieces)
print(len(llama_spm_tokens_set))
print(f"Before:{len(llama_spm_tokens_set)}")
for p in chinese_spm.pieces:
    piece = p.piece
    if piece not in llama_spm_tokens_set:
        new_p = sp_pb2_model.ModelProto().SentencePiece()
        new_p.piece = piece
        new_p.score = 0
        llama_spm.pieces.append(new_p)
print(f"New model pieces: {len(llama_spm.pieces)}")

output_sp_dir = '../merged_tokenizer_sp'
output_hf_dir = '../merged_tokenizer_hf'

vocab_content = ''
for p in llama_spm.pieces:
    vocab_content += f"{p.piece} {p.score}\n"
# 保存词表
with open(output_sp_dir+'/chinese_llama.vocab', "w", encoding="utf-8") as f:
    f.write(vocab_content)
# 保存spm模型
with open(output_sp_dir+'/chinese_llama.model', 'wb') as f:
    f.write(llama_spm.SerializeToString())

# 保存llama新tokenizer
tokenizer = LlamaTokenizer(vocab_file=output_sp_dir+'/chinese_llama.model')
tokenizer.save_pretrained(output_hf_dir)
print(f"Chinese-LLaMA tokenizer has been saved to {output_hf_dir}")

词表文件:

词表测试代码

from transformers import LlamaTokenizer

llama_tokenizer = LlamaTokenizer.from_pretrained(llama_tokenizer_dir)
chinese_llama_tokenizer = LlamaTokenizer.from_pretrained(output_hf_dir)
print(tokenizer.all_special_tokens)
print(tokenizer.all_special_ids)
print(tokenizer.special_tokens_map)
text='''白日依山尽,黄河入海流。欲穷千里目,更上一层楼。'''
text='''大模型是指具有非常大的参数数量的人工神经网络模型。 在深度学习领域,大模型通常是指具有数亿到数万亿参数的模型。'''
print("Test text:\n",text)
print(f"Tokenized by LLaMA tokenizer:{len(llama_tokenizer.tokenize(text))},{llama_tokenizer.tokenize(text)}")
print(f"Tokenized by GoGPT-LLaMA tokenizer:{len(chinese_llama_tokenizer.tokenize(text))},{chinese_llama_tokenizer.tokenize(text)}")

从结果可以看到,中文分词后长度显著减小,英文分词没有产生影响。

注:在对中文词表扩展后的LLaMA模型做增量预训练时,需要调整嵌入层的大小(model.resize_token_embeddings(len(tokenizer))),因为词表大小发生变化。

参考

[1] https://github.com/shibing624/MedicalGPT/tree/main

[2] https://github.com/yanqiangmiffy/how-to-train-tokenizer/tree/main

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

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

相关文章

Python---综合案例:通讯录管理系统---涉及点:列表、字典、死循环

需求&#xff1a; 开个一个通讯录的管理系统&#xff0c;主要用于实现存储班级中同学的信息&#xff08;姓名、年龄、电话&#xff09; 涉及点&#xff1a;列表、字典、死循环 相关链接&#xff1a;Python--列表及其应用场景---增、删、改、查。-CSDN博客 Python---字典---…

ip数据包

数据报文格式 首部 版本&#xff08;Version&#xff09; 版本字段占4bit&#xff0c;通信双方使用的版本必须一致。对于IPv4&#xff0c;字段的值是4。 首部长度&#xff08;Internet Header Length&#xff0c; IHL&#xff09; 占4bit&#xff0c;首部长度说明首部有多少…

ubutun上编译出现undefined reference to symbol ‘dladdr@@GLIBC_2.2.5‘的错误

作者&#xff1a;朱金灿 来源&#xff1a;clever101的专栏 为什么大多数人学不会人工智能编程&#xff1f;>>> ubutun上编译一段C程序&#xff0c;出现错误&#xff1a; /usr/bin/ld: /tmp/ccghh3FJ.o: undefined reference to symbol ‘dladdrGLIBC_2.2.5’ //lib/…

前端---CSS的盒模型

文章目录 什么是盒模型&#xff1f;设置边框设置内边距设置外边距块级元素水平居中 什么是盒模型&#xff1f; 页面上的每个HTML元素都是一个一个的“盒子”&#xff0c;这些盒子由&#xff1a;内容、内边距、边框、外边距组成。 我们可以和住的房子联系起来&#xff0c;更好…

HarmonyOS开发(二):TypeScript入门

1、编程语言介绍 ArkTS是HarmonyOS主推的应用开发语言&#xff0c;它是在TypeScript语言的基础之上&#xff0c;匹配ArkUI框架&#xff0c;扩展了声明式UI、状态管理等相应的能力&#xff0c;让开发者以更简洁、更自然的方式开发跨端应用。 ArkTS、TypeScript和JavaScript之间…

打开 Chrome 的 「内存节省程序」开关和关闭硬件加速

不知道从什么时候开始&#xff0c;应该是最近1个月&#xff0c;感觉 Mac 浏览器总是占用很高的 CPU&#xff0c;多开一些标签页&#xff0c;或者浏览器窗口&#xff0c;相互切换时系统就会变得无响应&#xff0c;从 Chrome 浏览器里找到一个「内存节省程序」的配置&#xff0c;…

数据校验:Spring Validation

Spring Validation概述 在开发中&#xff0c;我们经常遇到参数校验的需求&#xff0c;比如用户注册的时候&#xff0c;要校验用户名不能为空、用户名长度不超过20个字符、手机号是合法的手机号格式等等。如果使用普通方式&#xff0c;我们会把校验的代码和真正的业务处理逻辑耦…

二维码智慧门牌管理系统升级解决方案:运营可视化之道

文章目录 前言一、系统概述二、数据可视化与运营决策 前言 随着科技的飞速发展和人们生活水平的提高&#xff0c;传统的门牌管理系统已经无法满足现代社会的需求。在这个信息化、智能化的时代&#xff0c;一款升级版的二维码智慧门牌管理系统应运而生&#xff0c;它将以全新的…

手机能做静态二维码吗?用手机做二维码的教程

现在手机上有很多的功能&#xff0c;能够帮助我们应对日常生活中的各种问题&#xff0c;那么如果我们想要在手机上生成一个静态二维码&#xff0c;大家知道该怎么来操作吗&#xff1f;一般制作二维码需要专业的二维码生成工具才可以完成制作&#xff0c;那么下面小编来给大家分…

properties文件乱码

出现如下乱码&#xff1a; 按照步骤修改编码方式就可以解决啦 修改之后结果就是下面这样~

【LabVIEW学习】1.对labview的初步使用,控制数据流动

一。初步使用labview 1.程序图标 2.打开之后继续点击新建VI 原因&#xff1a;最后的程序后缀就是 .vi 3.新建之后&#xff0c;会有三个界面&#xff08;没有不要紧&#xff0c;找找肯定有&#xff09; 4.程序操作方法 1.拖动控件到前面板 2.此时程序框图会出现对应的控件 拖动…

利用Python群组分析方法剖析客户行为

大家好&#xff0c;如今的企业有能力收集大量的数据&#xff0c;这些数据可以帮助企业制定更好的策略并了解其客户的行为。Cohort分析可以在其中发挥作用&#xff0c;Cohort分析是一种了解客户行为或用户互动的强大工具&#xff0c;并为企业提供有价值的见解&#xff0c;本文中…

优雅的Java编程:将接口对象作为方法参数

theme: smartblue 目录 概述 在Java编程中&#xff0c;方法的参数传递方式通常是通过基本类型、对象引用或者集合等方式。然而&#xff0c;一种更加优雅且灵活的设计模式是将接口对象作为方法的参数。这种方式为我们带来了许多好处&#xff0c;包括降低耦合性、实现多态性和可…

微信小程序display常用属性和子元素排列方式介绍

wxss中display常用显示属性与css一致&#xff0c;介绍如下&#xff1a; 针对元素本身显示的属性&#xff1a; displayblock&#xff0c;元素显示换行displayinline&#xff0c;元素显示换行&#xff0c;但不可设置固定的宽度和高度&#xff0c;也不可设置上下方向的margin和p…

postgreSQL中的高速缓存

1. 高速缓存简介 ​如下图所示&#xff0c;当一个postgreSQL进程读取一个元组时&#xff0c;需要获取表的基本信息&#xff08;例如&#xff1a;表的oid、索引信息和统计信息等&#xff09;及元组的模式信息&#xff0c;这些信息被分别记录在多个系统表中。通常一个表的模式信…

2019年12月 Scratch(一级)真题解析#中国电子学会#全国青少年软件编程等级考试

一、单选题(共25题,每题2分,共50分) 第1题 下列关于舞台的描述,不正确的是? A:Scratch只能设置一个舞台 B:舞台不能进行编程 C:舞台可以有多个背景 D:舞台上可以有角色 答案:B A选项,scratch只有一个舞台,B选项,可以在舞台区进行编程,例如切换背景,设置背景…

[pytorch]设备选择以及卷积神经网络的应用

0.写在前面: 首先这篇文章还没写完,因为今天要尝试对我之前的一个框架做一个简单的更新迭代,所以目前先更新这么多. 1.关于设备的选择 首先,目前的大多数电脑都是自带一些GPU(图形计算单元,在这里被称之为cuda), 需要安装相关的驱动才能正常使用这些设备和调用他们的具体情况…

在Vue.js中,什么是Vuex?它的作用是什么?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

Model Inspector—软件模型静态规范检查工具

产品概述 Model Inspector&#xff08;MI&#xff09;原厂商是韩国Suresoft&#xff0c;是KOLAS国际公认测评机构&#xff0c;旨在提升安全关键领域软件可信度。MI用于开发过程中模型的静态检查&#xff0c;包括规范检查、复杂度度量&#xff0c;提供MAAB、HIS、CG、MISRA_AC_…

C++模拟实现——AVL树

AVL树 1.介绍 AVL树是对搜索二叉树的改进&#xff0c;通过特定的方法使得每个节点的左右子树高度差绝对值不超过1&#xff0c;使得避免出现歪脖子的情况&#xff0c;最核心的实现在于插入值部分是如何去实现平衡调整的&#xff0c;由于前面详细实现和解析过搜索二叉树&#x…