Hugging Face* *transformers**

Admin
发布于 2026-05-29 / 0 阅读
0
0

pip install transformers

* *transformers**:是由 Hugging Face 公司开发并开源的一个核心库,专门用于自然语言处理(NLP)、计算机视觉(CV)和音频任务。

* *transformers 库的用途**:它是目前深度学习领域最重要、最流行的库之一。它提供了大量最先进的预训练模型(如 GPT 系列、BERT、LLaMA、GLM 等),以及用于文本分类、信息抽取、问答、摘要、翻译、图像分类等任务的 API。开发者可以使用它极其方便地下载、加载和微调这些大模型,而无需从零开始编写复杂的神经网络代码。

深度学习框架依赖transformers 库本身不包含底层的深度学习计算引擎,它需要依赖 PyTorch 或 TensorFlow。通常你需要先安装好 PyTorch 或 TensorFlow,然后再安装 transformers。如果未安装底层框架transformers 可能会安装一个极简版,但在加载模型时会报错。

import torch

sentences = [
    'Today is a sunny day',
    'Today is a rainy day'
]

# Tokenization function
def tokenize(text):
    return text.lower().split()

# Build the vocabulary
def build_vocab(sentences):
    vocab = {}
    for sentence in sentences:
        tokens = tokenize(sentence)
        for token in tokens:
            if token not in vocab:
                vocab[token] = len(vocab) + 1  # starting index from 1, 0 can be used for padding
    return vocab

# Create the vocabulary index
vocab = build_vocab(sentences)

print("Vocabulary Index:", vocab)

下面我将为你详细解释这段Python代码的含义、实现原理、用途以及相关的注意事项。

### 1. 代码含义与实现原理

这段代码实现了一个自然语言处理(NLP)中最基础的任务:**构建文本词汇表并为其分配索引**。

代码的执行流程如下:

1. 定义语料库:给定了两个简单的英文句子。

2. 分词tokenize 函数将输入的连续文本字符串转换为离散的标记列表。它首先将所有字母转为小写,然后按空格切分。

3. 构建词汇表build_vocab 函数遍历所有句子,对每个句子进行分词。如果当前词语不在词汇表字典中,就将其加入字典,并赋予一个从1开始递增的整数索引len(vocab) + 1)。

4. 输出结果:打印出构建好的词汇表字典,键为单词,值为对应的索引。

最终输出结果

```text

Vocabulary Index: {'today': 1, 'is': 2, 'a': 3, 'sunny': 4, 'day': 5, 'rainy': 6}

```

---

### 2. 代码用途

在深度学习和NLP领域,计算机无法直接处理文本字符串,必须将文本转换为数值张量。这段代码的用途正是**文本数据预处理**:

* 特征编码:将离散的文本类别数据映射为连续的整数索引,这是后续进行词嵌入(Word Embedding,如Word2Vec、GloVe)或直接作为模型输入的先决条件。

* 与PyTorch配合:虽然代码中导入torch但未直接使用,但构建出的词汇字典通常会和 torch.nn.Embedding 层配合使用Embedding 层需要知道词汇表的大小,并通过这些整数索引来查找对应的词向量。

---

### 3. 注意事项与改进建议

虽然这段代码逻辑清晰且能正常运行,但在实际工程应用中,有以下几个需要注意和改进的地方:

#### (1) 分词方式的局限性

* 当前问题text.lower().split() 只能按空格切分,无法处理标点符号(如 "day." 会被切分为 "day." 而不是 "day"),也无法处理缩写(如 "don't")或非英文语言(如中文没有空格)。

* 改进建议:在实际项目中,建议使用成熟的分词工具,如 NLTK、spaCy,或者基于子词的分词器如 HuggingFace 的 transformers 库中的 BertTokenizer 等。

#### (2) 索引从1开始的合理性

* 当前设计:代码中 len(vocab) + 1 使得索引从 1 开始,这是**非常合理且常见**的做法。

* 原因:在深度学习模型中(尤其是使用PyTorch的 Embedding 或 RNNs 时),通常将索引 0 保留给 Padding(填充) 符号。因为不同长度的句子需要拼成Batch输入模型,短句子需要用0填充对齐,后续计算时可以通过 mask 忽略索引为0的词。

#### (3) 缺少未知词和填充词的特殊处理

