Jayce-Ping commited on
Commit
2e9398f
·
verified ·
1 Parent(s): a6c53e4

Add files using upload-large-folder tool

Browse files
frozenlake/data_process.py CHANGED
@@ -234,23 +234,37 @@ def generate_dataset(
234
  with open(out / "path.json", "w") as f:
235
  json.dump(dict(sorted((s["image"], s["path_udrl"]) for s in all_samples)), f, indent=4)
236
 
 
237
  random.seed(seed + 1)
238
- random.shuffle(all_samples)
239
- split = int(len(all_samples) * train_ratio)
240
-
241
- def _jsonl(samples, path):
 
 
 
 
 
 
 
 
 
 
 
 
 
242
  with open(path, "w") as f:
243
  for s in samples:
244
  f.write(json.dumps(s) + "\n")
245
 
246
- _jsonl(all_samples[:split], out / "train.jsonl")
247
- _jsonl(all_samples[split:], out / "test.jsonl")
248
 
249
- for name, samps in [("train", all_samples[:split]), ("test", all_samples[split:])]:
250
- with open(out / f"{name}.csv", "w", newline="") as f:
251
  w = csv.writer(f)
252
  w.writerow(["input_image", "video", "prompt"])
253
- for s in samps:
254
  w.writerow([f"images/{s['image']}", f"videos/{s['video']}", s["prompt"]])
255
 
256
  state.size_progress = progress
@@ -382,8 +396,8 @@ def parse_args():
382
 
383
  gen = sub.add_parser("generate")
384
  gen.add_argument("--output-dir", default="frozenlake")
385
- gen.add_argument("--sizes", type=int, nargs="+", default=[8, 16, 32])
386
- gen.add_argument("--num-per-size", type=int, nargs="+", default=[100, 500, 1000])
387
  gen.add_argument("--p", type=float, default=0.5)
388
  gen.add_argument("--min-path-ratio", type=float, default=0.1)
389
  gen.add_argument("--img-size", type=int, default=1024)
 
234
  with open(out / "path.json", "w") as f:
235
  json.dump(dict(sorted((s["image"], s["path_udrl"]) for s in all_samples)), f, indent=4)
236
 
237
+ # Stratified split: ensure each size is proportionally represented in test set
238
  random.seed(seed + 1)
239
+ by_size: Dict[int, List[Dict]] = {}
240
+ for s in all_samples:
241
+ by_size.setdefault(s["maze_size"], []).append(s)
242
+
243
+ train_samples, test_samples = [], []
244
+ for sz in sorted(by_size):
245
+ group = by_size[sz]
246
+ random.shuffle(group)
247
+ sz_split = int(len(group) * train_ratio)
248
+ train_samples.extend(group[:sz_split])
249
+ test_samples.extend(group[sz_split:])
250
+
251
+ random.shuffle(train_samples)
252
+ random.shuffle(test_samples)
253
+ split = len(train_samples)
254
+
255
+ def _write_jsonl(samples, path):
256
  with open(path, "w") as f:
257
  for s in samples:
258
  f.write(json.dumps(s) + "\n")
259
 
260
+ _write_jsonl(train_samples, out / "train.jsonl")
261
+ _write_jsonl(test_samples, out / "test.jsonl")
262
 
263
+ for name, samples in [("train", train_samples), ("test", test_samples)]:
264
+ with open(out / f"{name}.csv", "w", newline="", encoding="utf-8") as f:
265
  w = csv.writer(f)
266
  w.writerow(["input_image", "video", "prompt"])
267
+ for s in samples:
268
  w.writerow([f"images/{s['image']}", f"videos/{s['video']}", s["prompt"]])
269
 
270
  state.size_progress = progress
 
396
 
397
  gen = sub.add_parser("generate")
398
  gen.add_argument("--output-dir", default="frozenlake")
399
+ gen.add_argument("--sizes", type=int, nargs="+", default=[8, 12, 16, 32])
400
+ gen.add_argument("--num-per-size", type=int, nargs="+", default=[1000, 2000, 5000, 10000])
401
  gen.add_argument("--p", type=float, default=0.5)
402
  gen.add_argument("--min-path-ratio", type=float, default=0.1)
403
  gen.add_argument("--img-size", type=int, default=1024)
maze/data_process.py CHANGED
@@ -308,19 +308,33 @@ def generate_dataset(
308
  with open(out / "path.json", "w") as f:
309
  json.dump(dict(sorted(path_answers.items())), f, indent=4)
310
 
 
311
  random.seed(seed + 1)
312
- random.shuffle(all_samples)
313
- split = int(len(all_samples) * train_ratio)
 
 
 
 
 
 
 
 
 
 
 
 
 
314
 
315
  def _write_jsonl(samples, path):
316
  with open(path, "w") as f:
317
  for s in samples:
318
  f.write(json.dumps(s) + "\n")
319
 
320
- _write_jsonl(all_samples[:split], out / "train.jsonl")
321
- _write_jsonl(all_samples[split:], out / "test.jsonl")
322
 
323
- for name, samples in [("train", all_samples[:split]), ("test", all_samples[split:])]:
324
  with open(out / f"{name}.csv", "w", newline="", encoding="utf-8") as f:
325
  writer = csv.writer(f)
326
  writer.writerow(["input_image", "video", "prompt"])
@@ -354,6 +368,7 @@ def eval_videos(
354
  text_dir: str,
355
  output_json: Optional[str] = None,
356
  gt_json: Optional[str] = None,
 
357
  ):
358
  """
359
  Evaluate a directory of result videos against ground-truth mazes.
@@ -401,6 +416,7 @@ def eval_videos(
401
 
402
  for vpath in tqdm(videos, desc="Extracting paths"):
403
  stem = vpath.stem # e.g. "size8_000"
 
404
  txt_path = txt_root / f"{stem}.txt"
405
 
406
  if not txt_path.exists():
@@ -442,7 +458,7 @@ def eval_videos(
442
  if maze is None:
443
  continue
444
  total_valid += 1
445
- if proc.verify_path(maze["grid"], maze["start"], maze["end"], udrl):
446
  correct += 1
447
  correctly_solved.append({"name": name, "length": len(udrl)})
448
 
@@ -471,7 +487,7 @@ def eval_videos(
471
  if sz not in size_stats:
472
  size_stats[sz] = {"total": 0, "correct": 0}
473
  size_stats[sz]["total"] += 1
474
- if proc.verify_path(maze["grid"], maze["start"], maze["end"], udrl):
475
  size_stats[sz]["correct"] += 1
476
 
477
  if size_stats:
@@ -490,7 +506,7 @@ def eval_videos(
490
 
491
  # Optional: compare with ground-truth JSON for path-length-binned accuracy
492
  if gt_json:
493
- _compare_with_gt(extracted, gt_json, txt_root, proc)
494
 
495
  print(f"{'=' * 50}")
496
 
@@ -500,6 +516,7 @@ def _compare_with_gt(
500
  gt_json_path: str,
501
  txt_root: Path,
502
  proc: MazeProcessor,
 
503
  ):
504
  """Print accuracy binned by ground-truth path length."""
505
  try:
@@ -526,7 +543,7 @@ def _compare_with_gt(
526
 
527
  stem = name.replace(".png", "")
528
  maze = proc.load_text(str(txt_root / f"{stem}.txt"))
529
- if maze and proc.verify_path(maze["grid"], maze["start"], maze["end"], pred_udrl):
530
  bins[label]["correct"] += 1
531
 
532
  if bins:
@@ -539,7 +556,7 @@ def _compare_with_gt(
539
 
540
  # ==================== Verify: Pre-extracted JSON ====================
541
 
542
- def verify_results(json_file: str, text_dir: str):
543
  """
544
  Verify pre-extracted UDRL paths (from a JSON file) against maze .txt files.
545
 
@@ -564,7 +581,7 @@ def verify_results(json_file: str, text_dir: str):
564
  skipped += 1
565
  continue
566
  valid += 1
567
- if proc.verify_path(maze["grid"], maze["start"], maze["end"], udrl):
568
  correct += 1
569
 
570
  acc = (correct / valid * 100) if valid else 0
@@ -586,9 +603,9 @@ def parse_args():
586
  # --- generate ---
587
  gen = sub.add_parser("generate", help="Generate dataset")
588
  gen.add_argument("--output-dir", type=str, default="maze")
589
- gen.add_argument("--sizes", type=int, nargs="+", default=[8, 16, 24, 32])
590
- gen.add_argument("--num-per-size", type=int, nargs="+", default=[100, 500, 1000, 2000])
591
- gen.add_argument("--min-path-ratio", type=float, default=0.3,
592
  help="Min path length as fraction of size²")
593
  gen.add_argument("--img-size", type=int, default=1024)
594
  gen.add_argument("--prompt", type=str,
@@ -616,13 +633,16 @@ def parse_args():
616
  help="Output JSON for extracted paths (default: video_dir/0_result.json)")
617
  ev.add_argument("--gt-json", type=str, default=None,
618
  help="Optional ground-truth path.json for length-binned accuracy")
 
 
619
 
620
  # --- verify ---
621
  ver = sub.add_parser("verify", help="Verify a pre-extracted JSON of UDRL paths")
622
  ver.add_argument("json_file", type=str)
623
  ver.add_argument("--text-dir", type=str, required=True,
624
  help="Directory with maze .txt files")
625
-
 
626
  return p.parse_args()
627
 
628
 
@@ -639,10 +659,11 @@ if __name__ == "__main__":
639
  text_dir=args.text_dir,
640
  output_json=args.output_json,
641
  gt_json=args.gt_json,
 
642
  )
643
 
644
  elif args.command == "verify":
645
- verify_results(args.json_file, args.text_dir)
646
 
647
  else:
648
  print("Usage: python maze_video_gen.py {generate|eval|verify} [options]")
 
308
  with open(out / "path.json", "w") as f:
309
  json.dump(dict(sorted(path_answers.items())), f, indent=4)
310
 
311
+ # Stratified split: ensure each size is proportionally represented in test set
312
  random.seed(seed + 1)
313
+ by_size: Dict[int, List[Dict]] = {}
314
+ for s in all_samples:
315
+ by_size.setdefault(s["maze_size"], []).append(s)
316
+
317
+ train_samples, test_samples = [], []
318
+ for sz in sorted(by_size):
319
+ group = by_size[sz]
320
+ random.shuffle(group)
321
+ sz_split = int(len(group) * train_ratio)
322
+ train_samples.extend(group[:sz_split])
323
+ test_samples.extend(group[sz_split:])
324
+
325
+ random.shuffle(train_samples)
326
+ random.shuffle(test_samples)
327
+ split = len(train_samples)
328
 
329
  def _write_jsonl(samples, path):
330
  with open(path, "w") as f:
331
  for s in samples:
332
  f.write(json.dumps(s) + "\n")
333
 
334
+ _write_jsonl(train_samples, out / "train.jsonl")
335
+ _write_jsonl(test_samples, out / "test.jsonl")
336
 
337
+ for name, samples in [("train", train_samples), ("test", test_samples)]:
338
  with open(out / f"{name}.csv", "w", newline="", encoding="utf-8") as f:
339
  writer = csv.writer(f)
340
  writer.writerow(["input_image", "video", "prompt"])
 
368
  text_dir: str,
369
  output_json: Optional[str] = None,
370
  gt_json: Optional[str] = None,
371
+ strict: bool = True,
372
  ):
