核心内容摘要
NAS vs SAN:如何根据业务需求选择最佳存储架构?
实例代码#编码的例子 from transformers import BertTokenizer #
加载本地模型和分词器 model_dir D:\\本地模型\\google-bert\\bert-base-chinese tokenizer BertTokenizer.from_pretrained(model_dir) #打印特殊符号 print(tokenizer) sents [酒店太旧了大堂感觉象三星级的房间也就是的好点的三星级的条件在青岛这样的酒店是绝对算不上四星标准早餐走了两圈也没有 已经贴完了又给小区的妈妈买了一套。
最值得推荐, 屏幕大本本薄自带数字小键盘比较少见。
声音也还过得去。
usb接口多有四个。
独显看高清很好。
运行速度也还可以性价比高, 酒店环境很好 就是有一点点偏 交通不是很便利 去哪都需要达车 关键是不好打 酒店应该想办法解决一下] #批量编码句子 out tokenizer.batch_encode_plus( batch_text_or_text_pairs[sents[0],sents[1]], add_special_tokensTrue, #当句子长度大于max_length时截断 truncationTrue, #一律补零到max_length长度 paddingmax_length, max_length30, #可取tf,pt,np,默认为返回list return_tensorsNone, #返回attention_mask return_attention_maskTrue, #返回token_type_ids #返回offset_mapping 标识每个词的起止位置,这个参数只BertTokenizerFast使用 # return_offsets_mappingTrue, #返回length 标识长度 return_lengthTrue, ) #input_ids 就是编码后的词 #token_type_ids 第一个句子和特殊符号的位置是0,第二个句子的位置是1 #special_tokens_mask 特殊符号的位置是1,其他位置是0 #attention_mask pad的位置是0,其他位置是1 #length 返回句子长度 print(out) for k, v in out.items(): print(k,:,v) print(tokenizer.decode(out[input_ids][0]),tokenizer.decode(out[input_ids][1]))输出特殊符号无法识别的字符全部定义为unk实例2 字典操作# 字典操作中添加新词 from transformers import ( BertTokenizer, ) #
加载本地模型和分词器 model_dir D:\\本地模型\\google-bert\\bert-base-chinese tokenizer BertTokenizer.from_pretrained(model_dir) #打印特字典 vocabtokenizer.get_vocab() print(len(vocab)) print(阳 in vocab) print(光 in vocab) #以每一个中文字符为节点划分,所以添加的词不在vocab中 print(阳光 in vocab) #添加新词 tokenizer.add_tokens(new_tokens[阳光,大地]) vocab tokenizer.get_vocab() print(阳光 in vocab) print(tokenizer.tokenize(阳光)) print(len(vocab)) #添加新的特殊符号 tokenizer.add_special_tokens({eos_token:[EOS]}) vocab tokenizer.get_vocab() print(vocab) print(tokenizer) print([EOS] in vocab) outtokenizer.encode(text阳光照在大地上[EOS], text_pairNone, truncationTrue, paddingmax_length, max_length10, add_special_tokensTrue) print(out) #解码为原来的字符串 print(tokenizer.decode(out))BERTBidirectional Encoder Representations from Transformers使用的是WordPiece分词算法该算法将单词分解为更小的子词单元。
对于中文文本BERT分词器通常采用字符级分词将每个汉字视为独立的token。
词汇表字典是分词器的核心组成部分它决定了模型能够理解和处理哪些词汇。
当遇到词汇表中不存在的词汇时分词器会将其拆分为已知的子词这可能导致语义信息的丢失。
1 原始词汇表的局限性让我们通过代码示例来观察原始词汇表的局限性from transformers import BertTokenizer # 加载本地模型和分词器 model_dir D:\\本地模型\\google-bert\\bert-base-chinese tokenizer BertTokenizer.from_pretrained(model_dir) # 打印词汇表基本信息 vocab tokenizer.get_vocab() print(f原始词汇表大小: {len(vocab)}) # 检查单个字符是否在词汇表中 print(阳在词汇表中:, 阳 in vocab) # 输出: True print(光在词汇表中:, 光 in vocab) # 输出: True # 检查词语是否在词汇表中 print(阳光在词汇表中:, 阳光 in vocab) # 输出: False从输出结果可以看出虽然单个汉字阳和光都存在于词汇表中但它们的组合阳光却不在其中。
这是因为BERT-base-chinese模型采用字符级分词词汇表主要包含单个汉字和少量常见词语。
2 词汇缺失的影响当词汇表中缺少特定词语时分词器会将其拆分为单个字符。
例如阳光 → [阳, 光]人工智能 → [人, 工, 智, 能]这种拆分可能导致以下问题语义信息丢失词语的整体含义被分解序列长度增加影响模型处理效率上下文理解不准确模型难以捕捉词语的整体语义
解决方案动态添加新词
1 使用add_tokens方法扩展词汇表Transformers库提供了便捷的add_tokens方法允许我们动态地向分词器添加新词# 添加新词 tokenizer.add_tokens(new_tokens[阳光, 大地]) # 验证添加结果 vocab tokenizer.get_vocab() print(阳光在词汇表中:, 阳光 in vocab) # 输出: True print(f扩展后词汇表大小: {len(vocab)}) # 增加了2 # 测试分词效果 print(分词结果:, tokenizer.tokenize(阳光)) # 输出: [阳光]
2 方法详解add_tokens方法的主要特性支持批量添加可以一次添加多个新词保持分词一致性新词会被作为一个整体进行分词词汇表动态扩展不会影响原有词汇表的功能
实际应用场景
1 专业领域术语处理在医疗、法律、金融等专业领域存在大量专业术语。
例如在医疗领域可以添加medical_terms [冠状动脉, 心电图, 核磁共振, 化疗] tokenizer.add_tokens(new_tokensmedical_terms)
2 新兴词汇和网络用语随着语言的发展不断涌现出新词汇和网络用语new_words [元宇宙, 区块链, 内卷, 躺平] tokenizer.add_tokens(new_tokensnew_words)
3 特定应用场景定制针对具体应用场景可以添加相关词汇# 电商场景 ecommerce_words [包邮, 满减, 预售, 秒杀] tokenizer.add_tokens(new_tokensecommerce_words)
五、
注意事项与最佳实践
1 模型权重调整添加新词后模型的embedding层需要相应扩展。
如果继续使用原有模型新添加的词会被随机初始化。
建议对新词进行微调# 扩展模型embedding层 model.resize_token_embeddings(len(tokenizer)) # 对新添加的词进行微调 # ... 微调代码 ...
2 词汇添加策略必要性评估只添加高频且重要的词汇避免冗余不要添加已存在的子词组合批量处理对大量词汇进行批量添加以提高效率
3 性能考虑词汇表大小过大的词汇表会影响模型推理速度内存占用增加词汇表会占用更多内存训练效率微调时需要更多计算资源
完整示例代码from transformers import BertTokenizer, BertModel import torch #
加载分词器和模型 model_dir D:\\本地模型\\google-bert\\bert-base-chinese tokenizer BertTokenizer.from_pretrained(model_dir) model BertModel.from_pretrained(model_dir) #
原始词汇表分析 original_vocab_size len(tokenizer) print(f原始词汇表大小: {original_vocab_size}) #
添加新词 new_tokens [阳光, 大地, 人工智能, 机器学习] tokenizer.add_tokens(new_tokens) print(f添加{len(new_tokens)}个新词后词汇表大小: {len(tokenizer)}) #
调整模型embedding层 model.resize_token_embeddings(len(tokenizer)) #
测试分词效果 test_text 今天的阳光很好适合机器学习实践。
tokens tokenizer.tokenize(test_text) print(f分词结果: {tokens}) #
编码测试 inputs tokenizer(test_text, return_tensorspt) with torch.no_grad(): outputs model(**inputs) print(f编码后张量形状: {outputs.last_hidden_state.shape})
七、
总结动态扩展BERT分词器的词汇表是一项实用且重要的技术能够有效解决实际应用中的词汇覆盖问题。
通过本文的详细解析我们了解到问题根源预训练模型的词汇表难以覆盖所有应用场景解决方案使用add_tokens方法动态添加新词应用价值提升模型对专业术语、新兴词汇的理解能力最佳实践合理选择添加词汇注意模型权重调整在实际应用中建议根据具体需求制定词汇添加策略平衡模型性能和词汇覆盖范围。
通过合理的词汇扩展和模型微调可以显著提升模型在特定领域的表现。