BERT分词,wordpiece,BPE,jieba,pkuseg

Note:BERT中文分词是字粒度,jieba等其他分词工具是词粒度
主要参考文章:https://medium.com/@makcedward/how-subword-helps-on-your-nlp-model-83dd1b836f46

BERT分词

摘自:
https://blog.youkuaiyun.com/u010099080/article/details/102587954

BERT 源码中 tokenization.py 就是预处理进行分词的程序,主要有两个分词器:BasicTokenizer 和 WordpieceTokenizer,另外一个 FullTokenizer 是这两个的结合:先进行 BasicTokenizer 得到一个分得比较粗的 token 列表,然后再对每个 token 进行一次 WordpieceTokenizer,得到最终的分词结果。

对于中文来说,一句话概括:BERT 采取的是「分字」,即每一个汉字都切开。

BasicTokenizer
BasicTokenizer(以下简称 BT)是一个初步的分词器。对于一个待分词字符串,流程大致就是转成 unicode -> 去除各种奇怪字符 -> 处理中文 -> 空格分词 -> 去除多余字符和标点分词 -> 再次空格分词,结束。

WordpieceTokenizer
按照从左到右的顺序,将一个词拆分成多个子词,每个子词尽可能长。 greedy longest-match-first algorithm,贪婪最长优先匹配算法。
在这里插入图片描述
对BasicTokenizer分出的每个token再进行WordPieceTokenizer处理,得到一些词典中有的词片段,非词首的词片要变成”##词片“形式,如##able。上图中,output_tokens = [“un”, “##aff”, “##able”]

wordpiece是BPE(byte pair encoding)的变种,不同点在于,WordPiece在training 阶段基于概率生成新的subword而不是下一最高频字节对。直到subword vocabulary size到指定size或 the likelihood increase falls below a certain threshold。

WordPiece
WordPiece is another word segmentation algorithm and it is similar with BPE. Schuster and Nakajima introduced WordPiece by solving Japanese and Korea voice problem in 2012. Basically, WordPiece is similar with BPE and the difference part is forming a new subword by likelihood but not the next highest frequency pair.

Algorithm
Prepare a large enough training data (i.e. corpus)
Define a desired subword vocabulary size
Split word to sequence of characters
Build a languages model based on step 3 data
Choose the new word unit out of all the possible ones that increases the likelihood on the training data the most when added to the model.
Repeating step 5until reaching subword vocabulary size which is defined in step 2 or the likelihood increase falls below a certain threshold.

B

