VLM-R1GRPO微调, 实战训练教程(1):
https://www.dong-blog.fun/post/1961
本博客这次使用多图进行GRPO。
官方git项目:https://github.com/om-ai-lab/VLM-R1?tab=readme-ov-file
此项目更新了,支持更多功能。
git clone此项目:
git config --global http.proxy "http://127.0.0.1:10828" git config --global https.proxy "http://127.0.0.1:10828" git clone https://github.com/om-ai-lab/VLM-R1.git --depth=1
This repository supports:
单图:
json{
"id": 1,
"image": "Clevr_CoGenT_TrainA_R1/data/images/CLEVR_trainA_000001_16885.png",
"conversations": [
{"from": "human", "value": "<image>What number of purple metallic balls are there?"},
{"from": "gpt", "value": "0"}
]
}
多图:
json{
"id": 1,
"image": ["Clevr_CoGenT_TrainA_R1/data/images/CLEVR_trainA_000001_16885.png", "Clevr_CoGenT_TrainA_R1/data/images/CLEVR_trainA_000001_16886.png"],
"conversations": [
{"from": "human", "value": "<image><image>What number of purple metallic balls in total within the two images?"},
{"from": "gpt", "value": "3"}
]
}
python:e:\workcode\vlm-r1\VLM-R1\src\open-r1-multimodal\src\open_r1\grpo_jsonl.py# ... existing code ... if isinstance(item['image'], list): # if the image is a list, then it is a list of images (for multi-image input) item['image_path'] = [os.path.join(image_folder, image) for image in item['image']] del item['image'] # remove the image column so that it can be loaded later # ... existing code ...
python:e:\workcode\vlm-r1\VLM-R1\src\open-r1-multimodal\src\open_r1\grpo_jsonl.py# ... existing code ... 'prompt': [{ 'role': 'user', 'content': [ *({'type': 'image', 'text': None} for _ in range(len(example['image_path']))), {'type': 'text', 'text': question_prompt.format(Question=example['problem'])} ] }] # ... existing code ...
pythonVLMGRPOTrainer
├── 初始化阶段
│ ├── 加载基础模型 (支持LoRA和PEFT)
│ ├── 冻结视觉模块 (根据配置)
│ ├── 创建参考模型 (用于KL散度计算)
│ ├── 加载奖励模型集合 (支持多奖励函数融合)
│ └── 配置生成参数 (max_completion_length/temperature等)
│
├── 训练步骤
│ ├── 生成阶段
│ │ ├── 使用基础模型生成候选响应 (num_generations次/样本)
│ │ └── 使用vLLM加速生成 (可选)
│ │
│ ├── 奖励计算
│ │ ├── 调用所有奖励函数计算综合得分
│ │ └── 应用reward_weights加权
│ │
│ ├── 策略优化
│ │ ├── 计算策略梯度 (带epsilon裁剪)
│ │ ├── 多步迭代优化 (num_iterations次/批)
│ │ └── 同步参考模型 (TR-DPO策略)
│ │
│ └── 日志记录
│ ├── 记录(prompt, completion)样本
│ └── 监控KL散度/奖励值等指标
│
└── 特殊处理
├── DeepSpeed ZeRO-3支持
├── 梯度检查点优化
└── 多GPU分布式训练
python:e:\workcode\vlm-r1\VLM-R1\src\open-r1-multimodal\src\open_r1\trainer\grpo_trainer.py# 生成阶段核心逻辑(简化) def training_step(self, model, inputs): # 多步迭代优化 for _ in range(self.num_iterations): # 生成候选响应 with torch.no_grad(): outputs = model.generate( inputs, generation_config=self.generation_config, num_return_sequences=self.num_generations ) # 计算奖励值 rewards = [] for reward_func in self.reward_funcs: if isinstance(reward_func, PreTrainedModel): reward_values = reward_func(outputs).logits else: # 自定义奖励函数 reward_values = reward_func(inputs["prompt"], outputs) rewards.append(reward_values) total_reward = torch.stack(rewards).sum(0) # 策略梯度计算 policy_logits = model(outputs, labels=outputs).logits ref_logits = self.ref_model(outputs, labels=outputs).logits # 带裁剪的梯度更新 ratio = (policy_logits - ref_logits).exp() clipped_ratio = torch.clamp(ratio, 1-self.epsilon, 1+self.epsilon) loss = -torch.min(ratio * total_reward, clipped_ratio * total_reward).mean() # 梯度累积 loss = loss / self.args.gradient_accumulation_steps self.accelerator.backward(loss) # TR-DPO模型同步 if self.global_step % self.ref_model_sync_steps == 0: self._sync_ref_model() # 参考模型同步逻辑 def _sync_ref_model(self): # 指数移动平均更新 alpha = self.args.ref_model_mixup_alpha for param, ref_param in zip(self.model.parameters(), self.ref_model.parameters()): ref_param.data = alpha * param.data + (1 - alpha) * ref_param.data
x05生成训练数据集代码.py
pythonimport os
import json
from pathlib import Path
def generate_jsonl_dataset():
# 1. 读取prompt2.txt里的文件内容
with open('prompt2.txt', 'r', encoding='utf-8') as f:
prefix_str = f.read().strip()
# 基础路径
base_path = "/data/xiedong/VLM-train-project/tasks-json-ui-doctor"
# 输出文件
output_file = "ui_doctor_dataset.jsonl"
# 获取所有子目录并按数字排序
subdirs = [d for d in os.listdir(base_path) if os.path.isdir(os.path.join(base_path, d))]
# 过滤出纯数字的子目录并按数字大小排序
numeric_subdirs = sorted(
[d for d in subdirs if d.isdigit()],
key=lambda x: int(x)
)
sample_id = 1
with open(output_file, 'w', encoding='utf-8') as out_f:
# 遍历每个子目录(已排序)
for dir_name in numeric_subdirs:
dir_path = os.path.join(base_path, dir_name)
# 获取当前目录下的所有step_*.json文件并按数字排序
json_files = sorted(
[f for f in os.listdir(dir_path) if f.startswith('step_') and f.endswith('.json')],
key=lambda x: int(x.split('_')[1].split('.')[0])
)
# 遍历排序后的json文件
for file_name in json_files:
json_path = os.path.join(dir_path, file_name)
# 读取json文件
with open(json_path, 'r', encoding='utf-8') as json_f:
data = json.load(json_f)
# 处理input和output字段
input_data = data['input']
output_data = data['output']
# 收集图片路径
image_paths = []
# 处理screen_path1
if 'screen_path1' in input_data and input_data['screen_path1']:
img_path = os.path.join(dir_name, input_data['screen_path1'])
image_paths.append(img_path)
# 处理screen_path2
if 'screen_path2' in input_data and input_data['screen_path2']:
img_path = os.path.join(dir_name, input_data['screen_path2'])
image_paths.append(img_path)
# 构建conversations
conversations = [
{
"from": "human",
"value": prefix_str + json.dumps(input_data, ensure_ascii=False)
},
{
"from": "gpt",
"value": json.dumps(output_data, ensure_ascii=False)
}
]
# 构建最终样本
sample = {
"id": sample_id,
"image": image_paths,
"conversations": conversations
}
# 写入jsonl文件
out_f.write(json.dumps(sample, ensure_ascii=False) + '\n')
sample_id += 1
print(f"数据集已生成,共{sample_id-1}个样本,保存到{output_file}")
if __name__ == "__main__":
generate_jsonl_dataset()
一个json是这个样子:
json==================================================
完整的JSON结构:
==================================================
{
"id": 1,
"image": [
"43688/43688_2.jpg",
"43688/43688_3.jpg"
],
"conversations": [
{
"from": "human",
"value": "# Role: 手机任务执行专家\n\n## Profile\n- author: LangGPT\n- version: 1.0\n- language: 中英文\n- description: 你是一个手机任务执行专家,可以根据UI图和任务提示,输出具体的操作动作\n\n## Skills\n- 根据UI图识别出当前所在UI界面的信息\n- 为了完成任务,需要输出具体动作\n- 分析任务描述,提供精确的执行步骤\n- 精通不同类型的动作空间,并能生成相应的操作指令\n\n## Background\n在手机任务执行中,AI需要根据任务描述、UI图以及历史操作,确定精确的动作,并给出相应的操作参数。\n下面这个json是一个输入示例:\n{\n \"task_content\": \"在书架中找到剑来,前往内容页,使用章节下载功能,先选择第5章,第7章,再选择第10章进行下载。\",\n \"task_path\": {\n \"1\": \"打开APP\",\n \"2\": \"点击剑来\",\n \"3\": \"点击小说界面\",\n \"4\": \"点击订阅\",\n \"5\": \"点击继续订阅\",\n \"6\": \"等待\",\n \"7\": \"点击自定义\",\n \"8\": \"点击第5章 道破\",\n \"9\": \"点击第7章 碗水\",\n \"10\": \"等待\",\n \"11\": \"点击第10章 食牛之气\",\n \"12\": \"点击下载\",\n \"13\": \"等待\",\n \"14\": \"等待\"\n },\n \"screen_path1\": \"9953_0.jpg\",\n \"screen_path2\": \"9953_1.jpg\",\n \"history_path_all\": [\n \"打开APP\"\n ],\n \"app_name\": \"起点读书\",\n \"action_type_list\": {\n \"open_app\": \"打开APP\",\n \"click\": \"点击\",\n \"long_click\": \"长按\",\n \"type\": \"输入\",\n \"swipe\": \"滑动\",\n \"task_completed\": \"任务完成\",\n \"task_impossible\": \"任务无法完成\",\n \"inquiry\": \"反问\",\n \"wait\": \"等待\",\n \"back\": \"回退\"\n }\n}\n输入的json中的字段的含义是:\n- task_content 当前任务的总体描述\n- task_path 当前任务所需要的执行步骤\n- screen_path1 上次步骤中的手机UI图,真实情况下这是一张图而不是路径名\n- screen_path2 这次步骤中的手机UI图,真实情况下这是一张图而不是路径名\n- history_path_all 之前执行过的执行步骤\n- app_name 当前操作的APP名称\n- action_type_list 允许的动作空间的类型\n\n\n\n## 动作空间\n\n你的输出是此时应该进行的执行步骤,使用动作空间里的动作表达,下面是动作空间的所有允许操作:\n\n- open_app 打开APP,这代表打开微信:\n\"action_parameter\": {\n \"open_app\": \"微信\"\n}\n\n- click 点击区域对应边界框,这代表点击这个框\"37,378,227,633\"里面的区域:\n\"action_parameter\": {\n \"click\": \"37,378,227,633\"\n}\n\n- long_click 长按区域对应边界框,这代表长按这个框\"763,2183,1151,2706\"里面的区域:\n\"action_parameter\": {\n \"long_click\": \"763,2183,1151,2706\"\n}\n\n- type 输入内容,这代表输入\"无锡\"\n\"action_parameter\": {\n \"type\": \"无锡\"\n}\n\n• swipe 滑动区域,这代表从坐标\"158,1557\"滑动到\"122,1253\":\n\"action_parameter\": {\n \"swipe\": \"158,1557,122,1253\"\n}\n\n• task_completed 任务完成,这代表任务已完成并返回描述信息:\n\"action_parameter\": {\n \"task_completed\": \"任务已完成,已在视频号中搜索并浏览了与无锡相关的视频。视频内容介绍了无锡的城市风貌和地标建筑。\"\n}\n\n• inquiry 反问,这代表返回反问内容和候选列表:\n\"action_parameter\": {\n \"inquiry\": \"{\\n \\\"Question\\\": \\\"搜索笑脸后有多个表情包,请问您想发送哪一个?\\\",\\n \\\"CandidatesList\\\": \\\"['黄色大笑脸', '手绘风格笑脸', '红晕笑脸', '黄色微笑脸', '小笑脸', '手指笑脸', '捂脸笑脸', '狗狗笑脸', '向日葵笑脸', '简单线条笑脸', '气到变形笑脸', '太阳笑脸', '躺着的笑脸', '狡黠笑脸']\\\",\\n \\\"PicDescribe\\\": \\\"聊天界面中显示了表情搜索结果,包含多个笑脸表情包。\\\",\\n \\\"AnswerIndex\\\": 0\\n}\"\n}\n\n• wait 等待,这代表等待:\n\"action_parameter\": {\n \"wait\": \"\"\n}\n\n• back 回退,这代表回退:\n\"action_parameter\": {\n \"back\": \"\"\n}\n\n## Goals\n根据任务描述、UI图和历史执行步骤,生成准确的手机操作动作。\n\n## OutputFormat\n{\n \"action_type\": \"{动作类型}\",\n \"action_parameter\": {动作参数},\n \"action_description\": \"{动作描述}\"\n}\n这是一个输出例子,输出的json需要有字段action_type、action_parameter、action_description\n{\n \"action_type\": \"click\",\n \"action_parameter\": {\n \"click\": \"49,721,1368,1008\"\n },\n \"action_description\": \"点击剑来\"\n}\n\n## Rules\n1. 根据输入的任务内容和UI图,生成合适的手机操作。\n2. 动作类型和参数需要与实际手机操作的UI区域对应。\n3. 输出需要是json字符串,而且是有效的动作表达。\n\n## Workflows\n1. 收集并分析任务描述、UI图及历史步骤。\n2. 根据UI图识别当前步骤的具体位置和操作类型。\n3. 生成与任务相关的动作空间,并匹配合适的动作。\n4. 输出符合要求的手机操作动作,需要是json字符串表达格式。\n\n## 开始任务\n\n请根据以下的任务描述、UI图以及历史操作,确定精确的动作,输出相应的操作参数:{\"task_content\": \"打开淘宝 app。点击屏幕底部的 '购物车' 图标。浏览购物车中的商品,找到你喜欢的商品并点击进入商品详情页。点击商品店铺中的 '关注' 按钮。\", \"task_path\": {\"1\": \"打开APP\", \"2\": \"点击底部购物车\", \"3\": \"点击商品金丝楠木书签定制高端送礼\", \"4\": \"等待\", \"5\": \"点击店铺\", \"6\": \"点击关注\", \"7\": \"点击X按钮\", \"8\": \"点击UIAgent标注辅助工具\"}, \"screen_path1\": \"<image>\", \"screen_path2\": \"<image>\", \"history_path_all\": [\"打开APP\", \"点击底部购物车\", \"点击商品金丝楠木书签定制高端送礼\"], \"app_name\": \"淘宝\", \"action_type_list\": {\"open_app\": \"打开APP\", \"click\": \"点击\", \"long_click\": \"长按\", \"type\": \"输入\", \"swipe\": \"滑动\", \"task_completed\": \"任务完成\", \"task_impossible\": \"任务无法完成\", \"inquiry\": \"反问\", \"wait\": \"等待\", \"back\": \"回退\"}}"
},
{
"from": "gpt",
"value": "{\"action_type\": \"wait\", \"action_parameter\": {\"wait\": \"\"}, \"action_description\": \"等待\"}"
}
]
}
==================================================
解析conversations中的value字段:
==================================================
对话 1 (human):
----------------------------------------
(原始字符串内容):
# Role: 手机任务执行专家
## Profile
- author: LangGPT
- version: 1.0
- language: 中英文
- description: 你是一个手机任务执行专家,可以根据UI图和任务提示,输出具体的操作动作
## Skills
- 根据UI图识别出当前所在UI界面的信息
- 为了完成任务,需要输出具体动作
- 分析任务描述,提供精确的执行步骤
- 精通不同类型的动作空间,并能生成相应的操作指令
## Background
在手机任务执行中,AI需要根据任务描述、UI图以及历史操作,确定精确的动作,并给出相应的操作参数。
下面这个json是一个输入示例:
{
"task_content": "在书架中找到剑来,前往内容页,使用章节下载功能,先选择第5章,第7章,再选择第10章进行下载。",
"task_path": {
"1": "打开APP",
"2": "点击剑来",
"3": "点击小说界面",
"4": "点击订阅",
"5": "点击继续订阅",
"6": "等待",
"7": "点击自定义",
"8": "点击第5章 道破",
"9": "点击第7章 碗水",
"10": "等待",
"11": "点击第10章 食牛之气",
"12": "点击下载",
"13": "等待",
"14": "等待"
},
"screen_path1": "9953_0.jpg",
"screen_path2": "9953_1.jpg",
"history_path_all": [
"打开APP"
],
"app_name": "起点读书",
"action_type_list": {
"open_app": "打开APP",
"click": "点击",
"long_click": "长按",
"type": "输入",
"swipe": "滑动",
"task_completed": "任务完成",
"task_impossible": "任务无法完成",
"inquiry": "反问",
"wait": "等待",
"back": "回退"
}
}
输入的json中的字段的含义是:
- task_content 当前任务的总体描述
- task_path 当前任务所需要的执行步骤
- screen_path1 上次步骤中的手机UI图,真实情况下这是一张图而不是路径名
- screen_path2 这次步骤中的手机UI图,真实情况下这是一张图而不是路径名
- history_path_all 之前执行过的执行步骤
- app_name 当前操作的APP名称
- action_type_list 允许的动作空间的类型
## 动作空间
你的输出是此时应该进行的执行步骤,使用动作空间里的动作表达,下面是动作空间的所有允许操作:
- open_app 打开APP,这代表打开微信:
"action_parameter": {
"open_app": "微信"
}
- click 点击区域对应边界框,这代表点击这个框"37,378,227,633"里面的区域:
"action_parameter": {
"click": "37,378,227,633"
}
- long_click 长按区域对应边界框,这代表长按这个框"763,2183,1151,2706"里面的区域:
"action_parameter": {
"long_click": "763,2183,1151,2706"
}
- type 输入内容,这代表输入"无锡"
"action_parameter": {
"type": "无锡"
}
• swipe 滑动区域,这代表从坐标"158,1557"滑动到"122,1253":
"action_parameter": {
"swipe": "158,1557,122,1253"
}
• task_completed 任务完成,这代表任务已完成并返回描述信息:
"action_parameter": {
"task_completed": "任务已完成,已在视频号中搜索并浏览了与无锡相关的视频。视频内容介绍了无锡的城市风貌和地标建筑。"
}
• inquiry 反问,这代表返回反问内容和候选列表:
"action_parameter": {
"inquiry": "{\n \"Question\": \"搜索笑脸后有多个表情包,请问您想发送哪一个?\",\n \"CandidatesList\": \"['黄色大笑脸', '手绘风格笑脸', '红晕笑脸', '黄色微笑脸', '小笑脸', '手指笑脸', '捂脸笑脸', '狗狗笑脸', '向日葵笑脸', '简单线条笑脸', '气到变形笑脸', '太阳笑脸', '躺着的笑脸', '狡黠笑脸']\",\n \"PicDescribe\": \"聊天界面中显示了表情搜索结果,包含多个笑脸表情包。\",\n \"AnswerIndex\": 0\n}"
}
• wait 等待,这代表等待:
"action_parameter": {
"wait": ""
}
• back 回退,这代表回退:
"action_parameter": {
"back": ""
}
## Goals
根据任务描述、UI图和历史执行步骤,生成准确的手机操作动作。
## OutputFormat
{
"action_type": "{动作类型}",
"action_parameter": {动作参数},
"action_description": "{动作描述}"
}
这是一个输出例子,输出的json需要有字段action_type、action_parameter、action_description
{
"action_type": "click",
"action_parameter": {
"click": "49,721,1368,1008"
},
"action_description": "点击剑来"
}
## Rules
1. 根据输入的任务内容和UI图,生成合适的手机操作。
2. 动作类型和参数需要与实际手机操作的UI区域对应。
3. 输出需要是json字符串,而且是有效的动作表达。
## Workflows
1. 收集并分析任务描述、UI图及历史步骤。
2. 根据UI图识别当前步骤的具体位置和操作类型。
3. 生成与任务相关的动作空间,并匹配合适的动作。
4. 输出符合要求的手机操作动作,需要是json字符串表达格式。
## 开始任务
请根据以下的任务描述、UI图以及历史操作,确定精确的动作,输出相应的操作参数:
{"task_content": "打开淘宝 app。点击屏幕底部的 '购物车' 图标。浏览购物车中的商品,找到你喜欢的商品并点击进入商品详情页。点击商品店铺中的 '关注' 按钮。", "task_path": {"1": "打开APP", "2": "点击底部购物车", "3": "点击商品金丝楠木书签定制高端送礼", "4": "等待", "5": "点击店铺", "6": "点击关注", "7": "点击X按钮", "8": "点击UIAgent标注辅助工具"}, "screen_path1": "<image>", "screen_path2": "<image>", "history_path_all": ["打开APP", "点击底部购物车", "点击商品金丝楠木书签定制高端送礼"], "app_name": "淘宝", "action_type_list": {"open_app": "打开APP", "click": "点击", "long_click": "长按", "type": "输入", "swipe": "滑动", "task_completed": "任务完成", "task_impossible": "任务无法完成", "inquiry": "反问", "wait": "等待", "back": "回退"}}
对话 2 (gpt):
----------------------------------------
(JSON格式内容):docker run -it --gpus '"device=1,2,3"' \
--shm-size=64g \
-v ./tasks-json-ui-doctor:/tasks-json-ui-doctor \
-v ./ui_doctor_dataset.jsonl:/datasets/ui_doctor_dataset.jsonl \
-v ./VLM-R1:/VLM-R1 \
--net host \
kevinchina/deeplearning:2.5.1-cuda12.4-cudnn9-devel-vlmr1 bash
{
"action_type": "wait",
"action_parameter": {
"wait": ""
},
"action_description": "等待"
}
bashdocker build -f Dockerfile -t kevinchina/deeplearning:2.5.1-cuda12.4-cudnn9-devel-vlmr1-0401 . 或者: docker build --network=host --build-arg http_proxy=http://101.136.19.26:10828 --build-arg https_proxy=http://101.136.19.26:10828 -f Dockerfile -t kevinchina/deeplearning:2.5.1-cuda12.4-cudnn9-devel-vlmr1-0401 .
安装一些包:
pip install babel python-Levenshtein matplotlib pycocotools
bashdocker commit 810854b5d4b4 kevinchina/deeplearning:2.5.1-cuda12.4-cudnn9-devel-vlmr1-0401-package
启动容器:
bashcd /data/xiedong/VLM-train-project
docker run -it --gpus '"device=1,2,3,4,5"' \
--shm-size=64g \
-v ./tasks-json-ui-doctor:/tasks-json-ui-doctor \
-v ./ui_doctor_dataset.jsonl:/datasets/ui_doctor_dataset.jsonl \
-v ./Qwen2.5-VL-7B-Instruct:/Qwen2.5-VL-7B-Instruct \
--net host \
kevinchina/deeplearning:2.5.1-cuda12.4-cudnn9-devel-vlmr1-0401-package-rdma bash
在容器中编辑启动脚本:
bashcd /workspace
vim src/open-r1-multimodal/run_scripts/run_grpo_gui.sh
修改 --nproc_per_node 指定显卡,
修改 --model_name_or_path 指定模型文件,
修改 --image_folders 指定图片路径前缀,
修改 --data_file_paths 指定训练数据,
修改 --max_prompt_length 模型生成的最大长度,
修改 --num_train_epochs 指定训练轮数,
修改 --per_device_train_batch_size 指定batch。
-- num_generations 表示对每个提示(prompt)生成的不同回复数量,全局批次大小(num_processes * per_device_batch_size)必须能被这个值整除
最终我的:
bashcd src/open-r1-multimodal
export DEBUG_MODE="true"
# export CUDA_VISIBLE_DEVICES=4,5,6,7
RUN_NAME="Qwen2.5-VL-3B-GRPO-GUI_multi-image"
export LOG_PATH="./debug_log_$RUN_NAME.txt"
torchrun --nproc_per_node="5" \
--nnodes="1" \
--node_rank="0" \
--master_addr="127.0.0.1" \
--master_port="22346" \
src/open_r1/grpo_jsonl.py \
--deepspeed local_scripts/zero3.json \
--output_dir output/$RUN_NAME \
--model_name_or_path /Qwen2.5-VL-7B-Instruct \
--dataset_name none \
--image_folders /tasks-json-ui-doctor \
--data_file_paths /datasets/ui_doctor_dataset.jsonl \
--freeze_vision_modules true \
--max_prompt_length 4096 \
--num_generations 5 \
--per_device_train_batch_size 1 \
--gradient_accumulation_steps 1 \
--logging_steps 1 \
--bf16 \
--torch_dtype bfloat16 \
--data_seed 42 \
--report_to none \
--gradient_checkpointing true \
--attn_implementation flash_attention_2 \
--num_train_epochs 1 \
--run_name $RUN_NAME \
--save_steps 100 \
--save_only_model true
运行训练:
bashbash src/open-r1-multimodal/run_scripts/run_grpo_gui.sh
训练日志:
{'loss': 0.0, 'grad_norm': 7.915220396365858, 'learning_rate': 9.99982068141064e-07, 'completion_length': 138.40000915527344, 'rewards/accuracy_reward': 0.7174350023269653, 'rewards/format_reward': 1.0, 'reward': 1.7174350023269653, 'reward_std': 0.0657886490225792, 'kl': 0.0004730224609375, 'clip_ratio': 0.0, 'epoch': 0.0} 0%| | 3/167300 [00:57<871:05:01, 18.74s/it]
要执行一下命令,安装libibverbs1才能使用rdma网卡,加速训练
sudo apt-get update sudo apt-get install libibverbs1 -y
docker commit a04ef2131657 kevinchina/deeplearning:2.5.1-cuda12.4-cudnn9-devel-vlmr1-0401-package-rdma
数据集挂载到 /tasks-json-ui-doctor
子目录:tasks_json/
子目录:ui_doctor_dataset.jsonl
bashcd src/open-r1-multimodal
export DEBUG_MODE="true"
RUN_NAME="Qwen2.5-VL-7B-GRPO-GUI_multi-image"
export LOG_PATH="./debug_log_$RUN_NAME.txt"
torchrun --nproc_per_node=8 \
--nnodes=2 \
--node_rank=${RANK} \
--master_addr=${MASTER_ADDR} \
--master_port=${MASTER_PORT} \
src/open_r1/grpo_jsonl.py \
--deepspeed local_scripts/zero3.json \
--output_dir /output_qwen25vl7b_xd/$RUN_NAME \
--model_name_or_path /Qwen2.5-VL-7B-Instruct \
--dataset_name none \
--image_folders /tasks-json-ui-doctor/tasks_json \
--data_file_paths /tasks-json-ui-doctor/ui_doctor_dataset.jsonl \
--freeze_vision_modules true \
--max_prompt_length 4096 \
--num_generations 8 \
--per_device_train_batch_size 1 \
--gradient_accumulation_steps 1 \
--logging_steps 1 \
--bf16 \
--torch_dtype bfloat16 \
--data_seed 42 \
--report_to "tensorboard" \
--logging_dir "/mnt/clusterds123412sfdasd"
--gradient_checkpointing true \
--attn_implementation flash_attention_2 \
--num_train_epochs 2 \
--run_name $RUN_NAME \
--save_steps 100 \
--save_only_model true
环境变量:
CUDA_DEVICE_MAX_CONNECTIONS 1
NCCL_DEBUG INFO
NCCL_IB_DISABLE 0
本文作者:Dong
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC。本作品采用《知识共享署名-非商业性使用 4.0 国际许可协议》进行许可。您可以在非商业用途下自由转载和修改,但必须注明出处并提供原作者链接。 许可协议。转载请注明出处!