HuggingFace学习笔记

Transformers

pipeline()

做了三件事:preprocessing(Tokenizer分词并转成ID), pass to the model(将词向量处理成输出向量), postprocessing(将输出向量转化成最终结果)

AutoTokenizer class

可以根据checkpoint选择tokenizer的模型

一般tokenizer都是fast模式,得到的对象类型为BatchEncoding,具有回溯的功能(offset mapping)

  • tokenizer.token() 回溯pre-processing后的分词
  • tokenizer.word_ids() 回溯每个token对应的原word在text中的index
  • tokenizer(text, return_offsets_mapping = True)可以得到每个token在原text中的起始index(左开右闭)

AutoModel class

可以根据checkpoint选择model的模型

Tokenizer

训练新的tokenizer需要数据集,在对数据集进行处理时,要将数据集处理成一个iterator,这样方便tokenizer通过batches并行处理运行更快,但缺点是iterator只能用一次。创建iterator的方法是在创建列表时将[ ]替换为( ),或在函数中运用yield语句

Byte-Pair Encoding

代表模型:GPT

特点:不忽略空格以及双空格,分隔空格和标点

WordPiece

代表模型:Bert

特点:忽略空格,分隔标点

Unigram

代表模型:T5

特点:不忽略空格但忽略双空格,分割空格但不分隔标点

Fine-tune

获取数据集:

1
2
3
from datasets import load_dataset

raw_datasets = load_dataset("*", "*")

处理数据集:

1
2
3
4
5
6
7
8
9
10
from transformers import AutoTokenizer, DataCollatorWithPadding

checkpoint = "***"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)

def tokenize_fuction(example): # for Dataset.map() batch processing
return tokenizer(sentence, ***, truncation = True)

tokenized_datasets = raw_datasets.map(tokenize_function)
data_collator = DataCollatorWithPadding(tokenizer = tokenizer) # for padding

定义评估函数:

1
2
3
4
5
6
7
8
9
10
11
12
from transformers import TrainingArguments, AutoModelFor*
import numpy as np

training_args = TrainingArguments("test-trainer", evaluation_strategy = "epoch")
model = AuotoModelFor*(checkpoint, num_labels = 2)

def compute_metrics(eval_preds):
metric = evaluate.load("*", "*")
logits, labels = eval_preds
predictions = np.argmax(logits, axis = -1)
return metric.compute(predictions = predictions, references = labels)

开始训练:

1
2
3
4
5
6
7
8
9
10
11
12
13
from transformers import Trainer

trainer = Trainer(
model,
training_args,
train_dataset = tokenized_datasets["train"],
eval_dataset = tokenized_datasets["validation"],
data_collator = data_collator, # in fact, it's by default
tokenizer = tokenizer,
compute_metrics = compute_metrics
)

trainer.train()

Checkpoint

sentiment-analysis 文本情感分类

code_search_net 一个python的语料库

question-answering 顾名思义

bert-base-uncased 该模型不区分大小写

bert-base-cased 该模型区分大小写

