evaluate&transformers

This commit is contained in:
estom
2024-05-28 15:28:42 +08:00
parent decafa208b
commit f26991c13a
4052 changed files with 574 additions and 0 deletions

View File

@@ -0,0 +1,148 @@
## 说明
参数高效微调PEFT方法在微调过程中冻结预训练模型的参数并在其顶部添加少量可训练参数adapters。adapters被训练以学习特定任务的信息。这种方法已被证明非常节省内存同时具有较低的计算使用量同时产生与完全微调模型相当的结果。
## 使用
### 安装
```
pip install peft
```
### 加载adapter
要从huggingface的Transformers库中加载并使用PEFTadapter模型请确保Hub仓库或本地目录包含一个adapter_config.json文件和adapter权重如上例所示。然后您可以使用AutoModelFor类加载PEFT adapter模型。例如要为因果语言建模加载一个PEFT adapter模型
指定PEFT模型id
将其传递给AutoModelForCausalLM类
```
from transformers import AutoModelForCausalLM, AutoTokenizer
peft_model_id = "ybelkada/opt-350m-lora"
model = AutoModelForCausalLM.from_pretrained(peft_model_id)
```
您也可以通过load_adapter方法来加载 PEFT adapter。
```
from transformers import AutoModelForCausalLM, AutoTokenizer
model_id = "facebook/opt-350m"
peft_model_id = "ybelkada/opt-350m-lora"
model = AutoModelForCausalLM.from_pretrained(model_id)
model.load_adapter(peft_model_id)
```
基于8bit或4bit进行加载
bitsandbytes集成支持8bit和4bit精度数据类型这对于加载大模型非常有用因为它可以节省内存请参阅bitsandbytes指南以了解更多信息。要有效地将模型分配到您的硬件请在from_pretrained()中添加load_in_8bit或load_in_4bit参数并将device_map="auto"设置为:
```
from transformers import AutoModelForCausalLM, AutoTokenizer
peft_model_id = "ybelkada/opt-350m-lora"
model = AutoModelForCausalLM.from_pretrained(peft_model_id, device_map="auto", load_in_8bit=True)
```
### 添加adapter
你可以使用~peft.PeftModel.add_adapter方法为一个已有adapter的模型添加一个新的adapter只要新adapter的类型与当前adapter相同即可。例如如果你有一个附加到模型上的LoRA adapter
```
from transformers import AutoModelForCausalLM, OPTForCausalLM, AutoTokenizer
from peft import PeftConfig
model_id = "facebook/opt-350m"
model = AutoModelForCausalLM.from_pretrained(model_id)
lora_config = LoraConfig(
target_modules=["q_proj", "k_proj"],
init_lora_weights=False
)
model.add_adapter(lora_config, adapter_name="adapter_1")
```
添加一个新的adapter
```
# attach new adapter with same config
model.add_adapter(lora_config, adapter_name="adapter_2")
```
现在您可以使用~peft.PeftModel.set_adapter来设置要使用的adapter。
```
# use adapter_1
model.set_adapter("adapter_1")
output = model.generate(**inputs)
print(tokenizer.decode(output_disabled[0], skip_special_tokens=True))
# use adapter_2
model.set_adapter("adapter_2")
output_enabled = model.generate(**inputs)
print(tokenizer.decode(output_enabled[0], skip_special_tokens=True))
```
### 启用和禁用adapters
一旦您将adapter添加到模型中您可以启用或禁用adapter模块。要启用adapter模块
```
from transformers import AutoModelForCausalLM, OPTForCausalLM, AutoTokenizer
from peft import PeftConfig
model_id = "facebook/opt-350m"
adapter_model_id = "ybelkada/opt-350m-lora"
tokenizer = AutoTokenizer.from_pretrained(model_id)
text = "Hello"
inputs = tokenizer(text, return_tensors="pt")
model = AutoModelForCausalLM.from_pretrained(model_id)
peft_config = PeftConfig.from_pretrained(adapter_model_id)
# to initiate with random weights
peft_config.init_lora_weights = False
model.add_adapter(peft_config)
model.enable_adapters()
output = model.generate(**inputs)
```
要禁用adapter模块
```
model.disable_adapters()
output = model.generate(**inputs)
```
### 训练一个adapter
训练一个 PEFT adapter
PEFT适配器受Trainer类支持因此您可以为您的特定用例训练适配器。它只需要添加几行代码即可。例如要训练一个LoRA adapter
如果你不熟悉如何使用Trainer微调模型请查看微调预训练模型教程。
使用任务类型和超参数定义adapter配置参见~peft.LoraConfig以了解超参数的详细信息
```
from peft import LoraConfig
peft_config = LoraConfig(
lora_alpha=16,
lora_dropout=0.1,
r=64,
bias="none",
task_type="CAUSAL_LM",
)
```
将adapter添加到模型中。
```
model.add_adapter(peft_config)
```
现在可以将模型传递给Trainer了
```
trainer = Trainer(model=model, ...)
trainer.train()
```
要保存训练好的adapter并重新加载它
```
model.save_pretrained(save_dir)
model = AutoModelForCausalLM.from_pretrained(save_dir)
```

View File

@@ -0,0 +1,128 @@
https://blog.csdn.net/muyao987/article/details/125411129
### 安装
```
pip install evaluate
```
检查是否安装成功
```
python -c "import evaluate; print(evaluate.load('accuracy').compute(references=[1], predictions=[1]))"
```
### load
加载评估指标
evaluate中的每个指标都是一个单独的Python模块通过 evaluate.load()(点击查看文档) 函数快速加载其中load函数的常用参数如下
* path必选str类型。可以是指标名如 accuracy 或 社区的铁汁们贡献 的 muyaostudio/myeval如果源码安装还可以是路径名如./metrics/rouge 或 ./metrics/rogue/rouge.py。我用的后者因为直接传指标名会联网下载评价脚本但单位的网不给力。
* config_name可选str类型。指标的配置如 GLUE 指标的每个子集都有一个配置)
* module_type上文三种评价类型之一默认 metric可选 comparison 或 measurement
* cache_dir可选存储临时预测和引用的路径默认为 ~/.cache/huggingface/evaluate/)
```
import evaluate
# module_type 默认为 'metric'
accuracy = evaluate.load("accuracy")
# module_type 显式指定 'metric','comparison','measurement',防止重名。
word_length = evaluate.load("word_length", module_type="measurement")
```
### 列出
列出可用指标
list_evaluation_modules 列出官方(和社区)里有哪些指标,还能看到点赞信息,一共三个参数:
module_type要列出的评估模块类型None是全部可选metriccomparisonmeasurement。
include_community是否包含社区模块默认 True 。
with_details返回指标的完整详细Dict信息而不是str类型的指标名。默认 False。
```
print(evaluate.list_evaluation_modules(
module_type="measurement",
include_community=True,
with_details=True)
)
```
评估模块都有的属性
所有评估模块都附带一系列有用的属性,这些属性有助于使用存储在 evaluate.EvaluationModuleInfo 对象中的模块,属性如下:
description指标介绍
citationlatex参考文献
features输入格式和类型比如predictions、references等
inputs_description输入参数描述文档
homepage指标官网
license指标许可证
codebase_urls指标基于的代码地址
reference_urls指标的参考地址
### 计算指标
计算指标值(一次性计算/增量计算)
方式一:一次性计算
函数EvaluationModule.compute()传入list/array/tensor等类型的参数references和predictions。
```
>>> import evaluate
>>> metric_name = './evaluate/metrics/accuracy'
>>> accuracy = evaluate.load(metric_name)
>>> accuracy.compute(references=[0,1,0,1], predictions=[1,0,0,1])
{'accuracy': 0.5} # 输出结果
```
方式二:单增量的增量计算
函数: EvaluationModule.add()用于for循环一对一对地里添加ref和pred添加完退出循环之后统一计算指标。
```
>>> for ref, pred in zip([0,0,0,1], [0,0,0,1]):
... accuracy.add(references=ref, predictions=pred)
...
>>> accuracy.compute()
{'accuracy': 1.0} # 输出结果
```
方式三:多增量的增量计算
函数: EvaluationModule.add_batch()用于for循环多对多对地里添加ref和pred下面例子是一次添加3对添加完退出循环之后统一计算指标。
```
>>> for refs, preds in zip([[0,1],[0,1],[0,1]], [[1,0],[0,1],[0,1]]):
... accuracy.add_batch(references=refs, predictions=preds)
...
>>> accuracy.compute()
{'accuracy': 0.6666666666666666} # 输出结果
```
### 保存评价结果
函数evaluate.save(),参数为 path_or_file 用于存储文件的路径或文件。如果只提供文件夹,则结果文件将以 result-%Y%m%d-%H%M%S.json的格式保存可传 dict 类型的关键字参数 **result**params。
```
>>> result = accuracy.compute(references=[0,1,0,1], predictions=[1,0,0,1])
>>> hyperparams = {"model": "bert-base-uncased"}
>>> evaluate.save("./results/", experiment="run 42", **result, **hyperparams)
```
### 自动评估指标
自动评估
有点像 Trainer 的封装,可以直接把 evaluate.evaluator() 用做自动评估且能通过strategy参数的调整来计算置信区间和标准误差有助于评估值的稳定性
```
from transformers import pipeline
from datasets import load_dataset
from evaluate import evaluator
import evaluate
pipe = pipeline("text-classification", model="lvwerra/distilbert-imdb", device=0)
data = load_dataset("imdb", split="test").shuffle().select(range(1000))
metric = evaluate.load("accuracy")
results = eval.compute(model_or_pipeline=pipe, data=data, metric=metric,
label_mapping={"NEGATIVE": 0, "POSITIVE": 1},
strategy="bootstrap", n_resamples=200)
print(results)
>>> {'accuracy':
... {
... 'confidence_interval': (0.906, 0.9406749892841922),
... 'standard_error': 0.00865213251082787,
... 'score': 0.923
... }
... }
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

View File

@@ -0,0 +1,298 @@
## transofrmers最简单的说明
> 参考文档https://transformers.run/c2/2021-12-08-transformers-note-1/
> https://fancyerii.github.io/2021/05/11/huggingface-transformers-1/#%E7%AE%80%E4%BB%8B
> 官方文档https://huggingface.co/docs/transformers/v4.36.1/zh/index
### 是什么
目前各种Pretraining的Transformer模型层出不穷虽然这些模型都有开源代码但是它们的实现各不相同我们在对比不同模型时也会很麻烦。Huggingface Transformer能够帮我们跟踪流行的新模型并且提供统一的代码风格来使用BERT、XLNet和GPT等等各种不同的模型。
### 基本原则
huggingface的transfomers工具库只有configurationmodels和tokenizer三个主要类。所有的模型都可以通过统一的from_pretrained()函数来实现加载transformers会处理下载、缓存和其它所有加载模型相关的细节。而所有这些模型都统一在Hugging Face Models管理。基于上面的三个类提供更上层的pipeline和Trainer/TFTrainer从而用更少的代码实现模型的预测和微调。
因此它不是一个基础的神经网络库来一步一步构造Transformer而是把常见的Transformer模型封装成一个building block我们可以方便的在PyTorch或者TensorFlow里使用它。
## 2 快速开始
使用预训练模型最简单的方法就是使用pipeline函数它支持如下的任务
情感分析(Sentiment analysis):一段文本是正面还是负面的情感倾向
文本生成(Text generation):给定一段文本,让模型补充后面的内容
命名实体识别(Name entity recognition):识别文字中出现的人名地名的命名实体
问答(Question answering):给定一段文本以及针对它的一个问题,从文本中抽取答案
填词(Filling masked text)把一段文字的某些部分mask住然后让模型填空
摘要(Summarization):根据一段长文本中生成简短的摘要
翻译(Translation):把一种语言的文字翻译成另一种语言
特征提取(Feature extraction):把一段文字用一个向量来表示
### 情感分析
借助情感分析 pipeline我们只需要输入文本就可以得到其情感标签积极/消极)以及对应的概率:
```
from transformers import pipeline
classifier = pipeline("sentiment-analysis")
result = classifier("I've been waiting for a HuggingFace course my whole life.")
print(result)
results = classifier(
["I've been waiting for a HuggingFace course my whole life.", "I hate this so much!"]
)
print(results)
No model was supplied, defaulted to distilbert-base-uncased-finetuned-sst-2-english (https://huggingface.co/distilbert-base-uncased-finetuned-sst-2-english)
[{'label': 'POSITIVE', 'score': 0.9598048329353333}]
[{'label': 'POSITIVE', 'score': 0.9598048329353333}, {'label': 'NEGATIVE', 'score': 0.9994558691978455}]
```
pipeline 模型会自动完成以下三个步骤:
将文本预处理为模型可以理解的格式;
将预处理好的文本送入模型;
对模型的预测值进行后处理,输出人类可以理解的格式。
pipeline 会自动选择合适的预训练模型来完成任务。例如对于情感分析,默认就会选择微调好的英文情感模型 distilbert-base-uncased-finetuned-sst-2-english。
Transformers 库会在创建对象时下载并且缓存模型,只有在首次加载模型时才会下载,后续会直接调用缓存好的模型。
## 3 原理
实际上它的背后经过了三个步骤:
预处理 (preprocessing),将原始文本转换为模型可以接受的输入格式;
将处理好的输入送入模型;
对模型的输出进行后处理 (postprocessing),将其转换为人类方便阅读的格式。
![alt text](image/image.png)
### 使用分词器进行预处理
因为神经网络模型无法直接处理文本,因此首先需要通过预处理环节将文本转换为模型可以理解的数字。具体地,我们会使用每个模型对应的分词器 (tokenizer) 来进行:
将输入切分为词语、子词或者符号(例如标点符号),统称为 tokens
根据模型的词表将每个 token 映射到对应的 token 编号(就是一个数字);
根据模型的需要,添加一些额外的输入。
我们对输入文本的预处理需要与模型自身预训练时的操作完全一致,只有这样模型才可以正常地工作。注意,每个模型都有特定的预处理操作,如果对要使用的模型不熟悉,可以通过 Model Hub 查询。这里我们使用 AutoTokenizer 类和它的 from_pretrained() 函数,它可以自动根据模型 checkpoint 名称来获取对应的分词器。
情感分析 pipeline 的默认 checkpoint 是
distilbert-base-uncased-finetuned-sst-2-english下面我们手工下载并调用其分词器
```
from transformers import AutoTokenizer
checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
raw_inputs = [
"I've been waiting for a HuggingFace course my whole life.",
"I hate this so much!",
]
inputs = tokenizer(raw_inputs, padding=True, truncation=True, return_tensors="pt")
print(inputs)
```
```
{
'input_ids': tensor([
[ 101, 1045, 1005, 2310, 2042, 3403, 2005, 1037, 17662, 12172, 2607, 2026, 2878, 2166, 1012, 102],
[ 101, 1045, 5223, 2023, 2061, 2172, 999, 102, 0, 0,
0, 0, 0, 0, 0, 0]
]),
'attention_mask': tensor([
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]
])
}
```
可以看到,输出中包含两个键 input_ids 和 attention_mask其中 input_ids 对应分词之后的 tokens 映射到的数字编号列表,而 attention_mask 则是用来标记哪些 tokens 是被填充的这里“1”表示是原文“0”表示是填充字符
先不要关注 padding、truncation 这些参数,以及 attention_mask 项,后面我们会详细介绍:)。
### 将预处理好的输入送入模型
预训练模型的下载方式和分词器 (tokenizer) 类似Transformers 包提供了一个 AutoModel 类和对应的 from_pretrained() 函数。下面我们手工下载这个 distilbert-base 模型:
```
from transformers import AutoModel
checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
model = AutoModel.from_pretrained(checkpoint)
```
预训练模型的本体只包含基础的 Transformer 模块,对于给定的输入,它会输出一些神经元的值,称为 hidden states 或者特征 (features)。对于 NLP 模型来说,可以理解为是文本的高维语义表示。这些 hidden states 通常会被输入到其他的模型部分(称为 head以完成特定的任务例如送入到分类头中完成文本分类任务。
Transformer 模块的输出是一个维度为 (Batch size, Sequence length, Hidden size) 的三维张量,其中 Batch size 表示每次输入的样本(文本序列)数量,即每次输入多少个句子,上例中为 2Sequence length 表示文本序列的长度,即每个句子被分为多少个 token上例中为 16Hidden size 表示每一个 token 经过模型编码后的输出向量(语义表示)的维度。
预训练模型编码后的输出向量的维度通常都很大,例如 Bert 模型 base 版本的输出为 768 维,一些大模型的输出维度为 3072 甚至更高。
我们可以打印出这里使用的 distilbert-base 模型的输出维度:
from transformers import AutoTokenizer, AutoModel
checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = AutoModel.from_pretrained(checkpoint)
raw_inputs = [
"I've been waiting for a HuggingFace course my whole life.",
"I hate this so much!",
]
inputs = tokenizer(raw_inputs, padding=True, truncation=True, return_tensors="pt")
outputs = model(**inputs)
print(outputs.last_hidden_state.shape)
torch.Size([2, 16, 768])
Transformers 模型的输出格式类似 namedtuple 或字典可以像上面那样通过属性访问也可以通过键outputs["last_hidden_state"]甚至索引访问outputs[0])。
对于情感分析任务,很明显我们最后需要使用的是一个文本分类 head。因此实际上我们不会使用 AutoModel 类,而是使用 AutoModelForSequenceClassification
from transformers import AutoTokenizer
from transformers import AutoModelForSequenceClassification
checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = AutoModelForSequenceClassification.from_pretrained(checkpoint)
raw_inputs = [
"I've been waiting for a HuggingFace course my whole life.",
"I hate this so much!",
]
inputs = tokenizer(raw_inputs, padding=True, truncation=True, return_tensors="pt")
outputs = model(**inputs)
print(outputs.logits.shape)
torch.Size([2, 2])
可以看到,对于 batch 中的每一个样本模型都会输出一个两维的向量每一维对应一个标签positive 或 negative
### 对模型输出进行后处理
由于模型的输出只是一些数值,因此并不适合人类阅读。例如我们打印出上面例子的输出:
from transformers import AutoTokenizer
from transformers import AutoModelForSequenceClassification
checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = AutoModelForSequenceClassification.from_pretrained(checkpoint)
raw_inputs = [
"I've been waiting for a HuggingFace course my whole life.",
"I hate this so much!",
]
inputs = tokenizer(raw_inputs, padding=True, truncation=True, return_tensors="pt")
outputs = model(**inputs)
print(outputs.logits)
tensor([[-1.5607, 1.6123],
[ 4.1692, -3.3464]], grad_fn=<AddmmBackward0>)
模型对第一个句子输出
,对第二个句子输出
,它们并不是概率值,而是模型最后一层输出的 logits 值。要将他们转换为概率值,还需要让它们经过一个 SoftMax 层,例如:
import torch
predictions = torch.nn.functional.softmax(outputs.logits, dim=-1)
print(predictions)
tensor([[4.0195e-02, 9.5980e-01],
[9.9946e-01, 5.4418e-04]], grad_fn=<SoftmaxBackward0>)
所有 Transformers 模型都会输出 logits 值,因为训练时的损失函数通常会自动结合激活函数(例如 SoftMax与实际的损失函数例如交叉熵 cross entropy
这样模型的预测结果就是容易理解的概率值:第一个句子
,第二个句子
。最后,为了得到对应的标签,可以读取模型 config 中提供的 id2label 属性:
print(model.config.id2label)
{0: 'NEGATIVE', 1: 'POSITIVE'}
于是我们可以得到最终的预测结果:
第一个句子: NEGATIVE: 0.0402, POSITIVE: 0.9598
第二个句子: NEGATIVE: 0.9995, POSITIVE: 0.0005
## Model 与 Tokenizer
### 加载模型
除了像之前使用 AutoModel 根据 checkpoint 自动加载模型以外,我们也可以直接使用模型对应的 Model 类,例如 BERT 对应的就是 BertModel
```
from transformers import BertModel
model = BertModel.from_pretrained("bert-base-cased")
```
> 注意,在大部分情况下,我们都应该使用 AutoModel 来加载模型。这样如果我们想要使用另一个模型(比如把 BERT 换成 RoBERTa只需修改 checkpoint其他代码可以保持不变。
所有存储在 HuggingFace Model Hub 上的模型都可以通过 Model.from_pretrained() 来加载权重,参数可以像上面一样是 checkpoint 的名称,也可以是本地路径(预先下载的模型目录),例如:
```
from transformers import BertModel
model = BertModel.from_pretrained("./models/bert/")
```
Model.from_pretrained() 会自动缓存下载的模型权重,默认保存到 ~/.cache/huggingface/transformers我们也可以通过 HF_HOME 环境变量自定义缓存目录。
> 由于 checkpoint 名称加载方式需要连接网络,因此在大部分情况下我们都会采用本地路径的方式加载模型。
> 部分模型的 Hub 页面中会包含很多文件,我们通常只需要下载模型对应的 config.json 和 pytorch_model.bin以及分词器对应的 tokenizer.json、tokenizer_config.json 和 vocab.txt。
>
### 保存模型
保存模型通过调用 Model.save_pretrained() 函数实现,例如保存加载的 BERT 模型:
from transformers import AutoModel
model = AutoModel.from_pretrained("bert-base-cased")
model.save_pretrained("./models/bert-base-cased/")
这会在保存路径下创建两个文件:
config.json模型配置文件存储模型结构参数例如 Transformer 层数、特征空间维度等;
pytorch_model.bin又称为 state dictionary存储模型的权重。
简单来说,配置文件记录模型的结构,模型权重记录模型的参数,这两个文件缺一不可。我们自己保存的模型同样通过 Model.from_pretrained() 加载,只需要传递保存目录的路径。
### 加载与保存分词器
分词策略
根据切分粒度的不同,分词策略可以分为以下几种:
* 按词切分 (Word-based)
![alt text](image/image-1.png)
word_based_tokenization
例如直接利用 Python 的 split() 函数按空格进行分词:
tokenized_text = "Jim Henson was a puppeteer".split()
print(tokenized_text)
['Jim', 'Henson', 'was', 'a', 'puppeteer']
这种策略的问题是会将文本中所有出现过的独立片段都作为不同的 token从而产生巨大的词表。而实际上很多词是相关的例如 “dog” 和 “dogs”、“run” 和 “running”如果给它们赋予不同的编号就无法表示出这种关联性。
词表就是一个映射字典,负责将 token 映射到对应的 ID从 0 开始)。神经网络模型就是通过这些 token ID 来区分每一个 token。
当遇到不在词表中的词时,分词器会使用一个专门的
token 来表示它是 unknown 的。显然,如果分词结果中包含很多
就意味着丢失了很多文本信息,因此一个好的分词策略,应该尽可能不出现 unknown token。
* 按字符切分 (Character-based)
character_based_tokenization
这种策略把文本切分为字符而不是词语,这样就只会产生一个非常小的词表,并且很少会出现词表外的 tokens。
但是从直觉上来看,字符本身并没有太大的意义,因此将文本切分为字符之后就会变得不容易理解。这也与语言有关,例如中文字符会比拉丁字符包含更多的信息,相对影响较小。此外,这种方式切分出的 tokens 会很多,例如一个由 10 个字符组成的单词就会输出 10 个 tokens而实际上它们只是一个词。
因此现在广泛采用的是一种同时结合了按词切分和按字符切分的方式——按子词切分 (Subword tokenization)。
* **按子词切分 (Subword) **
高频词直接保留,低频词被切分为更有意义的子词。例如 “annoyingly” 是一个低频词,可以切分为 “annoying” 和 “ly”这两个子词不仅出现频率更高而且词义也得以保留。下图展示了对 “Lets do tokenization!“ 按子词切分的结果:
![alt text](image/image-2.png)
bpe_subword
可以看到“tokenization” 被切分为了 “token” 和 “ization”不仅保留了语义而且只用两个 token 就表示了一个长词。这种策略只用一个较小的词表就可以覆盖绝大部分文本,基本不会产生 unknown token。尤其对于土耳其语等黏着语几乎所有的复杂长词都可以通过串联多个子词构成。
加载与保存分词器
分词器的加载与保存与模型相似,使用 Tokenizer.from_pretrained() 和 Tokenizer.save_pretrained() 函数。例如加载并保存 BERT 模型的分词器:
from transformers import BertTokenizer
tokenizer = BertTokenizer.from_pretrained("bert-base-cased")
tokenizer.save_pretrained("./models/bert-base-cased/")
同样地,在大部分情况下我们都应该使用 AutoTokenizer 来加载分词器:
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")
tokenizer.save_pretrained("./models/bert-base-cased/")
调用 Tokenizer.save_pretrained() 函数会在保存路径下创建三个文件:
special_tokens_map.json映射文件里面包含 unknown token 等特殊字符的映射关系;
tokenizer_config.json分词器配置文件存储构建分词器需要的参数
vocab.txt词表一行一个 token行号就是对应的 token ID从 0 开始)。

View File

Before

Width:  |  Height:  |  Size: 214 KiB

After

Width:  |  Height:  |  Size: 214 KiB

View File

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 106 KiB

View File

Before

Width:  |  Height:  |  Size: 190 KiB

After

Width:  |  Height:  |  Size: 190 KiB

View File

Before

Width:  |  Height:  |  Size: 182 KiB

After

Width:  |  Height:  |  Size: 182 KiB

View File

Before

Width:  |  Height:  |  Size: 379 KiB

After

Width:  |  Height:  |  Size: 379 KiB

View File

Before

Width:  |  Height:  |  Size: 180 KiB

After

Width:  |  Height:  |  Size: 180 KiB

View File

Before

Width:  |  Height:  |  Size: 202 KiB

After

Width:  |  Height:  |  Size: 202 KiB

View File

Before

Width:  |  Height:  |  Size: 174 KiB

After

Width:  |  Height:  |  Size: 174 KiB

View File

Before

Width:  |  Height:  |  Size: 255 KiB

After

Width:  |  Height:  |  Size: 255 KiB

View File

Before

Width:  |  Height:  |  Size: 256 KiB

After

Width:  |  Height:  |  Size: 256 KiB

View File

Before

Width:  |  Height:  |  Size: 170 KiB

After

Width:  |  Height:  |  Size: 170 KiB

View File

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 102 KiB

View File

Before

Width:  |  Height:  |  Size: 251 KiB

After

Width:  |  Height:  |  Size: 251 KiB

View File

Before

Width:  |  Height:  |  Size: 184 KiB

After

Width:  |  Height:  |  Size: 184 KiB

View File

Before

Width:  |  Height:  |  Size: 202 KiB

After

Width:  |  Height:  |  Size: 202 KiB

View File

Before

Width:  |  Height:  |  Size: 181 KiB

After

Width:  |  Height:  |  Size: 181 KiB

View File

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 120 KiB

View File

Before

Width:  |  Height:  |  Size: 144 KiB

After

Width:  |  Height:  |  Size: 144 KiB

View File

Before

Width:  |  Height:  |  Size: 151 KiB

After

Width:  |  Height:  |  Size: 151 KiB

View File

Before

Width:  |  Height:  |  Size: 267 KiB

After

Width:  |  Height:  |  Size: 267 KiB

View File

Before

Width:  |  Height:  |  Size: 170 KiB

After

Width:  |  Height:  |  Size: 170 KiB

View File

Before

Width:  |  Height:  |  Size: 188 KiB

After

Width:  |  Height:  |  Size: 188 KiB

View File

Before

Width:  |  Height:  |  Size: 199 KiB

After

Width:  |  Height:  |  Size: 199 KiB

View File

Before

Width:  |  Height:  |  Size: 208 KiB

After

Width:  |  Height:  |  Size: 208 KiB

View File

Before

Width:  |  Height:  |  Size: 315 KiB

After

Width:  |  Height:  |  Size: 315 KiB

View File

Before

Width:  |  Height:  |  Size: 233 KiB

After

Width:  |  Height:  |  Size: 233 KiB

View File

Before

Width:  |  Height:  |  Size: 290 KiB

After

Width:  |  Height:  |  Size: 290 KiB

View File

Before

Width:  |  Height:  |  Size: 220 KiB

After

Width:  |  Height:  |  Size: 220 KiB

View File

Before

Width:  |  Height:  |  Size: 100 KiB

After

Width:  |  Height:  |  Size: 100 KiB

View File

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 106 KiB

View File

Before

Width:  |  Height:  |  Size: 254 KiB

After

Width:  |  Height:  |  Size: 254 KiB

View File

Before

Width:  |  Height:  |  Size: 157 KiB

After

Width:  |  Height:  |  Size: 157 KiB

View File

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 104 KiB

View File

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

Before

Width:  |  Height:  |  Size: 150 KiB

After

Width:  |  Height:  |  Size: 150 KiB

View File

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 80 KiB

Some files were not shown because too many files have changed in this diff Show More