大型网站建设历史,教育网站如何做经营,小程序开发公司如何寻找客户,广东省建设安全监督站的网站参考视频#xff1a;BERT代码(源码)从零解读【Pytorch-手把手教你从零实现一个BERT源码模型】_哔哩哔哩_bilibili 一、BertTokenizer
BertTokenizer 是基于 WordPiece 算法的 BERT 分词器#xff0c;继承自 PreTrainedTokenizer。
继承的PretrainedTokenizer#xff0c;具… 参考视频BERT代码(源码)从零解读【Pytorch-手把手教你从零实现一个BERT源码模型】_哔哩哔哩_bilibili 一、BertTokenizer
BertTokenizer 是基于 WordPiece 算法的 BERT 分词器继承自 PreTrainedTokenizer。
继承的PretrainedTokenizer具体操作的实现是在PretrainedTokenizer中的__call__执行。
1. 初始化 __init__
加载词汇表文件创建 token 到 ID 的映射初始化基础分词器和 WordPiece 分词器
# 加载词汇表
self.vocab load_vocab(vocab_file)
# 创建反向映射 (ID - token)
self.ids_to_tokens collections.OrderedDict([(ids, tok) for tok, ids in self.vocab.items()])# 初始化两个分词器
if do_basic_tokenize:self.basic_tokenizer BasicTokenizer(...) # 基础分词
self.wordpiece_tokenizer WordpieceTokenizer(...) # WordPiece分词1.1 加载词汇
Vocab 是 vocabulary词汇表的缩写指的是模型能够理解和处理的所有词汇的集合。
有不同类型的vocab: 在BERT中有几个特殊token
special_tokens {[PAD]: 填充短序列,[UNK]: 未知词汇,[CLS]: 分类任务的开始符,[SEP]: 句子分隔符,[MASK]: 掩码语言模型的掩码符
}
1.2 BasicTokenizer 基础分词
BasicTokenizer 负责将原始文本转换为基础的 token 序列。
主要参数
def __init__(self,do_lower_caseTrue, # 是否转换为小写never_splitNone, # 永不分割的词汇集合tokenize_chinese_charsTrue, # 是否处理中文字符strip_accentsNone, # 是否去除重音符号do_split_on_puncTrue, # 是否在标点符号处分割
):主要分词方法
1. 清理文本清除无效字符和空白字符 2. 处理中文字符在字符周围添加空格
3. unicode 标准化 Unicode 标准化有四种形式NFCNFKCNFDNFKD unicode_normalized_text unicodedata.normalize(NFC, text) NFC规范分解后再组合将字符分解后重新组合成最紧凑的形式 NFD规范分解将组合字符分解为基础字符 组合标记 NFKC兼容性分解后再组合更激进的标准化会转换兼容性字符 NFKD兼容性分解最彻底的分解形式。 4. 按空格分割成token
5. 对分割后的token做小写化和去重音
6. 再通过标点分割
def tokenize(self, text, never_splitNone):# 处理流程# 1. 清理文本text self._clean_text(text)# 2. 处理中文字符在字符周围添加空格if self.tokenize_chinese_chars:text self._tokenize_chinese_chars(text)# 3. Unicode 标准化unicode_normalized_text unicodedata.normalize(NFC, text)# 4. 按空格分割orig_tokens whitespace_tokenize(unicode_normalized_text)# 5. 处理每个 tokensplit_tokens []for token in orig_tokens:if token not in never_split:# 小写化和去重音if self.do_lower_case:token token.lower()if self.strip_accents is not False:token self._run_strip_accents(token)elif self.strip_accents:token self._run_strip_accents(token)# 6. 标点符号分割split_tokens.extend(self._run_split_on_punc(token, never_split))# 7. 最终清理output_tokens whitespace_tokenize( .join(split_tokens))return output_tokens1.3 WordPiece子词分词
WordPiece 是一种子词分词算法它将单词分解为更小的、有意义的片段以解决
词汇表大小限制未登录词OOV问题词汇的组合性表示
主要参数
def __init__(self, vocab, unk_token, max_input_chars_per_word100):self.vocab vocab # 词汇表字典self.unk_token unk_token # 未知词标记通常是 [UNK]self.max_input_chars_per_word 100 # 单词最大字符数限制核心算法最长贪心匹配 def tokenize(self, text):output_tokens []# 1. 按空格分割文本假设已经过 BasicTokenizer 处理for token in whitespace_tokenize(text):chars list(token)# 2. 检查单词长度限制if len(chars) self.max_input_chars_per_word:output_tokens.append(self.unk_token)continue# 3. 执行 WordPiece 分词is_bad Falsestart 0sub_tokens []while start len(chars):end len(chars)cur_substr None# 4. 贪心最长匹配while start end:substr .join(chars[start:end])# 5. 非首个子词添加 ## 前缀if start 0:substr ## substr# 6. 检查是否在词汇表中if substr in self.vocab:cur_substr substrbreakend - 1# 7. 如果没找到匹配标记为失败if cur_substr is None:is_bad Truebreaksub_tokens.append(cur_substr)start end# 8. 根据结果添加到输出if is_bad:output_tokens.append(self.unk_token)else:output_tokens.extend(sub_tokens)return output_tokens2. 核心分词方法 tokenize
分两种情况第一种do_basic_tokenize: 先基础分词在wordpiece第二种直接wordpiece。 3. Token与ID转换
def _convert_token_to_id(self, token):Token - IDreturn self.vocab.get(token, self.vocab.get(self.unk_token))def _convert_id_to_token(self, index):ID - Tokenreturn self.ids_to_tokens.get(index, self.unk_token)4. 特殊Token处理
def build_inputs_with_special_tokens(self, token_ids_0, token_ids_1None):构建BERT输入格式if token_ids_1 is None:# 单句[CLS] X [SEP]return [self.cls_token_id] token_ids_0 [self.sep_token_id]else:# 句对[CLS] A [SEP] B [SEP]cls [self.cls_token_id]sep [self.sep_token_id]return cls token_ids_0 sep token_ids_1 sep5. 特殊Token掩码
def get_special_tokens_mask(self, token_ids_0, token_ids_1None, already_has_special_tokensFalse):生成特殊token掩码1表示特殊token0表示普通tokenif token_ids_1 is not None:# 句对[1] [0]*len(A) [1] [0]*len(B) [1]return [1] ([0] * len(token_ids_0)) [1] ([0] * len(token_ids_1)) [1]# 单句[1] [0]*len(X) [1]return [1] ([0] * len(token_ids_0)) [1]二、DataFrame Parquet文件 是一种列式存储文件格式专为大数据分析和处理设计。 dfs 从数据集的单个文件读取内容
df concat合并dfs读取到的两个文件内容 三、Dataset dataset.map()流程 set_format() 作用 指定数据集返回的数据格式为 PyTorch 张量torch.Tensor并筛选需要保留的列如 input_ids、attention_mask
关键参数 type目标格式支持 torch、numpy、pandas 等。 columns保留的字段列表其他字段将被隐藏但不会删除。 output_all_columns若为 True即使未在 columns 中指定也会保留所有字段默认为 False。 为什么要这一步 (1) 适配 PyTorch 训练 PyTorch 的 DataLoader 和模型输入要求张量格式直接使用 NumPy/列表会报错。 自动转换省去手动调用 torch.tensor() 的麻烦。 (2) 减少内存占用 隐藏不需要的字段如未使用的 token_type_ids避免数据加载时的冗余传输。 (3) 灵活性 可随时切换格式例如从 torch 改为 numpy或重置为默认状态 # 重置为原始格式Arrow
tokenized_dataset.reset_format() DataCollatorForLanguageModeling
DataCollatorForLanguageModeling 是 HuggingFace Transformers 库中专门为语言模型如 BERT训练设计的数据整理器主要用于 动态生成掩码语言模型MLM任务所需的输入。 核心功能 (1) 动态掩码Dynamic Masking mlmTrue启用掩码语言模型任务随机遮盖输入 Token如 BERT 的预训练方式。 mlm_probability0.15每个 Token 有 15% 的概率被遮盖原始 BERT 论文的设置。 其中 80% 替换为 [MASK]如 hello → [MASK] 10% 替换为随机 Token如 hello → apple 10% 保持原 Token如 hello → hello (2) 批量填充Padding 自动将一批样本填充到相同长度根据 tokenizer.pad_token_id。 生成 attention_mask 标记有效 Token。 (3) 标签生成Labels 自动生成与 input_ids 长度相同的 labels其中 被遮盖的 Token 位置标注原始 Token ID用于计算损失。 未被遮盖的位置标注为 -100PyTorch 中忽略损失计算。 默认都是-100,在损失计算中设置忽略labels-100的位置 为什么需要DataCollatorForLanguageModeling 关键参数
def __init__(self,tokenizer, # 必须传入的分词器实例mlmTrue, # 是否启用MLM任务mlm_probability0.15, # 单Token被掩码的概率mask_replace_prob0.8, # 掩码Token替换为[MASK]的比例random_replace_prob0.1, # 掩码Token替换为随机词的比例pad_to_multiple_ofNone, # 填充长度对齐如8的倍数优化GPU显存return_tensorspt, # 输出格式pt/tf/npseedNone # 随机种子
):训练