问题集

  1. 不同数据格式的转换

    csv txt jsonl parquet
    CSV,全称为Comma-Separated Values(逗号分隔值),是一种简单的文件格式,被广泛用于存储表格数据,包括电子表格和数据库。
    在CSV文件中,每一行代表一个新的数据记录,每个记录包含一个或多个字段,这些字段由逗号分隔。尽管文件的名称指的是逗号分隔,但其他的分隔符,如制表符或空格,也被广泛使用。
    CSV文件的优点是简单且人类可读,可以被大多数的电子表格程序(如Microsoft Excel或Google Sheets)和许多编程语言处理。然而,CSV没有提供数据类型的信息,例如数值、字符串、日期等,这些都需要在解析文件时确定。
    TXT文件是一个纯文本文件格式,它只包含未格式化的文本内容,不包含任何特殊的文本格式化信息(如粗体、斜体、下划线、颜色等)或者图片、音频、视频等多媒体内容。
    TXT文件是最简单的文件格式之一,可以通过任何文本编辑器(例如记事本、Notepad++、Sublime Text等)打开和编辑。
    JSONL,或称为JSON Lines,是一种用于存储结构化数据的格式,尤其适合用来处理大量的数据对象或记录。
    在JSONL文件中,每一行包含一个独立的JSON对象,每个对象都是完整有效的JSON。
    Parquet是一种列式存储格式,被大量应用于Hadoop生态系统中。它设计用来对数据压缩、编码和处理进行优化,能够同时提供高效的数据压缩和编码方案。Parquet允许创建复杂的嵌套数据结构,并将类似的数据列存储在一起,使得在进行数据分析时读取效率更高。列式存储与传统的行式存储相比,有以下优点:
    1. 数据压缩:由于一列中的数据类型相同,可以更有效地进行数据压缩。
    2. 查询效率:列式存储可以在只读取需要的列的情况下完成查询,对于大数据分析任务特别有效。
    3. 存储效率:相比于行式存储,列式存储可以更有效地减少数据冗余。

    Parquet广泛用于大数据处理的场景,例如Apache Spark和Apache Arrow等工具均支持使用Parquet格式。

    以下是使用Python来实现这些文件格式之间转换的一些基本方法。注意,这些转换方法可能需要特定的Python库,例如pandas,json等。

    1. CSV转Parquet:

      1
      2
      3
      4
      import pandas as pd

      df = pd.read_csv('data.csv')
      df.to_parquet('data.parquet')
    2. Parquet转CSV:

      1
      2
      3
      4
      import pandas as pd

      df = pd.read_parquet('data.parquet')
      df.to_csv('data.csv', index=False)
    3. CSV转TXT:

      实际上,CSV本身就是一种TXT文件。只要确保数据以逗号(或者其他的分隔符)分隔,你就可以直接将文件的扩展名从.csv改为.txt。

    4. TXT转CSV:

      与CSV转TXT类似,你可以直接将文件的扩展名从.txt改为.csv。但是,你需要确保文件的内容符合CSV文件的格式要求。

    5. CSV转JSONL:

      1
      2
      3
      4
      import pandas as pd

      df = pd.read_csv('data.csv')
      df.to_json('data.jsonl', orient='records', lines=True)
    6. JSONL转CSV:

      1
      2
      3
      4
      import pandas as pd

      df = pd.read_json('data.jsonl', lines=True)
      df.to_csv('data.csv', index=False)
  2. 中文用哪种tokenizer?数学用哪种?

    • 在处理中文语料库时,由于中文是一种字母语言,词与词之间没有空格分隔,因此使用基于统计的分词方法(如BPE或WordPiece)可能不如使用基于语言模型的分词方法(如Unigram)效果好。

    • 处理数学公式的分词需要考虑的问题与处理自然语言文本有很大的不同。数学公式中的符号(如 “+”, “-”, “*”, “/” 等)以及变量和函数(如 “x”, “y”, “f()”, “g()” 等)都有特定的含义,并且他们的组合方式遵循特定的数学规则。因此,处理数学公式的分词算法需要能够理解这些规则,而这是BPE、WordPiece或Unigram等自然语言处理的分词算法通常无法做到的。

      对于数学公式,一个常见的做法是将每个符号、变量或函数都当作一个单独的“词”。例如,数学公式 “2x + y = 10" 可以被切分为 “2”, "”, “x”, “+”, “y”, “=”, “10”。这样可以确保分词后的公式保持原有的语义,并且可以被进一步处理,例如用于公式搜索、公式相似性计算等。

      然而,这种方法可能不适用于所有的情况。例如,如果你正在处理包含复杂函数或者高级数学符号的公式,可能需要使用更复杂的分词方法。对于这种情况,你可能需要考虑开发自定义的分词算法,或者使用专门用于处理数学公式的工具。

      总的来说,处理数学公式的分词是一个复杂的问题,需要根据你的具体需求和公式的复杂性来选择合适的方法。

  3. 新的tokenizer,模型参数还可不可以用?

    在大部分情况下,如果你对原始预训练模型对应的分词器(tokenizer)进行了fine-tune(调整),那么你可能需要同时也对模型进行fine-tune,以便让模型学习到新的词汇分布和语义表示。原因在于分词器和模型是配套的,二者共享同一词汇表。模型学习的词嵌入或者特征表示是基于特定的分词方式的,如果分词方式改变(比如添加了新的token,或者调整了分词策略),那么原始的模型可能就不能正确地解析和处理新的分词结果。

    例如,让我们假设你有一个BERT模型和相应的tokenizer。这个tokenizer有一个包含30,000个token的词汇表,模型也有30,000个对应的词嵌入。现在,你对tokenizer进行了fine-tune,添加了一些新的token,使得词汇表扩展到了31,000个token。然而,原始的BERT模型仍然只有30,000个词嵌入,对于新增的1,000个token,它没有相应的词嵌入,因此无法正确处理包含这些新token的文本。

    然而,也存在一些特殊情况。如果你的fine-tune操作只涉及到分词策略的微调,例如修改一些正则表达式或者调整一些阈值,但并没有改变词汇表,那么你可能可以继续使用原始的模型。但这还是取决于你的具体操作和应用场景。

    总的来说,当你对tokenizer进行fine-tune时,你应该同时考虑对模型进行相应的fine-tune,以确保模型和tokenizer的一致性。


HuggingFace学习笔记
https://markouv.github.io/2023/07/13/NLP/HuggingFace /
作者
Kov
发布于
2023年7月13日
许可协议