WordPiece 分词如何解决 NLP 中的生僻词问题

在自然语言处理(NLP)领域,我们面临的一个核心挑战是如何处理那些模型从未见过的词汇。传统的处理方法往往难以有效应对这一问题,这使得它们不再适用于现代的应用场景。现有的方法主要存在以下几个问题:

  • 词级分词会导致词汇表极其庞大(包含超过 500,000 个标记)
  • 词汇表外(OOV)的词汇(生僻词或新词)会彻底破坏模型的预测能力
  • 字符级分词会丢失语义信息
  • 模型必须从头学习构词法,这效率非常低

WordPiece 分词提供了一种解决方案,它已成为 BERT 和 GPT 等 Transformer 模型的基石。它在词汇表大小和语义保留之间找到了完美的平衡点。

词汇表膨胀与生僻词问题

让我们考虑这样一个句子:“The bioengineering startup developed unbreakable materials.”(这家生物工程初创公司开发出了坚不可摧的材料)。传统的词级分词器需要分别为“bioengineering”、“startup”、“unbreakable”和“materials”建立独立的索引。如果这些词中有任何一个不在训练词汇表中,模型就会失效。

传统分词方法面临的主要挑战:

  • 词汇表会随着文本语料库的大小呈指数级增长
  • 技术术语和专有名词会制造无穷无尽的边缘情况
  • 对于庞大的词汇表,内存需求变得令人望而却步
  • 模型训练的计算成本变得极其高昂

WordPiece 通过将单词分解为有意义的子单元来解决这些问题。它不再将“unbreakable”视为一个单一的未知标记,而是将其分解为可识别的部分:["un", "##break", "##able"]。这里的“##”前缀表示该标记是前一部分的延续,它既保留了单词的边界,也实现了灵活的分解。

这种方法确保了即使是全新的单词也能通过其组成部分被理解,从而提高了模型的鲁棒性和泛化能力。

WordPiece 分词的工作原理

该算法采用数据驱动的方法来构建词汇表。它从单个字符开始,逐步合并最常出现的相邻字符对,直到达到目标词汇表大小。

算法步骤:

  • 初始化词汇表,包含所有单个字符
  • 统计语料库中所有相邻符号对的频率
  • 将出现频率最高的一对合并为一个单独的标记
  • 用新的合并标记更新语料库
  • 重复上述步骤,直到达到预期的词汇表大小(通常为 30K-50K 个标记)

在实际的分词过程中,WordPiece 使用了一种贪婪的最长匹配策略。对于每个单词,它会找到词汇表中存在的尽可能长的子词,然后将其标记为一个 token,并对剩余的字符重复此过程。

分词过程:

  • 从每个单词的开头开始
  • 在词汇表中查找匹配的最长子词
  • 将其添加到标记列表中,并加上适当的前缀
  • 移动到下一个未处理的字符
  • 继续直到处理完整个单词

这种统计学基础确保了常见的模式自然地涌现为单独的标记,而罕见的组合则被分解为更熟悉的组件。

Wordpiece 的具体实现

让我们使用 transformers 库 来实现基本的 WordPiece 分词。本示例重点关注核心功能,避免不必要的复杂性。

  • 导入 BertTokenizer 并加载预训练的 bert-base-uncased 模型,该模型应用了 WordPiece 分词并将输入文本转换为小写。
  • 定义一个函数 simple_tokenize(text) 来展示 BERT 如何将输入分词为子词并将其映射为 token IDs。
  • 对整个句子进行分词,打印生成的 WordPiece 标记,并将它们转换为相应的词汇表 ID。
  • 将输入拆分为单个单词,并展示 BERT 如何将每个单词分解为子词标记。
  • 在三个示例句子上测试该函数,以说明对生僻词、复合词和复杂单词的处理,示例之间有清晰的分隔。

Python


from transformers import BertTokenizer

Initialize the tokenizer with pre-trained BERT vocabulary

tokenizer = BertTokenizer.from_pretrained(‘bert-base-uncased‘)

def simple_tokenize(text):

"""

Basic WordPiece tokenization example

"""

print(f"Original text: {text}")

# Convert text to WordPiece tokens

tokens = tokenizer.tokenize(text)

print(f"WordPiece tokens: {tokens}")

# Convert tokens to numerical IDs

tokenids = tokenizer.converttokenstoids(tokens)

print(f"Token IDs: {token_ids}")

# Show how individual words break down

words = text.split()

print("

Word breakdown:")

for word in words:

word_tokens = tokenizer.tokenize(word)

print(f" ‘{word}‘ → {word_tokens}")

Test with different examples

test_sentences = [

"Tokenization helps handle rare words.",

"The unbreakable smartphone survived.",

"Bioengineering revolutionizes manufac

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。如需转载,请注明文章出处豆丁博客和来源网址。https://shluqu.cn/25845.html
点赞
0.00 平均评分 (0% 分数) - 0