{ "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 }