* 当前问题:如果在模型预测时遇到了训练集(词汇表)中没有的新词,代码会报错或无法处理。

* 改进建议:应该在词汇表中显式地加入 <PAD>(填充符,索引0)和 <UNK>(未知词符,通常索引1),并将其他词的索引顺延。当遇到词汇表外的词时,统一映射为 <UNK>

#### (4) 导入了未使用的库

* 当前问题:代码第一行 import torch 并未在后续代码中使用,属于冗余代码,应予以删除,或者在后续代码中真正使用 torch 来将索引转换为张量。

---

### 4. 改进后的代码示例

结合上述注意事项,这里提供一个更健壮、更符合工业界标准的代码版本:

import torch

sentences = [
    'Today is a sunny day.',
    'Today is a rainy day!'
]

# 改进的分词函数:简单去除标点并按空格切分(实际工程建议用正则或分词库)
def tokenize(text):
    # 简单的标点处理
    punctuation = ".,!?;:"
    for p in punctuation:
        text = text.replace(p, "")
    return text.lower().split()

# 改进的词汇表构建函数:预留 PAD 和 UNK
def build_vocab(sentences):
    vocab = {'<PAD>': 0, '<UNK>': 1}  # 预留特殊标记
    for sentence in sentences:
        tokens = tokenize(sentence)
        for token in tokens:
            if token not in vocab:
                vocab[token] = len(vocab)  # 索引将从2开始自动递增
    return vocab

vocab = build_vocab(sentences)
print("Vocabulary Index:", vocab)

# 演示如何将文本转换为 PyTorch 张量
def text_to_tensor(text, vocab):
    tokens = tokenize(text)
    # 未知词映射为 <UNK> 的索引 1
    indices = [vocab.get(token, vocab['<UNK>']) for token in tokens]
    return torch.tensor(indices, dtype=torch.long)

# 测试
test_sentence = "Today is a snowy day"
tensor_output = text_to_tensor(test_sentence, vocab)

print(f"Test Sentence: '{test_sentence}'")
print(f"Tensor Output: {tensor_output}")
# 输出: tensor([2, 3, 4, 1, 6]) 
# 其中 snowy 不在词汇表中,被转换为了 1 (<UNK>)

```

希望这个详细的解释和改进示例对你有所帮助!如果你还有其他关于代码或深度学习预处理的问题,欢迎随时提问。

访问国内镜像:https://hf-mirror.com/google-bert/bert-base-uncased/tree/main

下载以下 3个核心文件(点击文件右侧的下载图标):

vocab.txt (词表文件,必须)

config.json (配置文件,必须)

tokenizer.json (快速分词器配置,必须)

from transformers import BertTokenizerFast

sentences = [
    'Today is a sunny day',
    'Today is a rainy day'
]

# 🔥 核心修改:将 'bert-base-uncased' 改为本地文件夹路径 './bert-base-uncased-local'
# 这样代码就不会去外网下载,而是直接读取你本地文件夹中的 vocab.txt 等文件

local_model_path = './bert-base-uncased-local'
tokenizer = BertTokenizerFast.from_pretrained(local_model_path)

# Tokenize the sentences and encode them
encoded_inputs = tokenizer(sentences, padding=True, truncation=True, return_tensors='pt')

# To see the tokens for each input (helpful for understanding the output)
tokens = [tokenizer.convert_ids_to_tokens(ids) for ids in encoded_inputs["input_ids"]]

# To get the word index similar to Keras' tokenizer
word_index = tokenizer.get_vocab()

print("Tokens:", tokens)
print("Token IDs:", encoded_inputs['input_ids'])
print("Word Index:", dict(list(word_index.items())[:10]))  # show only the first 10 for brevity

这段代码使用的是Hugging Facetransformers库,主要功能是**加载本地的BERT分词器,对输入文本进行分词和编码,并展示分词结果、对应的数字ID以及词表**。

下面我将从实现原理、用途和注意事项三个方面为你详细解释这段代码:

### 一、 实现原理与代码逐行解释

1. 加载本地分词器

```python

local_model_path = './bert-base-uncased-local'

tokenizer = BertTokenizerFast.from_pretrained(local_model_path)

