HuggingFace——Tokenizer的简单记录

news/2024/5/19 13:20:14 标签: HuggingFace, Pytorch, python, transformers, tokenizer

Tokenizer [ 中文Course | API|详述文档]

下载使用

针对AutoTokenizer来说,如果是从在线仓库中下载,其是要访问:

python">    commit_hash = kwargs.get("_commit_hash", None)
    resolved_config_file = cached_file(
        pretrained_model_name_or_path,
        TOKENIZER_CONFIG_FILE,
        cache_dir=cache_dir,
        force_download=force_download,
        resume_download=resume_download,
        proxies=proxies,
        use_auth_token=use_auth_token,
        revision=revision,
        local_files_only=local_files_only,
        _raise_exceptions_for_missing_entries=False,
        _raise_exceptions_for_connection_errors=False,
        _commit_hash=commit_hash,
    )
    if resolved_config_file is None:
        logger.info("Could not locate the tokenizer configuration file, will try to use the model config instead.")
        return {}
    commit_hash = extract_commit_hash(resolved_config_file, commit_hash)

    with open(resolved_config_file, encoding="utf-8") as reader:
        result = json.load(reader) # 加载"tokenizer_config.json"
    result["_commit_hash"] = commit_hash
    return result

其中TOKENIZER_CONFIG_FILE是指:

# Slow tokenizers used to be saved in three separated files
SPECIAL_TOKENS_MAP_FILE = "special_tokens_map.json"
ADDED_TOKENS_FILE = "added_tokens.json"
TOKENIZER_CONFIG_FILE = "tokenizer_config.json"

针对不同的预训练模型,分词工具是不同的,比如:

  • Byte-level BPE, 用于 GPT-2;
  • WordPiece, 用于 BERT;
  • SentencePiece or Unigram, 用于多个多语言模型
    一般来说,具体使用哪些分词工具是在repo里面的tokenizer.json文件中配置的,比如hfl/roberta-ext模型中的tokenizer.json中可以看到下面的配置信息:
"model":
    {
        "type": "WordPiece",
        "unk_token": "[UNK]",
        "continuing_subword_prefix": "##",
        "max_input_chars_per_word": 100,
        "vocab":
        {
            "[PAD]": 0,
            ……
        }       
    }

官方是建议使用Auto* 类,因为Auto* 类设计与架构无关。

transformers/v4.21.0/en/main_classes/tokenizer#tokenizer">Tokenizer的一些输出展示

tokenizer = AutoTokenizer.from_pretrained('bert-base-chinese')
query_context_tokens = tokenizer('王广善先生!', '香港中文大学教授',
                        return_token_type_ids=True,
                        return_attention_mask=True,
                        return_offsets_mapping=True,
                        return_special_tokens_mask=True)
                        
tokens = query_context_tokens['input_ids']
st = tokenizer.decode(tokens)
type_ids = query_context_tokens['token_type_ids']
mask = query_context_tokens['attention_mask']
offsets_mapping = query_context_tokens['offset_mapping']  # 这个在官网并没有找到,也并不是很清楚到底指什么,但是可以从输出的结果中可以看出一些规律
special_tokens_mask = query_context_tokens['special_tokens_mask']
print('st:',st)
print('tokens:',tokens)
print('type_ids',type_ids)
print('attention_mask', attention_mask)
print('offsets_mapping', offsets_mapping)
print('special_tokens_mask', special_tokens_mask)

输出结果为

