Image Classification
Transformers
Safetensors
nula
computer-vision
cnn
cifar10
adversarial-robustness
stress-test
downsampling
anti-aliasing
custom_code
Instructions to use MamaPearl/nula-cifar10-robust-v0 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use MamaPearl/nula-cifar10-robust-v0 with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("image-classification", model="MamaPearl/nula-cifar10-robust-v0", trust_remote_code=True) pipe("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/hub/parrots.png")# Load model directly from transformers import AutoModelForImageClassification model = AutoModelForImageClassification.from_pretrained("MamaPearl/nula-cifar10-robust-v0", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
Update train.py
Browse files
train.py
CHANGED
|
@@ -1,155 +1,103 @@
|
|
| 1 |
-
|
| 2 |
-
import
|
| 3 |
-
from torch.
|
| 4 |
-
from
|
| 5 |
from tqdm.auto import tqdm
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
self.ds = hf_ds
|
| 23 |
-
self.transform = transform
|
| 24 |
-
|
| 25 |
-
def __len__(self):
|
| 26 |
-
return len(self.ds)
|
| 27 |
-
|
| 28 |
-
def __getitem__(self, i):
|
| 29 |
-
ex = self.ds[i]
|
| 30 |
-
img = ex["img"]
|
| 31 |
-
label = ex["label"]
|
| 32 |
-
|
| 33 |
-
if not isinstance(img, Image.Image):
|
| 34 |
-
img = Image.fromarray(img)
|
| 35 |
-
x = self.transform(img)
|
| 36 |
-
return { "pixel_values": x, "labels": label }
|
| 37 |
-
|
| 38 |
-
train_ds = CIFAR10Wrapper(dataset["train"], train_transform)
|
| 39 |
-
test_ds = CIFAR10Wrapper(dataset["test"], test_transform)
|
| 40 |
-
|
| 41 |
-
train_loader = DataLoader(
|
| 42 |
-
train_ds,
|
| 43 |
-
batch_size=128,
|
| 44 |
-
shuffle=True,
|
| 45 |
-
num_workers=0,
|
| 46 |
-
pin_memory=True
|
| 47 |
-
)
|
| 48 |
-
|
| 49 |
-
test_loader = DataLoader(
|
| 50 |
-
test_ds,
|
| 51 |
-
batch_size=256,
|
| 52 |
-
shuffle=False,
|
| 53 |
-
num_workers=0,
|
| 54 |
-
pin_memory=True
|
| 55 |
-
)
|
| 56 |
-
|
| 57 |
-
batch = next(iter(train_loader))
|
| 58 |
-
print(batch["pixel_values"].shape)
|
| 59 |
-
print(batch['labels'].shape)
|
| 60 |
-
from torch.optim.lr_scheduler import SequentialLR, LinearLR, CosineAnnealingLR
|
| 61 |
-
|
| 62 |
-
cfg = NulaConfig(
|
| 63 |
-
block_channels=(128, 256, 512),
|
| 64 |
-
classifier_hidden_dim=512,
|
| 65 |
-
use_se=True
|
| 66 |
-
)
|
| 67 |
-
|
| 68 |
-
DEVICE = "cuda" if pt.cuda.is_available() else "cpu"
|
| 69 |
-
model = NulaForImageClassification(cfg).to(DEVICE)
|
| 70 |
-
|
| 71 |
-
optimizer = pt.optim.AdamW(
|
| 72 |
-
model.parameters(),
|
| 73 |
-
lr=1e-3,
|
| 74 |
-
weight_decay=0.01
|
| 75 |
-
)
|
| 76 |
-
warmup = LinearLR(optimizer, start_factor=0.1, end_factor=1.0, total_iters=5)
|
| 77 |
-
cosine = CosineAnnealingLR(optimizer, T_max=45)
|
| 78 |
-
scheduler = SequentialLR(optimizer, schedulers=[warmup, cosine], milestones=[5])
|
| 79 |
-
|
| 80 |
-
def train_one_epoch(model, loader, optimizer, device, grad_clip=1.0):
|
| 81 |
model.train()
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
total_correct = 0
|
| 85 |
-
total_examples = 0
|
| 86 |
-
|
| 87 |
-
pbar = tqdm(loader, desc="training...", leave=False)
|
| 88 |
-
|
| 89 |
for batch in pbar:
|
| 90 |
x = batch["pixel_values"].to(device, non_blocking=True)
|
| 91 |
y = batch["labels"].to(device, non_blocking=True)
|
| 92 |
optimizer.zero_grad(set_to_none=True)
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
optimizer.step()
|
| 102 |
total_loss += loss.item() * y.size(0)
|
| 103 |
-
|
| 104 |
-
total_correct += (preds == y).sum().item()
|
| 105 |
total_examples += y.size(0)
|
| 106 |
-
|
| 107 |
pbar.set_postfix(loss=f"{loss.item():.4f}", acc=f"{100 * total_correct / total_examples:.2f}%")
|
| 108 |
return total_loss / total_examples, total_correct / total_examples
|
| 109 |
|
| 110 |
@pt.no_grad()
|
| 111 |
def evaluate(model, loader, device):
|
| 112 |
model.eval()
|
| 113 |
-
total_loss = 0.0
|
| 114 |
-
total_correct = 0
|
| 115 |
-
total_examples = 0
|
| 116 |
-
|
| 117 |
for batch in loader:
|
| 118 |
x = batch["pixel_values"].to(device, non_blocking=True)
|
| 119 |
y = batch["labels"].to(device, non_blocking=True)
|
| 120 |
-
|
| 121 |
out = model(pixel_values=x, labels=y)
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
preds = logits.argmax(dim=1)
|
| 125 |
-
|
| 126 |
-
total_loss += loss.item() * y.size(0)
|
| 127 |
-
total_correct += (preds == y).sum().item()
|
| 128 |
total_examples += y.size(0)
|
| 129 |
return total_loss / total_examples, total_correct / total_examples
|
| 130 |
|
| 131 |
-
|
| 132 |
-
best_val_acc = 0.0
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import torch as pt
|
| 3 |
+
from torch.amp import autocast, GradScaler
|
| 4 |
+
from torch.optim.lr_scheduler import LinearLR, CosineAnnealingLR, SequentialLR
|
| 5 |
from tqdm.auto import tqdm
|
| 6 |
+
from safetensors.torch import load_file
|
| 7 |
+
from src.configuration_nula import NulaConfig
|
| 8 |
+
from src.modeling_nula import NulaForImageClassification
|
| 9 |
+
from src.dataset import get_loaders, get_device
|
| 10 |
+
|
| 11 |
+
NUM_EPOCHS = 50
|
| 12 |
+
LR = 1e-3
|
| 13 |
+
WEIGHT_DECAY = 0.01
|
| 14 |
+
WARMUP_STEPS = 5
|
| 15 |
+
GRAD_CLIP = 1.0
|
| 16 |
+
SAVE_EVERY = 5
|
| 17 |
+
CHECKPOINT_DIR = "./checkpoints"
|
| 18 |
+
BEST_MODEL_DIR = "./nula-best-model"
|
| 19 |
+
FINAL_MODEL_DIR = "./nula-final-model"
|
| 20 |
+
|
| 21 |
+
def train_epoch(model, loader, optimizer, scaler, device, epoch):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
model.train()
|
| 23 |
+
total_loss, total_correct, total_examples = 0.0, 0, 0
|
| 24 |
+
pbar = tqdm(loader, desc=f"epoch {epoch}", leave=False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
for batch in pbar:
|
| 26 |
x = batch["pixel_values"].to(device, non_blocking=True)
|
| 27 |
y = batch["labels"].to(device, non_blocking=True)
|
| 28 |
optimizer.zero_grad(set_to_none=True)
|
| 29 |
+
with autocast("cuda"):
|
| 30 |
+
out = model(pixel_values=x, labels=y)
|
| 31 |
+
loss = out.loss
|
| 32 |
+
scaler.scale(loss).backward()
|
| 33 |
+
scaler.unscale_(optimizer)
|
| 34 |
+
pt.nn.utils.clip_grad_norm_(model.parameters(), max_norm=GRAD_CLIP)
|
| 35 |
+
scaler.step(optimizer)
|
| 36 |
+
scaler.update()
|
|
|
|
| 37 |
total_loss += loss.item() * y.size(0)
|
| 38 |
+
total_correct += (out.logits.argmax(dim=1) == y).sum().item()
|
|
|
|
| 39 |
total_examples += y.size(0)
|
|
|
|
| 40 |
pbar.set_postfix(loss=f"{loss.item():.4f}", acc=f"{100 * total_correct / total_examples:.2f}%")
|
| 41 |
return total_loss / total_examples, total_correct / total_examples
|
| 42 |
|
| 43 |
@pt.no_grad()
|
| 44 |
def evaluate(model, loader, device):
|
| 45 |
model.eval()
|
| 46 |
+
total_loss, total_correct, total_examples = 0.0, 0, 0
|
|
|
|
|
|
|
|
|
|
| 47 |
for batch in loader:
|
| 48 |
x = batch["pixel_values"].to(device, non_blocking=True)
|
| 49 |
y = batch["labels"].to(device, non_blocking=True)
|
|
|
|
| 50 |
out = model(pixel_values=x, labels=y)
|
| 51 |
+
total_loss += out.loss.item() * y.size(0)
|
| 52 |
+
total_correct += (out.logits.argmax(dim=1) == y).sum().item()
|
|
|
|
|
|
|
|
|
|
|
|
|
| 53 |
total_examples += y.size(0)
|
| 54 |
return total_loss / total_examples, total_correct / total_examples
|
| 55 |
|
| 56 |
+
def train_model(model, train_loader, test_loader, optimizer, scheduler, scaler, device):
|
| 57 |
+
best_val_acc = 0.0
|
| 58 |
+
os.makedirs(CHECKPOINT_DIR, exist_ok=True)
|
| 59 |
+
|
| 60 |
+
print(f"training on {device}")
|
| 61 |
+
for epoch in range(1, NUM_EPOCHS + 1):
|
| 62 |
+
train_loss, train_acc = train_epoch(model, train_loader, optimizer, scaler, device, epoch)
|
| 63 |
+
val_loss, val_acc = evaluate(model, test_loader, device)
|
| 64 |
+
scheduler.step()
|
| 65 |
+
|
| 66 |
+
if epoch % SAVE_EVERY == 0:
|
| 67 |
+
save_path = f"{CHECKPOINT_DIR}/epoch{epoch}"
|
| 68 |
+
model.save_pretrained(save_path)
|
| 69 |
+
|
| 70 |
+
if val_acc > best_val_acc:
|
| 71 |
+
best_val_acc = val_acc
|
| 72 |
+
model.save_pretrained(BEST_MODEL_DIR)
|
| 73 |
+
print(f"new best: {100 * best_val_acc:.2f}%")
|
| 74 |
+
|
| 75 |
+
current_lr = optimizer.param_groups[0]["lr"]
|
| 76 |
+
print(f"={'—'*60}=")
|
| 77 |
+
print(f"epoch [{epoch}/{NUM_EPOCHS}]")
|
| 78 |
+
print(f"lr: {current_lr:.6f}")
|
| 79 |
+
print(f"train_loss: {train_loss:.4f}")
|
| 80 |
+
print(f"train_acc: {train_acc*100:.2f}%")
|
| 81 |
+
print(f"val loss: {val_loss:.4f}")
|
| 82 |
+
print(f"val_acc: {val_acc*100:.2f}%")
|
| 83 |
+
print(f"best: {best_val_acc*100:.2f}%")
|
| 84 |
+
|
| 85 |
+
model.save_pretrained(FINAL_MODEL_DIR)
|
| 86 |
+
print("final model saved")
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
if __name__ == "__main__":
|
| 90 |
+
DEVICE = get_device()
|
| 91 |
+
train_loader, test_loader = get_loaders()
|
| 92 |
+
|
| 93 |
+
cfg = NulaConfig(block_channels=(128, 256, 512), classifier_hidden_dim=512, use_se=True)
|
| 94 |
+
model = NulaForImageClassification(cfg).to(DEVICE)
|
| 95 |
+
|
| 96 |
+
optimizer = pt.optim.AdamW(model.parameters(), lr=LR, weight_decay=WEIGHT_DECAY)
|
| 97 |
+
warmup = LinearLR(optimizer, start_factor=0.1, end_factor=1.0, total_iters=WARMUP_STEPS)
|
| 98 |
+
cosine = CosineAnnealingLR(optimizer, T_max=NUM_EPOCHS - WARMUP_STEPS)
|
| 99 |
+
scheduler = SequentialLR(optimizer, schedulers=[warmup, cosine], milestones=[WARMUP_STEPS])
|
| 100 |
+
scaler = GradScaler("cuda")
|
| 101 |
+
|
| 102 |
+
print("enjoy <3\n")
|
| 103 |
+
train_model(model, train_loader, test_loader, optimizer, scheduler, scaler, DEVICE)
|