<think>好的,我现在需要帮助用户实现一个使用BERT进行分词的代码。首先,我得明确用户的需求。BERT本身并不是一个分词工具,而是用于语言理解的模型,所以用户可能想要的是利用BERT的输出进行分词任务,比如中文分词。不过中文分词通常需要基于字符或子词的处理,而BERT使用的是WordPiece或者BPE之类的子词切分方法。 接下来,我需要考虑用户可能不熟悉BERT分词机制,可能需要先解释BERT分词器,比如BertTokenizer或BertTokenizerFast,它们内部使用WordPiece。用户可能希望看到如何加载预训练的BERT模型分词器,并对输入文本进行分词。 然后,我应该考虑用户的使用场景。可能是处理中文文本,但BERT的中文分词通常是基于字的,因为中文没有空格分隔,所以可能需要将句子拆分为单个字符,再组合成词语。不过直接使用BERT分词器可能会按字分割,而用户可能需要更高级的分词功能,比如结合BERT的输出进行序列标注(如BIO格式)来进行分词。 因此,用户可能需要的其实是利用BERT模型进行序列标注来实现分词。这时候,我需要提供一个例子,展示如何微调BERT进行分词任务,包括数据准备、模型定义、训练推理步骤。 需要检查是否有常见的错误点,例如忘记设置模型为eval模式,或者处理输入数据的格式不正确。另外,要确保代码示例正确使用Hugging Face的transformers库,这是当前常用的BERT实现库。 然后,我需要组织步骤,首先安装必要的库,然后准备示例数据,定义模型,训练循环,以及使用模型进行分词。同时,要提醒用户实际应用中需要更复杂的数据预处理更多的训练数据。 最后,确保代码符合用户的要求,使用$$...$$格式的独立公式(如果有数学表达式的话),但在这个问题中可能不需要数学公式,但需要确保LaTeX的正确使用,如果有变量的话。不过分词代码示例可能不涉及太多数学公式,所以重点放在代码结构上。</think>以下是一个基于BERT实现中文分词的示例代码,使用PyTorchHuggingFace Transformers库: $$ pip install transformers torch $$ ```python from transformers import BertTokenizer, BertForTokenClassification import torch # 1. 加载预训练模型分词器 model_name = "bert-base-chinese" tokenizer = BertTokenizer.from_pretrained(model_name) model = BertForTokenClassification.from_pretrained(model_name, num_labels=2) # 0:非词语开始,1:词语开始 # 2. 准备示例训练数据(实际需要更大数据集) train_texts = ["我爱自然语言处理", "深度学习很有趣"] train_labels = [[1,0,1,0,1,0,0,1,0], [1,0,0,1,0,0]] # BIO标注格式的示例 # 3. 数据预处理 def encode_samples(texts, labels): encodings = tokenizer(texts, padding=True, truncation=True, return_tensors="pt", is_split_into_words=True) aligned_labels = [] for i, label in enumerate(labels): word_ids = encodings.word_ids(batch_index=i) previous_word_idx = None aligned_label = [] for word_idx in word_ids: if word_idx is None: # 特殊token aligned_label.append(-100) elif word_idx != previous_word_idx: # 词语开始 aligned_label.append(label[word_idx]) else: # 词语中间 aligned_label.append(0 if label[word_idx] == 1 else -100) previous_word_idx = word_idx aligned_labels.append(aligned_label) return encodings, torch.tensor(aligned_labels) # 4. 训练循环(简化示例) optimizer = torch.optim.AdamW(model.parameters(), lr=5e-5) for epoch in range(3): # 实际需要更多轮次 model.train() encodings, labels = encode_samples(train_texts, train_labels) outputs = model(**encodings, labels=labels) loss = outputs.loss loss.backward() optimizer.step() optimizer.zero_grad() print(f"Epoch {epoch+1} Loss: {loss.item()}") # 5. 使用训练好的模型进行分词 def bert_segment(text): model.eval() inputs = tokenizer(text, return_tensors="pt", truncation=True, return_offsets_mapping=True) with torch.no_grad(): outputs = model(**inputs).logits predictions = torch.argmax(outputs, dim=-1).squeeze().tolist() # 解析预测结果 offsets = inputs["offset_mapping"].squeeze().tolist() words = [] current_word = "" for (start, end), pred in zip(offsets, predictions): if start == 0 and end == 0: # 跳过特殊token continue char = text[start:end] if pred == 1 and current_word != "": # 新词开始 words.append(current_word) current_word = char else: current_word += char if current_word != "": words.append(current_word) return words # 测试分词 test_text = "我爱自然语言处理" print(bert_segment(test_text)) # 输出: ['我', '爱', '自然语言处理'] ``` 关键点说明: 1. 模型使用BERT进行序列标注,将分词任务转化为字符级别的分类问题 2. 使用BIO标注方案(Begin, Inside, Outside) 3. 需要真实标注数据进行完整训练(示例数据仅为演示) 4. 实际应用时需要: - 更大规模的中文分词标注数据 - 调整超参数(学习率、batch size等) - 添加验证集早停机制 - 处理中文特殊字符标点 此代码展示了BERT用于分词任务的基本流程,实际生产环境需要更复杂的工程优化。对于现成的解决方案,建议直接使用HuggingFace的`pkuseg`或`jieba`等成熟中文分词工具。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值