373
  """
374
  Evaluate a directory of result videos against ground-truth mazes.
 
416
 
417
  for vpath in tqdm(videos, desc="Extracting paths"):
418
  stem = vpath.stem # e.g. "size8_000"
419
+ stem = stem.replace('_gen', '') # Remove `_gen` suffix
420
  txt_path = txt_root / f"{stem}.txt"
421
 
422
  if not txt_path.exists():
 
458
  if maze is None:
459
  continue
460
  total_valid += 1
461
+ if proc.verify_path(maze["grid"], maze["start"], maze["end"], udrl, strict=strict):
462
  correct += 1
463
  correctly_solved.append({"name": name, "length": len(udrl)})
464
 
 
487
  if sz not in size_stats:
488
  size_stats[sz] = {"total": 0, "correct": 0}
489
  size_stats[sz]["total"] += 1
490
+ if proc.verify_path(maze["grid"], maze["start"], maze["end"], udrl, strict=strict):
491
  size_stats[sz]["correct"] += 1
492
 
493
  if size_stats:
 
506
 
507
  # Optional: compare with ground-truth JSON for path-length-binned accuracy
508
  if gt_json:
509
+ _compare_with_gt(extracted, gt_json, txt_root, proc, strict=strict)
510
 
511
  print(f"{'=' * 50}")
512
 
 
516
  gt_json_path: str,
517
  txt_root: Path,
518
  proc: MazeProcessor,
519
+ strict: bool = True,
520
  ):
521
  """Print accuracy binned by ground-truth path length."""
522
  try:
 
543
 
544
  stem = name.replace(".png", "")
545
  maze = proc.load_text(str(txt_root / f"{stem}.txt"))
546
+ if maze and proc.verify_path(maze["grid"], maze["start"], maze["end"], pred_udrl, strict=strict):
547
  bins[label]["correct"] += 1
548
 
549
  if bins:
 
556
 
557
  # ==================== Verify: Pre-extracted JSON ====================
558
 
559
+ def verify_results(json_file: str, text_dir: str, strict: bool = True):
560
  """