st: [CLS] 王 广 善 先 生 ! [SEP]香 港 中 文 大 学 教 授 [SEP] 
tokens: [101, 4374, 2408, 1587, 1044, 4495, 8013, 102, 7676, 3949, 704, 3152, 1920, 2110, 3136, 2956, 102]
type_ids: [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1]
attention_mask: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] 
offset_mapping: [(0, 0), (0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (0, 0), (0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (0, 0)]
special_tokens_mask: [1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1]

那么Tokenizer是怎么工作的

Tokenizer的本质其实也是一个pipeline,大体的工作流程可以分为下面的组成:
在这里插入图片描述

也就是在正式分开文本之前,需要经过Normalization和Pre-tokenization。

Normalization

Normalization这一步骤涉及一些常规清理,例如删除不必要的空格、小写和/或删除重音符号。如果你熟悉Unicode normalization(例如 NFC 或 NFKC),这也是 tokenizer 可能应用的东西。

🤗Transformers tokenizer 有一个属性叫做 backend_tokenizer 它提供了对 🤗 Tokenizers 库中底层标记器的访问:

python">from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
print(type(tokenizer.backend_tokenizer))

> <class 'tokenizers.Tokenizer'>

Pre-tokenization

分词器不能单独在原始文本上进行训练。相反,我们首先需要将文本拆分为小实体,例如单词。这就是Pre-tokenization这一步骤的用武之地。

要查看快速分词器如何执行预分词,我们可以使用 pre_tokenize_str() 的方法 pre_tokenizer 的属性 tokenizer 目的:

python">tokenizer.backend_tokenizer.pre_tokenizer.pre_tokenize_str("Hello, how are  you?")
> [('Hello', (0, 5)), (',', (5, 6)), ('how', (7, 10)), ('are', (11, 14)), ('you', (16, 19)), ('?', (19, 20))]

由于我们使用的是 BERT 分词器,预分词涉及对空格和标点符号进行拆分。对于这一步,其他标记器可以有不同的规则。例如,如果我们使用 GPT-2 标记器:

python">tokenizer = AutoTokenizer.from_pretrained("gpt2")
tokenizer.backend_tokenizer.pre_tokenizer.pre_tokenize_str("Hello, how are  you?")
> 它也会在空格和标点符号上拆分,但它会保留空格并将它们替换为 Ġ 符号,如果我们解码token,则使其能够恢复原始空格:
> [('Hello', (0, 5)), (',', (5, 6)), ('Ġhow', (6, 10)), ('Ġare', (10, 14)), ('Ġ', (14, 15)), ('Ġyou', (15, 19)),
 ('?', (19, 20))]

另请注意,与 BERT 分词器不同,此分词器不会忽略双空格

最后一个例子,让我们看一下基于 SentencePiece 算法的 T5 分词器:

python">tokenizer = AutoTokenizer.from_pretrained("t5-small")
tokenizer.backend_tokenizer.pre_tokenizer.pre_tokenize_str("Hello, how are  you?")
> [('▁Hello,', (0, 6)), ('▁how', (7, 10)), ('▁are', (11, 14)), ('▁you?', (16, 20))]

与 GPT-2 标记器一样,这个标记器保留空格并用特定标记替换它们( _ ),但 T5 分词器只在空格上拆分,而不是标点符号。还要注意,它默认在句子的开头添加了一个空格(之前 Hello ) 并忽略了之间的双空格 areyou .

剩下的就是探讨分词的底层原理了:从chapter 5之后的内容,分别探讨了BPE、WordPiece、Unigram

tokenizer%E8%AE%AD%E7%BB%83%E6%96%B0%E7%9A%84tokenizer">根据已有的tokenizer训练新的tokenizer

如果自己感兴趣的语言中没有可用的语言模型,或者如果自己的语料库与所使用的语言模型所训练的语料库有很大不同,那么此时就可能希望从适合自己的数据的tokenizer从头开始重新训练模型。

这将需要在自己的数据集上训练一个新的tokenizer。 但这究竟是什么意思? 在Tokenizer简介 中第一次查看标记器时,看到大多数 Transformer 模型使用_子词分词算法_。 为了识别哪些子词是感兴趣的并且在手头的语料库中最常出现,tokenizer需要仔细查看语料库中的所有文本——我们称之为training的过程。这种训练的确切规则取决于所使用的标记器的类型。

注意:⚠️ 训练标记器与训练模型不同!模型训练使用随机梯度下降使每个batch的loss小一点。它本质上是随机的(这意味着在进行两次相同的训练时,您必须设置一些随机数种子才能获得相同的结果)。训练标记器是一个统计过程,它试图确定哪些子词最适合为给定的语料库选择,用于选择它们的确切规则取决于分词算法。它是确定性的,这意味着在相同的语料库上使用相同的算法进行训练时,您总是会得到相同的结果。

更准确地说,Tokenizer库是围绕一个中央“Tokenizer”类构建的,构建这个类的每一部分可以在子模块的列表中重新组合:

  • normalizers 包含可以使用的所有可能的Normalizer类型(完整列表在这里)。
  • pre_tokenizesr 包含可以使用的所有可能的PreTokenizer类型(完整列表在这里)。
  • models 包含可以使用的各种类型的Model,如BPE、WordPiece和Unigram(完整列表在这里)。
  • trainers 包含所有不同类型的 trainer,可以使用一个语料库训练你的模型(每种模型一个;完整列表在这里)。
  • post_processors 包含可以使用的各种类型的PostProcessor(完整列表在这里)。
  • decoders 包含各种类型的Decoder,可以用来解码标记化的输出(完整列表在这里)。

在这里可以看到如何从头开始训练一个tokenizer

PS:tokenizer的使用还会持续更新,欢迎交流。


http://www.niftyadmin.cn/n/1915.html

相关文章

实验六 TCP及应用分析

我喜欢月亮&#xff0c;月亮不知道 实验六 TCP及应用分析1.telnet程序和tcp连接分析2.http协议分析3.ftp协议分析文中小鲨鱼是指Wireshark软件 本文参考教材是四川轻化工大学陈年老师所编著的"TCP/IP协议分析教程与实验" 1.telnet程序和tcp连接分析 目的:在真实网…

表达矩阵任意两个基因相关性分析 批量相关性分析 tcga geo 矩阵中相关性强的基因对 基因相关性

使用场景 1.已经确定研究的基因&#xff0c;但是想探索他潜在的功能&#xff0c;可以通过跟这个基因表达最相关的基因来反推他的功能&#xff0c;这种方法在英语中称为guilt of association&#xff0c;协同犯罪。 2.我们的注释方法依赖于TCGA大样本&#xff0c;既然他可以注释…

滤波器基础知识介绍

一、滤波器的基本知识 拿带通滤波器为例来说明滤波器的基本知识。 带通&#xff1a;滤波器允许通过的频率范围。 阻带&#xff1a;滤波器阻碍频率通过的范围。 过渡带&#xff1a;带通和阻带之间的范围称为过渡带。理想滤波器认为没有过渡带。 二、高通滤波器 高通滤波器&…

【C++修理之路】内存管理

目录&#xff1a;内存管理是什么&#xff1f;内存的分配new的初始化new和delete的用法malloc/free和new/delete的区别try catch的用法内存泄漏如何检测内存泄漏&#xff08;了解&#xff09;内存泄漏分类&#xff08;了解&#xff09;如何避免内存泄漏内存管理是什么&#xff1…

Linux系统 (三)- 权限介绍

~~~~前言命令行解释器 -- Command Line Interpreter ShellLinux操作系统命令行解释器对命令行解释器的初步认识命令行解释器的意义shell分类命令行解释器 CLI Shell图形界面 GUI ShellLinux权限Linux中用户分类su基本语法sudo基本语法配置操作权限管理权限是什么文件分类文件属…

算法开篇——数组

1、数组理论基础 总结刷题顺序全部来自代码随想录 数组是非常基础的数据结构&#xff0c;在面试中&#xff0c;考察数组的题目一般在思维上都不难&#xff0c;主要是考察对代码的掌控能力 也就是说&#xff0c;想法很简单&#xff0c;但实现起来可能就不是那么回事了。 数组…

代码随想录算法训练营第四天|24. 两两交换链表中的节点,19.删除链表的倒数第N个节点,面试题 02.07. 链表相交,142.环形链表II

代码随想录算法训练营第四天24.两两交换链表中的节点19.删除链表的倒数第N个节点02.07.链表相交142.环形链表II总结24.两两交换链表中的节点 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本…

eNSP - 基本命令解析

undo ter mo 一&#xff0c;单交换机VLAN划分 命令解释 进入系统配置模式 system-view 退到系统视图 quit 删除vlan20 undo vlan 20 交换机命名 sysname 显示vlan display v…