ai-agent-book 精选快照(<2MB 代码与文档,来自 github.com/bojieli/ai-agent-book)
Build latest book artifacts / build (push) Canceled after 0s
dependency resolution / resolve (3.11) (push) Canceled after 0s
dependency resolution / resolve (3.13) (push) Canceled after 0s
deploy-pages / build (push) Canceled after 0s
deploy-pages / deploy (push) Canceled after 0s
i18n consistency check / check (push) Canceled after 0s
provider adoption tests / test (chapter2/context-compression) (push) Canceled after 0s
provider adoption tests / test (chapter2/prompt-injection) (push) Canceled after 0s
provider adoption tests / test (chapter2/system-hint) (push) Canceled after 0s
provider adoption tests / test (chapter3/log-sanitization) (push) Canceled after 0s
web-search-agent tests / test (push) Canceled after 0s
web-search-agent tests / agentbook (push) Canceled after 0s

This commit is contained in:
2026-08-20 13:12:50 +00:00
commit b119135836
10275 changed files with 3284984 additions and 0 deletions
+26
View File
@@ -0,0 +1,26 @@
# 实验 6-13:RGB 视觉策略的跨环境测试
本目录对应实验 6-13;运行器、验证器与证据中的实验标识均已统一为 `6-13`
这是一个可在本地 GPU 上完成的“仿真环境迁移到现实环境”代理实验。它不声称已经在 SO100 真机上完成零样本抓取,而是用可控的 RGB 训练环境和变化后的测试环境,检验训练时扩大画面变化范围是否有助于应对真实相机可能遇到的背景、光照和噪声差异。
## 运行
```bash
cd chapter6/rgb-sim2real-grasping
python pipeline.py --train-size 4096 --test-size 1024 --epochs 10 --seeds 20260808,20260809,20260810 --output-dir validation/runs/local-gpu
python validate_evidence.py validation/runs/local-gpu/evidence.json
```
正式协议使用 3 个随机种子、4 种训练条件、2 种测试环境,每种条件训练 4096 个样本、训练 10 轮。脚本训练相同结构的 RGB 策略:
- `source_clean`:只看固定的训练画面;
- `source_background`:只改变训练背景;
- `source_appearance`:只改变物体外观;
- `source_full`:同时改变背景、外观、光照和噪声。
所有策略都在固定训练画面和两种变化后的测试环境中测试。验收要求固定画面策略在训练环境的准确率超过 0.85,完整随机化策略在两个测试环境的准确率超过 0.65,并且在两个环境都优于固定画面训练。输出包含模型 checkpoint、逐种子逐条件的指标矩阵、训练指标、训练画面/测试画面预览图和 SHA-256。
## 如何解读
这个实验只证明“扩大训练分布可以缓解视觉差距”,不证明仿真已经等价于真实机器人。真机部署仍需相机标定、真实参数测量、急停、观察员和 SO100 硬件;原 `upstream.lock.json` 记录的 LeRobot/ManiSkill 路径作为后续的硬件扩展保留。
@@ -0,0 +1,86 @@
{
"schema_version": "1.0",
"experiment_id": "6-13",
"status": "blocked",
"upstream": {
"repository": "https://github.com/StoneT2000/lerobot-sim2real.git",
"commit": "87d6c1d969f6e0ca4dc5697940804e231118a63a",
"guide_path": "docs/zero_shot_rgb_sim2real.md",
"guide_blob": "844d113a726d7c3c8494700496591a2604f742e0"
},
"run": {
"started_at": null,
"ended_at": null,
"operator": null,
"host": "documentation-only-host",
"gpu": null,
"robot_actuation_authorized": false
},
"stages": [
{
"stage": 1,
"name": "environment_alignment",
"status": "not_run",
"robot_actuation_required": true,
"simulation_config_sha256": null,
"real_frame_sha256": null,
"overlay_sha256": null,
"alignment_error_px": null
},
{
"stage": 2,
"name": "background_replacement",
"status": "not_run",
"robot_actuation_required": false,
"background_sha256": null,
"config_sha256": null,
"composite_sha256": null
},
{
"stage": 3,
"name": "domain_randomization",
"status": "not_run",
"robot_actuation_required": false,
"parameters": [],
"real_measurements_sha256": null,
"reset_distribution_sha256": null
},
{
"stage": 4,
"name": "ppo_training",
"status": "blocked",
"robot_actuation_required": false,
"algorithm": "PPO",
"rgb_only": true,
"timesteps": 0,
"evaluation_episodes": 0,
"simulation_success_rate": null,
"checkpoint_sha256": null,
"metrics_sha256": null
},
{
"stage": 5,
"name": "real_world_deployment",
"status": "blocked",
"robot_actuation_required": true,
"executed": false,
"zero_shot": true,
"fine_tuning_steps": 0,
"control_frequency_hz": null,
"step_confirmation_enabled": false,
"trials": 0,
"successes": 0,
"video_sha256": null,
"safety": {
"robot_calibrated": false,
"clear_workspace": false,
"emergency_stop_ready": false,
"human_observer_present": false
}
}
],
"artifacts": [],
"blockers": [
"This host has no verified NVIDIA training runtime, aligned real-scene inputs, trained checkpoint, SO-100, or robot-actuation authorization. No stage was claimed complete and no hardware action was attempted."
]
}
@@ -0,0 +1,18 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://ai-agent-book.local/schemas/experiment-6-13-local-gpu.json",
"title": "Experiment 6-13 local GPU RGB domain transfer evidence",
"type": "object",
"required": ["schema_version", "experiment_id", "status", "kind", "metrics", "artifacts", "hardware_extension", "blockers"],
"properties": {
"schema_version": {"const": "3.0"},
"experiment_id": {"const": "6-13"},
"status": {"const": "complete"},
"kind": {"const": "local_gpu_rgb_domain_transfer"},
"metrics": {"type": "object"},
"artifacts": {"type": "array"},
"hardware_extension": {"type": "object"},
"blockers": {"type": "array"}
},
"additionalProperties": true
}
+214
View File
@@ -0,0 +1,214 @@
#!/usr/bin/env python3
"""Experiment 6-13: RGB domain-transfer benchmark on the local GPU.
The benchmark is intentionally self-contained. It trains a small RGB policy
on a source visual domain and evaluates it on a shifted target domain, with
and without domain randomization. It is a production-grade local proxy for
the sim-to-real argument; SO-100 deployment remains a separately gated
extension and is never implied by this run.
"""
from __future__ import annotations
import argparse
import json
import sys
import time
from pathlib import Path
from typing import Any
import numpy as np
import torch
from PIL import Image, ImageDraw
from torch import nn
from torch.utils.data import DataLoader, TensorDataset
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from robotics_lab_common import device_info, relative_or_absolute, select_device, seed_everything, sha256, write_json
IMAGE_SIZE = 32
CLASSES = ("left", "right", "up", "down", "grasp")
def label_for(object_xy: tuple[float, float], target_xy: tuple[float, float]) -> int:
dx, dy = target_xy[0] - object_xy[0], target_xy[1] - object_xy[1]
if abs(dx) < 0.10 and abs(dy) < 0.10:
return 4
if abs(dx) >= abs(dy):
return 1 if dx > 0 else 0
return 3 if dy > 0 else 2
def render_sample(rng: np.random.Generator, domain: str) -> tuple[np.ndarray, int]:
object_xy = tuple(rng.uniform(0.18, 0.82, size=2))
target_xy = tuple(rng.uniform(0.18, 0.82, size=2))
label = label_for(object_xy, target_xy)
if domain == "source_clean":
background = np.full((IMAGE_SIZE, IMAGE_SIZE, 3), [220, 220, 220], dtype=np.float32)
object_color, target_color = (214, 60, 60), (45, 130, 65)
noise = 0.0
elif domain in {"source_background", "source_full"}:
if domain == "source_background":
base = rng.uniform(45, 225, size=(1, 1, 3)).astype(np.float32)
background = np.broadcast_to(base, (IMAGE_SIZE, IMAGE_SIZE, 3)).copy()
background += rng.normal(0, 9, size=background.shape)
object_color, target_color = (214, 60, 60), (45, 130, 65)
else:
base = rng.uniform(45, 225, size=(1, 1, 3)).astype(np.float32)
background = np.broadcast_to(base, (IMAGE_SIZE, IMAGE_SIZE, 3)).copy()
background += rng.normal(0, 9, size=background.shape)
object_color = (int(rng.uniform(180, 245)), int(rng.uniform(45, 105)), int(rng.uniform(35, 100)))
target_color = (int(rng.uniform(35, 100)), int(rng.uniform(125, 205)), int(rng.uniform(75, 170)))
noise = 3.0
elif domain == "source_appearance":
background = np.full((IMAGE_SIZE, IMAGE_SIZE, 3), rng.uniform(150, 235), dtype=np.float32)
object_color = (int(rng.uniform(170, 245)), int(rng.uniform(45, 110)), int(rng.uniform(35, 100)))
target_color = (int(rng.uniform(35, 100)), int(rng.uniform(120, 210)), int(rng.uniform(75, 175)))
noise = 2.0
elif domain in {"target_realistic", "target_bright"}:
base = rng.uniform(45, 175, size=(IMAGE_SIZE, IMAGE_SIZE, 1))
stripes = (np.sin(np.arange(IMAGE_SIZE)[None, :, None] / 3.0) * 18.0).astype(np.float32)
background = np.repeat(base, 3, axis=2) + stripes
if domain == "target_bright":
background = np.clip(background + 55, 0, 255)
object_color, target_color = (235, 185, 55), (70, 160, 205)
noise = 14.0
else:
raise ValueError(f"unknown domain: {domain}")
image = Image.fromarray(np.uint8(np.clip(background, 0, 255)), mode="RGB")
draw = ImageDraw.Draw(image)
ox, oy = int(object_xy[0] * IMAGE_SIZE), int(object_xy[1] * IMAGE_SIZE)
tx, ty = int(target_xy[0] * IMAGE_SIZE), int(target_xy[1] * IMAGE_SIZE)
draw.rectangle((tx - 4, ty - 4, tx + 4, ty + 4), outline=target_color, width=2)
draw.ellipse((ox - 3, oy - 3, ox + 3, oy + 3), fill=object_color, outline=(20, 20, 20))
array = np.asarray(image, dtype=np.float32)
if noise:
array += rng.normal(0, noise, size=array.shape)
array = np.clip(array / 255.0, 0.0, 1.0).transpose(2, 0, 1)
return array.astype(np.float32), label
def make_dataset(size: int, domain: str, seed: int) -> tuple[torch.Tensor, torch.Tensor]:
rng = np.random.default_rng(seed)
images, labels = zip(*(render_sample(rng, domain) for _ in range(size)))
return torch.from_numpy(np.stack(images)), torch.tensor(labels, dtype=torch.long)
class RGBPolicy(nn.Module):
def __init__(self) -> None:
super().__init__()
self.net = nn.Sequential(
nn.Conv2d(3, 16, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2),
nn.Conv2d(16, 32, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2),
nn.Conv2d(32, 48, 3, padding=1), nn.ReLU(),
)
self.head = nn.Sequential(nn.Flatten(), nn.Linear(48 * 8 * 8, 128), nn.ReLU(), nn.Linear(128, len(CLASSES)))
def forward(self, x: torch.Tensor) -> torch.Tensor:
return self.head(self.net(x))
def train_policy(images: torch.Tensor, labels: torch.Tensor, device: torch.device, seed: int, epochs: int) -> tuple[RGBPolicy, list[float]]:
generator = torch.Generator().manual_seed(seed)
loader = DataLoader(TensorDataset(images, labels), batch_size=128, shuffle=True, generator=generator)
model = RGBPolicy().to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=2e-3)
criterion = nn.CrossEntropyLoss()
losses: list[float] = []
for _ in range(epochs):
total, count = 0.0, 0
for batch_images, batch_labels in loader:
optimizer.zero_grad(set_to_none=True)
loss = criterion(model(batch_images.to(device)), batch_labels.to(device))
loss.backward()
optimizer.step()
total += float(loss.item()) * len(batch_labels)
count += len(batch_labels)
losses.append(total / count)
return model, losses
def accuracy(model: RGBPolicy, images: torch.Tensor, labels: torch.Tensor, device: torch.device) -> float:
with torch.no_grad():
prediction = model(images.to(device)).argmax(dim=1).cpu()
return float((prediction == labels).float().mean().item())
def save_preview(path: Path, images: torch.Tensor, labels: torch.Tensor) -> None:
tile = (images[:16].permute(0, 2, 3, 1).numpy() * 255).astype(np.uint8)
canvas = Image.new("RGB", (IMAGE_SIZE * 4, IMAGE_SIZE * 4), "white")
for index, array in enumerate(tile):
canvas.paste(Image.fromarray(array), ((index % 4) * IMAGE_SIZE, (index // 4) * IMAGE_SIZE))
path.parent.mkdir(parents=True, exist_ok=True)
canvas.save(path)
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--train-size", type=int, default=4096, help="examples per seed and training variant")
parser.add_argument("--test-size", type=int, default=1024, help="examples per seed and target domain")
parser.add_argument("--epochs", type=int, default=10)
parser.add_argument("--seeds", default="20260808,20260809,20260810")
parser.add_argument("--output-dir", type=Path, default=Path(__file__).parent / "validation" / "runs" / "local-gpu")
parser.add_argument("--allow-cpu", action="store_true")
args = parser.parse_args()
try:
seeds = [int(value) for value in args.seeds.split(",")]
except ValueError:
parser.error("--seeds must be comma-separated integers")
if args.train_size < 2048 or args.test_size < 512 or args.epochs < 8 or len(seeds) < 3:
parser.error("the benchmark requires at least 2048 train examples, 512 test examples, 8 epochs and 3 seeds")
seed_everything(seeds[0])
try:
device = select_device(not args.allow_cpu)
except RuntimeError as exc:
parser.error(str(exc))
started = time.perf_counter()
variants = ("source_clean", "source_background", "source_appearance", "source_full")
target_domains = ("target_realistic", "target_bright")
rows: list[dict[str, Any]] = []
checkpoint_model: RGBPolicy | None = None
for seed in seeds:
source_test_x, source_test_y = make_dataset(args.test_size, "source_clean", seed + 100)
target_tests = {domain: make_dataset(args.test_size, domain, seed + 200 + index) for index, domain in enumerate(target_domains)}
for variant_index, variant in enumerate(variants):
train_x, train_y = make_dataset(args.train_size, variant, seed + variant_index)
model, losses = train_policy(train_x, train_y, device, seed + 50 + variant_index, args.epochs)
if seed == seeds[0] and variant == "source_full":
checkpoint_model = model
rows.append({"seed": seed, "variant": variant, "source_accuracy": accuracy(model, source_test_x, source_test_y, device), "target_accuracy": {domain: accuracy(model, images, labels, device) for domain, (images, labels) in target_tests.items()}, "final_loss": losses[-1]})
grouped: dict[str, dict[str, Any]] = {}
for variant in variants:
grouped[variant] = {}
for domain in target_domains:
values = [row["target_accuracy"][domain] for row in rows if row["variant"] == variant]
grouped[variant][domain] = {"mean": float(np.mean(values)), "std": float(np.std(values)), "values": values}
source_values = [row["source_accuracy"] for row in rows if row["variant"] == variant]
grouped[variant]["source"] = {"mean": float(np.mean(source_values)), "std": float(np.std(source_values)), "values": source_values}
replay_a = make_dataset(256, "source_full", seeds[0])
replay_b = make_dataset(256, "source_full", seeds[0])
metrics = {"device": device_info(device), "protocol": {"seeds": seeds, "variants": list(variants), "target_domains": list(target_domains), "train_size_per_variant": args.train_size, "test_size_per_domain": args.test_size, "epochs": args.epochs, "total_training_examples": len(seeds) * len(variants) * args.train_size}, "rows": rows, "summary": grouped, "dataset_replay_match": bool(torch.equal(replay_a[0], replay_b[0]) and torch.equal(replay_a[1], replay_b[1])), "wall_time_ms": round((time.perf_counter() - started) * 1000, 3)}
args.output_dir.mkdir(parents=True, exist_ok=True)
preview_source = args.output_dir / "source_preview.png"
preview_target = args.output_dir / "target_preview.png"
source_preview_x, source_preview_y = make_dataset(64, "source_clean", seeds[0] + 1000)
target_preview_x, target_preview_y = make_dataset(64, "target_realistic", seeds[0] + 1001)
save_preview(preview_source, source_preview_x, source_preview_y)
save_preview(preview_target, target_preview_x, target_preview_y)
checkpoint_path = args.output_dir / "randomized_policy.pt"
if checkpoint_model is None:
raise RuntimeError("source_full checkpoint was not produced")
torch.save({"model": {key: value.detach().cpu() for key, value in checkpoint_model.state_dict().items()}, "seed": seeds[0], "classes": CLASSES}, checkpoint_path)
matrix_path = args.output_dir / "matrix.json"
write_json(matrix_path, {"rows": rows, "summary": grouped})
metrics_path = args.output_dir / "metrics.json"
write_json(metrics_path, metrics)
evidence = {"schema_version": "3.0", "experiment_id": "6-13", "status": "complete", "kind": "local_gpu_rgb_domain_transfer", "seed": seeds[0], "metrics": metrics, "artifacts": [{"kind": "checkpoint", "path": relative_or_absolute(checkpoint_path, args.output_dir), "sha256": sha256(checkpoint_path)}, {"kind": "metrics", "path": relative_or_absolute(metrics_path, args.output_dir), "sha256": sha256(metrics_path)}, {"kind": "matrix", "path": relative_or_absolute(matrix_path, args.output_dir), "sha256": sha256(matrix_path)}, {"kind": "source_preview", "path": relative_or_absolute(preview_source, args.output_dir), "sha256": sha256(preview_source)}, {"kind": "target_preview", "path": relative_or_absolute(preview_target, args.output_dir), "sha256": sha256(preview_target)}], "hardware_extension": {"status": "gated", "actuation_attempted": False, "upstream": "StoneT2000/lerobot-sim2real"}, "blockers": [] if not args.allow_cpu else ["CPU debug mode is not a GPU acceptance run"]}
evidence_path = args.output_dir / "evidence.json"
write_json(evidence_path, evidence)
print(json.dumps(evidence, indent=2))
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,95 @@
#!/usr/bin/env python3
"""Read-only, stage-aware preflight for Experiment 6-13."""
from __future__ import annotations
import argparse
import importlib.util
import json
import platform
import shutil
import subprocess
from datetime import datetime, timezone
from pathlib import Path
COMMIT = "87d6c1d969f6e0ca4dc5697940804e231118a63a"
PINNED_BLOBS = {
"docs/zero_shot_rgb_sim2real.md": "844d113a726d7c3c8494700496591a2604f742e0",
"env_config.json": "e32727956fc9dbf64336b53b77bc1a6044e2f5ef",
"lerobot_sim2real/config/real_robot.py": "f522e6d1dab0ef4ff4a0204497c1616995346ad7",
"lerobot_sim2real/scripts/record_reset_distribution.py": "ff20e1c3ea34b6d75f646c325f6fe49e1d83903c",
"lerobot_sim2real/scripts/camera_alignment.py": "5d7a323075e43ba5c0a24bd2ce6c910f89e4a9c6",
"lerobot_sim2real/scripts/capture_background_image.py": "f30d97cd7ead0cdfe9b38ea6c9523a5f38b404aa",
"lerobot_sim2real/scripts/train_ppo_rgb.py": "af900d1e247349b61b707b4a63d30e0d297c9ea9",
"lerobot_sim2real/scripts/eval_ppo_rgb.py": "506a4c190eb99b7cd2691562edb78f6f0dd748e3",
}
def git(repo: Path, *args: str) -> str:
return subprocess.run(["git", "-C", str(repo), *args], check=False, capture_output=True, text=True).stdout.strip()
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--upstream", type=Path, required=True)
parser.add_argument("--real-frame", type=Path, help="existing real-camera frame; file is not opened")
parser.add_argument("--greenscreen", type=Path, help="existing background image; file is not opened")
parser.add_argument("--checkpoint", type=Path, help="existing trained checkpoint; file is not opened")
parser.add_argument("--camera", type=Path, help="camera device; path is checked only")
parser.add_argument("--robot-port", type=Path, help="robot device; path is checked only")
parser.add_argument("--hardware-run-authorized", action="store_true")
parser.add_argument("--safety-checklist-complete", action="store_true")
parser.add_argument("--output", type=Path)
args = parser.parse_args()
checks: list[dict[str, object]] = []
def add(check_id: str, passed: bool, detail: str, stages: list[int]) -> None:
checks.append({"id": check_id, "passed": passed, "stages": stages, "detail": detail})
head = git(args.upstream, "rev-parse", "HEAD")
add("pinned_commit", head == COMMIT, f"expected {COMMIT}; found {head or 'not a git checkout'}", [1, 2, 3, 4, 5])
for path, blob in PINNED_BLOBS.items():
found = git(args.upstream, "rev-parse", f"HEAD:{path}")
add(f"blob:{path}", found == blob, f"expected {blob}; found {found or 'missing'}", [1, 2, 3, 4, 5])
for module in ("torch", "mani_skill"):
found = importlib.util.find_spec(module) is not None
add(f"python_module:{module}", found, "installed" if found else "not importable", [1, 2, 3, 4])
nvidia_smi = shutil.which("nvidia-smi")
add("nvidia_gpu", bool(nvidia_smi), nvidia_smi or "nvidia-smi not found", [3, 4])
add("offline_real_frame", bool(args.real_frame and args.real_frame.is_file()), str(args.real_frame or "not supplied; optional and not equivalent to the live upstream script"), [])
add("camera_path", bool(args.camera and args.camera.exists()), str(args.camera or "not supplied"), [1, 2])
add("greenscreen", bool(args.greenscreen and args.greenscreen.is_file()), str(args.greenscreen or "not supplied"), [3, 4])
add("checkpoint", bool(args.checkpoint and args.checkpoint.is_file()), str(args.checkpoint or "not supplied"), [5])
add("robot_port", bool(args.robot_port and args.robot_port.exists()), str(args.robot_port or "not supplied"), [1, 2, 5])
add("hardware_authorization", args.hardware_run_authorized, "explicit" if args.hardware_run_authorized else "not granted", [1, 2, 5])
add("safety_checklist", args.safety_checklist_complete, "attested" if args.safety_checklist_complete else "not attested", [1, 2, 5])
readiness = {}
for stage in range(1, 6):
failed = [str(item["id"]) for item in checks if stage in item["stages"] and not item["passed"]]
readiness[str(stage)] = {"preflight": "ready" if not failed else "blocked", "blockers": failed}
report = {
"schema_version": "1.0",
"experiment_id": "6-13",
"kind": "non_actuating_preflight",
"generated_at": datetime.now(timezone.utc).isoformat(),
"host": platform.node() or "unknown",
"upstream_path": str(args.upstream.resolve()),
"stage_readiness": readiness,
"status": "ready" if all(item["preflight"] == "ready" for item in readiness.values()) else "blocked",
"checks": checks,
"hardware_boundary": "Pinned stage 1 can actuate during real_env.reset; stage 2 connects hardware and disables torque; stages 3-4 are GPU-only; stage 5 actuates the policy.",
"actuation_attempted": False
}
rendered = json.dumps(report, indent=2) + "\n"
if args.output:
args.output.parent.mkdir(parents=True, exist_ok=True)
args.output.write_text(rendered, encoding="utf-8")
print(f"wrote {args.output}")
else:
print(rendered, end="")
return 0 if report["status"] == "ready" else 1
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,22 @@
import json
import unittest
from pathlib import Path
from validate_evidence import validate
class EvidenceGateTests(unittest.TestCase):
def test_local_gpu_evidence_is_accepted(self):
run = Path(__file__).parent / "validation" / "runs" / "local-gpu" / "evidence.json"
if not run.is_file():
self.skipTest("run the local GPU experiment first")
data = json.loads(run.read_text(encoding="utf-8"))
self.assertEqual(validate(data, run.parent), [])
def test_without_randomization_is_not_a_transfer_claim(self):
data = {"schema_version": "3.0", "experiment_id": "6-13", "status": "complete", "kind": "local_gpu_rgb_domain_transfer", "metrics": {"device": {"device": "mps"}, "protocol": {"seeds": [1, 2, 3], "variants": ["source_clean", "source_background", "source_appearance", "source_full"], "target_domains": ["a", "b"], "total_training_examples": 24576}, "summary": {"source_clean": {"source": {"mean": 0.95}, "a": {"mean": 0.7}, "b": {"mean": 0.7}}, "source_full": {"a": {"mean": 0.8}, "b": {"mean": 0.8}}}, "dataset_replay_match": True}, "artifacts": [], "hardware_extension": {"actuation_attempted": False}}
self.assertTrue(validate(data))
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,25 @@
{
"experiment_id": "6-13",
"repository": "https://github.com/StoneT2000/lerobot-sim2real.git",
"commit": "87d6c1d969f6e0ca4dc5697940804e231118a63a",
"guide": {
"published_url": "https://github.com/StoneT2000/lerobot-sim2real/blob/87d6c1d969f6e0ca4dc5697940804e231118a63a/docs/zero_shot_rgb_sim2real.md",
"path": "docs/zero_shot_rgb_sim2real.md",
"git_blob": "844d113a726d7c3c8494700496591a2604f742e0"
},
"files": {
"env_config.json": "e32727956fc9dbf64336b53b77bc1a6044e2f5ef",
"system_id_so100.npy": "047b0110496f15f3a78a41b59c9f041cbbbbfd91",
"docs/assets/camera_alignment_step_1.2.png": "688f0089c4a99bb2f608a805cbbb9fd96fb80830",
"docs/assets/camera_alignment_step_1.3.png": "20943d0a0eff5b64afaafb04dab3522791e3bcf2",
"docs/assets/eval_return_success_curves.png": "7185d982e165081ec0ad5ded4eb21dc9f172bac9",
"docs/assets/tutorial_result_video.mp4": "d15f57adfd8b889ed8bb4d44d073f0cf7ba96c4a",
"lerobot_sim2real/config/real_robot.py": "f522e6d1dab0ef4ff4a0204497c1616995346ad7",
"lerobot_sim2real/scripts/record_reset_distribution.py": "ff20e1c3ea34b6d75f646c325f6fe49e1d83903c",
"lerobot_sim2real/scripts/camera_alignment.py": "5d7a323075e43ba5c0a24bd2ce6c910f89e4a9c6",
"lerobot_sim2real/scripts/capture_background_image.py": "f30d97cd7ead0cdfe9b38ea6c9523a5f38b404aa",
"lerobot_sim2real/scripts/train_ppo_rgb.py": "af900d1e247349b61b707b4a63d30e0d297c9ea9",
"lerobot_sim2real/scripts/eval_ppo_rgb.py": "506a4c190eb99b7cd2691562edb78f6f0dd748e3"
},
"verified_at": "2026-07-29"
}
@@ -0,0 +1,81 @@
#!/usr/bin/env python3
"""Validate local GPU RGB domain-transfer evidence for Experiment 6-13."""
from __future__ import annotations
import argparse
import hashlib
import json
import sys
from pathlib import Path
from typing import Any
def file_sha256(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as handle:
for chunk in iter(lambda: handle.read(1024 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
def validate(data: dict[str, Any], evidence_dir: Path | None = None) -> list[str]:
errors: list[str] = []
def expect(condition: bool, message: str) -> None:
if not condition:
errors.append(message)
expect(data.get("schema_version") == "3.0", "schema_version must be 3.0")
expect(data.get("experiment_id") == "6-13", "experiment_id must be 6-13")
expect(data.get("kind") == "local_gpu_rgb_domain_transfer", "wrong evidence kind")
expect(data.get("status") == "complete", "local evidence must be complete")
metrics = data.get("metrics", {})
expect(metrics.get("device", {}).get("device") in {"mps", "cuda"}, "evidence must use a local GPU accelerator")
protocol = metrics.get("protocol", {})
expect(len(protocol.get("seeds", [])) >= 3, "at least three training seeds are required")
expect(set(protocol.get("variants", [])) == {"source_clean", "source_background", "source_appearance", "source_full"}, "all four randomization conditions are required")
expect(len(protocol.get("target_domains", [])) >= 2, "at least two target visual domains are required")
expect(protocol.get("total_training_examples", 0) >= 20000, "at least 20000 training examples are required")
summary = metrics.get("summary", {})
expect(summary.get("source_clean", {}).get("source", {}).get("mean", 0) > 0.85, "clean source accuracy must exceed 0.85")
for domain in protocol.get("target_domains", []):
clean = summary.get("source_clean", {}).get(domain, {}).get("mean", 0)
full = summary.get("source_full", {}).get(domain, {}).get("mean", 0)
expect(full > 0.65, f"full randomization target accuracy is too low for {domain}")
expect(full > clean, f"full randomization must improve target accuracy for {domain}")
expect(metrics.get("dataset_replay_match") is True, "repeating a fixed dataset seed must reproduce the exact data")
artifacts = data.get("artifacts", [])
expect(len(artifacts) == 5, "checkpoint, metrics, matrix and two preview artifacts are required")
if evidence_dir is not None:
for index, artifact in enumerate(artifacts):
path = evidence_dir / str(artifact.get("path", ""))
expect(path.is_file(), f"artifact[{index}] does not exist")
if path.is_file():
expect(file_sha256(path) == artifact.get("sha256"), f"artifact[{index}] hash mismatch")
extension = data.get("hardware_extension", {})
expect(extension.get("actuation_attempted") is False, "local run must not claim hardware actuation")
return errors
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("evidence", type=Path)
args = parser.parse_args()
try:
data = json.loads(args.evidence.read_text(encoding="utf-8"))
except (OSError, json.JSONDecodeError) as exc:
print(f"INVALID: {exc}", file=sys.stderr)
return 2
errors = validate(data, args.evidence.resolve().parent)
if errors:
print("INVALID")
for error in errors:
print(f"- {error}")
return 1
print("VALID: experiment 6-13 local GPU evidence")
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,226 @@
{
"schema_version": "1.0",
"experiment_id": "6-13",
"kind": "reference_and_blocker_audit_not_acceptance",
"generated_at": "2026-07-29T15:35:16.622749+00:00",
"host": {
"node": "bojMacBook-Pro.local",
"platform": "macOS-26.3-arm64-arm-64bit",
"machine": "arm64"
},
"source_integrity": {
"head": "87d6c1d969f6e0ca4dc5697940804e231118a63a",
"expected_head": "87d6c1d969f6e0ca4dc5697940804e231118a63a",
"passed": true,
"files": [
{
"path": "docs/zero_shot_rgb_sim2real.md",
"expected_blob": "844d113a726d7c3c8494700496591a2604f742e0",
"found_blob": "844d113a726d7c3c8494700496591a2604f742e0",
"passed": true
},
{
"path": "docs/assets/camera_alignment_step_1.2.png",
"expected_blob": "688f0089c4a99bb2f608a805cbbb9fd96fb80830",
"found_blob": "688f0089c4a99bb2f608a805cbbb9fd96fb80830",
"passed": true
},
{
"path": "docs/assets/camera_alignment_step_1.3.png",
"expected_blob": "20943d0a0eff5b64afaafb04dab3522791e3bcf2",
"found_blob": "20943d0a0eff5b64afaafb04dab3522791e3bcf2",
"passed": true
},
{
"path": "docs/assets/eval_return_success_curves.png",
"expected_blob": "7185d982e165081ec0ad5ded4eb21dc9f172bac9",
"found_blob": "7185d982e165081ec0ad5ded4eb21dc9f172bac9",
"passed": true
},
{
"path": "docs/assets/tutorial_result_video.mp4",
"expected_blob": "d15f57adfd8b889ed8bb4d44d073f0cf7ba96c4a",
"found_blob": "d15f57adfd8b889ed8bb4d44d073f0cf7ba96c4a",
"passed": true
},
{
"path": "env_config.json",
"expected_blob": "e32727956fc9dbf64336b53b77bc1a6044e2f5ef",
"found_blob": "e32727956fc9dbf64336b53b77bc1a6044e2f5ef",
"passed": true
},
{
"path": "system_id_so100.npy",
"expected_blob": "047b0110496f15f3a78a41b59c9f041cbbbbfd91",
"found_blob": "047b0110496f15f3a78a41b59c9f041cbbbbfd91",
"passed": true
},
{
"path": "lerobot_sim2real/scripts/record_reset_distribution.py",
"expected_blob": "ff20e1c3ea34b6d75f646c325f6fe49e1d83903c",
"found_blob": "ff20e1c3ea34b6d75f646c325f6fe49e1d83903c",
"passed": true
},
{
"path": "lerobot_sim2real/scripts/camera_alignment.py",
"expected_blob": "5d7a323075e43ba5c0a24bd2ce6c910f89e4a9c6",
"found_blob": "5d7a323075e43ba5c0a24bd2ce6c910f89e4a9c6",
"passed": true
},
{
"path": "lerobot_sim2real/scripts/capture_background_image.py",
"expected_blob": "f30d97cd7ead0cdfe9b38ea6c9523a5f38b404aa",
"found_blob": "f30d97cd7ead0cdfe9b38ea6c9523a5f38b404aa",
"passed": true
},
{
"path": "lerobot_sim2real/scripts/train_ppo_rgb.py",
"expected_blob": "af900d1e247349b61b707b4a63d30e0d297c9ea9",
"found_blob": "af900d1e247349b61b707b4a63d30e0d297c9ea9",
"passed": true
}
]
},
"runtime": {
"python": "3.11.4",
"mani_skill_importable": false,
"nvidia_smi": null,
"apple_mps_available": true,
"upstream_training_backend": "CUDA (the pinned PPO implementation sets device cuda when available and the documented setup requires NVIDIA >=8GB)"
},
"stages": {
"1": {
"name": "environment_alignment",
"robot_actuation_required": true,
"reference_asset_verified": {
"path": "docs/assets/camera_alignment_step_1.2.png",
"sha256": "195d35f2f944345db9d21215d7bbf1745370605c20959cff315293ebcd58415c",
"width": 1260,
"height": 1260,
"channels": 3,
"mean_rgb": [
144.2132,
117.0811,
103.9883
],
"pixel_stddev": 33.3767
},
"local_upstream_invocation": {
"command": [
"/Users/boj/miniconda3/bin/python",
"/tmp/lerobot-sim2real-audit-20260729/lerobot_sim2real/scripts/camera_alignment.py",
"--help"
],
"return_code": 1,
"timed_out": false,
"output": "Traceback (most recent call last):\n File \"/tmp/lerobot-sim2real-audit-20260729/lerobot_sim2real/scripts/camera_alignment.py\", line 7, in <module>\n from mani_skill.utils.wrappers.flatten import FlattenRGBDObservationWrapper\nModuleNotFoundError: No module named 'mani_skill'\n"
},
"complete": false,
"blocker": "No authorized/calibrated SO-100 camera run or ManiSkill runtime. The pinned script connects the robot and calls real_env.reset(), so only --help was probed; the verified image is upstream reference evidence, not this host's alignment."
},
"2": {
"name": "background_replacement",
"robot_actuation_required": false,
"reference_asset_verified": {
"path": "docs/assets/camera_alignment_step_1.3.png",
"sha256": "f8e79ebf6f727dc703d091978af60b04563b8eb37ee4360df14809dd36c75503",
"width": 1260,
"height": 1260,
"channels": 3,
"mean_rgb": [
113.6085,
114.9122,
112.5164
],
"pixel_stddev": 57.1852
},
"local_upstream_invocation": {
"command": [
"/Users/boj/miniconda3/bin/python",
"/tmp/lerobot-sim2real-audit-20260729/lerobot_sim2real/scripts/capture_background_image.py",
"--help"
],
"return_code": 1,
"timed_out": false,
"output": "Traceback (most recent call last):\n File \"/tmp/lerobot-sim2real-audit-20260729/lerobot_sim2real/scripts/capture_background_image.py\", line 3, in <module>\n from mani_skill.utils.wrappers.flatten import FlattenRGBDObservationWrapper\nModuleNotFoundError: No module named 'mani_skill'\n"
},
"complete": false,
"blocker": "No local empty-scene background capture or ManiSkill runtime; the verified composite is upstream reference evidence, not a local composite."
},
"3": {
"name": "domain_randomization_and_real_dynamics_calibration",
"robot_actuation_required": false,
"real_dynamics_measurement": {
"path": "system_id_so100.npy",
"sha256": "4ca6cc4cd5c26540685d54e2cd2babde2204d0d3f369a63b5e817b1e7cf381db",
"source": "real SO-100 system-identification capture committed by the pinned upstream",
"samples": 139,
"joints": 6,
"qpos_dtype": "float32",
"target_qpos_dtype": "float32",
"mean_absolute_tracking_error_by_joint": [
0.09687472,
0.13199401,
0.14799425,
0.0692635,
0.11893595,
0.0782366
],
"max_absolute_tracking_error_by_joint": [
0.18611592,
0.23677669,
0.22161102,
0.18297092,
0.18330097,
0.19700873
],
"best_tracking_lag_samples_by_joint": [
3,
4,
4,
4,
3,
3
],
"sample_period_seconds": null,
"note": "The upstream artifact contains no timestamps, so lag is reported in samples and is not converted to milliseconds."
},
"local_upstream_invocation": {
"command": [
"/Users/boj/miniconda3/bin/python",
"/tmp/lerobot-sim2real-audit-20260729/lerobot_sim2real/scripts/record_reset_distribution.py",
"--help"
],
"return_code": 1,
"timed_out": false,
"output": "Traceback (most recent call last):\n File \"/tmp/lerobot-sim2real-audit-20260729/lerobot_sim2real/scripts/record_reset_distribution.py\", line 5, in <module>\n from mani_skill.utils.wrappers.record import RecordEpisode\nModuleNotFoundError: No module named 'mani_skill'\n"
},
"complete": false,
"blocker": "Pinned real dynamics were measured, but randomized ManiSkill resets could not execute without ManiSkill/NVIDIA and the required visual/physical ranges were not locally evaluated."
},
"4": {
"name": "rgb_only_ppo_training_and_evaluation",
"robot_actuation_required": false,
"local_upstream_invocation": {
"command": [
"/Users/boj/miniconda3/bin/python",
"/tmp/lerobot-sim2real-audit-20260729/lerobot_sim2real/scripts/train_ppo_rgb.py",
"--help"
],
"return_code": 1,
"timed_out": false,
"output": "Traceback (most recent call last):\n File \"/tmp/lerobot-sim2real-audit-20260729/lerobot_sim2real/scripts/train_ppo_rgb.py\", line 6, in <module>\n import tyro\nModuleNotFoundError: No module named 'tyro'\n"
},
"complete": false,
"simulation_success_rate": null,
"blocker": "No importable ManiSkill or NVIDIA CUDA runtime; no PPO checkpoint or >90% direct evaluation exists on this host. Apple MPS is not a proven substitute for this pinned CUDA path."
},
"5": {
"name": "zero_shot_real_world_deployment",
"robot_actuation_required": true,
"complete": false,
"blocker": "No SO-100, authorized operator, calibrated workspace, E-stop, observer, or stage-4 checkpoint; no actuation was attempted."
}
},
"actuation_attempted": false
}
@@ -0,0 +1,261 @@
{
"schema_version": "1.0",
"experiment_id": "6-13",
"kind": "non_actuating_preflight",
"generated_at": "2026-07-29T15:36:54.758593+00:00",
"host": "bojMacBook-Pro.local",
"upstream_path": "/private/tmp/lerobot-sim2real-audit-20260729",
"stage_readiness": {
"1": {
"preflight": "blocked",
"blockers": [
"python_module:mani_skill",
"camera_path",
"robot_port",
"hardware_authorization",
"safety_checklist"
]
},
"2": {
"preflight": "blocked",
"blockers": [
"python_module:mani_skill",
"camera_path",
"robot_port",
"hardware_authorization",
"safety_checklist"
]
},
"3": {
"preflight": "blocked",
"blockers": [
"python_module:mani_skill",
"nvidia_gpu",
"greenscreen"
]
},
"4": {
"preflight": "blocked",
"blockers": [
"python_module:mani_skill",
"nvidia_gpu",
"greenscreen"
]
},
"5": {
"preflight": "blocked",
"blockers": [
"checkpoint",
"robot_port",
"hardware_authorization",
"safety_checklist"
]
}
},
"status": "blocked",
"checks": [
{
"id": "pinned_commit",
"passed": true,
"stages": [
1,
2,
3,
4,
5
],
"detail": "expected 87d6c1d969f6e0ca4dc5697940804e231118a63a; found 87d6c1d969f6e0ca4dc5697940804e231118a63a"
},
{
"id": "blob:docs/zero_shot_rgb_sim2real.md",
"passed": true,
"stages": [
1,
2,
3,
4,
5
],
"detail": "expected 844d113a726d7c3c8494700496591a2604f742e0; found 844d113a726d7c3c8494700496591a2604f742e0"
},
{
"id": "blob:env_config.json",
"passed": true,
"stages": [
1,
2,
3,
4,
5
],
"detail": "expected e32727956fc9dbf64336b53b77bc1a6044e2f5ef; found e32727956fc9dbf64336b53b77bc1a6044e2f5ef"
},
{
"id": "blob:lerobot_sim2real/config/real_robot.py",
"passed": true,
"stages": [
1,
2,
3,
4,
5
],
"detail": "expected f522e6d1dab0ef4ff4a0204497c1616995346ad7; found f522e6d1dab0ef4ff4a0204497c1616995346ad7"
},
{
"id": "blob:lerobot_sim2real/scripts/record_reset_distribution.py",
"passed": true,
"stages": [
1,
2,
3,
4,
5
],
"detail": "expected ff20e1c3ea34b6d75f646c325f6fe49e1d83903c; found ff20e1c3ea34b6d75f646c325f6fe49e1d83903c"
},
{
"id": "blob:lerobot_sim2real/scripts/camera_alignment.py",
"passed": true,
"stages": [
1,
2,
3,
4,
5
],
"detail": "expected 5d7a323075e43ba5c0a24bd2ce6c910f89e4a9c6; found 5d7a323075e43ba5c0a24bd2ce6c910f89e4a9c6"
},
{
"id": "blob:lerobot_sim2real/scripts/capture_background_image.py",
"passed": true,
"stages": [
1,
2,
3,
4,
5
],
"detail": "expected f30d97cd7ead0cdfe9b38ea6c9523a5f38b404aa; found f30d97cd7ead0cdfe9b38ea6c9523a5f38b404aa"
},
{
"id": "blob:lerobot_sim2real/scripts/train_ppo_rgb.py",
"passed": true,
"stages": [
1,
2,
3,
4,
5
],
"detail": "expected af900d1e247349b61b707b4a63d30e0d297c9ea9; found af900d1e247349b61b707b4a63d30e0d297c9ea9"
},
{
"id": "blob:lerobot_sim2real/scripts/eval_ppo_rgb.py",
"passed": true,
"stages": [
1,
2,
3,
4,
5
],
"detail": "expected 506a4c190eb99b7cd2691562edb78f6f0dd748e3; found 506a4c190eb99b7cd2691562edb78f6f0dd748e3"
},
{
"id": "python_module:torch",
"passed": true,
"stages": [
1,
2,
3,
4
],
"detail": "installed"
},
{
"id": "python_module:mani_skill",
"passed": false,
"stages": [
1,
2,
3,
4
],
"detail": "not importable"
},
{
"id": "nvidia_gpu",
"passed": false,
"stages": [
3,
4
],
"detail": "nvidia-smi not found"
},
{
"id": "offline_real_frame",
"passed": false,
"stages": [],
"detail": "not supplied; optional and not equivalent to the live upstream script"
},
{
"id": "camera_path",
"passed": false,
"stages": [
1,
2
],
"detail": "not supplied"
},
{
"id": "greenscreen",
"passed": false,
"stages": [
3,
4
],
"detail": "not supplied"
},
{
"id": "checkpoint",
"passed": false,
"stages": [
5
],
"detail": "not supplied"
},
{
"id": "robot_port",
"passed": false,
"stages": [
1,
2,
5
],
"detail": "not supplied"
},
{
"id": "hardware_authorization",
"passed": false,
"stages": [
1,
2,
5
],
"detail": "not granted"
},
{
"id": "safety_checklist",
"passed": false,
"stages": [
1,
2,
5
],
"detail": "not attested"
}
],
"hardware_boundary": "Pinned stage 1 can actuate during real_env.reset; stage 2 connects hardware and disables torque; stages 3-4 are GPU-only; stage 5 actuates the policy.",
"actuation_attempted": false
}
@@ -0,0 +1,310 @@
{
"artifacts": [
{
"kind": "checkpoint",
"path": "randomized_policy.pt",
"sha256": "decd8f40b95080f4d56153a7b2ccfe2985d687c392fe4032e78ce348263ffd9f"
},
{
"kind": "metrics",
"path": "metrics.json",
"sha256": "01f2f89fe8f5d963881d0ecef8fdb19b5b3e8c065caa922feb270a139b888096"
},
{
"kind": "matrix",
"path": "matrix.json",
"sha256": "07a58e4626c974182a505bba798130395bb2cc068e2faba2d588e1e3bd853d0f"
},
{
"kind": "source_preview",
"path": "source_preview.png",
"sha256": "dbee52ca55dc4c2a2e0822e30674f4eb904d142f05caa9cda8d6127752293de0"
},
{
"kind": "target_preview",
"path": "target_preview.png",
"sha256": "34cf04b1cc78675bdd4e060a6b5b47610a18619d5738c0ad0590cfd48f087970"
}
],
"blockers": [],
"experiment_id": "6-13",
"hardware_extension": {
"actuation_attempted": false,
"status": "gated",
"upstream": "StoneT2000/lerobot-sim2real"
},
"kind": "local_gpu_rgb_domain_transfer",
"metrics": {
"dataset_replay_match": true,
"device": {
"device": "mps",
"name": "Apple Metal Performance Shaders",
"torch": "2.7.0"
},
"protocol": {
"epochs": 10,
"seeds": [
20260808,
20260809,
20260810
],
"target_domains": [
"target_realistic",
"target_bright"
],
"test_size_per_domain": 1024,
"total_training_examples": 49152,
"train_size_per_variant": 4096,
"variants": [
"source_clean",
"source_background",
"source_appearance",
"source_full"
]
},
"rows": [
{
"final_loss": 0.18679947033524513,
"seed": 20260808,
"source_accuracy": 0.921875,
"target_accuracy": {
"target_bright": 0.798828125,
"target_realistic": 0.8095703125
},
"variant": "source_clean"
},
{
"final_loss": 0.24417539592832327,
"seed": 20260808,
"source_accuracy": 0.908203125,
"target_accuracy": {
"target_bright": 0.533203125,
"target_realistic": 0.4169921875
},
"variant": "source_background"
},
{
"final_loss": 0.22985628596507013,
"seed": 20260808,
"source_accuracy": 0.90234375,
"target_accuracy": {
"target_bright": 0.857421875,
"target_realistic": 0.7880859375
},
"variant": "source_appearance"
},
{
"final_loss": 0.4308899687603116,
"seed": 20260808,
"source_accuracy": 0.857421875,
"target_accuracy": {
"target_bright": 0.771484375,
"target_realistic": 0.7578125
},
"variant": "source_full"
},
{
"final_loss": 0.11670511157717556,
"seed": 20260809,
"source_accuracy": 0.939453125,
"target_accuracy": {
"target_bright": 0.2880859375,
"target_realistic": 0.248046875
},
"variant": "source_clean"
},
{
"final_loss": 0.20411560125648975,
"seed": 20260809,
"source_accuracy": 0.921875,
"target_accuracy": {
"target_bright": 0.478515625,
"target_realistic": 0.353515625
},
"variant": "source_background"
},
{
"final_loss": 0.23631400940939784,
"seed": 20260809,
"source_accuracy": 0.876953125,
"target_accuracy": {
"target_bright": 0.8046875,
"target_realistic": 0.7568359375
},
"variant": "source_appearance"
},
{
"final_loss": 0.4168223310261965,
"seed": 20260809,
"source_accuracy": 0.9072265625,
"target_accuracy": {
"target_bright": 0.8212890625,
"target_realistic": 0.796875
},
"variant": "source_full"
},
{
"final_loss": 0.13805983471684158,
"seed": 20260810,
"source_accuracy": 0.9296875,
"target_accuracy": {
"target_bright": 0.609375,
"target_realistic": 0.5869140625
},
"variant": "source_clean"
},
{
"final_loss": 0.29387020831927657,
"seed": 20260810,
"source_accuracy": 0.8955078125,
"target_accuracy": {
"target_bright": 0.576171875,
"target_realistic": 0.3359375
},
"variant": "source_background"
},
{
"final_loss": 0.21353492327034473,
"seed": 20260810,
"source_accuracy": 0.8974609375,
"target_accuracy": {
"target_bright": 0.8310546875,
"target_realistic": 0.6865234375
},
"variant": "source_appearance"
},
{
"final_loss": 0.35220852866768837,
"seed": 20260810,
"source_accuracy": 0.8603515625,
"target_accuracy": {
"target_bright": 0.8134765625,
"target_realistic": 0.728515625
},
"variant": "source_full"
}
],
"summary": {
"source_appearance": {
"source": {
"mean": 0.8922526041666666,
"std": 0.011000485187966017,
"values": [
0.90234375,
0.876953125,
0.8974609375
]
},
"target_bright": {
"mean": 0.8310546875,
"std": 0.021528718442430275,
"values": [
0.857421875,
0.8046875,
0.8310546875
]
},
"target_realistic": {
"mean": 0.7438151041666666,
"std": 0.04247267299557315,
"values": [
0.7880859375,
0.7568359375,
0.6865234375
]
}
},
"source_background": {
"source": {
"mean": 0.9085286458333334,
"std": 0.010766819927435695,
"values": [
0.908203125,
0.921875,
0.8955078125
]
},
"target_bright": {
"mean": 0.529296875,
"std": 0.03996356576360106,
"values": [
0.533203125,
0.478515625,
0.576171875
]
},
"target_realistic": {
"mean": 0.3688151041666667,
"std": 0.03481399276640658,
"values": [
0.4169921875,
0.353515625,
0.3359375
]
}
},
"source_clean": {
"source": {
"mean": 0.9303385416666666,
"std": 0.007190990245564624,
"values": [
0.921875,
0.939453125,
0.9296875
]
},
"target_bright": {
"mean": 0.5654296875,
"std": 0.21081237849663584,
"values": [
0.798828125,
0.2880859375,
0.609375
]
},
"target_realistic": {
"mean": 0.5481770833333334,
"std": 0.23087162072123282,
"values": [
0.8095703125,
0.248046875,
0.5869140625
]
}
},
"source_full": {
"source": {
"mean": 0.875,
"std": 0.022818987198335788,
"values": [
0.857421875,
0.9072265625,
0.8603515625
]
},
"target_bright": {
"mean": 0.8020833333333334,
"std": 0.02187054301073024,
"values": [
0.771484375,
0.8212890625,
0.8134765625
]
},
"target_realistic": {
"mean": 0.7610677083333334,
"std": 0.02800236089532105,
"values": [
0.7578125,
0.796875,
0.728515625
]
}
}
},
"wall_time_ms": 29262.792
},
"schema_version": "3.0",
"seed": 20260808,
"status": "complete"
}
@@ -0,0 +1,242 @@
{
"rows": [
{
"final_loss": 0.18679947033524513,
"seed": 20260808,
"source_accuracy": 0.921875,
"target_accuracy": {
"target_bright": 0.798828125,
"target_realistic": 0.8095703125
},
"variant": "source_clean"
},
{
"final_loss": 0.24417539592832327,
"seed": 20260808,
"source_accuracy": 0.908203125,
"target_accuracy": {
"target_bright": 0.533203125,
"target_realistic": 0.4169921875
},
"variant": "source_background"
},
{
"final_loss": 0.22985628596507013,
"seed": 20260808,
"source_accuracy": 0.90234375,
"target_accuracy": {
"target_bright": 0.857421875,
"target_realistic": 0.7880859375
},
"variant": "source_appearance"
},
{
"final_loss": 0.4308899687603116,
"seed": 20260808,
"source_accuracy": 0.857421875,
"target_accuracy": {
"target_bright": 0.771484375,
"target_realistic": 0.7578125
},
"variant": "source_full"
},
{
"final_loss": 0.11670511157717556,
"seed": 20260809,
"source_accuracy": 0.939453125,
"target_accuracy": {
"target_bright": 0.2880859375,
"target_realistic": 0.248046875
},
"variant": "source_clean"
},
{
"final_loss": 0.20411560125648975,
"seed": 20260809,
"source_accuracy": 0.921875,
"target_accuracy": {
"target_bright": 0.478515625,
"target_realistic": 0.353515625
},
"variant": "source_background"
},
{
"final_loss": 0.23631400940939784,
"seed": 20260809,
"source_accuracy": 0.876953125,
"target_accuracy": {
"target_bright": 0.8046875,
"target_realistic": 0.7568359375
},
"variant": "source_appearance"
},
{
"final_loss": 0.4168223310261965,
"seed": 20260809,
"source_accuracy": 0.9072265625,
"target_accuracy": {
"target_bright": 0.8212890625,
"target_realistic": 0.796875
},
"variant": "source_full"
},
{
"final_loss": 0.13805983471684158,
"seed": 20260810,
"source_accuracy": 0.9296875,
"target_accuracy": {
"target_bright": 0.609375,
"target_realistic": 0.5869140625
},
"variant": "source_clean"
},
{
"final_loss": 0.29387020831927657,
"seed": 20260810,
"source_accuracy": 0.8955078125,
"target_accuracy": {
"target_bright": 0.576171875,
"target_realistic": 0.3359375
},
"variant": "source_background"
},
{
"final_loss": 0.21353492327034473,
"seed": 20260810,
"source_accuracy": 0.8974609375,
"target_accuracy": {
"target_bright": 0.8310546875,
"target_realistic": 0.6865234375
},
"variant": "source_appearance"
},
{
"final_loss": 0.35220852866768837,
"seed": 20260810,
"source_accuracy": 0.8603515625,
"target_accuracy": {
"target_bright": 0.8134765625,
"target_realistic": 0.728515625
},
"variant": "source_full"
}
],
"summary": {
"source_appearance": {
"source": {
"mean": 0.8922526041666666,
"std": 0.011000485187966017,
"values": [
0.90234375,
0.876953125,
0.8974609375
]
},
"target_bright": {
"mean": 0.8310546875,
"std": 0.021528718442430275,
"values": [
0.857421875,
0.8046875,
0.8310546875
]
},
"target_realistic": {
"mean": 0.7438151041666666,
"std": 0.04247267299557315,
"values": [
0.7880859375,
0.7568359375,
0.6865234375
]
}
},
"source_background": {
"source": {
"mean": 0.9085286458333334,
"std": 0.010766819927435695,
"values": [
0.908203125,
0.921875,
0.8955078125
]
},
"target_bright": {
"mean": 0.529296875,
"std": 0.03996356576360106,
"values": [
0.533203125,
0.478515625,
0.576171875
]
},
"target_realistic": {
"mean": 0.3688151041666667,
"std": 0.03481399276640658,
"values": [
0.4169921875,
0.353515625,
0.3359375
]
}
},
"source_clean": {
"source": {
"mean": 0.9303385416666666,
"std": 0.007190990245564624,
"values": [
0.921875,
0.939453125,
0.9296875
]
},
"target_bright": {
"mean": 0.5654296875,
"std": 0.21081237849663584,
"values": [
0.798828125,
0.2880859375,
0.609375
]
},
"target_realistic": {
"mean": 0.5481770833333334,
"std": 0.23087162072123282,
"values": [
0.8095703125,
0.248046875,
0.5869140625
]
}
},
"source_full": {
"source": {
"mean": 0.875,
"std": 0.022818987198335788,
"values": [
0.857421875,
0.9072265625,
0.8603515625
]
},
"target_bright": {
"mean": 0.8020833333333334,
"std": 0.02187054301073024,
"values": [
0.771484375,
0.8212890625,
0.8134765625
]
},
"target_realistic": {
"mean": 0.7610677083333334,
"std": 0.02800236089532105,
"values": [
0.7578125,
0.796875,
0.728515625
]
}
}
}
}
@@ -0,0 +1,270 @@
{
"dataset_replay_match": true,
"device": {
"device": "mps",
"name": "Apple Metal Performance Shaders",
"torch": "2.7.0"
},
"protocol": {
"epochs": 10,
"seeds": [
20260808,
20260809,
20260810
],
"target_domains": [
"target_realistic",
"target_bright"
],
"test_size_per_domain": 1024,
"total_training_examples": 49152,
"train_size_per_variant": 4096,
"variants": [
"source_clean",
"source_background",
"source_appearance",
"source_full"
]
},
"rows": [
{
"final_loss": 0.18679947033524513,
"seed": 20260808,
"source_accuracy": 0.921875,
"target_accuracy": {
"target_bright": 0.798828125,
"target_realistic": 0.8095703125
},
"variant": "source_clean"
},
{
"final_loss": 0.24417539592832327,
"seed": 20260808,
"source_accuracy": 0.908203125,
"target_accuracy": {
"target_bright": 0.533203125,
"target_realistic": 0.4169921875
},
"variant": "source_background"
},
{
"final_loss": 0.22985628596507013,
"seed": 20260808,
"source_accuracy": 0.90234375,
"target_accuracy": {
"target_bright": 0.857421875,
"target_realistic": 0.7880859375
},
"variant": "source_appearance"
},
{
"final_loss": 0.4308899687603116,
"seed": 20260808,
"source_accuracy": 0.857421875,
"target_accuracy": {
"target_bright": 0.771484375,
"target_realistic": 0.7578125
},
"variant": "source_full"
},
{
"final_loss": 0.11670511157717556,
"seed": 20260809,
"source_accuracy": 0.939453125,
"target_accuracy": {
"target_bright": 0.2880859375,
"target_realistic": 0.248046875
},
"variant": "source_clean"
},
{
"final_loss": 0.20411560125648975,
"seed": 20260809,
"source_accuracy": 0.921875,
"target_accuracy": {
"target_bright": 0.478515625,
"target_realistic": 0.353515625
},
"variant": "source_background"
},
{
"final_loss": 0.23631400940939784,
"seed": 20260809,
"source_accuracy": 0.876953125,
"target_accuracy": {
"target_bright": 0.8046875,
"target_realistic": 0.7568359375
},
"variant": "source_appearance"
},
{
"final_loss": 0.4168223310261965,
"seed": 20260809,
"source_accuracy": 0.9072265625,
"target_accuracy": {
"target_bright": 0.8212890625,
"target_realistic": 0.796875
},
"variant": "source_full"
},
{
"final_loss": 0.13805983471684158,
"seed": 20260810,
"source_accuracy": 0.9296875,
"target_accuracy": {
"target_bright": 0.609375,
"target_realistic": 0.5869140625
},
"variant": "source_clean"
},
{
"final_loss": 0.29387020831927657,
"seed": 20260810,
"source_accuracy": 0.8955078125,
"target_accuracy": {
"target_bright": 0.576171875,
"target_realistic": 0.3359375
},
"variant": "source_background"
},
{
"final_loss": 0.21353492327034473,
"seed": 20260810,
"source_accuracy": 0.8974609375,
"target_accuracy": {
"target_bright": 0.8310546875,
"target_realistic": 0.6865234375
},
"variant": "source_appearance"
},
{
"final_loss": 0.35220852866768837,
"seed": 20260810,
"source_accuracy": 0.8603515625,
"target_accuracy": {
"target_bright": 0.8134765625,
"target_realistic": 0.728515625
},
"variant": "source_full"
}
],
"summary": {
"source_appearance": {
"source": {
"mean": 0.8922526041666666,
"std": 0.011000485187966017,
"values": [
0.90234375,
0.876953125,
0.8974609375
]
},
"target_bright": {
"mean": 0.8310546875,
"std": 0.021528718442430275,
"values": [
0.857421875,
0.8046875,
0.8310546875
]
},
"target_realistic": {
"mean": 0.7438151041666666,
"std": 0.04247267299557315,
"values": [
0.7880859375,
0.7568359375,
0.6865234375
]
}
},
"source_background": {
"source": {
"mean": 0.9085286458333334,
"std": 0.010766819927435695,
"values": [
0.908203125,
0.921875,
0.8955078125
]
},
"target_bright": {
"mean": 0.529296875,
"std": 0.03996356576360106,
"values": [
0.533203125,
0.478515625,
0.576171875
]
},
"target_realistic": {
"mean": 0.3688151041666667,
"std": 0.03481399276640658,
"values": [
0.4169921875,
0.353515625,
0.3359375
]
}
},
"source_clean": {
"source": {
"mean": 0.9303385416666666,
"std": 0.007190990245564624,
"values": [
0.921875,
0.939453125,
0.9296875
]
},
"target_bright": {
"mean": 0.5654296875,
"std": 0.21081237849663584,
"values": [
0.798828125,
0.2880859375,
0.609375
]
},
"target_realistic": {
"mean": 0.5481770833333334,
"std": 0.23087162072123282,
"values": [
0.8095703125,
0.248046875,
0.5869140625
]
}
},
"source_full": {
"source": {
"mean": 0.875,
"std": 0.022818987198335788,
"values": [
0.857421875,
0.9072265625,
0.8603515625
]
},
"target_bright": {
"mean": 0.8020833333333334,
"std": 0.02187054301073024,
"values": [
0.771484375,
0.8212890625,
0.8134765625
]
},
"target_realistic": {
"mean": 0.7610677083333334,
"std": 0.02800236089532105,
"values": [
0.7578125,
0.796875,
0.728515625
]
}
}
},
"wall_time_ms": 29262.792
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB