你好,我是 Tyler。
前面我们一起学习了提示语工程方法,你掌握得如何了?从今天开始,我们即将踏入一个新的篇章——模型工程。
正式开始之前,我想先从顶层帮你理解一下两者之间的异同。其实这两个领域的工作,本质上都是进行知识注入。不同的是,提示语工程采用了上下文学习的方法,通过提供少量示例代码向模型注入新知识。而模型工程则是通过参数学习的方法(更新模型参数)学习新知。
在模型工程部分,我们的学习重点就是理解参数学习的体系和方法。今天我们要解决的关键的问题是参数学习的数据从何而来。
模型发展
为了学习模型工程,我们先来学习一下 OpenAI 大火之后,陆续出现的一些大模型工作。我相信你在很多地方都已经见过各种各样的大型语言模型,比如那些经典的“羊驼系列”,包括 LLAMA(美洲驼)、ALPACA(羊驼)、VICUNA(小羊驼)、GUANACO(骆马),甚至是华佗(不过因为大家开的玩笑多了,现在已经改名为“本草”)。
在阅读这些论文后,你会发现,在这些研究中,他们都在努力回答两个关键问题——第一个问题是如何获取训练数据,第二个问题是如何获得足够的计算资源。
这两个核心问题,也是每个涉及大型模型训练的技术团队都不可避免的现实挑战。幸运的是,由于这两个问题足够重要,目前已经有许多的公开研究工作在致力于解决这些难题。
我们先来解决第一个问题,即:“训练数据从何而来?”。
训练数据从何而来
我们知道,OpenAI 为了对齐 LLM 与人类的交互方式,投入了大量的人工标注成本,对 GPT-3 这类大型语言预训练模型进行了指令微调。
不过,相比与 Google、Meta 这些大厂的财大气粗,学术研究者、大公司内部的创业团队,或者是初创公司,很难获得这种资源。因此,怎么低成本获取大量的指令微调数据,成为了他们的重要课题,目前其中最有代表性的工作就是 Self-Instruct。
Self-Instruct
总的来说,Self-Instruct 从一组初始示例样本开始,以 LLM 的自我引导方式生成新的指令和示例。至于具体的实现步骤,你可以先看看后面这张图,再听我分步讲解。
第一步,准备种子数据。我们需要创建一个种子数据集,这一步,是唯一需要标注人员的参与环节。我们需要为每个任务准备一条指令和一个示例,同时在这里我们需要明确这些指令是用于分类,还是其他的用途。以下提供了指令的示例。
示例 #1 通过构造指令,让大语言模型给出早餐建议的示例样例。
{
"id": "seed_task_0",
"name": "breakfast_suggestion",
"instruction": "Is there anything I can eat for a breakfast that doesn't include eggs, yet includes protein, and has roughly 700-1000 calories?",
"instances": [{"input": "", "output": "Yes, you can have 1 oatmeal banana protein shake and 4 strips of bacon. The oatmeal banana protein shake may contain 1/2 cup oatmeal, 60 grams whey protein powder, 1/2 medium banana, 1tbsp flaxseed oil and 1/2 cup watter, totalling about 550 calories. The 4 strips of bacon contains about 200 calories."}],
"is_classification": false
}
示例 #2 通过构造指令,让大语言模型给出两个词之间关系的示例样例。
{
"id": "seed_task_1",
"name": "antonym_relation",
"instruction": "What is the relation between the given pairs?",
"instances": [{"input": "Night : Day :: Right : Left", "output": "The relation between the given pairs is that they are opposites."}], "is_classification": false
}
第二步,生成提示指令,也就是利用大型预训练语言模型(LLM)来生成新的指令。
就像之前提到的,每个任务都包含一条指令和一个示例。在每一轮的数据生成中,我们都从这个任务池里面,随机选择 8 个任务指令作为上下文示例。这 8 个指令中包含了 6 个人工编写的样本和 2 个来自前一轮模型生成的样本,这可以有效地提高生成指令的多样性。
以下是一些生成新指令的示例提示(生成提示指令,用于后续示例样本的生成)。
Come up with a series of tasks:
Task1: {instruction for existing task 1}
Task2: {instruction for existing task 2}
...
Task8: {instruction for existing task 8}
Task9:
第三步,判断任务类型。我们要判断生成的指令是否属于分类任务。为什么需要这一步呢?因为这两类任务后续的处理方法和生成步骤是不同的,要区分处理。
示例提示是后面这样。
Can the following task be regarded as a classification task with finite output labels?
Task: Given my personality and the job, tell me if I would be suitable.
Is it classification? Yes
...
Task: Given a set of numbers, find all possible subsets that sum to a given number.
Is it classification? No
Task: {instruction for the target task}
接下来是生成示例样本的步骤。完成上一步后,我们继续为这两类任务,采用不同的生成方法。
在非分类任务上,我们使用输入优先的方法,这是一种直观和自然的方法,我们首先根据指令生成输入字段,然后生成输出。
以下是非分类任务的示例提示。
Come up with examples for the following tasks. Try to generate multiple examples when possible. If the task doesn’t require additional input, you can generate the output directly.
Task: Which exercises are best for reducing belly fat at home?
Output:
- Lying Leg Raises
- Leg In And Out
- Plank
- Side Plank
- Sit-ups
Task: Sort the given list ascendingly.
Example 1
List: [10, 92, 2, 5, -4, 92, 5, 101]
Output: [-4, 2, 5, 5, 10, 92, 92, 101]
Example 2
Input 2 - List: [9.99, 10, -5, -1000, 5e6, 999]
Output: [-1000, -5, 9.99, 10, 999, 5e6]
Task: {Instruction for the target task}
但这种方法不适用于分类任务。对于分类任务,更适合使用输出优先方法。这种方法会首先生成分类标签,然后根据分类标签生成输入。以下是分类任务的示例提示。
Given the classification task definition and the class labels, generate an input that corresponds to each of the class labels. If the task doesn’t require input, just generate the correct class label.
Task: Classify the sentiment of the sentence into positive, negative, or mixed.
Class label: mixed
Sentence: I enjoy the flavor of the restaurant but their service is too slow.
Class label: Positive
Sentence: I had a great day today. The weather was beautiful and I spent time with friends.
Class label: Negative
Sentence: I was really disappointed by the latest superhero movie. I would not recommend it.
Task: Which of the following is not an input type? (a) number (b) date (c) phone number (d) email address (e) all of these are valid inputs.
Class label: (e)
...
Task: {Instruction for the target task}
第四步,我们会过滤生成内容,完成数据过滤和后处理这些任务。为了确保生成数据的质量,只有当新生成的指令与现有指令的 ROUGE-L 重叠小于 0.7 时,才会将其添加到任务池中,以确保指令的这质量和多样性。同时,这一步还会排除包含“图片”和“图表”这些关键词的指令,并过滤掉完全相同的,或具有相同输入、但输出不同的示例。
最后,在获得足够的指令和示例后,算法就会停止生成任务。
Self-Instruct 论文里总共生成了 52,000 条指令和 82,000 个示例数据,总体而言,生成的指令具有实际意义,尽管可能存在一些噪音,但大多数符合正确格式。
在实际应用中,Self-Instruct 微调后的大语言模型,能做到优于 GPT-3 基础模型的效果。
前面的课程(第 18 节课末尾)我提到过,这类的数据增强方法,本质上其实是模型反演攻击或成员推理攻击。所以当时这个方法发布的时候,有一部分声音在担心这个漏洞很可能会被 OpenAI 的风控策略所封堵。但是随着 Meta 开源了 Llama 系列模型后,这种声音就变得越来越少了。 因为随着开源模型和闭源模型的差距不断减小,对这类数据反演工具防御的意义越来越小。有这个时间,还不如快马加鞭,加快自家大模型的发展速度,而不是层层封堵后来者。
这类数据增强方法可以让后来者充分地发挥“后发优势”,让这个领域充满了不确定性,从这个角度来讲,在大模型领域中没有永远的赢家,而是充满了不确定性。这让该领域能更健康地发展。
下面我们来聊聊 Self-Instruct 最著名的应用——Alpaca,它为后续层出不穷的开源大模型指出了一个更加普惠的入局方式,可以用极小的成本得到自己的领域大模型。 Alpaca
Alpaca 是 LLaMA-7B 的微调版本,它采用了 Self-Instruct 方式生成的数据进行了指令微调。具体来说,它利用了 OpenAI 的 text-davinc-003 模型,用 175 对人工标注的种子数据,构建了 52K 条指令微调数据,使用 OpenAI API 的成本仅仅不到 500 美元。
Alpaca 对 Self-Instruct 提供的方案进行了修改,使其相对简化。它使用的提示语 prompt 大致是后面这样。
You are asked to come up with a set of 20 diverse task instructions. These task instructions will be given to a GPT model and we will evaluate the GPT model for completing the instructions.
Here are the requirements:
1. Try not to repeat the verb for each instruction to maximize diversity.
2. The language used for the instruction also should be diverse. For example, you should combine questions with imperative instrucitons.
3. The type of instructions should be diverse. The list should include diverse types of tasks like open-ended generation, classification, editing, etc.
2. A GPT language model should be able to complete the instruction. For example, do not ask the assistant to create any visual or audio output. For another example, do not ask the assistant to wake you up at 5pm or set a reminder because it cannot perform any action.
3. The instructions should be in English.
4. The instructions should be 1 to 2 sentences long. Either an imperative sentence or a question is permitted.
5. You should generate an appropriate input to the instruction. The input field should contain a specific example provided for the instruction. It should involve realistic data and should not contain simple placeholders. The input should provide substantial content to make the instruction challenging but should ideally not exceed 100 words.
6. Not all instructions require input. For example, when a instruction asks about some general information, "what is the highest peak in the world", it is not necssary to provide a specific context. In this case, we simply put "<noinput>" in the input field.
7. The output should be an appropriate response to the instruction and the input. Make sure the output is less than 100 words.
List of 20 tasks:
###
1. Instruction: Is there anything I can eat for a breakfast that doesn't include eggs, yet includes protein, and has roughly 700-1000 calories?
1. Inputs: <noinput>
1. Output: Yes, you can have 1 oatmeal banana protein shake and 4 strips of bacon. The oatmeal banana protein shake may contain 1/2 cup oatmeal, 60 grams whey protein powder, 1/2 medium banana, 1tbsp flaxseed oil and 1/2 cup water, totalling about 550 calories. The 4 strips of bacon contains about 200 calories.
###
2. Instruction: Generate an appropriate subjective title for the following email:
2. Inputs: Hi [person name],I'm writing to ask you if you are happy to be a panelist of our workshop on multimodality at CVPR. The workshop will be held on June 20, 2023. \n\nBest,\n[my name]
2. Output: Invitition to be a panelist for CVPR 2023 workshop on Multimodality
###
3. Instruction:
我们可以看到,在前面这个提示模板中提供了两个种子示例,随后通过调用 OpenAI 的 GPT API 来续写新的样例数据。
随后,斯坦福的研究团队基于 LoRA 训练框架和 Llama 开源预训练模型,对这些生成增强数据进行了微调训练,得到了 Alpaca 模型,事实表明通过这种方法得到的模型,可以在指定任务上达到 SOTA 的效果。
这种成本对于小型的研究团队来说不成问题,这种用很少成本完成特定领域的大语言模型微调的方式,这给相关方向的研究人员打开了思路。
在此之后,领域大型语言模型如雨后春笋般涌现,比如 Guanaco 模型在 Alpaca 的基础上增加了多语言语料和指令任务。“小羊驼” 模型 Vicuna-13B 则是基于 LLaMA, 并使用从 ShareGPT 采集的对话数据对进行了指令微调,在特定的实验设置下,仅使用了 300 美元训练成本,就达到了与 ChatGPT 相媲美的性能水平。
总结
我们做个总结吧。
之前我们学习的提示语工程方法,这是一种通过提供示例来向模型注入新知识的方式。而从这节课开始探讨的模型工程,则是另一种向模型注入知识的方法。模型工程采用参数学习的方法,通过更新模型参数来获取新知识。
我们深入研究了数据获取方面的问题,介绍了 Self-Instruct 方法。该方法主要有四个步骤。
使用一组人工编写的指令(本例中为 175 条)来初始化任务池,并随机选择一些指令。
利用预训练的大型语言模型(如 GPT-3)来确定任务的类别。
在将回应添加到任务池之前,进行回应的收集、修剪和过滤。
这节课我们学习了 Alpaca 的数据增强方法,下节课里,我将继续带你学习它是如何用极低的成本,使用这些增强数据来微调预训练大语言模型的。
思考题
根据这节课学习的知识,你认为使用 Alpaca 增强数据微调模型的上限是什么?
使用 Alpaca 方法,为它提供红楼梦的原文,让它帮你扩充后四十回的故事内容。
恭喜完成我们第 24 次打卡学习,期待你在留言区和我交流互动。如果你觉得有收获,也欢迎你分享给你身边的朋友,邀 TA 一起讨论。