当前位置: 首页 > news >正文

NLP —— Transformers库使用

目录一、概念二、管道方式Pipline三、自动模型AutoModel四、具体模型方式① 设置变量②加载原始数据③ 数据二次处理④创建数据加载器⑤自己定义模型类⑥ 模型训练⑦模型评估五、预训练模型使用总结一、概念Transformers库 是由 2017年谷歌大脑团队论文提出的在python中的Transformers库 是由Huggingface公式 提出、开发、维护。主要分为三层应用结构1.管道Pipline方式高度集成的极简使用开箱即用。2.自动模型AutoMode方式可载入并使用BertTology系列模型3.具体模型SpecificModel方式在使用时需要明确指定具体的模型并安装对应模型中的特定参数进行微调调用该方式相对复杂但具有较高的灵活度。二、管道方式Pipline使用例文本分类model pipeline(tasktext-classification,modelr本地模型路径) # - 预测 pred_result model(这家餐馆的卫生太差了吃了拉稀非常不推荐) print(pred_result) # [{label: star 5, score: 0.6314295530319214}]API文本分类text-classification 或者sentiment-analysis特征抽取feature-extraction完形填空fill-mask阅读理解question-answering文本摘要summarization命名实体识别ner三、自动模型AutoModelimport torch # 自动加载模型的配置文件 from transformers import AutoConfig # 自动加载对应的模型 from transformers import AutoModel # 自动加载模型词汇表分词器 from transformers import AutoTokenizer # 文本分类 from transformers import AutoModelForSequenceClassification # 完型填空 from transformers import AutoModelForMaskedLM # 阅读理解 from transformers import AutoModelForQuestionAnswering # 文本摘要 from transformers import AutoModelForSeq2SeqLM # NER命名实体识别 from transformers import AutoModelForTokenClassification例文本分类① 创建分词器从预训练模型中创建得到分词器my_tokenizer AutoTokenizer.from_pretrained(“预训练模型路径”)② 创建模型对象根据具体的业务需求选择对应的类my_model AutoModelForSequenceClassification.from_pretrained(“预训练模型路径”)③ 准备数据message “xxxxxxx”④ 文本分词并转为模型需要的数据类型也就是张量data_tensor my_tokenizer.encode(textmessage, return_tensorspt, paddingmax_length, truncationTrue,max_length10) print(f分词器处理后的结果{data_tensor}, {type(data_tensor)})⑤ 将处理后的数据输入到模型中得到结果my_model.eval() result my_model(data_tensor) print(f运行结果{result}, {type(result)}) # 获得预测分类概率值最高的分类ID print(result[0].argmax(dim-1))例特征抽取model AutoModel.from_pretrained(预训练模型路径)分词器用. encode_plus 比 encode 会返回更加丰富的信息data_tensor tokenizer.encode_plus( textsens, return_tensorspt, paddingmax_length, truncationTrue, max_length30 ) 返回值解释 1- input_ids句子对应的词索引 2- token_type_ids词索引来源于的句子索引。句子索引从0开始 3- attention_mask注意力掩码。0表示不看input_ids对应位置的词索引1反之 { input_ids: tensor([[ 101, 872, 3221, 6443, 102, 782, 4495, 6421, 1963, 862, 6629, 1928, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]), token_type_ids: tensor([[0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0]]), attention_mask: tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0]])}调用模型model.eval() result model(**data_tensor) # 对字典进行解包操作 print(result) print(最后一个隐藏状态信息, result.last_hidden_state.shape) print(池化层信息, result.pooler_output.shape)例完形填空model AutoModelForMaskedLM.from_pretrained(“预训练模型路径”)准备数据content 我想明天去[MASK]家吃饭.数据处理# 推荐完型填空类的任务不要设置padding、truncation此类的参数 data_tensor tokenizer.encode_plus( textcontent, return_tensorspt )模型调用model.eval() result model(**data_tensor) print(fresult--类型{type(result)}) print(fresult--内容{result}) 结果形状是[1, 12, 21128]解释如下 1- 1上面传递给大模型的有1条句子 2- 12上面传递给大模型的句子中含句子开头、句子结尾、标点符号、[MASK]在内总共有12个词 3- 21128chinese-bert-wwm大模型的词汇表中有这么多个词 这里写[0][6]原因是[MASK]所在的索引是6 print(fresult中logits--形状{result.logits.shape}) print(fresult中logits某个词--形状{result.logits[0][6].shape}) print(fresult中logits某个词--结果数据{result.logits[0][6]}) # 获得概率最高词的索引信息 pred_word_index torch.argmax(result.logits[0][6]).item() # 将概率最高词的索引转成能够识别的内容 pred_word_content tokenizer.convert_ids_to_tokens(pred_word_index) print(f填充词的索引{pred_word_index}对应的内容{pred_word_content}) # 填充词的索引1961对应的内容她例阅读理解question-answer,根据文本以及问题从文本里面解答问题的答案model AutoModelForQuestionAnswering.from_pretrained(model_path)准备数据context 我叫张三 我是一个程序员 我的喜好是打篮球 questions [我是谁, 我是做什么的, 我的爱好是什么]模型调用# 3- 对问题列表进行循环。每次让大模型回答一个问题。这是与pipeline的主要区别 for question in questions: # 3.1- 数据处理 data_tensor tokenizer.encode_plus(question,context,return_tensorspt) print(data_tensor) # 3.2- 调用模型 model.eval() result model(**data_tensor) # print(result) # 3.3- 处理结果 # 获得答案中预测概率最高start开始索引 start_index torch.argmax(result.start_logits).item() # 获得答案中预测概率最高end结束索引 end_index torch.argmax(result.end_logits).item() 1 # 通过start和end对context因为问题的答案肯定存在于上下文中上下文进行切片得到答案 answer tokenizer.convert_ids_to_tokens(data_tensor.input_ids[0][start_index:end_index]) print(f问题是{question}对应的答案{answer})例文本摘要model AutoModelForSeq2SeqLM.from_pretrained(model_path)准备数据 文章 text 一段话# 3- 处理数据 data_tensor tokenizer.encode_plus(text,return_tensorspt) # 4- 得到文本摘要生成文本内容 model.eval() result model.generate(**data_tensor) print(result) # 就是一个普通张量 # 5- 结果解析 # 5.1- 使用decode进行解码 decode_result_1 [tokenizer.decode(word_index,skip_special_tokensTrue,clean_up_tokenization_spacesFalse) for word_index in result[0]] print(fdecode处理后的结果{ .join(decode_result_1)}) decode_result_2 [tokenizer.decode(word_index,skip_special_tokensFalse,clean_up_tokenization_spacesFalse) for word_index in result[0]] print(fdecode处理后的结果{ .join(decode_result_2)}) # 5.2- 直接使用convert_ids_to_tokens print(convert_ids_to_tokens处理后的结果, .join(tokenizer.convert_ids_to_tokens(result[0],skip_special_tokensTrue)))例命名实体识别多了一个configmodel AutoModelForTokenClassification.from_pretrained(model_path) config AutoConfig.from_pretrained(model_path)# 2- 准备数据 content 鲁迅原名周树人代表作有《朝花夕拾》在外交部上班今天他去故宫游览 # 3- 数据处理 data_tensor tokenizer.encode_plus(textcontent,return_tensorspt) # 4- 调用 model.eval() result model(**data_tensor) print(result) [1, 34, 32]形状解释 1- 1上面有1条句子 2- 34上面句子中含开头、结尾、标点符号在内有34个词 3- 32该模型支持的命名实体的种类有32。每种大模型支持的命名实体的种类不同 # print(result.logits.shape) # 形状[1, 34, 32] # 5- 结果解析 words tokenizer.convert_ids_to_tokens(data_tensor.input_ids[0]) for word,prob_list in zip(words, result.logits[0]): # 过滤掉特殊符号例如句子的开始、结束 if word in tokenizer.all_special_tokens: continue # 1- 获得每个词对应的命名实体类别索引 ner_index torch.argmax(prob_list).item() # 2- 根据索引获得命名实体的名称 ner_type_name config.id2label.get(ner_index) print(f词{word}命名实体类别索引{ner_index}命名实体的名称{ner_type_name})四、具体模型方式举例以Bert模型为例处理二分类问题① 设置变量1 设备2加载字典和分词工具3加载Bert模型device torch.device(cuda if torch.cuda.is_available() else cpu) # device torch.device(cpu) # 就改这里别用 mps # 加载字典和分词工具 tokenizer BertTokenizer.from_pretrained(pretrained_model_name_or_path./model/bert-base-chinese) # 这里导入模型要使用BearModel,而不是BertModelForSequenceClassification # 因为这里使用预训练模型进行特征提取下游自己指定多分类输出层线性层 # 加载预训练模型 Bert模型 bert_model BertModel.from_pretrained(./model/bert-base-chinese) bert_model bert_model.to(device) # 必须把 bert 也放到 device 上②加载原始数据def load_data(): # slpit 只能是train data1 load_dataset(csv, data_files./data/train.csv) #data1 - DatasetDict({ # train: Dataset({ # features: [label, text], # num_rows: 9600 # }) # }) data2 load_dataset(csv, data_files./data/train.csv, splittrain) # data2 - Dataset({ # features: [label, text], # num_rows: 9600 # }) print(data2 - ,data2) print(data2类型 - ,type(data2)) return data2③ 数据二次处理def collate_fn1(dataset): 迭代器 对数据进行二次处理的函数就是这一批次的数据需要接受一个函数地址 # batch_size 4. 一次处理4数据 :param dataset: :return: sents [i[text] for i in dataset] labels [i[label] for i in dataset] print(sents,type(sents)) print(labels) batch_encode_plus 对一次batch的数据一次编码 要对文本数值化文本张量化,对标签进行张量化 data tokenizer.batch_encode_plus( batch_text_or_text_pairssents, truncationTrue, paddingmax_length, max_length300, return_tensorspt ) data {input_ids:tensor(), 数据数值化文本张量化后的结果 token_type_ids:tensor(), 文本句子类型0代表一个句子 attention_mask:tensor()} 掩码 1代表掩码需要掩码 0代表填充的 labels 标签张量化 intput_ids data[input_ids] attention_mask data[attention_mask] token_type_ids data[token_type_ids] labels torch.LongTensor(labels) return (intput_ids, attention_mask, token_type_ids, labels)④创建数据加载器def load_dataLoader(dataset_train): mydataloader torch.utils.data.DataLoader( datasetdataset_train, batch_size4, collate_fncollate_fn1, shuffleTrue, drop_lastTrue ) # for intput_ids, attention_mask, token_type_ids, labels in mydataloader: # print(intput_ids - ,intput_ids) # print(attention_mask - ,attention_mask) # print(token_type_ids - ,token_type_ids) # print(labels - ,labels) # break return mydataloader⑤自己定义模型类class MyModule(nn.Module): def __init__(self): super().__init__() 因为用的是bert模型维度768维度输入是 768 处理的是二分类问题所以输出维度是2 定义线性层。 self.linear nn.Linear(in_features768, out_features2) def forward(self, input_ids, token_type_ids, attention_mask): 先试用Bert模型进行特征提取 【可选】 冻结或者不冻结 torch.no_grad 如果效果不好就不冻结 1- 推荐使用torch.no_grad()冻结Bert的参数训练。可以不加那么回对Bert的110M个参数都会进行训练比较耗时 2- bert_model()里面的参数要使用关键字传参 # with torch.no_grad(): out bert_model( input_idsinput_ids, token_type_idstoken_type_ids, attention_maskattention_mask ) 做分类任务 → 推荐用 pooler_output 做特征提取 → 用 last_hidden_state[:,0] : 取所有句子 0 取第 0 个位置也就是 [BOS_never_used_51bce0c785ca2f68081bfa7d91973934]token out.last_hidden_state[:, 0] 最后一个时间步的隐藏状态 词向量 out.pooler_output 句向量 #print(last_hidden_state -- ,out.last_hidden_state.shape) 【4 300 768】 #print(pooler_output -- ,out.pooler_output.shape) 【4 768】 #output self.linear(out.last_hidden_state[:, 0]) output self.linear(out.pooler_output) # print(output --,output.shape) # 然后把特征送给下游的自定义输出层线性层实现二分类任务 return output⑥ 模型训练1创建自定义模型2可选冻结预训练模型梯度更新不冻结 效果更好耗时3创建优化器4创建损失函数5获取加载数据6数据加载器处理数据7训练《1》 前向传播《2》损失计算《3》梯度清零《4》反向传播《5》梯度更新《6》模型保存def train_model(): # 5.1 创建模型 my_model MyModule().to(devicedevice) # #bert模型 预训练冻结梯度更新 # for param in bert_model.parameters(): # param.requires_grad_(False) my_model.train() # 5.2 创建优化器 my_optimizer torch.optim.AdamW(my_model.parameters(), lr5e-4) # 5.3 创建损失函数 my_cross nn.CrossEntropyLoss() # 5.4 加载数据 my_data load_data() # 5.5 数据加载器 my_dataloader load_dataLoader(my_data) # 5.6 训练 #轮次 epochs 1 for epoch in range(epochs): 进度条 pip install tqdm enumerate 序列化 for i, (input_ids, token_type_ids, attention_mask, labels) in enumerate(tqdm(my_dataloader), start1): # 1 模型前向传播 output my_model( input_idsinput_ids.to(device), token_type_idstoken_type_ids.to(device), attention_maskattention_mask.to(device) ) labels labels.to(device) # 2 损失计算 # 预测值 与 真实值 计算损失 loss my_cross(output, labels) # 3 梯度清零 my_optimizer.zero_grad() # 4 反向传播 loss.backward() # 5 梯度更新 my_optimizer.step() # 6 打印日志 if i % 5 0: pred torch.argmax(output, dim-1) accuracy (pred labels).sum().item() / len(labels) print(f训练轮次:{epoch1}) print(f本轮损失值:{loss.item()}) print(f准确率:{accuracy}) #模型保存 torch.save(my_model.state_dict(), f./save_model/my_model_{epoch 31}.pth)⑦模型评估注意with torch.no_grad(): # 测试必须加 no_graddef test_model(): my_data load_data() my_dataloader load_dataLoader(my_data) my_model MyModule() my_model.load_state_dict(torch.load(./save_model/my_model_31.pth)) my_model my_model.to(devicedevice) my_model.eval() # 准备参数totalaccuracy num 0 total 0 with torch.no_grad(): # 测试必须加 no_grad for i, (input_ids, token_type_ids, attention_mask, labels) in enumerate(tqdm(my_dataloader), start1): # 预测值 output my_model( input_idsinput_ids.to(device), token_type_idstoken_type_ids.to(device), attention_maskattention_mask.to(device) ) labels labels.to(device) #真实值 y_pre torch.argmax(output, dim-1) num (y_pre labels).sum().item() total len(labels) print(准确率:accuracy--, num/total*100)五、预训练模型使用总结1- pipeline管道优点代码开发非常简单缺点底层高度封装可调整的超参数少使用一般用来快速验证预训练模型/大模型是否满足业务需求2- AutoModel自动模型优点代码相对比较简单有一定可以可调整的超参数缺点相对具体模型来说可调整的超参数相对较少3- 指定模型优点可调整的超参数很多能够针对具体的大模型进行指定参数的微调。每种大模型的可调整的参数都是不一样缺点比较灵活不同的大模型可调整的参数有区别使用针对业务场景需要比较高的情况推荐使用后续LoRA、QLoRA
http://www.gsyq.cn/news/1380111.html

