{
"cells": [
{
"cell_type": "code",
"execution_count": 5,
"id": "b1fad05e",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"test num: 4000\n",
"train num: 48008\n"
]
}
],
"source": [
"import json\n",
"import random\n",
"\n",
"random.seed(2026)\n",
"\n",
"\n",
"tvb_path = '/data4/runqing/dLLM-RL/data/reversal_data/video_reverse_rl_data_option_reversal.json'\n",
"videor1_path = '/data4/runqing/dLLM-RL/data/reversal_data/Video-R1-Reversal-QA.json'\n",
"\n",
"with open(tvb_path, 'r') as f_tvb, \\\n",
" open(videor1_path, 'r') as f_r1:\n",
" tvb_data = json.load(f_tvb)\n",
" r1_data = json.load(f_r1)\n",
"\n",
"random.shuffle(tvb_data)\n",
"random.shuffle(r1_data)\n",
"\n",
"act_test_num = 0\n",
"ego_test_num = 0\n",
"scene_test_num = 0\n",
"\n",
"data_id = 0\n",
"\n",
"train_data = []\n",
"test_data = []\n",
"for idx, data in enumerate(tvb_data):\n",
" fwd_data = {\n",
" \"data_id\": data_id,\n",
" \"reversal_type\": 'forward',\n",
" \"prompt\": data['forward']['question'],\n",
" \"options\": data['forward']['options'],\n",
" \"response\": data['forward']['answer'],\n",
" \"video_abs_path\": data['video_abs_path'],\n",
" \"task_type\": data['task_type']\n",
" }\n",
" bwd_data = {\n",
" \"data_id\": data_id,\n",
" \"reversal_type\": 'backward',\n",
" \"prompt\": data['backward']['question'],\n",
" \"options\": data['backward']['options'],\n",
" \"response\": data['backward']['answer'],\n",
" \"video_abs_path\": data['video_abs_path'],\n",
" \"task_type\": data['task_type']\n",
" }\n",
" if data['task_type'] == \"Action Sequence\" and act_test_num < 100:\n",
" # if act_test_num < 100:\n",
" test_data.append(fwd_data)\n",
" test_data.append(bwd_data)\n",
" act_test_num += 1\n",
" data_id += 1\n",
" elif data['task_type'] == \"Egocentric Sequence\" and ego_test_num < 350:\n",
" # if ego_test_num < 100:\n",
" test_data.append(fwd_data)\n",
" test_data.append(bwd_data)\n",
" ego_test_num += 1\n",
" data_id += 1\n",
" elif data['task_type'] == \"Scene Transition\" and scene_test_num < 50:\n",
" # if ego_test_num < 100:\n",
" test_data.append(fwd_data)\n",
" test_data.append(bwd_data)\n",
" scene_test_num += 1\n",
" data_id += 1\n",
" else:\n",
" train_data.append(fwd_data)\n",
" train_data.append(bwd_data)\n",
" data_id += 1\n",
"\n",
"r1_test_num = 0\n",
"\n",
"for idx, data in enumerate(r1_data):\n",
" fwd_answer = 'no answer'\n",
" bwd_answer = 'no answer'\n",
" try:\n",
" for op in data['forward_data']['options']:\n",
" if data['forward_data']['solution'] in op:\n",
" fwd_answer = op\n",
"\n",
" for op in data['backward_data']['options']:\n",
" if data['backward_data']['solution'] in op:\n",
" bwd_answer = op\n",
" except:\n",
" pass\n",
"\n",
" fwd_data = {\n",
" \"data_id\": data_id,\n",
" \"reversal_type\": 'forward',\n",
" \"prompt\": data['forward_data']['problem'],\n",
" \"options\": data['forward_data']['options'],\n",
" \"response\": fwd_answer,\n",
" \"video_abs_path\": '/data4/runqing/hf/Video-R1-data/' + data['path'].split('./')[-1],\n",
" \"task_type\": 'video-r1'\n",
" }\n",
" bwd_data = {\n",
" \"data_id\": data_id,\n",
" \"reversal_type\": 'backward',\n",
" \"prompt\": data['backward_data']['problem'],\n",
" \"options\": data['backward_data']['options'],\n",
" \"response\": bwd_answer,\n",
" \"video_abs_path\": '/data4/runqing/hf/Video-R1-data/' + data['path'].split('./')[-1],\n",
" \"task_type\": 'video-r1'\n",
" }\n",
"\n",
" if r1_test_num < 1500:\n",
" test_data.append(fwd_data)\n",
" test_data.append(bwd_data)\n",
" r1_test_num += 1\n",
" data_id += 1\n",
" else:\n",
" train_data.append(fwd_data)\n",
" train_data.append(bwd_data)\n",
" data_id += 1\n",
"\n",
"print('test num:', len(test_data))\n",
"print('train num:', len(train_data))\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "fac1cf9e",
"metadata": {},
"outputs": [],
"source": [
"test_path = '/data4/runqing/dLLM-RL/data/video_reversal_sft_test.json'\n",
"train_path = '/data4/runqing/dLLM-RL/data/video_reversal_sft_train.json'\n",
"with open(train_path, 'w') as f_train, \\\n",
" open(test_path, 'w') as f_test:\n",
" json.dump(train_data[:20000], f_train, indent=4, ensure_ascii=False)\n",
" json.dump(test_data, f_test, indent=4, ensure_ascii=False)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e38521b3",
"metadata": {},
"outputs": [],
"source": [
"{\n",
" \"problem_id\": 1,\n",
" \"video_abs_path\": \"/data4/runqing/hf/TVBench/video/action_sequence/6H78U.mp4\",\n",
" \"task_type\": \"Action Sequence\",\n",
" \"forward\": {\n",
" \"question\": \"What did the person do after \\\"Put down the blanket\\\"\",\n",
" \"options\": [\n",
" \"A. Turned on the TV\",\n",
" \"B. Washed the dishes\",\n",
" \"C. Hung up the clothes\",\n",
" \"D. Took the towel\"\n",
" ],\n",
" \"answer\": \"D. Took the towel\"\n",
" },\n",
" \"backward\": {\n",
" \"question\": \"What did the person do before \\\"Took the towel\\\"\",\n",
" \"options\": [\n",
" \"A. Wrote a note\",\n",
" \"B. Washed hands\",\n",
" \"C. Put down the blanket\",\n",
" \"D. Grabbed a pillow\"\n",
" ],\n",
" \"answer\": \"C. Put down the blanket\"\n",
" }\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "157ec86d",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"act_test_num 200\n",
"ego_test_num 700\n",
"scene_test_num 100\n",
"r1_test_num 1000\n",
"train num: 2000\n"
]
}
],
"source": [
"import json\n",
"import random\n",
"\n",
"random.seed(2026)\n",
"\n",
"\n",
"sft_train_path = '/data4/runqing/dLLM-RL/data/video_reversal_sft_train.json'\n",
"# videor1_path = '/data4/runqing/dLLM-RL/data/reversal_data/Video-R1-Reversal-QA.json'\n",
"\n",
"with open(sft_train_path, 'r') as f_sft:\n",
" sft_data = json.load(f_sft)\n",
"\n",
"# random.shuffle(sft_data)\n",
"\n",
"act_test_num = 0\n",
"ego_test_num = 0\n",
"scene_test_num = 0\n",
"r1_test_num = 0\n",
"\n",
"data_id = 0\n",
"\n",
"train_data = []\n",
"test_data = []\n",
"for idx, data in enumerate(sft_data):\n",
" if data['task_type'] == \"Action Sequence\" and act_test_num < 200:\n",
" # if act_test_num < 100:\n",
" train_data.append(data)\n",
" act_test_num += 1\n",
" data_id += 1\n",
" elif data['task_type'] == \"Egocentric Sequence\" and ego_test_num < 700:\n",
" # if ego_test_num < 100:\n",
" train_data.append(data)\n",
"\n",
" ego_test_num += 1\n",
" data_id += 1\n",
" elif data['task_type'] == \"Scene Transition\" and scene_test_num < 100:\n",
" # if ego_test_num < 100:\n",
" train_data.append(data)\n",
"\n",
" scene_test_num += 1\n",
" data_id += 1\n",
" elif data['task_type'] == \"video-r1\" and r1_test_num < 1000:\n",
" train_data.append(data)\n",
" r1_test_num += 1\n",
" data_id += 1\n",
"\n",
"print('act_test_num', act_test_num)\n",
"print('ego_test_num', ego_test_num)\n",
"print('scene_test_num', scene_test_num)\n",
"print('r1_test_num', r1_test_num)\n",
"\n",
"# print('test num:', len(test_data))\n",
"print('train num:', len(train_data))\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "a86408a4",
"metadata": {},
"outputs": [],
"source": [
"# test_path = '/data4/runqing/dLLM-RL/data/video_reversal_sft_test.json'\n",
"rl_train_path = '/data4/runqing/dLLM-RL/data/video_reversal_rl_train.json'\n",
"with open(rl_train_path, 'w') as f_train:\n",
" json.dump(train_data, f_train, indent=4, ensure_ascii=False)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "0920ebb7",
"metadata": {},
"outputs": [],
"source": [
"rl_train_100_path = '/data4/runqing/dLLM-RL/data/video_reversal_rl_train_100.json'\n",
"with open(rl_train_100_path, 'w') as f_train:\n",
" json.dump(train_data[:100], f_train, indent=4, ensure_ascii=False)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c3bed4b0",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": 7,
"id": "2960a3bb",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Total samples: 20000\n",
"Unique videos to check: 7542\n",
"Starting integrity check with 16 workers...\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"100%|██████████| 7542/7542 [03:53<00:00, 32.30it/s]\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"==============================\n",
"Scan Complete!\n",
"Healthy samples saved: 19512\n",
"Removed samples: 488\n",
"Corrupted unique videos: 154\n",
"Detailed log saved to corrupted_videos.log\n",
"==============================\n"
]
}
],
"source": [
"import json\n",
"import subprocess\n",
"import os\n",
"from concurrent.futures import ProcessPoolExecutor\n",
"from tqdm import tqdm\n",
"\n",
"# --- 配置区 ---\n",
"JSON_PATH = \"/data4/runqing/dLLM-RL/data/video_reversal_sft_train.json\"\n",
"OUTPUT_CLEAN_JSON = \"/data4/runqing/dLLM-RL/data/video_reversal_sft_train_cleaned.json\"\n",
"LOG_FILE = \"corrupted_videos.log\"\n",
"NUM_WORKERS = 16 # 根据你的 CPU 核心数调整\n",
"\n",
"def check_video_integrity(video_path):\n",
" \"\"\"\n",
" 使用 ffmpeg 检查视频完整性\n",
" 返回: (video_path, is_ok, error_msg)\n",
" \"\"\"\n",
" if not os.path.exists(video_path):\n",
" return video_path, False, \"File not found\"\n",
" \n",
" # ffmpeg 命令解释:\n",
" # -v error: 只显示错误信息\n",
" # -i: 输入文件\n",
" # -map 0:v:0: 只检查第一个视频流(忽略音频错误)\n",
" # -f null -: 解码但不保存输出,直接丢弃\n",
" cmd = [\n",
" 'ffmpeg', '-v', 'error', '-i', video_path, \n",
" '-map', '0:v:0', '-f', 'null', '-'\n",
" ]\n",
" \n",
" try:\n",
" # 执行命令,捕获 stderr\n",
" result = subprocess.run(cmd, capture_output=True, text=True, timeout=60)\n",
" if result.returncode == 0:\n",
" # 如果 returncode 为 0 且 stderr 为空,通常认为视频是健康的\n",
" if not result.stderr.strip():\n",
" return video_path, True, None\n",
" else:\n",
" # 即使返回 0,如果有 stderr,可能存在 mmco 等警告/错误\n",
" return video_path, False, result.stderr.strip().split('\\n')[0]\n",
" else:\n",
" return video_path, False, result.stderr.strip().split('\\n')[0]\n",
" except subprocess.TimeoutExpired:\n",
" return video_path, False, \"Timeout during decoding\"\n",
" except Exception as e:\n",
" return video_path, False, str(e)\n",
"\n",
"def main():\n",
" with open(JSON_PATH, 'r', encoding='utf-8') as f:\n",
" data = json.load(f)\n",
"\n",
" # 1. 提取去重后的视频路径列表(同一个视频可能对应多个 QA 任务)\n",
" unique_video_paths = list(set(item['video_abs_path'] for item in data))\n",
" print(f\"Total samples: {len(data)}\")\n",
" print(f\"Unique videos to check: {len(unique_video_paths)}\")\n",
"\n",
" # 2. 并行检查\n",
" corrupted_paths = {}\n",
" healthy_paths = set()\n",
"\n",
" print(f\"Starting integrity check with {NUM_WORKERS} workers...\")\n",
" with ProcessPoolExecutor(max_workers=NUM_WORKERS) as executor:\n",
" results = list(tqdm(executor.map(check_video_integrity, unique_video_paths), total=len(unique_video_paths)))\n",
"\n",
" for path, is_ok, err in results:\n",
" if is_ok:\n",
" healthy_paths.add(path)\n",
" else:\n",
" corrupted_paths[path] = err\n",
"\n",
" # 3. 过滤原始数据并保存新 JSON\n",
" cleaned_data = [item for item in data if item['video_abs_path'] in healthy_paths]\n",
" \n",
" with open(OUTPUT_CLEAN_JSON, 'w', encoding='utf-8') as f:\n",
" json.dump(cleaned_data, f, indent=4, ensure_ascii=False)\n",
"\n",
" # 4. 打印报告\n",
" print(\"\\n\" + \"=\"*30)\n",
" print(f\"Scan Complete!\")\n",
" print(f\"Healthy samples saved: {len(cleaned_data)}\")\n",
" print(f\"Removed samples: {len(data) - len(cleaned_data)}\")\n",
" print(f\"Corrupted unique videos: {len(corrupted_paths)}\")\n",
" \n",
" if corrupted_paths:\n",
" print(f\"Detailed log saved to {LOG_FILE}\")\n",
" with open(LOG_FILE, 'w') as f:\n",
" for path, err in corrupted_paths.items():\n",
" f.write(f\"[{err}] {path}\\n\")\n",
" print(\"=\"*30)\n",
"\n",
"if __name__ == \"__main__\":\n",
" main()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5a49e3d8",
"metadata": {},
"outputs": [
{
"ename": "",
"evalue": "",
"output_type": "error",
"traceback": [
"\u001b[1;31m在当前单元格或上一个单元格中执行代码时 Kernel 崩溃。\n",
"\u001b[1;31m请查看单元格中的代码,以确定故障的可能原因。\n",
"\u001b[1;31m单击此处了解详细信息。\n",
"\u001b[1;31m有关更多详细信息,请查看 Jupyter log。"
]
}
],
"source": [
"import json\n",
"\n",
"data_path = '/data4/runqing/dLLM-RL/data/video_reversal_sft_train_cleaned_10k.json'\n",
"save_path = '/data4/runqing/dLLM-RL/data/video_reversal_sft_train_cleaned_5k.json'\n",
"\n",
"with open(data_path, 'r') as f, \\\n",
" open(save_path, 'w') as fout:\n",
" data = json.load(f)\n",
" json.dump(data[:5000], fout, indent=4, ensure_ascii=False)\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "650497d2",
"metadata": {},
"outputs": [],
"source": [
"import re\n",
"s = 'sadasfdsf s dfds f A'\n",
"\n",
"pattern = re.compile(r'(.*?)', re.IGNORECASE | re.DOTALL)\n",
" \n",
"matches = pattern.findall(s)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "335191ed",
"metadata": {},
"outputs": [
{
"ename": "AttributeError",
"evalue": "'NoneType' object has no attribute 'group'",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)",
"Cell \u001b[0;32mIn[15], line 6\u001b[0m\n\u001b[1;32m 3\u001b[0m p_str \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mA\u001b[39m\u001b[38;5;124m'\u001b[39m\n\u001b[1;32m 4\u001b[0m p_match \u001b[38;5;241m=\u001b[39m re\u001b[38;5;241m.\u001b[39msearch(\u001b[38;5;124mr\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m^([A-Z])[\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124m.\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124ms]\u001b[39m\u001b[38;5;124m'\u001b[39m, p_str)\n\u001b[0;32m----> 6\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[43mp_match\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mgroup\u001b[49m(\u001b[38;5;241m1\u001b[39m) \u001b[38;5;241m==\u001b[39m g_match\u001b[38;5;241m.\u001b[39mgroup(\u001b[38;5;241m1\u001b[39m))\n",
"\u001b[0;31mAttributeError\u001b[0m: 'NoneType' object has no attribute 'group'"
]
}
],
"source": [
"g_str = 'A. daugbdiusagd'\n",
"g_match = re.search(r'^([A-Z])[\\.\\s]', g_str)\n",
"p_str = 'A'\n",
"p_match = re.search(r'^([A-Z])[\\.\\s]', p_str)\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "f6a03f0d",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'A'"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"g_match.group(1)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2780f549",
"metadata": {},
"outputs": [],
"source": [
"print(p_match.group(1) == g_match.group(1))"
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "bb06acce",
"metadata": {},
"outputs": [],
"source": [
"def z_score_normalize(lst):\n",
" mean = sum(lst) / len(lst) if len(lst) > 0 else 0.0\n",
" std = (sum((x - mean) ** 2 for x in lst) / len(lst)) ** 0.5 if len(lst) > 0 else 0.0\n",
" if std == 0:\n",
" return [0 for _ in lst]\n",
" return [(x - mean) / std for x in lst]\n",
"\n",
"raw_rewards= [\n",
" 1.5,\n",
" 1.5\n",
" ]\n",
"\n",
"rewards = z_score_normalize(raw_rewards)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8b56830a",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[0, 0]"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
},
{
"ename": "",
"evalue": "",
"output_type": "error",
"traceback": [
"\u001b[1;31m在当前单元格或上一个单元格中执行代码时 Kernel 崩溃。\n",
"\u001b[1;31m请查看单元格中的代码,以确定故障的可能原因。\n",
"\u001b[1;31m单击此处了解详细信息。\n",
"\u001b[1;31m有关更多详细信息,请查看 Jupyter log。"
]
}
],
"source": [
"rewards"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "dllm-rl",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.19"
}
},
"nbformat": 4,
"nbformat_minor": 5
}