前言
此篇文章旨在通过对 OpenAI API 中的 Fine-tuning 接口的详解来帮助刚刚开始使用OpenAI API 或者准备开始使用 OpenAI API 的朋友 更深入的理解API接口包括但不限于 接口概念,接口应用,参数详解,通过对接口的深入了解,更好的应用在自己的产品中,作为作者本身也想记录这个学习过程作为自己的学习笔记,如有错误之处还请指正谢谢!
-
什么是 Fine-tuning (微调)
-
Fine-tuning 基本使用流程
-
创建微调任务时重要参数详解
-
模型微调与GPTs训练的区别
- 其他知识点
什么是 Fine-tuning (微调)
官方: 微调(Fine-Tuning)是指在一个预训练的AI模型上进行进一步训练,以便更好地适应特定的任务或领域。这种方法在使用AI模型时非常重要,因为预训练模型(如GPT-3或GPT-4)通常是在大量通用数据上进行训练的,而微调则允许我们将这些模型调整到特定的应用场景或数据集上,从而提高模型在特定任务上的性能。
比喻:想象你有一本百科全书(预训练模型),它包含了大量的通用知识。你希望这本书能更好地回答关于某个特定领域的问题,比如医学。为此,你会收集大量医学书籍和资料(特定领域的数据集),然后在这些资料的基础上对百科全书进行补充和修改(微调),使其在医学问题上的表现更加出色。
Fine-tuning 基本使用流程
import openai
import json
# 设置API密钥 (建议配置在环境变量中)
openai.api_key = 'your-api-key'
# 示例训练数据
training_data = [
{
"prompt": "房子价格为$500,000,挂牌经纪公司是XYZ Realty,联系人John Doe,联系电话123-456-7890,房屋面积为1200平方英尺。\n\n###\n\n",
"completion": "{\"价格\": \"$500,000\", \"挂牌经纪公司\": \"XYZ Realty\", \"挂牌经纪人\": \"John Doe\", \"联系方式\": \"123-456-7890\", \"房屋面积\": \"1200平方英尺\"}"
},
# 可以添加更多类似的示例...
]
# 将数据写入JSONL文件
with open("training_data.jsonl", "w") as f:
for item in training_data:
f.write(json.dumps(item) + "\n")
# 上传数据文件
response = openai.File.create(
file=open("training_data.jsonl", "rb"),
purpose='fine-tune'
)
file_id = response['id']
print(f"File ID: {file_id}")
# 创建微调任务
# 创建接口的其他超参数会在后面另做介绍
response = openai.FineTune.create(
training_file=file_id,
model="gpt-3.5-turbo"
)
fine_tune_id = response['id']
print(f"Fine-tune ID: {fine_tune_id}")
# 获取微调后的模型ID
response = openai.FineTune.retrieve(fine_tune_id)
fine_tuned_model = response['fine_tuned_model']
print(f"Fine-tuned model: {fine_tuned_model}")
# 使用微调后的模型
response = openai.Completion.create(
model=fine_tuned_model,
prompt="房子价格为$500,000,挂牌经纪公司是XYZ Realty,联系人John Doe,联系电话123-456-7890,房屋面积为1200平方英尺。\n\n###\n\n"
)
print(response.choices[0].text.strip())
创建微调任务时重要参数详解
-
batch_size(批量大小):
- 决定每次参数更新时处理的样本数量。
- 小批量(1-32):训练速度慢,计算开销大,梯度波动较大。
- 中等批量(32-128):较好的平衡点。
- 大批量(128以上):训练速度快,梯度稳定,但显存要求高。
-
learning_rate(学习率):
- 控制每次参数更新时模型的步长大小。
- 学习率过大:训练速度快,但容易发散。
- 学习率过小:训练稳定,但收敛速度慢。
- 动态学习率调整:通过学习率衰减或自适应学习率方法进一步优化。
-
num_epochs(训练轮次):
- 表示整个训练数据集被模型完整使用的次数。
- 轮次过少:欠拟合。
- 轮次过多:过拟合。
- 适当轮次:帮助模型充分学习数据中的模式。
-
validation_file(验证文件):
- 用于在训练过程中评估模型的性能,检测过拟合现象。
- 早停法(Early Stopping):监控验证损失,在验证损失未改善时提前停止训练。
下面是一个示例代码,通过分轮次训练和手动监控验证损失来实现早停法:
import openai
import time
# 设置API密钥
openai.api_key = 'your-api-key'
# 上传训练和验证数据文件
training_response = openai.File.create(
file=open("training_data.jsonl", "rb"),
purpose='fine-tune'
)
training_file_id = training_response['id']
print(f"Training File ID: {training_file_id}")
validation_response = openai.File.create(
file=open("validation_data.jsonl", "rb"),
purpose='fine-tune'
)
validation_file_id = validation_response['id']
print(f"Validation File ID: {validation_file_id}")
# 定义早停条件
patience = 2 # 允许验证损失未改善的轮次数
min_delta = 0.01 # 最小改善值
best_loss = float('inf')
epochs_no_improve = 0
# 分轮次训练
for epoch in range(10): # 假设最多训练10轮
print(f"Starting epoch {epoch + 1}")
# 创建微调任务
response = openai.FineTune.create(
training_file=training_file_id,
validation_file=validation_file_id,
model="gpt-3.5-turbo",
num_epochs=1, # 每次训练一个轮次
batch_size=32,
learning_rate_multiplier=0.1
)
fine_tune_id = response['id']
print(f"Fine-tune ID: {fine_tune_id}")
# 等待训练完成
while True:
status_response = openai.FineTune.retrieve(fine_tune_id)
status = status_response['status']
if status in ['succeeded', 'failed']:
break
print(f"Training status: {status}")
time.sleep(30) # 等待30秒后再检查状态
if status == 'failed':
print("Training failed")
break
# 获取验证损失
validation_loss = status_response['validation_loss']
print(f"Validation loss: {validation_loss}")
# 早停法检查
if validation_loss < best_loss - min_delta:
best_loss = validation_loss
epochs_no_improve = 0
else:
epochs_no_improve += 1
if epochs_no_improve >= patience:
print("Early stopping triggered")
break
print("Training complete")
模型微调与GPTs调教的区别
-
数据处理方式:
- 微调: 微调需要在大量特定领域的数据上进行进一步训练。这些数据会被模型用来调整其内部参数,从而优化特定任务的表现。
- GPTs: 你上传的知识库文件和对话规范更像是为现有模型提供额外的信息和使用指南,但并没有改变模型的内部参数。
-
训练过程:
- 微调: 微调涉及一个实际的训练过程,这个过程可能需要几分钟到几小时不等,具体取决于数据集的大小和模型的复杂性。
- GPTs: 不需要额外的训练时间,只是直接将信息和规则添加到现有模型中。
其他知识点
我在这里想用个特别的例子来解释一下 梯度。
梯度的数学定义我就不发在这里了,随处可见,我用一种直观解释,希望能帮大家更好理解梯度的概念
想象一个山峰,梯度就像是山坡的陡峭程度和方向。你站在山上的某一点,梯度告诉你哪个方向下坡最快,以及有多陡。
在大概整理一下梯度的作用
- 指导参数更新:梯度告诉我们如何调整模型参数以减少损失。
- 优化过程中的导航:在高维参数空间中,梯度引导模型朝着最优解的方向前进。
- 提高模型性能:通过梯度下降算法,模型逐步逼近损失函数的最小值,从而提高预测性能。