Hugging Face 入门:模型、Tokenizer 与数据集的使用

Hugging Face 介绍

Hugging Face 是一家专注于人工智能和自然语言处理(NLP)的公司,成立于 2016 年。它提供了一个广受欢迎的开源平台,允许开发者和研究人员访问和使用先进的机器学习模型。

  • Transformers 库:Hugging Face 核心库,包含了大量预训练模型(BERT、GPT、T5 等)。
  • Datasets 库:提供了一个数据集库,方便用户查找、加载和使用各种常见的机器学习数据集。
  • Model Hub:一个在线平台,用户可以分享和下载模型,提供了多种预训练模型.
  • Hugging Face Hub:Hugging Face 云平台,允许协作和托管模型,可在云端进行训练和推理。

Hugging Face 相关库的安装

  • 安装前需要准备基础环境:Anaconda,CUDA,pytorch
  • Hugging Face 提供了 transformers 库,用于加载和使用模型。
  • pip install transformers datasets tokenizers

Hugging Face 模型访问

Hugging Face 提供了一个庞大的模型库;Models - Hugging Face 在模型页中使用左侧的过滤器按任务、框架、语言等条件筛选你需要的模型。

py 复制代码
import requests
from transformers import pipeline
from dotenv import load_dotenv
import os

load_dotenv()
API_URL = f"{os.getenv('HF_BASE_URL')}/models/uer/gpt2-chinese-cluecorpussmall"
API_KEY = f"{os.getenv('HF_KEY')}"


# 在线访问模型
headers = {"Authorization": f"Bearer {API_KEY}"}
response = requests.post(API_URL, headers=headers, json={
                         "inputs": "你好,Hugging face"})
print(response.json())


# 离线访问模型,第一次需要下载模型
generator = pipeline("text-generation", model="gpt2")
# truncation:输入文本超过 模型限制的最大输入 时会被截断
# num_return_sequences:希望从模型中获得多少个独立生成的文本序列
output = generator("I am a text generation model.", max_length=50, truncation=True, num_return_sequences=2)
print(output)

GPT 和 BERT

BERT 和 GPT 是基于 Transformer 结构的两个不同方向的模型 ,而 Transformer 由编码器解码器两个部分构成;

  • BERT 是一个 双向编码器 ,主要用于 理解任务,例如文本分类、命名实体识别、问答等。BERT 的目标是捕捉上下文信息,理解句子的含义。
  • GPT 是一个 自回归解码器 ,主要用于 生成任务,例如文本生成、对话生成、创作等。GPT 的目标是根据给定的上下文生成流畅的文本

Transformer 模型

输入处理:词向量 与 位置向量

  1. embeddings:每个词 通过 embedding 转为词向量
  2. positional embedding:每个输入的词向量都加上了一个位置向量(确定每个单词的位置、句子中不同单词之间的距离)
  3. embedding with time signal:将这些表示位置的向量添加到词向量中,得到的新向量,可以为模型提供更多有意义的信息,比如词的位置,词之间的距离等。

Encoder 、Decoder

  • encoders:编码部分由多层编码器(Encoder)组成
  • decoders:解码部分由多层的解码器(Decoder)组成

每层编码器网络结构是一样的,每层解码器网络结构也是一样的。不同层编码器和解码器网络结构不共享参数。

单层的编码器和解码器 注意组成

  • Self-Attention Layer:处理一个词时,关注输入序列中其他位置的词。
  • Feed Forward Neural Network(前馈神经网络,缩写为 FFNN):全连接层,每个自注意力模块后都跟随一个全连接层,通常包括两个线性变换和一个激活函数 (例如 ReLU)激活函数直接会影响模型的输出。
  • Encoder-Decoder Attention:也称 Cross-Attention 允许解码器在生成输出时,能够动态地关注编码器生成的隐藏状态。

GPT 生成模型

  • tokenizer 配置介绍
json 复制代码
{  
    "do_lower_case": false,  # 是否将输入转为小写
    "unk_token": "[UNK]",  # 未知标记:模型未能识别字符
    "sep_token": "[SEP]",  # 分割标记:分割两个句子或者文本片段
    "pad_token": "[PAD]",  # 填充标记:填充输入序列,使得所有序列的长度一致
    "cls_token": "[CLS]",  # 分类标记:输入序列的起始标记
    "mask_token": "[MASK]",  # 遮蔽标记:在训练时,部分单词会被替换为[MASK],模型需预测被掩蔽的词汇
    "tokenize_chinese_chars": true, # 中文文本是否需要分割,为 true 表示会将中文字符单独作为一个 Token 来处理
    "strip_accents": null,  # 是否移除文本中的重音符号(例如,é 变为 e)
    "model_max_length": 1024  # 限制模型输入的最大长度
}
  • 示例介绍