相关文章:

  • taotoken模型广场功能详解与模型选型决策指南
  • 2026年厂区节能减排公司有哪些?工业能源托管与余热回收系统厂家实力推荐 - 品牌2025
  • 告别英文界面:Cobalt Strike 4.8 保姆级汉化安装与首次连接指南
  • WPF中Style和ControlTemplate的触发器有什么不同
  • 企业内统一AI开发环境借助Taotoken CLI实现快速配置
  • 项目文档:基于51单片机的篮球计分器设计
  • 用Icarus Verilog破解数字电路调试困局的实战心法
  • request接口调用的三种方法(1)
  • qobuz-dl 终极指南:如何轻松下载无损音乐建立个人高品质音乐库
  • sd卡分区了数据还能恢复吗,只需3种方法和视频教学,数据就能神奇地回来!
  • AI 分析重构(AI-Assisted Refactoring)详解
  • 济南黄金回收怎么选?福运来人气与口碑双冠 - 黄金回收
  • 音乐格式转换终极指南:3步解锁所有加密音频
  • 原神自动化助手GIS:3大核心功能彻底解放你的双手
  • 如何快速解锁加密音乐文件:3个简单步骤让音乐自由播放
  • ncmdumpGUI终极指南:3分钟搞定网易云音乐NCM文件转换
  • 2026最新实测快消品行业GEO优化公司哪家好?靠谱服务商与平台推荐 - 博客万
  • 卷积神经网络学习报告
  • 快速开发AI应用原型时如何利用模型广场进行选型
  • 基于MCP39F511与蓝牙的安卓电能监测App开发全解析
  • 如何快速释放硬件性能:轻量级系统优化工具完整指南
  • 揭秘Midjourney V6光效失控真相:3类高频报错日志解析+实时渲染帧率优化至1.8s/图的硬核方案
  • 2026年5月最新!西安综合高中哪家好:五所西安职业高中学校的差异化选择逻辑全面分析 - 深度智识库
  • 2026年,搜极星定义GEO监测工具新标准
  • Mermaid Live Editor终极指南:5分钟掌握免费在线图表编辑器
  • FAIR原则下的跨学科科学异常检测:从引力波到蝴蝶翅膀的机器学习实战
  • 流量回放测试的进阶玩法:用生产流量喂给测试环境
  • 音乐解锁终极指南:3步解密主流平台加密音频文件
  • 炉石传说脚本终极指南:如何用智能助手解放双手自动对战
  • 浏览器端音频解密技术:如何让加密音乐在本地重获新生?