```

- BertTokenizerFast 是基于Rust实现的快速分词器,比普通版本速度快很多。

- from_pretrained 方法通常用于从Hugging Face Hub下载模型,但在这里,传入了一个**本地路径**。程序会自动寻找该路径下的 vocab.txt(词表文件)tokenizer.jsonconfig.json 等配置文件来初始化分词器,从而实现**离线加载**。

2. 文本分词与编码

```python

encoded_inputs = tokenizer(sentences, padding=True, truncation=True, return_tensors='pt')

```

这一行是核心操作,它同时完成了多个步骤:

- 分词:将句子切分为词元。例如 "Today" 会被切分为 "today"(因为uncased模型会转为小写)。

- 转换为ID (Convert to IDs):根据词表将每个Token映射为整数索引。

- 添加特殊标记:自动在句首添加 [CLS] (ID为101),句末添加 [SEP] (ID为102)。

- 填充padding=True 会将短句子补零(PAD的ID通常为0),使得batch内所有序列等长。

- 截断truncation=True 确保如果句子超过模型最大长度(如512),会被自动截断。

- 返回张量return_tensors='pt' 表示返回PyTorch的Tensor格式,可以直接送入神经网络模型。

3. 提取与展示信息

```python

tokens = [tokenizer.convert_ids_to_tokens(ids) for ids in encoded_inputs["input_ids"]]

word_index = tokenizer.get_vocab()

```

- convert_ids_to_tokens:将编码后的数字ID反向转换回Token字符串,方便我们直观地看到分词结果(包括 [CLS], [SEP], [PAD])。

- get_vocab:获取完整的 词典映射(Token -> ID),类似于Keras Tokenizer的 word_index

---

### 二、 用途

1. 自然语言处理(NLP)的数据预处理:这是使用BERT等预训练模型进行文本分类、命名实体识别、阅读理解等任务前的标准必备步骤。神经网络无法直接理解字符串,必须通过此步骤将其转化为数字矩阵。

2. 离线/内网环境部署:代码中特意强调了使用本地路径 ./bert-base-uncased-local,这在企业内网环境、Docker容器部署或无外网的服务器上非常实用,避免了因网络问题导致的模型下载失败。

---

### 三、 注意事项

1. 本地文件夹的内容要求

- 指定的 ./bert-base-uncased-local 文件夹中必须包含必要的分词器文件,至少要有 vocab.txt,或者 tokenizer.jsontokenizer_config.json。如果文件缺失from_pretrained 会报错。

2. Padding的副作用

- 代码中使用了 padding=True,由于第一句话较短,第二句话较长,第一句话会被补齐。注意,返回的 encoded_inputs 中除了 input_ids,还会包含一个 attention_mask 张量(全1代表真实Token,0代表Padding)。**在将数据喂给BERT模型时,必须同时传入 attention_mask**,否则模型会把Padding的0也当作有效信息进行处理。

3. Uncased模型的大小写处理

- bert-base-uncased 模型的词表中全部是小写字母。因此,输入的 "Today" 在分词时会被自动转换为 "today"。如果你的任务对大小写敏感(如区分专有名词),应该使用 bert-base-cased 及其对应的分词器。

4. 子词切分

- BERT使用的是WordPiece分词算法。对于词表中没有的词(OOV,Out-of-Vocabulary),它会被切分为更小的子词。例如,"sunnyday" 可能会被切分为 ["sunny", "##day"]## 表示该词元是前一个词的后续部分)。在这个例子中,"sunny" 和 "rainy" 都在词表中,所以被完整保留。

### 💡 补充:预期输出示例

运行该代码,你大致会看到如下输出:

```text

Tokens: [['[CLS]', 'today', 'is', 'a', 'sunny', 'day', '[SEP]'], ['[CLS]', 'today', 'is', 'a', 'rainy', 'day', '[SEP]']]

Token IDs: tensor([[ 101, 2769, 2003, 1037, 4756, 2154, 102, 0],

[ 101, 2769, 2003, 1037, 5398, 2154, 102, 0]])

Word Index: {'[PAD]': 0, '[unused0]': 1, ..., 'the': 1996, ...}

```

(注:由于两句话长度恰好相同,这里可能没有触发明显的0填充,但如果第一句是 "Today is sunny",就会出现 [PAD] 即 ID为0的填充项)


评论