Image Segmentation
PyTorch
English
painting-vision-robotics-kit
semantic-segmentation
robotics
edge-ai
construction-ai
autonomous-painting
wall-painting-robot
paint-coverage-estimation
building-facade
drywall
skirting-detection
window-detection
lidar
depth-validation
segformer
deeplabv3
Eval Results (legacy)
Upload test_train_aug.py with huggingface_hub
Browse files- test_train_aug.py +51 -0
test_train_aug.py
CHANGED
|
@@ -63,6 +63,7 @@ def main():
|
|
| 63 |
assert groups[1]["lr"] == 1e-3 and groups[1]["params"] and groups[0]["params"]
|
| 64 |
head_ids = {id(p) for p in groups[1]["params"]}
|
| 65 |
assert all(id(p) in head_ids for p in model.drywall_head.parameters())
|
|
|
|
| 66 |
assert all(id(p) in head_ids for p in model.segmenter.classifier.parameters())
|
| 67 |
print("ok head parameter group")
|
| 68 |
|
|
@@ -76,6 +77,56 @@ def main():
|
|
| 76 |
assert torch.allclose(after, before + 0.5, atol=1e-5)
|
| 77 |
print("ok EMA update")
|
| 78 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 79 |
print("training augmentation tests passed")
|
| 80 |
|
| 81 |
|
|
|
|
| 63 |
assert groups[1]["lr"] == 1e-3 and groups[1]["params"] and groups[0]["params"]
|
| 64 |
head_ids = {id(p) for p in groups[1]["params"]}
|
| 65 |
assert all(id(p) in head_ids for p in model.drywall_head.parameters())
|
| 66 |
+
assert all(id(p) in head_ids for p in model.condition_head.parameters())
|
| 67 |
assert all(id(p) in head_ids for p in model.segmenter.classifier.parameters())
|
| 68 |
print("ok head parameter group")
|
| 69 |
|
|
|
|
| 77 |
assert torch.allclose(after, before + 0.5, atol=1e-5)
|
| 78 |
print("ok EMA update")
|
| 79 |
|
| 80 |
+
# End to end on a tiny synthetic set: wallpaper paste keeps masks valid, and
|
| 81 |
+
# evaluate() scores every class/material with a status and per-source groups.
|
| 82 |
+
import tempfile
|
| 83 |
+
from pathlib import Path
|
| 84 |
+
from torch.utils.data import DataLoader
|
| 85 |
+
from label_schema import CLASSES, MATERIAL_CLASSES
|
| 86 |
+
from make_synthetic_rooms import write_dataset
|
| 87 |
+
from train import WallDataset, evaluate
|
| 88 |
+
with tempfile.TemporaryDirectory() as tmp:
|
| 89 |
+
write_dataset(tmp, {"train": 4, "val": 14}, seed=2, size=(96, 128))
|
| 90 |
+
random.seed(1)
|
| 91 |
+
train_ds = WallDataset(tmp, "train", 96, augment=True, crop=64, wallpaper_paste=1.0)
|
| 92 |
+
for i in range(len(train_ds)):
|
| 93 |
+
x, y, m, c = train_ds[i]
|
| 94 |
+
assert x.shape == (3, 64, 64) and y.shape == m.shape == c.shape == (64, 64)
|
| 95 |
+
assert not ((c != IGNORE) & ~((y >= 1) & (y <= 3))).any(), "condition only on wall"
|
| 96 |
+
wall = (y == 1) | (y == 2)
|
| 97 |
+
assert not ((m != IGNORE) & ~((y >= 1) & (y <= 3))).any()
|
| 98 |
+
assert ((m == 2) & wall).any() or not wall.any(), "pasted wallpaper should be labelled"
|
| 99 |
+
val_ds = WallDataset(tmp, "val", 96)
|
| 100 |
+
assert val_ds.coverage_report()["classes_missing"] == []
|
| 101 |
+
assert val_ds.coverage_report()["materials_missing"] == []
|
| 102 |
+
scores = evaluate(build_model("deeplabv3_mobilenet_v3_large", 10).eval(), DataLoader(val_ds, batch_size=4),
|
| 103 |
+
torch.device("cpu"), groups=val_ds.groups(Path(tmp) / "metadata.csv"))
|
| 104 |
+
assert set(scores["per_class"]) == set(CLASSES) and set(scores["material"]) == set(MATERIAL_CLASSES)
|
| 105 |
+
assert scores["classes_without_ground_truth"] == [] and scores["materials_without_ground_truth"] == []
|
| 106 |
+
assert all(scores["per_class"][c]["iou"] is not None for c in CLASSES)
|
| 107 |
+
assert list(scores["by_group"]) == ["environment:indoor", "source:synthetic"]
|
| 108 |
+
assert scores["images"] == 14 and scores["ece_semantic"] is not None
|
| 109 |
+
assert set(scores["condition"]) == {"sound", "paint_failure", "rust"}
|
| 110 |
+
print("ok wallpaper paste + full-coverage evaluate")
|
| 111 |
+
|
| 112 |
+
# Temperature scaling recovers a known overconfidence factor.
|
| 113 |
+
from train import fit_temperature
|
| 114 |
+
|
| 115 |
+
class Overconfident(torch.nn.Module):
|
| 116 |
+
def forward(self, x):
|
| 117 |
+
n = x.shape[0]
|
| 118 |
+
g = torch.Generator().manual_seed(0)
|
| 119 |
+
logits = torch.randn(n, 10, 16, 16, generator=g)
|
| 120 |
+
return {"semantic": logits * 4.0, "drywall": torch.zeros(n, 3, 16, 16)}
|
| 121 |
+
|
| 122 |
+
g = torch.Generator().manual_seed(0)
|
| 123 |
+
logits = torch.randn(8, 10, 16, 16, generator=g)
|
| 124 |
+
labels = torch.distributions.Categorical(logits=logits.permute(0, 2, 3, 1)).sample()
|
| 125 |
+
loader = [(torch.zeros(8, 3, 16, 16), labels, torch.full((8, 16, 16), IGNORE), torch.full((8, 16, 16), IGNORE))]
|
| 126 |
+
t_sem, t_mat = fit_temperature(Overconfident(), loader, torch.device("cpu"), pixels_per_image=256)
|
| 127 |
+
assert 3.0 < t_sem < 5.5 and t_mat == 1.0, (t_sem, t_mat)
|
| 128 |
+
print("ok temperature scaling")
|
| 129 |
+
|
| 130 |
print("training augmentation tests passed")
|
| 131 |
|
| 132 |
|