python 复制代码
from transformers import BertTokenizer, BertForSequenceClassification, pipeline
from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
from huggingface_hub.constants import HF_HUB_CACHE


# 下载模型和分词器下载到本地
model_name = "uer/gpt2-chinese-cluecorpussmall"
# 模型缓存地址,如果不指定,默认为  ~/.cache/huggingface/hub 目录下
cache_dir = HF_HUB_CACHE

# 下载并加载模型和分词器(一般下载模型的时候连同分词器也会一并下载) 模型与分词器一一对应
model = AutoModelForCausalLM.from_pretrained(model_name, cache_dir=cache_dir)
tokenizer = AutoTokenizer.from_pretrained(model_name, cache_dir=cache_dir)

# "text-generation" 文本生成 pipeline
generator = pipeline("text-generation", model=model,tokenizer=tokenizer, device="cuda")
output = generator(
    # 输入种子文本(prompt)模型根据这个初始文本,生成后续的文本
    "这是很久之前的事情了,",
    # 生成文本的最大长度(最多包含 50 个 tokens)
    max_length=50,
    # 从模型中获得多少个独立生成的文本序列
    num_return_sequences=1,
    # 输入文本超过模型所能支持的最大输入长度(tokenizer_config中定义的model_max_length)时会被截断
    truncation=True,
    temperature=0.7,top_k=50,top_p=0.9,
    # 生成的文本中是否清理分词时引入的空格。值为 True,生成的文本会清除多余的空格;
    clean_up_tokenization_spaces=True
)

为何模型和分词工具是一一对应的?

  • 分词工具依赖词典或者规则把文本切分成词语或小单元(比如字或子词),然后转成数字。每个模型训练时,都是用特定的分词工具和方式来学习的。
  • 模型会根据它训练时使用的分词方式来理解文本。如果你换了分词工具,文本的切分和数字表示就会变,模型可能就无法正确理解这些新的数据
python 复制代码
model = AutoModelForCausalLM.from_pretrained(model_name, cache_dir=cache_dir)
tokenizer = AutoTokenizer.from_pretrained(model_name, cache_dir=cache_dir)

top_k、temperature、top_p 理解

  • 假设模型所能识别的字符大小为 21128,对于文本生成模型来说,取到每个字符的概率为 1/21128;
    • top_k=50:表示模型生成每个词只考虑概率最高的 50 个候选词;如果希望每次生成的结果都一样,可以将top_k 设置为 1
    • temperature=0.7:表示从 top_k 指定的候选词中选择候选词;越小->越保守(选择概率较高的词汇);越大->越多样(选择越多样的词汇)。
    • top_p=0.9:核采样,通过控制概率的累积和来筛选词汇
      • 候选词 A:0.5 B:0.4 C:0.2 D:0.1 而 A 与 B 的累积概率已经到达0.9(0.5+0.4)所以,候选词只能在A与B之前选。

Bert 模型

py 复制代码
from transformers import BertTokenizer, BertForSequenceClassification, pipeline
from transformers import AutoModel, AutoTokenizer, pipeline
from huggingface_hub.constants import HF_HUB_CACHE

# 模型缓存地址,如果不指定,默认为  ~/.cache/huggingface/hub 目录下
cache_dir = HF_HUB_CACHE

# 加载模型和分词器
model = BertForSequenceClassification.from_pretrained(
    "bert-base-chinese", cache_dir=cache_dir)
tokenizer = BertTokenizer.from_pretrained(
    "bert-base-chinese", cache_dir=cache_dir)

# 创建分类pipleine
classifier = pipeline("text-classification", model=model,
                      tokenizer=tokenizer, device="cuda")

# 进行文本分类
result = classifier("你好,我是一款语言模型")
print(result)
print(model)

打印结果如下,可以看到,并没有给出我们想要的结果,原因就是因为 我们并没有实现它的分类层

py 复制代码
[{'label': 'LABEL_0', 'score': 0.5539349317550659}]
BertForSequenceClassification(
  (bert): BertModel(
    # embeddings:向量化,将文本 转为 模型可输入的向量
    (embeddings): BertEmbeddings(
    )
    # encoder:特征提取,根据 词向量 提取、理解 特征
    (encoder): BertEncoder(
    )
    (pooler): BertPooler(
    )
  )
  (dropout): Dropout 
  # classifier:模型的分类层,out_features=2 表示一个2分类模型
  (classifier): Linear(in_features=768, out_features=2, bias=True)
)

Tokenizer 模型是如何处理字符数据?

  1. 分词器 根据预定的词表 vocabulary 将文本转化为 tokens ,并通常将其转化为 数字 ID 。 例如:"你好,世界!"=>["你好", ",", "世界", "!"]

  2. Tokenizer 会将每个 token 映射到一个 数字 ID(每个 token 在词表中的索引行)。

  3. 向量化 (将 tokens 转化为向量)是由模型的 嵌入层(Embedding layer) 来完成的,它根据 tokens 的 ID 获取其对应的向量表示。这些向量再传递给模型的其他层进行进一步处理。