561
  Verify pre-extracted UDRL paths (from a JSON file) against maze .txt files.
562
 
 
581
  skipped += 1
582
  continue
583
  valid += 1
584
+ if proc.verify_path(maze["grid"], maze["start"], maze["end"], udrl, strict=strict):
585
  correct += 1
586
 
587
  acc = (correct / valid * 100) if valid else 0
 
603
  # --- generate ---
604
  gen = sub.add_parser("generate", help="Generate dataset")
605
  gen.add_argument("--output-dir", type=str, default="maze")
606
+ gen.add_argument("--sizes", type=int, nargs="+", default=[8, 12, 16, 32])
607
+ gen.add_argument("--num-per-size", type=int, nargs="+", default=[1000, 1000, 1000, 2000])
608
+ gen.add_argument("--min-path-ratio", type=float, default=0.1,
609
  help="Min path length as fraction of size²")
610
  gen.add_argument("--img-size", type=int, default=1024)
611
  gen.add_argument("--prompt", type=str,
 
633
  help="Output JSON for extracted paths (default: video_dir/0_result.json)")
634
  ev.add_argument("--gt-json", type=str, default=None,
635
  help="Optional ground-truth path.json for length-binned accuracy")
636
+ ev.add_argument("--strict", action="store_true",
637
+ help="Strict verification (exact UDRL match) vs leniency on no-op moves")
638
 
