大模型开发(五):P-Tuning项目——新零售决策评价系统(下)

P-Tuning项目——新零售决策评价系统(下)

  • 0 前言
  • 1 P-Tuning原理
  • 2 数据处理

0 前言

上篇文章我们介绍了使用PET方式微调BERT模型,PET属于提示词微调的一种,另一种比较常见的提示词微调是P-Tuning,我们今天在相同的项目上面用P-Tuning看看。

1 P-Tuning原理

P-Tuning 的目标是减少对人工设计模板(硬模板)的依赖,使用特殊字符(特殊字符可以自由学习也可以自己指定),将模版与原始文本拼在一起输入预训练模型,预训练模型会对模板中的mask做预测,得到一个label。
在这里插入图片描述
图中[u1][u2][u3][u4][u5][u6]都是伪标记,它们都是词表中没有使用过的token,所谓没有使用,指的是没有在训练集和验证集中出现过,所以构建软模板时,要找那种肯定不会出现在训练集和验证集的token。也就是说,软模板不再是人能理解的,只有模型能理解。

本项目的结构和PET大致相同,除了数据处理部分,其他代码只需要略微修改即可,因此我们这里只讲数据处理部分。

2 数据处理

数据处理的代码在 data_handle/data_preprocess.py 中,大致过程就是先插入Mask,后插入伪标记,我做了比较详细的注释,代码如下:

import torch
import numpy as np
from rich import print
from functools import partial
from datasets import load_dataset
from transformers import AutoTokenizerdef convert_example(examples: dict,tokenizer,max_seq_len: int,max_label_len: int,p_embedding_num=6,train_mode=True,return_tensor=False
) -> dict:"""将样本数据转换为模型接收的输入数据。Args:examples (dict): 训练数据样本, e.g. -> {"text": ['娱乐	嗨放派怎么停播了','体育	世界杯为何迟迟不见宣传',...]}max_label_len (int): 最大label长度,若没有达到最大长度,则padding为最大长度p_embedding_num (int): p-tuning token(伪标记) 的个数train_mode (bool): 训练阶段 or 推理阶段。return_tensor (bool): 是否返回tensor类型,如不是,则返回numpy类型。Returns:dict (str: np.array) -> tokenized_output = {'input_ids': [[101, 3928, ...], [101, 4395, ...]],'token_type_ids': [[0, 0, ...], [0, 0, ...]],'mask_positions': [[5, 6, ...], [3, 4, ...]],'mask_labels': [[183, 234], [298, 322], ...]}"""# 定义输出格式(Bert模型的接收格式)tokenized_output = {'input_ids': [],'attention_mask': [],'mask_positions': [],  # 记录label的位置(即MASK Token的位置)'mask_labels': []  # 记录MASK Token的原始值(即Label值)}# 遍历样本数据,将样本填充到模板中,并转化为Bert模型的输入格式for i, example in enumerate(examples['text']):try:# 将[MASK]插在[CLS]之后,[MASK]的位置可以在任何位置,但提示词的开头和结尾必须为[CLS]和[SEP]start_mask_position = 1if train_mode:# 如果是训练模式,则既有样本的label,也有样本的文本内容label, content = example.strip().split('\t', 1) # 第二个参数为1表示最多分割1次,结果列表中最多包含2个元素else:# 如果是评估(推理)模式,则只有样本的文本内容content = example.strip()# 将文本转换为Bert模型的输入格式encoded_inputs = tokenizer(text=content,truncation=True,max_length=max_seq_len,padding='max_length')# encoded_inputs包含三个键:'input_ids', 'token_type_ids', 'attention_mask'except:continue# 生成 MASK Tokens, 和label长度一致mask_tokens = ['[MASK]'] * max_label_len# 将 MASK Tokens 转为 idmask_ids = tokenizer.convert_tokens_to_ids(mask_tokens)# 构建 prompt token(s),即构建伪标记,[[unused1] [unused2] ... [unused6]]p_tokens = ["[unused{}]".format(i + 1) for i in range(p_embedding_num)]# 伪标记 转 idp_tokens_ids = tokenizer.convert_tokens_to_ids(p_tokens)# 获取input_idsinput_ids = encoded_inputs['input_ids']# 去掉最后的[SEP]tmp_input_ids = input_ids[:-1]# 裁剪content的长度tmp_input_ids = tmp_input_ids[:max_seq_len - len(mask_ids) - len(p_tokens_ids) - 1]# 因为要插入 p_embedding_num 个伪标记,并且标签长度为 max_label_len,并且最后要加上[SEP]# 所以原来的 input_ids 只能保存 max_seq_len - len(mask_ids) - len(p_tokens_ids) - 1 个token# 插入[MASK]对应的idtmp_input_ids = tmp_input_ids[:start_mask_position] + mask_ids + tmp_input_ids[start_mask_position:]# 插入后,tmp_input_ids 变为 [CLS][MASK][MASK]世界杯...# 补上[SEP]input_ids = tmp_input_ids + [input_ids[-1]]# 插入伪标记input_ids = p_tokens_ids + input_ids  # [unused1][unused2]...[CLS][MASK][MASK]世界杯...[SEP]# 将 Mask Tokens 的位置记录下来mask_positions = [len(p_tokens_ids) + start_mask_position + i for i in range(max_label_len)]# 将填充后的提示词加入到输出字典中tokenized_output['input_ids'].append(input_ids)# 如果输入需要token_type_ids,可以进行添加,if 'token_type_ids' in encoded_inputs:  # 兼容不需要 token_type_id 的模型, e.g. Roberta-Basetmp = encoded_inputs['token_type_ids']if 'token_type_ids' not in tokenized_output:# 循环第一轮时,'token_type_ids'不在字典tokenized_output中,所以需要增加键值对tokenized_output['token_type_ids'] = [tmp]else:# 从第二轮循环开始,直接在列表里添加tokenized_output['token_type_ids'].append(tmp)# 收集Bert模型需要的其他信息tokenized_output['attention_mask'].append(encoded_inputs['attention_mask'])tokenized_output['mask_positions'].append(mask_positions)# 对于训练模式,则需要将label转化为Bert模型的输入格式if train_mode:mask_labels = tokenizer(text=label)  # label token 转 idmask_labels = mask_labels['input_ids'][1:-1]  # 丢掉[CLS]和[SEP]mask_labels = mask_labels[:max_label_len]   # 如果标签的长度大于max_label_len,则截断mask_labels += [tokenizer.pad_token_id] * (max_label_len - len(mask_labels))  # 将 label 补到最长tokenized_output['mask_labels'].append(mask_labels)     # 收集处理后的标签# 将数据转化为torch.tensor或者numpy.array格式,方便后续处理for k, v in tokenized_output.items():if return_tensor:tokenized_output[k] = torch.LongTensor(v)else:tokenized_output[k] = np.array(v)return tokenized_outputif __name__ == '__main__':# 导入数据train_dataset = load_dataset('text', data_files={'train': '../data/train.txt'})print(f'train_dataset==>{train_dataset}')print(train_dataset['train']['text'][0])print('-'*80)# 创建分词器tokenizer = AutoTokenizer.from_pretrained('../../预训练模型/bert-base-chinese')# 函数式编程new_func = partial(convert_example,tokenizer=tokenizer,max_seq_len=20,max_label_len=2,p_embedding_num=6)# 数据批处理new_dataset = train_dataset.map(new_func, batched=True)# 打印print(f'dataset---》{new_dataset}')for value in new_dataset['train']:# value将是一个字典,包含输入的text、input_ids、token_type_id、attention_mask、mask_position和mask_labelprint(type(value))for k, v in value.items():print(k, v)print(len(value['input_ids']))break

