Upload encoder/code/k3_kaggle_driver.py with huggingface_hub
Browse files- encoder/code/k3_kaggle_driver.py +57 -16
encoder/code/k3_kaggle_driver.py
CHANGED
|
@@ -11,8 +11,13 @@ holds the sequence so a change is one upload, not one edited cell:
|
|
| 11 |
|
| 12 |
Everything lands in /kaggle/working/k3, which Kaggle saves as the version output.
|
| 13 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
Env: FLIP_NB_STAGES (default "restore,setup,prep,train,export,e2e"),
|
| 15 |
-
FLIP_EPOCHS (matte target, default 20),
|
| 16 |
"""
|
| 17 |
|
| 18 |
import importlib.util
|
|
@@ -23,6 +28,7 @@ import subprocess
|
|
| 23 |
import sys
|
| 24 |
import tarfile
|
| 25 |
import time
|
|
|
|
| 26 |
|
| 27 |
WORK = pathlib.Path(os.environ.get("FLIP_WORK", "/kaggle/working"))
|
| 28 |
OUT = WORK / "k3"
|
|
@@ -31,8 +37,9 @@ K3 = WORK / "k3_encoder_distill.py"
|
|
| 31 |
STAGES = [s.strip() for s in os.environ.get(
|
| 32 |
"FLIP_NB_STAGES", "restore,setup,prep,train,export,e2e").split(",") if s.strip()]
|
| 33 |
EPOCHS = os.environ.get("FLIP_EPOCHS", "20")
|
|
|
|
|
|
|
| 34 |
|
| 35 |
-
os.environ.setdefault("HF_ENDPOINT", "https://hf-mirror.com")
|
| 36 |
os.environ.setdefault("PYTHONUNBUFFERED", "1")
|
| 37 |
|
| 38 |
|
|
@@ -40,25 +47,59 @@ def p(*a):
|
|
| 40 |
print(f"[{time.strftime('%H:%M:%S')}]", *a, flush=True)
|
| 41 |
|
| 42 |
|
| 43 |
-
def
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
|
| 48 |
|
| 49 |
def restore():
|
| 50 |
W = OUT / "weights"
|
| 51 |
W.mkdir(parents=True, exist_ok=True)
|
| 52 |
-
|
| 53 |
-
p("k3 script", K3.stat().st_size, "B")
|
| 54 |
if not (WORK / "inputs").is_dir():
|
| 55 |
-
|
|
|
|
| 56 |
tf.extractall(WORK)
|
| 57 |
for src, dst in (("matte_full.pt", "matte.pt"),
|
| 58 |
("dino_model.pt", "dino.pt"),
|
| 59 |
("vae_model.pt", "vae.pt")):
|
| 60 |
-
|
| 61 |
-
p("weights", dst, (W / dst).stat().st_size)
|
| 62 |
imgs = sorted((WORK / "inputs").rglob("*.jp*g"))
|
| 63 |
p("inputs", len(imgs), "->", imgs[0].name if imgs else None)
|
| 64 |
|
|
@@ -84,7 +125,8 @@ def load_k3():
|
|
| 84 |
|
| 85 |
|
| 86 |
def main():
|
| 87 |
-
p("stages", STAGES, "epochs", EPOCHS)
|
|
|
|
| 88 |
if "restore" in STAGES:
|
| 89 |
restore()
|
| 90 |
if "setup" in STAGES or "prep" in STAGES:
|
|
@@ -92,7 +134,7 @@ def main():
|
|
| 92 |
k3 = None
|
| 93 |
if "train" in STAGES:
|
| 94 |
k3 = load_k3()
|
| 95 |
-
p("
|
| 96 |
k3.train_matte("cuda")
|
| 97 |
import torch # noqa: PLC0415
|
| 98 |
if torch.cuda.is_available():
|
|
@@ -100,14 +142,13 @@ def main():
|
|
| 100 |
if "export" in STAGES:
|
| 101 |
k3 = k3 or load_k3()
|
| 102 |
p("export")
|
| 103 |
-
meta
|
| 104 |
-
p("meta", meta)
|
| 105 |
if "e2e" in STAGES:
|
| 106 |
k3 = k3 or load_k3()
|
| 107 |
p("e2e")
|
| 108 |
k3.e2e()
|
| 109 |
p((OUT / "e2e.json").read_text())
|
| 110 |
-
p("outputs")
|
| 111 |
for f in sorted(OUT.rglob("*")):
|
| 112 |
if f.is_file() and f.suffix in (".onnx", ".json", ".pt", ".txt"):
|
| 113 |
p(" ", f.relative_to(WORK), f.stat().st_size)
|
|
|
|
| 11 |
|
| 12 |
Everything lands in /kaggle/working/k3, which Kaggle saves as the version output.
|
| 13 |
|
| 14 |
+
Why not huggingface_hub for the restore: resolving a file through hf-mirror
|
| 15 |
+
loses the x-repo-commit header, and the hub client reads that as "not on
|
| 16 |
+
huggingface.co". Plain GET on /resolve/main/<path> works on both hosts, so the
|
| 17 |
+
restore goes that way and tries huggingface.co first, the mirror second.
|
| 18 |
+
|
| 19 |
Env: FLIP_NB_STAGES (default "restore,setup,prep,train,export,e2e"),
|
| 20 |
+
FLIP_EPOCHS (matte target, default 20), FLIP_HF_BASE (force one host).
|
| 21 |
"""
|
| 22 |
|
| 23 |
import importlib.util
|
|
|
|
| 28 |
import sys
|
| 29 |
import tarfile
|
| 30 |
import time
|
| 31 |
+
import urllib.request
|
| 32 |
|
| 33 |
WORK = pathlib.Path(os.environ.get("FLIP_WORK", "/kaggle/working"))
|
| 34 |
OUT = WORK / "k3"
|
|
|
|
| 37 |
STAGES = [s.strip() for s in os.environ.get(
|
| 38 |
"FLIP_NB_STAGES", "restore,setup,prep,train,export,e2e").split(",") if s.strip()]
|
| 39 |
EPOCHS = os.environ.get("FLIP_EPOCHS", "20")
|
| 40 |
+
BASES = [b for b in (os.environ.get("FLIP_HF_BASE"),
|
| 41 |
+
"https://huggingface.co", "https://hf-mirror.com") if b]
|
| 42 |
|
|
|
|
| 43 |
os.environ.setdefault("PYTHONUNBUFFERED", "1")
|
| 44 |
|
| 45 |
|
|
|
|
| 47 |
print(f"[{time.strftime('%H:%M:%S')}]", *a, flush=True)
|
| 48 |
|
| 49 |
|
| 50 |
+
def probe():
|
| 51 |
+
for base in BASES:
|
| 52 |
+
t0 = time.time()
|
| 53 |
+
try:
|
| 54 |
+
req = urllib.request.Request(f"{base}/api/models/{REPO_ID}",
|
| 55 |
+
headers={"User-Agent": "flip-k3"})
|
| 56 |
+
with urllib.request.urlopen(req, timeout=25) as fh:
|
| 57 |
+
p("probe", base, fh.status, f"{time.time() - t0:.1f}s")
|
| 58 |
+
except Exception as exc: # noqa: BLE001
|
| 59 |
+
p("probe", base, "FAIL", type(exc).__name__, str(exc)[:120])
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
def get(url, timeout=600):
|
| 63 |
+
req = urllib.request.Request(url, headers={"User-Agent": "flip-k3"})
|
| 64 |
+
with urllib.request.urlopen(req, timeout=timeout) as fh:
|
| 65 |
+
return fh.read()
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
def fetch(path, dst, timeout=600):
|
| 69 |
+
dst = pathlib.Path(dst)
|
| 70 |
+
if dst.exists() and dst.stat().st_size > 1024:
|
| 71 |
+
p("have", dst.name, dst.stat().st_size)
|
| 72 |
+
return dst
|
| 73 |
+
dst.parent.mkdir(parents=True, exist_ok=True)
|
| 74 |
+
err = None
|
| 75 |
+
for base in BASES:
|
| 76 |
+
try:
|
| 77 |
+
t0 = time.time()
|
| 78 |
+
blob = get(f"{base}/{REPO_ID}/resolve/main/{path}", timeout)
|
| 79 |
+
tmp = dst.with_suffix(dst.suffix + ".part")
|
| 80 |
+
tmp.write_bytes(blob)
|
| 81 |
+
os.replace(tmp, dst)
|
| 82 |
+
p("got", dst.name, dst.stat().st_size,
|
| 83 |
+
f"{time.time() - t0:.0f}s from", base)
|
| 84 |
+
return dst
|
| 85 |
+
except Exception as exc: # noqa: BLE001
|
| 86 |
+
err = f"{type(exc).__name__}: {str(exc)[:100]}"
|
| 87 |
+
p(" miss", base, err)
|
| 88 |
+
raise RuntimeError(f"cannot fetch {path}: {err}")
|
| 89 |
|
| 90 |
|
| 91 |
def restore():
|
| 92 |
W = OUT / "weights"
|
| 93 |
W.mkdir(parents=True, exist_ok=True)
|
| 94 |
+
fetch("encoder/code/k3_encoder_distill.py", K3)
|
|
|
|
| 95 |
if not (WORK / "inputs").is_dir():
|
| 96 |
+
tgz = fetch("encoder/checkpoints/inputs.tgz", WORK / "dl/inputs.tgz")
|
| 97 |
+
with tarfile.open(tgz) as tf:
|
| 98 |
tf.extractall(WORK)
|
| 99 |
for src, dst in (("matte_full.pt", "matte.pt"),
|
| 100 |
("dino_model.pt", "dino.pt"),
|
| 101 |
("vae_model.pt", "vae.pt")):
|
| 102 |
+
fetch(f"encoder/checkpoints/{src}", W / dst)
|
|
|
|
| 103 |
imgs = sorted((WORK / "inputs").rglob("*.jp*g"))
|
| 104 |
p("inputs", len(imgs), "->", imgs[0].name if imgs else None)
|
| 105 |
|
|
|
|
| 125 |
|
| 126 |
|
| 127 |
def main():
|
| 128 |
+
p("stages", STAGES, "epochs", EPOCHS, "py", sys.version.split()[0])
|
| 129 |
+
probe()
|
| 130 |
if "restore" in STAGES:
|
| 131 |
restore()
|
| 132 |
if "setup" in STAGES or "prep" in STAGES:
|
|
|
|
| 134 |
k3 = None
|
| 135 |
if "train" in STAGES:
|
| 136 |
k3 = load_k3()
|
| 137 |
+
p("matte: resume from weights/matte.pt, target epoch", EPOCHS)
|
| 138 |
k3.train_matte("cuda")
|
| 139 |
import torch # noqa: PLC0415
|
| 140 |
if torch.cuda.is_available():
|
|
|
|
| 142 |
if "export" in STAGES:
|
| 143 |
k3 = k3 or load_k3()
|
| 144 |
p("export")
|
| 145 |
+
p("meta", k3.export())
|
|
|
|
| 146 |
if "e2e" in STAGES:
|
| 147 |
k3 = k3 or load_k3()
|
| 148 |
p("e2e")
|
| 149 |
k3.e2e()
|
| 150 |
p((OUT / "e2e.json").read_text())
|
| 151 |
+
p("outputs under", OUT)
|
| 152 |
for f in sorted(OUT.rglob("*")):
|
| 153 |
if f.is_file() and f.suffix in (".onnx", ".json", ".pt", ".txt"):
|
| 154 |
p(" ", f.relative_to(WORK), f.stat().st_size)
|