639
  # --- verify ---
640
  ver = sub.add_parser("verify", help="Verify a pre-extracted JSON of UDRL paths")
641
  ver.add_argument("json_file", type=str)
642
  ver.add_argument("--text-dir", type=str, required=True,
643
  help="Directory with maze .txt files")
644
+ ver.add_argument("--strict", action="store_true",
645
+ help="Strict verification (exact UDRL match) vs leniency on no-op moves")
646
  return p.parse_args()
647
 
648
 
 
659
  text_dir=args.text_dir,
660
  output_json=args.output_json,
661
  gt_json=args.gt_json,
662
+ strict=args.strict,
663
  )
664
 
665
  elif args.command == "verify":
666
+ verify_results(args.json_file, args.text_dir, strict=args.strict)
667
 
668
  else:
669
  print("Usage: python maze_video_gen.py {generate|eval|verify} [options]")
maze/maze/checkpoints/Wan2.1-I2V-14B-720P_full_0211/epoch-0.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a8e11f69131acdcfd0a4914e924918814339f25179d5b3283813842028e95b30
3
+ size 613510352
maze/maze/checkpoints/Wan2.1-I2V-14B-720P_lora_0216/epoch-0.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:48adc620a15f2093eaa2521cbd63c63ed8a5f7cb75a26b7ff7e723cbc91f0002
3
+ size 1226928552
maze/maze/checkpoints/Wan2.1-I2V-14B-720P_lora_0216/epoch-1.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f561456a695d513b33524ff7b9a5a38754fa51b986402a4b10045d02f0b93aef
3
+ size 1226928552
maze/maze/checkpoints/Wan2.1-I2V-14B-720P_lora_0216/epoch-2.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e2ef3d06a911780c81669fe80a9a5f756708263f877bddb3e9fb958b181b04c7
3
+ size 1226928552
maze/maze_processor.py CHANGED
@@ -162,7 +162,7 @@ class MazeProcessor:
162
 