AI模型的本质是基于矩阵运算,输入的数据通常是高维矩阵(张量),本质上也都是数字。

AI 模型处理的核心任务可分为图像视觉、音频处理和自然语言处理(NLP)。

  • 图像和音频较为简单,因为它们本身就是数字(如图像像素值和音频采样值),可以直接输入模型。
  • NLP 最难的地方就是如何将一句话变成一串数字?

加载字典和分词器

ini 复制代码
模型所能识别的字符都是有限的
vocab_size=21128
    vocab.txt(字典)中字符的数量;
    模型不能识别的字符就用 special_tokens 中的 unk_token 指定的特殊标记来表示

vocab.txt 
    以 ## 开头的字符:表示带有上下文编码的字符;
    单个字符:是大多数的预训练模型采用中文分词,优点:扩展性强;中文中有很多 多音字

因此 严格的来讲,大多数预训练模型所能识别的字符为 vocab_size/2

token 字符编码的逻辑就是将输入的文本 转为 vocab.txt 中每个字符所对应的索引下标

py 复制代码
from transformers import BertTokenizer
from huggingface_hub.constants import HF_HUB_CACHE

cache_dir = HF_HUB_CACHE

# 加载字典和分词器
token = BertTokenizer.from_pretrained("bert-base-chinese", cache_dir=cache_dir)

#准备要编码的文本数据
sents = ["吃饭、睡觉、打豆豆,","打卡、发呆、摸虾鱼。"]

#批量编码句子
out = token.batch_encode_plus(
    batch_text_or_text_pairs=[sents[0],sents[1]],
    # 编码时添加 special_tokens 为了给模型看
    add_special_tokens=True,
    # 当句子长度大于max_length(上限是model_max_length)时,截断
    truncation=True,
    # 编码之后的长度
    max_length=6,
    # 补0 对齐文本 到 max_length;不够6就用0补齐,超出6就截断
    padding="max_length",
    # 编码后返回的数值类型 可取值为tf,pt,np,默认为list
    return_tensors=None,
    # 编码之后需要给到 transformer 模型的输入
    return_attention_mask=True,
    return_token_type_ids=True,
    return_special_tokens_mask=True,
    # 返回序列长度
    return_length=True
)
#解码文本数据
print(token.decode(out["input_ids"][0]),token.decode(out["input_ids"][1]))

dataset 数据集

py 复制代码
from datasets import load_dataset,load_from_disk

# 加载数据集,未指定cache_dir 默认缓存到 ~/.cache/huggingface/datasets
dataset = load_dataset(path="lansinuote/ChnSentiCorp")
print(dataset)

# 将数据保存到指定的磁盘中  注意:这里使用的都是相对路径
dataset.save_to_disk(".cache/data/lansinuote/ChnSentiCorp")

# 加载保存后的数据集
dataset = load_from_disk(".cache/data/lansinuote/ChnSentiCorp")
print(dataset)

# 打印数据集
train_data = dataset["test"]
for data in train_data:
    print(data)


# 转为csv格式(实际项目大多使用的csv数据集)
dataset['train'].to_csv(".cache/data/lansinuote/ChnSentiCorp/csv/train.csv")


# 直接从CSV文件加载数据集
dataset = load_dataset('csv', data_files='.cache/data/lansinuote/ChnSentiCorp/csv/train.csv')
print(dataset)
相关推荐
月下西楼17 小时前
发现了个好东西:Dify,快速搭应用的小帮手
ai 编程
谦哥17 小时前
从开发新手角度对比 dify 和 n8n:哪个更适合你?
前端·javascript·ai 编程
酱酱们的每日掘金18 小时前
AI 编程避坑全攻略、Cursor + MCP 要冲击的不仅是前端丨AI Coding 周刊第 1 期
cursor·mcp·ai 编程
芦半山19 小时前
闲谈丨一名AI体验者的自述
android·ai 编程
Captaincc1 天前
👨‍💻 cursor user rules 实践
ai 编程
掘金酱1 天前
[周二直播] 用 Trae 和 Flutter 开发你的第一款全平台"答案之书" APP|AI For Code工作坊 Vol.8
flutter·trae·ai 编程
Captaincc2 天前
Cursor (AI IDE) 工作原理
cursor·ai 编程
代码小学僧2 天前
新版本 Cursor rules .mdc格式文件使用经验分享
前端·cursor·ai 编程
洪喵喵2 天前
效率狂飙:用十分钟时间,解锁 MCP+Cursor 开发姿势
前端·cursor·ai 编程
前端双越老师2 天前
AI 时代如何准备前端面试
人工智能·面试·ai 编程