二、transformers基础组件之Tokenizer

在使用神经网络处理自然语言处理任务时,我们首先需要对数据进行预处理,将数据从字符串转换为神经网络可以接受的格式,一般会分为如下几步:

- Step1 分词:使用分词器对文本数据进行分词(字、字词);
- Step2 构建词典:根据数据集分词的结果,构建词典映射(这一步并不绝对,如果采用预训练词向量,词典映 射要根据词向量文件进行处理);
- Step3 数据转换:根据构建好的词典,将分词处理后的数据做映射,将文本序列转换为数字序列;
- Step4 数据填充与截断:在以batch输入到模型的方式中,需要对过短的数据进行填充,过长的数据进行截断, 保证数据长度符合模型能接受的范围,同时batch内的数据维度大小一致。

在transformers工具包中,只需要借助Tokenizer模块便可以快速的实现上述全部工作,它的功能就是将文本转换为神经网络可以处理的数据。Tokenizer工具包无需额外安装,会随着transformers一起安装。

1 Tokenizer 基本使用(对单条数据进行处理)

Tokenizer 基本使用:
(1) 加载保存(from_pretrained / save_pretrained)
(2) 句子分词(tokenize)
(3) 查看词典 (vocab)
(4) 索引转换(convert_tokens_to_ids / convert_ids_to_tokens)
(5) 填充截断(padding / truncation)
(6) 其他输入(attention_mask / token_type_ids)

不同的模型会对应不同的tokenizer。transformers中需要导入AutoTokenizer,AutoTokenizer会根据不同的模型导入对应的tokenizer

1.1. Tokenizer的加载与保存

from transformers import AutoTokenizer
# 从HuggingFace加载,输入模型名称,即可加载对于的分词器
tokenizer = AutoTokenizer.from_pretrained("../models/roberta-base-finetuned-dianping-chinese")

tokenizer打印结果如下:

BertTokenizerFast(name_or_path='/root/autodl-fs/models/roberta-base-finetuned-dianping-chinese', vocab_size=21128, model_max_length=1000000000000000019884624838656, is_fast=True, padding_side='right', truncation_side='right', 
special_tokens={'unk_token': '[UNK]', 'sep_token': '[SEP]', 'pad_token': '[PAD]', 'cls_token': '[CLS]', 'mask_token': '[MASK]'}, clean_up_tokenization_spaces=True),  added_tokens_decoder={0: AddedToken("[PAD]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),100: AddedToken("[UNK]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),101: AddedToken("[CLS]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),102: AddedToken("[SEP]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),103: AddedToken("[MASK]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),
}

将tokenizer 保存到本地后可以直接从本地加载

# tokenizer 保存到本地
tokenizer.save_pretrained("./roberta_tokenizer")
# 从本地加载tokenizer
tokenizer = AutoTokenizer.from_pretrained("./roberta_tokenizer/")

1.2. 句子分词

sen = "弱小的我也有大梦想!"
tokens = tokenizer.tokenize(sen)
#['弱', '小', '的', '我', '也', '有', '大', '梦', '想', '!']

1.3. 查看字典

tokenizer.vocab
tokenizer.vocab_size  #21128
{'##椪': 16551,'##瀅': 17157,'##蝕': 19128,'##魅': 20848,'##隱': 20460,'儆': 1024,'嫣': 2073,'簧': 5082,'镁': 7250,'maggie': 12423,'768': 12472,'1921': 10033,'焜': 4191,'渎': 3932,'鎂': 7110,'谥': 6471,'app': 8172,'噱': 1694,'goo': 9271,'345': 11434,'##rin': 13250,'ᆷ': 324,'redis': 12599,'/': 8027,'莅': 5797,
...'##轰': 19821,'387': 12716,'##齣': 21031,'##ント': 10002,...}
Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...

1.4. 索引转换

# 将词序列转换为id序列
ids = tokenizer.convert_tokens_to_ids(tokens)
#[2483, 2207, 4638, 2769, 738, 3300, 1920, 3457, 2682, 106]# 将id序列转换为token序列
tokens = tokenizer.convert_ids_to_tokens(ids)
#['弱', '小', '的', '我', '也', '有', '大', '梦', '想', '!']# 将token序列转换为string
str_sen = tokenizer.convert_tokens_to_string(tokens)
#'弱 小 的 我 也 有 大 梦 想!'

上面的把各个步骤都分开了,简洁的方法:

# 将字符串转换为id序列,又称之为编码
ids = tokenizer.encode(sen, add_special_tokens=True)
# [101, 2483, 2207, 4638, 2769, 738, 3300, 1920, 3457, 2682, 106, 102]# 将id序列转换为字符串,又称之为解码
str_sen = tokenizer.decode(ids, skip_special_tokens=False)
# '[CLS] 弱 小 的 我 也 有 大 梦 想! [SEP]'

下面的方法比上面多了两个special_tokens:[CLS][SEP],这是特定tokenizer给定的,句子开头和句子结尾

1.5. 填充与截断

以上是针对单条数据,如果是针对多条数据会涉及到填充和截断。把短的数据补齐,长的数据截断。

# 填充
ids = tokenizer.encode(sen, padding="max_length", max_length=15)
# [101, 2483, 2207, 4638, 2769, 738, 3300, 1920, 3457, 2682, 106, 102, 0, 0, 0]
# 截断
ids = tokenizer.encode(sen, max_length=5, truncation=True)
# [101, 2483, 2207, 4638, 102]

填充和阶段的长度包含了两个special_tokens:[CLS][SEP]

1.6. 其他输入部分

数据处理里面还有一个地方要特别注意:既然数据中存在着填充,就要告诉模型,哪些是填充,哪些是有效的数据。这个时候需要attention_mask。也就是说,对于上面的例子,ids为0的元素对应的attention_mask的元素应为0,不为0的元素位置attention_mask的元素应为0。
另外香BERT这样的模型需要token_type_ids标定是第几个句子。

1.6.1 手动生成方式(体现定义)

如果是手动设定attention_mask和token_type_ids如下:

attention_mask = [1 if idx != 0 else 0 for idx in ids]
token_type_ids = [0] * len(ids)
#ids:   ([101, 2483, 2207, 4638, 2769, 738, 3300, 1920, 3457, 2682, 106, 102, 0, 0, 0],
#attention_mask:  [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
#token_type_ids:  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
1.6.2 快速调用方式

transformers肯定不会让手动生成,有自动的方法。就是encode_plus

inputs = tokenizer.encode_plus(sen, padding="max_length", max_length=15)

使用encode_plus生成的是一个字典如下:

{
'input_ids': [101, 2483, 2207, 4638, 2769, 738, 3300, 1920, 3457, 2682, 106, 102, 0, 0, 0], 
'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0]
}

‘input_ids’:分此后转换的id
‘token_type_ids’:属于第几个句子
‘attention_mask’:1对应的’input_ids’元素是非填充元素,是真实有效的

调用encode_plus方法名字太长了,不好记,等效的方法就是可以直接用 tokenizer而不使用任何方法

inputs = tokenizer(sen, padding="max_length", max_length=15)

得到和上面一样的结果:

{
'input_ids': [101, 2483, 2207, 4638, 2769, 738, 3300, 1920, 3457, 2682, 106, 102, 0, 0, 0], 
'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0]
}

2 处理batch数据

上面是处理单条数据,现在看看怎么处理batch数据

sens = ["弱小的我也有大梦想","有梦想谁都了不起","追逐梦想的心,比梦想本身,更可贵"]
res = tokenizer(sens)
#{'input_ids': [[101, 2483, 2207, 4638, 2769, 738, 3300, 1920, 3457, 2682, 102], [101, 3300, 3457, 2682, 6443, 6963, 749, 679, 6629, 102], [101, 6841, 6852, 3457, 2682, 4638, 2552, 8024, 3683, 3457, 2682, 3315, 6716, 8024, 3291, 1377, 6586, 102]], 'token_type_ids': [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], 'attention_mask': [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]}

sens是个列表有3个句子,得到的res是一个字典,包含:‘input_ids’;‘token_type_ids’;‘attention_mask’,每个都是一个列表,列表的每个元素对应每个句子’input_ids’;‘token_type_ids’;‘attention_mask’

以batch的方式去处理比一个一个的处理速度更快。

3 Fast/Slow Tokenizer

Tokenizer有快的版本和慢的版本

3.1 FastTokenizer

  • 基于Rust实现,速度快
  • offsets_mapping、 word_ids SlowTokenizer
sen = "弱小的我也有大Dreaming!"
fast_tokenizer = AutoTokenizer.from_pretrained(model_path)

请添加图片描述

FastTokenizer会有一些特殊的返回。比如return_offsets_mapping,用来指示每个token对应到原文的起始位置。

inputs = fast_tokenizer(sen, return_offsets_mapping=True)
{'input_ids': [101, 2483, 2207, 4638, 2769, 738, 3300, 1920, 10252, 8221, 106, 102], 
'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], # "弱小的我也有大Dreaming!"
# Dreaming被分为两个词(7, 12), (12, 15)
# 该字段中保存着每个token对应到原文中的起始与结束位置
'offset_mapping': [(0, 0), (0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 12), (12, 15), (15, 16), (0, 0)]
}
# word_ids方法,该方法会返回分词后token序列对应原始实际词的索引,特殊标记的值为None。
# Dreaming被分为两个词【7, 7】
inputs.word_ids()
# [None, 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, None]

3.2 SlowTokenizer

  • 基于Python实现,速度慢
slow_tokenizer = AutoTokenizer.from_pretrained(model_path, use_fast=False)

请添加图片描述两种方式的时间对比如下:

请添加图片描述

4 特殊Tokenizer的加载

一些非官方实现的模型,自己实现了tokenizer,如果想用他们自己实现的tokenizer,需要指定trust_remote_code=True

from transformers import AutoTokenizer# 需要设置trust_remote_code=True
# 表示信任远程代码
tokenizer = AutoTokenizer.from_pretrained("THUDM/chatglm-6b", trust_remote_code=True)
tokenizer

即使保存到本地,然后从本地加载也要设置trust_remote_code=True

tokenizer.save_pretrained("chatglm_tokenizer")# 需要设置trust_remote_code=True
tokenizer = AutoTokenizer.from_pretrained("chatglm_tokenizer", trust_remote_code=True)

参考链接:【手把手带你实战HuggingFace Transformers-入门篇】基础组件之Tokenizer_哔哩哔哩_bilibili

Transformers基本组件(一)快速入门Pipeline、Tokenizer、Model_transformers.pipeline-CSDN博客

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

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

相关文章

镜像和容器的管理

一、镜像的管理 获取镜像并生成相关容器 # 拉取镜像 docker pull alpine # 默认是latest,也就是最新版本,也可指定版本(在镜像名后边加“:版本号”) # 或者 # 从主机中导入镜像到docker中 docker image load -i /test#生成容器 …

设计模式简述(十九)桥梁模式

桥梁模式 描述基本组件使用 描述 桥梁模式是一种相对简单的模式,通常以组合替代继承的方式实现。 从设计原则来讲,可以说是单一职责的一种体现。 将原本在一个类中的功能,按更细的粒度拆分到不同的类中,然后各自独立发展。 基本…

ImportError: DLL load failed: 找不到指定的程序。

查看其他博客说是缺少libssl-1_1-x64.dll 和 libcrypto-1_1-x64.dll 然后去下载放到博客说的目录下 没有用 解决不了一点 OpenSSL for Windows 64位 完整安装包 在这里 项目地址: https://gitcode.com/open-source-toolkit/eb627 注意事项 此安装包仅适用于64位Windows系…

电池单元和电极性能

电芯设计中的挑战 对于电池制造商来说,提高电池能量和功率密度至关重要。在高功率密度和长循环寿命之间取得平衡是电池设计中的关键挑战,通常需要仔细优化材料、电极结构和热管理系统。另一个关键挑战是通过优化重量体积比来降低电池单元的总体成本。 工…

数据加密与隐私保护:让你的信息固若金汤

数据加密与隐私保护:让你的信息固若金汤 大家好,我是 Echo_Wish,今天聊聊一个 人人都关心、但很多人没做好 的话题——数据加密与隐私保护的最佳实践。 为什么要重视数据安全? 现在是数字化时代,从个人照片、银行卡信息到企业机密,数据泄露的风险无处不在。你可能觉得自…

【高数上册笔记篇02】:数列与函数极限

【参考资料】 同济大学《高等数学》教材樊顺厚老师B站《高等数学精讲》系列课程 (注:本笔记为个人数学复习资料,旨在通过系统化整理替代厚重教材,便于随时查阅与巩固知识要点) 仅用于个人数学复习,因为课…

C++(8):类型限定符

目录 1. const:定义常量 2. volatile:易变性修饰 3. restrict(C非标准) 4. mutable:突破常量性 5. static:静态存储 6. register(已弃用) 分类修正说明 1. const:…

Nginx yum 安装

一、环境准备 一台装有 CentOS 7.9 的虚拟机 二、安装 安装 yum install -y nginx -y:所有的安装选项都选择 yes。 启动 nginx systemctl enable nginx --now enable:设置 nginx 为开机启动。--now:马上启动 nginx。 查看 nginx 服务状态…

【5分钟学Docker】Docker快速使用

目录 1. 概述 2. 基本操作 2.1. 镜像操作 2.2. 容器操作 2.3. 运行操作 2.4. 镜像保存 2.5. 镜像分享 3. 高级操作 4. 挂载 4.1. 目录挂载 4.2. 卷映射 1. 概述 Docker 镜像有镜像名称和TAG 2. 基本操作 2.1. 镜像操作 查看镜像 docker images docker image ls …

5000字总结 HTML5 中的音频和视频,关羽标签、属性、API 和最佳实践

HTML5 音频与视频开发完全指南&#xff1a;标签、属性、API 与最佳实践 一、引言&#xff1a;HTML5 媒体时代的到来 在 HTML5 之前&#xff0c;网页中的音频和视频播放依赖 Flash、Silverlight 等第三方插件&#xff0c;存在兼容性差、性能瓶颈和安全隐患。HTML5 引入的 <…

【C语言】(9)—指针3

文章目录 一、字符指针的深入理解二、数组指针详解三、二维数组传参的本质四、函数指针及其应用五、函数指针数组与转移表 一、字符指针的深入理解 1.1 字符指针的基本使用 字符指针(char*)是指向字符类型数据的指针&#xff0c;它有两种常见的使用方式&#xff1a; // 方式一…

MDK调试技巧

1、自动生成反汇编 fromelf -c -o "$LL.txt" "#L" 解释&#xff1a; 1、fromelf 是 ARM Compiler 工具链中的一个命令行工具&#xff0c;从fromelf这个名字上我们就能看到它是用来处理elf文件的&#xff0c;elf 全称 Executable and Linking Format &…

嵌入式STM32学习——433M无线遥控灯

1.433M无限模块工作原理&#xff1a; 数据发射模块的工作频率为315M&#xff0c;采用声表谐振器SAW稳频&#xff0c;频率稳定度极高&#xff0c;当环境温度在-25~85度之间变化时&#xff0c;频飘仅为3ppm。 接收到信号&#xff0c;接收模块对应针脚输出高电平&#xff0c;有DO…

JDBC工具类的三个版本

一、JDBC连接数据库的7个步骤 1、加载驱动 2、获取连接 3、编写sql 4、获取执行sql的stmt对象 有两种 stmt&#xff08;存在sql注入问题 字符串拼接&#xff09; pstmt&#xff08;预编译可以防止sql注入&#xff09; 5、执行sql 拿到结果集 6、遍历结果集 7、关闭资源…

3.1/Q1,Charls最新文章解读

文章题目&#xff1a;Predictive model for sarcopenia in chronic kidney disease: a nomogram and machine learning approach using CHARLS data DOI&#xff1a;10.3389/fmed.2025.1546988 中文标题&#xff1a;慢性肾病肌肉减少症的预测模型&#xff1a;使用 CHARLS 数据的…

DEEPPOLAR:通过深度学习发明非线性大核极坐标码(2)

目录 2.问题的提出和背景 2.1 信道编码 2.2.极化码 极坐标编码 极坐标解码 原文&#xff1a;《DEEPPOLAR: Inventing Nonlinear Large-Kernel Polar Codes via Deep Learning》 2.问题的提出和背景 2.1 信道编码 信道编码是一种为传输添加冗余的技术&#xff0c;使其对…

手机当电脑播放器 soundwire

soundwire server免费下载_soundwire serverPC下载_3DM软件 win11可用延迟1秒 安卓端音频缓冲区大小改成8k延迟就没那么夸张了 我用audiorelay连上了没声音

LVGL中的事件

文章目录 &#x1f9f1; 一、什么是 LVGL 事件&#xff1f;&#x1f3af; 二、事件回调的注册参数解释&#xff1a;示例&#xff1a; &#x1f4da; 三、常见事件类型&#xff08;lv_event_code_t&#xff09;✅ 1. 输入类事件&#xff08;用户交互&#xff09;✅ 2. 组件状态类…

警惕C#版本差异多线程中的foreach陷阱

警惕C#版本差异多线程中的foreach陷阱​ 同样的代码,不同的结果闭包捕获的“时间差”问题绕过闭包陷阱的三种方法Lambda立即捕获(代码简洁)显式传递参数(兼容性最佳)使用Parallel.ForEach(官方推荐)注意事项:版本兼容性指南警惕多线程中的foreach陷阱:C#版本差异引发的…

mac u盘重装mac10.15Catalina系统

我的电脑提mac2017的air 重装过程 (文件夹中间有空格时为 Install\ macOS\ Catalina 才行) &#xff08;有需要的&#xff0c;最好做一下备份&#xff0c;有些东西可以及时找到配置和文件之类的&#xff0c; u盘制作是在mac电脑上操作的) 一、先下载系统镜像文件或自行到官方…