输出

train_dataset==>DatasetDict({train: Dataset({features: ['text'],num_rows: 63})
})
电脑	(1)这款笔记本外观感觉挺漂亮的,分量吗,对我来说不算沉。 (2)安装了WindowsXP系统后,运行的速度挺快。发热量没有想象中那么大。可能尚未运行很耗资源的程序,没有感到内存的弊病。不过,1G的内存确实有点小。 (3)附赠的包很不错,挺有手感的。但是附赠的鼠标实在是太小了,幸好同时订了一个双飞燕的鼠标哟。
--------------------------------------------------------------------------------
dataset---》DatasetDict({train: Dataset({features: ['text', 'input_ids', 'attention_mask', 'mask_positions', 'mask_labels', 'token_type_ids'],num_rows: 63})
})
<class 'dict'>
text 电脑	(1)这款笔记本外观感觉挺漂亮的,分量吗,对我来说不算沉。 (2)安装了WindowsXP系统后,运行的速度挺快。发热量没有想象中那么大。可能尚未运行很耗资源的程序,没有感到内存的弊病。不过,1G的内存确实有点小。 (3)附赠的包很不错,挺有手感的。但是附赠的鼠标实在是太小了,幸好同时订了一个双飞燕的鼠标哟。
input_ids [1, 2, 3, 4, 5, 6, 101, 103, 103, 113, 122, 114, 6821, 3621, 5011, 6381, 3315, 1912, 6225, 102]
attention_mask [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
mask_positions [7, 8]
mask_labels [4510, 5554]
token_type_ids [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
20

我个人有几个暂时理解不了的点:

  1. 上面这段程序,构建的软模板为:[unused1] [unused2] ... [unused5] [unused6] [CLS] [MASK] [MASK] {text} [SEP],而start_mask_position=1,也就是说start_mask_position竟然是 [MASK] 插入到文本中的位置,假如start_mask_position不是1的话,是不是意味着要在文本中间插入?
  2. 为什么模板不是以 [CLS]开头?我查到的资料是,P-Tuning允许 [CLS]位置调整,也可以把模板改成这样: [CLS] [unused1] [unused2] [MASK][MASK] [unused3] [unused4] [unused5] [unused6] {text} [SEP]
  3. 似乎[unused1] [unused2]...[unused6] [CLS] {MASK} {text} [SEP],和前面PET的模板这是一条{MASK}评论:{textA},没有本质区别,都是人工构建的模板,指定伪标记为哪些token([unused1][unused2]等),出现在哪些位置,指定{MASK}在什么位置({textA}的前面),这些都是人工指定的,并不是模型生成的。既然都是人配置的,它为什么能比硬模板效果好呢?我的理解是,在微调之前,模板中的每个token,模型都是理解的,而软模板在微调之前,里面的[unused1] [unused2]模型并不认识,是在微调过程中,模型逐渐理解了;而硬模板的话,预训练模型本来就知道你的硬模板的token是什么意思,他们之间本来就存在一些联系。
  4. 很多人都说软模版是一种可学习模板,但模板好像从训练开始到结束,始终没改变过,这个“可学习”该如何理解?

AI邻域的很多问题搞不明白很正常,上面的部分解释很牵强,但这种方式却能起作用,这可能就是这个学科的特点吧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/71677.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

分布式中间件:Redis介绍

目录 Redis 概述 Redis 的特点 高性能 丰富的数据结构 持久化 分布式特性 简单易用 Redis 的数据结构 字符串&#xff08;String&#xff09; 哈希&#xff08;Hash&#xff09; 列表&#xff08;List&#xff09; 集合&#xff08;Set&#xff09; 有序集合&…

在昇腾GPU上部署DeepSeek大模型与OpenWebUI:从零到生产的完整指南

引言 随着国产AI芯片的快速发展&#xff0c;昇腾&#xff08;Ascend&#xff09;系列GPU凭借其高性能和兼容性&#xff0c;逐渐成为大模型部署的重要选择。本文将以昇腾300i为例&#xff0c;手把手教你如何部署DeepSeek大模型&#xff0c;并搭配OpenWebUI构建交互式界面。无论…

系统思考—组织诊断

“未经过诊断的行动是盲目的。” — 托马斯爱迪生 最近和一家教育培训机构沟通时&#xff0c;发现他们面临一个有意思的问题&#xff1a;每年招生都挺不错&#xff0c;但教师的整体绩效一直提升缓慢&#xff0c;导致师生之间存在长期的不匹配。管理层试了很多办法&#xff0c;…

AI大模型学习(五): LangChain(四)

Langchian读取数据库 案例&#xff1a;在数据库中表格数据上的问题系统的基本方法,将涵盖使用链和代理的视线,通过查询数据库中的数据并得到自然语言的答案,两者之间的主要区别在于,我们代理可以根据多次循环查询数据库以回答问题 实现思路: 1.将问题转换成DSL查询,模型将用…

人工智能与深度学习的应用案例:从技术原理到实践创新

第一章 引言 人工智能(AI)作为21世纪最具变革性的技术之一,正通过深度学习(Deep Learning)等核心技术推动各行业的智能化进程。从计算机视觉到自然语言处理,从医疗诊断到工业制造,深度学习通过模拟人脑神经网络的层次化学习机制,实现了对复杂数据的高效分析与决策。本…

支持向量机的深度解析:从理论到C++实现

支持向量机(SVM)是一种强大的监督学习算法,广泛应用于分类和回归任务。本文详细探讨了SVM的理论基础,包括最大间隔分离超平面、软间隔和核技巧(Kernel Trick)的数学原理,并通过LaTeX公式推导其优化目标。接着,我们用C++实现了一个简单的线性SVM,包括梯度下降优化求解支…

企业如何选择研发项目进度管理软件?盘点15款实用工具

这篇文章介绍了以下工具: 1. PingCode&#xff1b; 2. Worktile&#xff1b; 3. 腾讯 TAPD&#xff1b; 4. 华为 DevCloud&#xff1b; 5. 亿方云&#xff1b; 6. 阿里云效&#xff1b; 7. CODING 码云&#xff1b; 8. 明道云&#xff1b; 9. 进度猫&#xff1b; 10. 轻流等。 …

c++: 容器vector

文章目录 介绍initializer_list与string的不同底层总代码 介绍 C 中的 vector 是一种序列容器&#xff0c;它允许你在运行时动态地插入和删除元素。 vector 是基于数组的数据结构&#xff0c;但它可以自动管理内存&#xff0c;这意味着你不需要手动分配和释放内存。 与 C 数组相…

Qt常用控件之表格QTableWidget

表格QTableWidget QTableWidget 是一个表格控件&#xff0c;行和列交汇形成的每个单元格&#xff0c;是一个 QTableWidgetItem 对象。 1. QTableWidget属性 QTableWidget 的属性只有两个&#xff1a; 属性说明rowCount当前行的个数。columnCount当前列的个数。 2. QTableW…

Golang学习笔记_47——访问者模式

Golang学习笔记_44——命令模式 Golang学习笔记_45——备忘录模式 Golang学习笔记_46——状态模式 文章目录 一、核心概念1. 定义2. 解决的问题3. 核心角色4. 类图 二、特点分析三、适用场景1. 编译器实现2. 财务系统3. UI组件系统 四、Go语言实现示例完整实现代码执行结果 五、…

栈概念和结构

文章目录 1. 栈的概念2. 栈的分类3. 栈的实现&#xff08;数组栈&#xff09;3.1 接口设计&#xff08;Stack.h&#xff09;3.2 接口实现&#xff08;Stack.c&#xff09;1&#xff09;初始化销毁2&#xff09;栈顶插入删除3&#xff09;栈顶元素、空栈、大小 3.3 完整代码Stac…

GitCode 助力 vue3-element-admin:开启中后台管理前端开发新征程

源码仓库&#xff1a; https://gitcode.com/youlai/vue3-element-admin 后端仓库&#xff1a; https://gitcode.com/youlai/youlai-boot 开源助力&#xff0c;开启中后台快速开发之旅 vue3-element-admin 是一款精心打造的免费开源中后台管理前端模板&#xff0c;它紧密贴合…

算法.习题篇

算法 — 地大复试 模拟 while循环和MOD循环计数 1.约瑟夫问题 http://bailian.openjudge.cn/practice/3254 using namespace std;bool isNoPeople(vector<bool> c)//判断当前数组是否一个小孩都没有了 {bool nopeople true;for (bool ival : c){if ( ival true)nop…

大白话JavaScript实现一个函数,将字符串中的每个单词首字母大写。

大白话JavaScript实现一个函数&#xff0c;将字符串中的每个单词首字母大写。 答题思路 理解需求&#xff1a;要写一个函数&#xff0c;它能接收一个字符串&#xff0c;然后把这个字符串里每个单词的第一个字母变成大写。分解步骤 拆分单词&#xff1a;一般单词之间是用空格隔…

react中如何使用使用react-redux进行数据管理

以上就是react-redux的使用过程&#xff0c;下面我们开始优化部分&#xff1a;当一个组件只有一个render生命周期&#xff0c;那么我们可以改写成一个无状态组件&#xff08;UI组件到无状态组件&#xff0c;性能提升更好&#xff09;

广告营销,会被AI重构吗?

DeepSeek设计&#xff0c;即梦AI绘图&#xff0c;剪映成片。 DeepSeek的热度还在高开疯走。 用户对于各个场景下DS应用的探索也还在持续&#xff0c;各种DS的模式被挖掘出来&#xff0c;超级个体们开始给手下的大模型团队进行分工&#xff0c;实践出各种场景下最佳的排列组合方…

国产编辑器EverEdit - 宏功能介绍

1 宏 1.1 应用场景 宏是一种重复执行简单工作的利器&#xff0c;可以让用户愉快的从繁琐的工作中解放出来&#xff0c;其本质是对键盘和菜单的操作序列的录制&#xff0c;并不会识别文件的内容&#xff0c;属于无差别无脑执行。 特别是对一些有规律的重复按键动作&#xff0c;…

vscode离线配置远程服务器

目录 一、前提 二、方法 2.1 查看vscode的commit_id 2.2 下载linux服务器安装包 2.3 安装包上传到远程服务器&#xff0c;并进行文件解压缩 三、常见错误 Failed to set up socket for dynamic port forward to remote port&#xff08;vscode报错解决方法&#xff09;-C…

OmniDrive(1): 论文解读

多模态大语言模型(MLLMs)的发展推动了基于 LLM 的自动驾驶研究,以利用其强大的推理能力。然而,利用多模态大语言模型(MLLMs)强大的推理能力来改进planning具有挑战性,因为这需要超越二维推理的完整三维情境感知能力。因为这不单单需要 2D 推理还需要完整的 3D 场景感知能…

ubuntu22.04安装RAGFlow配合DeepSeek搭建本地知识库

一、简介 RAGFlow 是一个基于对文档的深入理解的开源 RAG&#xff08;检索增强生成&#xff09;引擎。当与 LLM 集成时&#xff0c;它能够提供真实的问答功能&#xff0c;并以来自各种复杂格式数据的有根据的引用为后盾。 二、安装 1.环境要求 CPU ≥ 4 核 &#xff08;x86…