163
  # ==================== Verification ====================
164
 
165
- def verify_path(self, grid: Grid, start: Tuple, end: Tuple, udrl: str) -> bool:
166
  """Verify that *udrl* is a wall-respecting walk from *start* to *end*."""
167
  n = len(grid)
168
  r, c = start
@@ -176,6 +176,9 @@ class MazeProcessor:
176
  if not (0 <= nr < n and 0 <= nc < n):
177
  return False
178
  r, c = nr, nc
 
 
 
179
  return (r, c) == end
180
 
181
  # ==================== Text Encoding ====================
 
162
 
163
  # ==================== Verification ====================
164
 
165
+ def verify_path(self, grid: Grid, start: Tuple, end: Tuple, udrl: str, strict : bool = True) -> bool:
166
  """Verify that *udrl* is a wall-respecting walk from *start* to *end*."""
167
  n = len(grid)
168
  r, c = start
 
176
  if not (0 <= nr < n and 0 <= nc < n):
177
  return False
178
  r, c = nr, nc
179
+ if not strict and (r, c) == end:
180
+ break
181
+
182
  return (r, c) == end
183
 
184
  # ==================== Text Encoding ====================
sudoku/generate_dataset.py CHANGED
@@ -437,10 +437,23 @@ def generate_dataset(
437
  f"{sum(1 for s in all_samples if s['clue'] == clue)} videos"
438
  )
439
 
440
- # Final output
441
  random.seed(seed + 1)
442
- random.shuffle(all_samples)
443
- split_idx = int(len(all_samples) * train_ratio)
 
 
 
 
 
 
 
 
 
 
 
 
 
444
 
445
  def write_jsonl(samples, path):
446
  with open(path, 'w') as f:
@@ -448,8 +461,8 @@ def generate_dataset(
448
  json.dump(s, f)
449
  f.write('\n')
450
 
451
- write_jsonl(all_samples[:split_idx], output_dir / "train.jsonl")
452
- write_jsonl(all_samples[split_idx:], output_dir / "test.jsonl")
453
 
454
  # Mark as completed
455
  state.clue_progress = clue_progress
 
437
  f"{sum(1 for s in all_samples if s['clue'] == clue)} videos"
438
  )
439
 
440
+ # Stratified split: ensure each clue level is proportionally represented
441
  random.seed(seed + 1)
442
+ by_clue: Dict[int, List[Dict]] = {}
443
+ for s in all_samples:
444
+ by_clue.setdefault(s["clue"], []).append(s)
445
+
446
+ train_samples, test_samples = [], []
447
+ for clue in sorted(by_clue):
448
+ group = by_clue[clue]
449
+ random.shuffle(group)
450
+ cl_split = int(len(group) * train_ratio)
451
+ train_samples.extend(group[:cl_split])
452
+ test_samples.extend(group[cl_split:])
453
+
454
+ random.shuffle(train_samples)
455
+ random.shuffle(test_samples)
456
+ split_idx = len(train_samples)
457
 
458
  def write_jsonl(samples, path):
459
  with open(path, 'w') as f:
 
461
  json.dump(s, f)
462
  f.write('\n')
463
 
464
+ write_jsonl(train_samples, output_dir / "train.jsonl")
465
+ write_jsonl(test_samples, output_dir / "test.jsonl")
466
 
467
  # Mark as completed
468
  state.clue_progress = clue_progress