Phi Silica 的 LoRA 微调
您可以使用低秩自适应 (LoRA) 对 Phi Silica 模型进行微调,以增强其针对特定用例的表现。通过使用 LoRA 优化 Microsoft Windows 本地语言模型 Phi Silica,您可以获得更准确的结果。此过程包括训练 LoRA 适配器,然后在推理过程中应用它,从而提高模型的准确性。
Phi Silica 功能在中国不可用。
先决条件
- 您已经确定了一个增强 Phi Silica 响应的用例。
- 您已经选择了评估标准来决定什么是“好的响应”。
- 您已经试用了 Phi Silica API,但它们不符合您的评估标准。
训练您的适配器
要训练用于微调 Windows 11 上 Phi Silica 模型的 LoRA 适配器,必须首先生成训练过程所需的数据集。
生成用于 LoRA 适配器的数据集
要生成数据集,您需要将数据拆分为两个文件
train.json:用于训练适配器。test.json:用于在训练期间及之后评估适配器的性能。
这两个文件都必须使用 JSON 格式,其中每一行都是一个代表单个样本的独立 JSON 对象。每个样本应包含用户和助手之间交换的消息列表。
每个消息对象都需要两个字段
content:消息内容。role:"user"(用户)或"assistant"(助手),指示发送者。
请参阅以下示例
{"messages": [{"content": "Hello, how do I reset my password?", "role": "user"}, {"content": "To reset your password, go to the settings page and click 'Reset Password'.", "role": "assistant"}]}
{"messages": [{"content": "Can you help me find nearby restaurants?", "role": "user"}, {"content": "Sure! Here are some restaurants near your location: ...", "role": "assistant"}]}
{"messages": [{"content": "What is the weather like today?", "role": "user"}, {"content": "Today's forecast is sunny with a high of 25°C.", "role": "assistant"}]}
训练技巧
- 每行样本末尾无需逗号。
- 尽可能包含高质量和多样化的示例。为获得最佳结果,请在
train.json文件中收集至少几千个训练样本。 test.json文件可以更小,但应涵盖您期望模型处理的各类交互。- 创建
train.json和test.json文件,每行一个 JSON 对象,每个对象包含用户和助手之间的简短对话。数据的质量和数量将极大地影响 LoRA 适配器的有效性。
训练 LoRA 适配器
要训练 LoRA 适配器,您需要满足以下必备条件
- 拥有 Azure 订阅,并在 Azure 容器应用 (Azure Container Apps) 中有可用配额。
- 我们建议使用 A100 GPU 或更高级别的 GPU 来高效运行微调作业。
- 检查您在 Azure 门户中是否有可用配额。如果您需要帮助查找配额,请参阅查看配额。
请按照以下步骤创建工作区并启动微调作业
-
导航到 模型工具 > 微调 (Model Tools > Fine-tuning) 并选择 新建项目 (New Project)。
-
从模型目录 (Model Catalog) 中选择 "microsoft/phi-silica",然后选择 下一步 (Next)。
-
在对话框中,选择一个项目文件夹并输入项目名称。将为该项目打开一个新的 VS Code 窗口。

-
从方法 (Method) 列表中选择 "LoRA"。

-
在 数据 > 训练数据集名称 (Data > Training Dataset name) 和 测试数据集名称 (Test Dataset name) 下,选择您的
train.json和test.json文件。 -
选择 云端运行 (Run with Cloud)。

-
在对话框中,选择用于访问 Azure 订阅的 Microsoft 帐户。
-
选择帐户后,从订阅下拉菜单中选择一个资源组。
-
注意您的微调作业已成功启动并显示作业状态。
使用 刷新 (Refresh) 按钮手动更新状态。微调作业通常平均需要 45 到 60 分钟才能完成。
-
作业完成后,您可以选择 下载 (Download) 以获取新训练的 LoRA 适配器,并选择 显示指标 (Show Metrics) 以检查微调指标。

LoRA 微调建议
超参数选择
为 LoRA 微调设置的默认超参数应能提供一个合理的基准微调结果以供比较。我们已尽力找到适用于大多数用例和数据集的默认设置。
不过,如果您有需要,我们也保留了参数扫描的灵活性。
训练超参数
我们的标准参数搜索空间为
| 参数名称 | 最小值 | 最大值 | 分布 |
|---|---|---|---|
| learning_rate (学习率) | 1e-4 | 1e-2 | Log-uniform (对数均匀分布) |
| weight_decay (权重衰减) | 1e-5 | 1e-1 | Log-uniform (对数均匀分布) |
| adam_beta1 | 0.9 | 0.99 | Uniform (均匀分布) |
| adam_beta2 | 0.9 | 0.999 | Uniform (均匀分布) |
| adam_epsilon | 1e-9 | 1e-6 | Log-uniform (对数均匀分布) |
| num_warmup_steps (预热步数) | 0 | 10000 | Uniform (均匀分布) |
| lora_dropout | 0 | 0.5 | Uniform (均匀分布) |
我们还会搜索学习率调度程序,在 linear_with_warmup 或 cosine_with_warmup 中进行选择。如果 num_warmup_steps 参数设置为 0,则线性或余弦选项的效果相同。
学习率、学习率调度程序和预热步数之间是相互影响的。保持其中两个固定并改变第三个,将使您更深入地了解它们如何改变数据集训练的输出。
权重衰减和 LoRA Dropout 参数有助于控制过拟合。如果您发现适配器在从训练集到评估集的泛化效果不佳,请尝试增加这些参数的值。
adam_ 参数会影响 Adam 优化器在训练步骤中的行为。有关该优化器的更多信息,请参阅例如 PyTorch 文档。
公开的其他许多参数类似于 PEFT 库中同名的对应参数。有关这些参数的更多信息,请参阅 transformers 文档。
数据超参数
数据超参数 train_nsamples 和 test_nsamples 分别控制训练和测试所需的样本数量。使用更多的训练集样本通常是一个好主意。使用更多的测试样本会使测试指标噪声更小,但每次评估运行所需的时间会更长。
train_batch_size 和 test_batch_size 参数分别控制训练和测试每个批次使用的样本数量。通常测试可以比训练使用更大的批次,因为运行测试示例所占用的 GPU 内存比训练示例少。
train_seqlen 和 test_seqlen 参数控制训练和测试序列的长度。通常,在达到 GPU 内存限制之前,长度越长越好。默认值应该能达到一个良好的平衡。
选择系统提示词 (System Prompt)
我们发现,选择用于训练的系统提示词时,一个行之有效的策略是保持简单(1 到 2 句),同时仍鼓励模型以您想要的格式输出。我们还发现,在训练和推理时使用略有不同的系统提示词可以改善结果。
您期望的输出与基础模型之间的差异越大,系统提示词的帮助就越大。
例如,如果您进行训练只是为了稍微改变基础模型的风格,例如使用更简单的语言以吸引年轻读者,则可能根本不需要系统提示词。
但是,如果您期望的输出具有更多结构,则需要使用系统提示词引导模型达到目的。例如,如果您需要带有特定键的 JSON 表,系统提示词的第一句话可以描述模型在用通俗语言回答时应该是什么样子的。第二句话可以进一步详细说明 JSON 表格的格式。在训练时使用第一句话,而在推理时使用这两句话,可能会为您提供想要的结果。
参数
此处列出了所有可以微调的参数。如果某个参数未出现在工作流页面 UI 中,请将其手动添加到 <您的项目路径>/<模型名称>/lora/lora.yaml 中。
[
################## Basic config settings ##################
{
"groupId": "data",
"fields": [
{
"name": "system_prompt",
"type": "Optional",
"defaultValue": null,
"info": "Optional system prompt. If specified, the system prompt given here will be prepended to each example in the dataset as the system prompt when training the LoRA adapter. When running inference the same (or a very similar) system prompt should be used. Note: if a system prompt is specified in the training data, giving a system prompt here will overwrite the system prompt in the dataset.",
"label": "System prompt"
},
{
"name": "varied_seqlen",
"type": "bool",
"defaultValue": false,
"info": "Varied sequence lengths in the calibration data. If False (default), training examples will be concatenated together until they are finetune_[train/test]_seqlen tokens long. This makes memory usage more consistent and predictable. If True, each individual example will be truncated to finetune_[train/test]_seqlen tokens. This can sometimes give better training performance, but also gives unpredictable memory usage. It can cause `out of memory` errors mid training, if there are long training examples in your dataset.",
"label": "Allow varied sequence length in data"
},
{
"name": "finetune_dataset",
"type": "str",
"defaultValue": "wikitext2",
"info": "Dataset to finetune on.",
"label": "Dataset name or path"
},
{
"name": "finetune_train_nsamples",
"type": "int",
"defaultValue": 4096,
"info": "Number of samples to load from the train set for finetuning.",
"label": "Number of finetuning samples"
},
{
"name": "finetune_test_nsamples",
"type": "int",
"defaultValue": 128,
"info": "Number of samples to load from the test set for finetuning.",
"label": "Number of test samples"
},
{
"name": "finetune_train_batch_size",
"type": "int",
"defaultValue": 4,
"info": "Batch size for finetuning training.",
"label": "Training batch size"
},
{
"name": "finetune_test_batch_size",
"type": "int",
"defaultValue": 8,
"info": "Batch size for finetuning testing.",
"label": "Test batch size"
},
{
"name": "finetune_train_seqlen",
"type": "int",
"defaultValue": 2048,
"info": "Maximum sequence length for finetuning training. Longer sequences will be truncated.",
"label": "Max training sequence length"
},
{
"name": "finetune_test_seqlen",
"type": "int",
"defaultValue": 2048,
"info": "Maximum sequence length for finetuning testing. Longer sequences will be truncated.",
"label": "Max test sequence length"
}
]
},
{
"groupId": "finetuning",
"fields": [
{
"name": "early_stopping_patience",
"type": "int",
"defaultValue": 5,
"info": "Number of evaluations with no improvement after which training will be stopped.",
"label": "Early stopping patience"
},
{
"name": "epochs",
"type": "float",
"defaultValue": 1,
"info": "Number of total epochs to run.",
"label": "Epochs"
},
{
"name": "eval_steps",
"type": "int",
"defaultValue": 64,
"info": "Number of training steps to perform before each evaluation.",
"label": "Steps between evaluations"
},
{
"name": "save_steps",
"type": "int",
"defaultValue": 64,
"info": "Number of steps after which to save model checkpoint. This _must_ be a multiple of the number of steps between evaluations.",
"label": "Steps between checkpoints"
},
{
"name": "learning_rate",
"type": "float",
"defaultValue": 0.0002,
"info": "Learning rate for training.",
"label": "Learning rate"
},
{
"name": "lr_scheduler_type",
"type": "str",
"defaultValue": "linear",
"info": "Type of learning rate scheduler.",
"label": "Learning rate scheduler",
"optionValues": [
"linear",
"linear_with_warmup",
"cosine",
"cosine_with_warmup"
]
},
{
"name": "num_warmup_steps",
"type": "int",
"defaultValue": 400,
"info": "Number of warmup steps for learning rate scheduler. Only relevant for a _with_warmup scheduler.",
"label": "Scheduler warmup steps (if supported)"
}
]
}
################## Advanced config settings ##################
{
"groupId": "advanced",
"fields": [
{
"name": "seed",
"type": "int",
"defaultValue": 42,
"info": "Seed for sampling the data.",
"label": "Random seed"
},
{
"name": "evaluation_strategy",
"type": "str",
"defaultValue": "steps",
"info": "Evaluation strategy to use.",
"label": "Evaluation strategy",
"optionValues": [
"steps",
"epoch",
"no"
]
},
{
"name": "lora_dropout",
"type": "float",
"defaultValue": 0.1,
"info": "Dropout rate for LoRA.",
"label": "LoRA dropout"
},
{
"name": "adam_beta1",
"type": "float",
"defaultValue": 0.9,
"info": "Beta1 hyperparameter for Adam optimizer.",
"label": "Adam beta 1"
},
{
"name": "adam_beta2",
"type": "float",
"defaultValue": 0.95,
"info": "Beta2 hyperparameter for Adam optimizer.",
"label": "Adam beta 2"
},
{
"name": "adam_epsilon",
"type": "float",
"defaultValue": 1e-08,
"info": "Epsilon hyperparameter for Adam optimizer.",
"label": "Adam epsilon"
},
{
"name": "num_training_steps",
"type": "Optional",
"defaultValue": null,
"info": "The number of training steps there will be. If not set (recommended), this will be calculated internally.",
"label": "Number of training steps"
},
{
"name": "gradient_accumulation_steps",
"type": "int",
"defaultValue": 1,
"info": "Number of updates steps to accumulate before performing a backward/update pass.",
"label": "gradient accumulation steps"
},
{
"name": "eval_accumulation_steps",
"type": "Optional",
"defaultValue": null,
"info": "Number of predictions steps to accumulate before moving the tensors to the CPU.",
"label": "eval accumulation steps"
},
{
"name": "eval_delay",
"type": "Optional",
"defaultValue": 0,
"info": "Number of epochs or steps to wait for before the first evaluation can be performed, depending on the eval_strategy.",
"label": "eval delay"
},
{
"name": "weight_decay",
"type": "float",
"defaultValue": 0.0,
"info": "Weight decay for AdamW if we apply some.",
"label": "weight decay"
},
{
"name": "max_grad_norm",
"type": "float",
"defaultValue": 1.0,
"info": "Max gradient norm.",
"label": "max grad norm"
},
{
"name": "gradient_checkpointing",
"type": "bool",
"defaultValue": false,
"info": "If True, use gradient checkpointing to save memory at the expense of slower backward pass.",
"label": "gradient checkpointing"
}
]
}
]
修改 Azure 订阅和资源组
如果您想修改之前设置的 Azure 订阅和资源组,可以在 <您的项目路径>/model_lab.workspace.provision.config 文件中进行更新或删除。
使用 Phi Silica LoRA 适配器进行推理
Phi Silica API 是受限访问功能的一部分(请参阅 LimitedAccessFeatures 类)。有关更多信息或申请解锁令牌,请使用 LAF 访问令牌申请表。
目前仅在配备 ARM 处理器的 Copilot+ PC 上支持使用 Phi Silica LoRA 适配器进行推理。
使用 Windows AI API 进行推理:带 LoRA 适配器的 Phi Silica