Huyt's picture
Upload eval_final.py with huggingface_hub
a12e09f verified
Raw
History Blame Contribute Delete
2.75 kB
"""Re-evaluate a checkpoint using timm's canonical inference transform.
train.py evaluates with its own Resize/CenterCrop, which differs slightly from the
transform timm.data.create_transform builds from the model config -- the one a
downstream user gets by following the README. Reporting numbers from that path keeps
the model card reproducible.
"""
import json
import sys
from pathlib import Path
import numpy as np
import timm
import torch
from PIL import Image, ImageFile
from sklearn.metrics import classification_report, confusion_matrix, f1_score
from torch.utils.data import DataLoader, Dataset
ImageFile.LOAD_TRUNCATED_IMAGES = True
HERE = Path(__file__).parent
CACHE = HERE / "data_256"
class DS(Dataset):
def __init__(self, files, labels, idx, tf):
self.f = [files[i] for i in idx]
self.y = [labels[i] for i in idx]
self.tf = tf
def __len__(self):
return len(self.f)
def __getitem__(self, i):
with Image.open((CACHE / self.f[i]).with_suffix(".jpg")) as im:
return self.tf(im.convert("RGB")), self.y[i]
def main(run_dir: str):
run = Path(run_dir)
r = json.loads((run / "results.json").read_text())
split = json.loads((HERE / "splits.json").read_text())
model = timm.create_model(r["model"], pretrained=False, num_classes=len(r["classes"]))
model.load_state_dict(torch.load(run / "best.pt", map_location="cpu"))
model.eval().cuda()
cfg = timm.data.resolve_data_config({}, model=model)
tf = timm.data.create_transform(**cfg)
print("eval transform:", cfg)
out = {}
for name in ("val", "test"):
dl = DataLoader(DS(split["files"], split["labels"], split[name], tf),
batch_size=128, num_workers=8, pin_memory=True)
P, G = [], []
with torch.no_grad():
for x, y in dl:
P.append(model(x.cuda()).argmax(1).cpu())
G.append(y)
p, g = torch.cat(P).numpy(), torch.cat(G).numpy()
out[name] = (p, g, (p == g).mean(), f1_score(g, p, average="macro", zero_division=0))
print(f"{name}: acc {out[name][2]:.4f} macro-F1 {out[name][3]:.4f}")
p, g, acc, f1 = out["test"]
r["test_acc"] = float(acc)
r["test_macro_f1"] = float(f1)
r["val_macro_f1_timm_tf"] = float(out["val"][3])
r["eval_transform"] = "timm.data.create_transform (canonical)"
r["report"] = classification_report(g, p, target_names=r["classes"],
output_dict=True, zero_division=0)
r["confusion_matrix"] = confusion_matrix(g, p).tolist()
(run / "results.json").write_text(json.dumps(r, indent=2))
print(f"updated {run}/results.json")
if __name__ == "__main__":
main(sys.argv[1])