tests/test.sh exit code (0 → resolved); the classification below is post-hoc and cannot change it.ls -la && echo "---SUBMISSION---" && ls -la submission/ && echo "---DATA---" && ls -la data/ && python3 -c "import numpy as np; d=np.load('data/train.npz'); print({k:(v.shape,v.dtype) for k,v in d.items()}); print('y range', d['y'].min(), d['y'].max(), 'classes', len(set(d['y'].tolist()))); print('X range', d['X'].min(), d['X'].max())"total 101
drwxr-xr-x 4 user user 4096 Jun 30 22:15 .
drwxr-xr-x 21 root root 4096 Jun 30 22:15 ..
-rw-r--r-- 1 user user 14238 Jun 30 22:15 PROMPT.txt
-rw-r--r-- 1 user user 5 Jun 30 22:15 agent.pid
-rw-r--r-- 1 user user 0 Jun 30 22:15 agent.stderr
-rw-r--r-- 1 user user 4694 Jun 30 22:15 agent_trajectory.jsonl
drwxr-xr-x 2 user user 60 Jun 30 22:15 data
-rw-r--r-- 1 user user 0 Jun 30 22:15 run.log
-rwxr-xr-x 1 user user 57740 Jun 30 11:01 run_checks.py
drwxr-xr-x 2 user user 128 Jun 30 22:15 submission
-rwxr-xr-x 1 user user 998 Jun 30 11:01 test.sh
-rwxr-xr-x 1 user user 629 Jun 30 11:01 timer.sh
---SUBMISSION---
total 80
drwxr-xr-x 2 user user 128 Jun 30 22:15 .
drwxr-xr-x 4 user user 4096 Jun 30 22:15 ..
-rw-r--r-- 1 user user 5490 Jun 30 11:01 advtrain.py
-rw-r--r-- 1 user user 8776 Jun 30 11:01 attack.py
-rw-r--r-- 1 user user 18341 Jun 30 11:01 autograd.py
-rw-r--r-- 1 user user 2167 Jun 30 11:01 data.py
-rw-r--r-- 1 user user 15988 Jun 30 11:01 nn.py
-rw-r--r-- 1 user user 8853 Jun 30 11:01 optim.py
-rw-r--r-- 1 user user 3742 Jun 30 11:01 train.py
---DATA---
total 2904
drwxr-xr-x 2 user user 60 Jun 30 22:15 .
drwxr-xr-x 4 user user 4096 Jun 30 22:15 ..
-rw-r--r-- 1 user user 2967336 Jun 30 11:01 train.npz
{'X': ((3600, 1, 16, 16), dtype('float32')), 'y': ((3600,), dtype('int64'))}
y range 0 5 classes 6
X range 0.0 1.0/app/submission/autograd.py
1 """Reverse-mode automatic differentiation over numpy arrays (IMPLEMENT THIS). 2 3 A ``Tensor`` wraps a single ``numpy.ndarray`` (``float64``) and records the operation that 4 produced it so that ``.backward()`` can walk the graph in reverse-topological order and 5 accumulate ``.grad`` (the gradient of the scalar on which ``.backward()`` was called w.r.t. 6 this tensor) into every leaf. 7 8 This task is ADVERSARIAL ROBUSTNESS: the model is a small convolutional classifier and the 9 attacks (PGD/FGSM/MI-FGSM/PGD-L2/CW) ascend on the gradient of an attack loss w.r.t. the INPUT 10 image, so the autograd engine must (a) flow gradients back to PARAMETERS (for training) AND 11 (b) flow gradients back to the INPUT tensor (for the attack). BOTH directions are exercised by the 12 verifier's finite-difference gradient checks, so the convolution's input-gradient (the ``_col2im`` 13 adjoint) is load-bearing. 14 15 Contract (the verifier's conformance suite differentiates your analytic backward against finite 16 differences and checks your forward against its own reference, so match this exactly): 17 18 * ``Tensor(data, requires_grad=False)`` -- ``data`` is array-like, stored as ``float64`` in 19 ``self.data``; ``self.grad`` starts as ``None`` and becomes a same-shape ``float64`` array after 20 backward. ``requires_grad`` leaves accumulate grad; non-requiring leaves do not. 21 * Every op returns a NEW ``Tensor`` whose ``requires_grad`` is the OR of its differentiable inputs. 22 …[truncated 18629 chars]
/app/submission/nn.py
1 """Neural-network layers + a small convolutional classifier, built on the autograd engine 2 (IMPLEMENT THE FORWARDS). 3 4 Every module exposes ``params()`` -> list[Tensor] (the leaf tensors with ``requires_grad=True``) 5 and ``named_params()`` -> dict[str, Tensor] with STABLE names that match the checkpoint format the 6 verifier loads. ``SmallCNN.state_dict()`` / ``load_state_dict()`` round-trip a plain 7 ``dict[str, np.ndarray]`` (saved as an ``.npz``); the verifier loads YOUR checkpoint into its OWN 8 reference SmallCNN via these names, so the names + shapes below are part of the contract. 9 10 Naming contract for SmallCNN (do not change -- the verifier indexes by these exact keys): 11 conv1.weight (C1, C_in, 3, 3) conv1.bias (C1,) 12 conv2.weight (C2, C1, 3, 3) conv2.bias (C2,) 13 fc1.weight (C2*(H/4)*(W/4), F) fc1.bias (F,) 14 fc2.weight (F, n_classes) fc2.bias (n_classes,) 15 16 Architecture (pinned): for an (N, C_in, H, W) input image batch, 17 conv1 (C_in->C1, 3x3, pad 1) -> relu 18 maxpool 2x2 (H,W -> H/2,W/2) 19 conv2 (C1->C2, 3x3, pad 1) -> relu 20 maxpool 2x2 (H/2,W/2 -> H/4,W/4) 21 flatten -> fc1 (-> F) -> relu -> fc2 (-> n_classes) logits. 22 ``Linear`` computes ``x @ weight + bias`` (weight is (in, out)). No BatchNorm inside SmallCNN (so 23 the attack runs a single deterministic eval-mode forward with no running-stat dependence). 24 25 The other …[truncated 15896 chars]
/app/submission/optim.py
1 """Optimizers + LR schedulers over a flat list of autograd ``Tensor`` parameters (IMPLEMENT THESE). 2 3 Every optimizer operates IN PLACE on ``param.data`` using ``param.grad`` (the gradient accumulated 4 by ``Tensor.backward``). ``zero_grad()`` resets every grad to None. The EXACT update formula each 5 optimizer must match (the verifier checks one and several steps against its own reference) is in 6 its docstring. 7 8 The adversarial-training loop uses AdamW (decoupled decay, with ``no_decay_ndim`` excluding 1-D 9 params/biases) + global grad-norm clipping; the rest of the optimizer zoo + the four LR schedulers 10 are part of the from-scratch framework the conformance suite audits. 11 """ 12 from __future__ import annotations 13 14 import math 15 from typing import List 16 17 import numpy as np 18 19 from autograd import Tensor 20 21 22 class Optimizer: 23 def __init__(self, params: List[Tensor]): 24 self.params = list(params) 25 26 def zero_grad(self): 27 for p in self.params: 28 p.grad = None 29 30 31 class SGD(Optimizer): 32 """SGD + momentum + optional Nesterov + (coupled/L2) weight decay: 33 g = grad + wd*param; v = mu*v + g; step = (g + mu*v) if nesterov else v; param -= lr*step.""" 34 35 def __init__(self, params, lr=0.1, momentum=0.0, weight_decay=0.0, nesterov=False): 36 super().__init__(params) 37 self.lr = lr 38 self.momentum = momentum 39 self.weight_decay = weight …[truncated 8125 chars]
/app/submission/attack.py
1 """White-box evasion attacks built on the from-scratch autograd engine (IMPLEMENT THESE). 2 3 An adversary perturbs each input within a norm budget (L-inf eps in the [0,1] pixel domain by 4 default) and tries to make the classifier WRONG. Every attack ascends on the gradient of an attack 5 loss with respect to the INPUT image, which is exactly the gradient the autograd engine produces 6 when the input is wrapped in a ``requires_grad=True`` Tensor and the loss is backpropagated -- so a 7 correct ``conv2d`` input-gradient (the ``_col2im`` adjoint) is load-bearing. 8 9 THE PRIMITIVE 10 input_grad(model, x, y) d/dx of mean cross-entropy of model(x) vs y (ndarray). 11 loss_input_grad(model, x, y, loss_fn) d/dx of an ARBITRARY scalar attack loss loss_fn(logits,y). 12 13 L-INF ATTACKS 14 fgsm(model, x, y, eps) clip(x + eps*sign(input_grad)). 15 pgd_attack(model, x, y, eps, steps, alpha) iterated FGSM with random start + project to the 16 L-inf eps-ball around x AND the [0,1] box each step. 17 mi_fgsm(model, x, y, eps, steps, alpha, mu) momentum-iterative FGSM: accumulate a decaying 18 momentum of the L1-NORMALIZED gradient, step on its sign, 19 project each step. 20 targeted_pgd(model, x, y_target, eps, steps, alpha) DESCEND CE toward y_target (step on the 21 …[truncated 7820 chars]
/app/submission/advtrain.py
1 """Adversarial-training objectives built on the from-scratch autograd engine (IMPLEMENT THESE).
2
3 Several standard recipes turn a fragile classifier into a robust one. Each crafts adversarial
4 inputs per minibatch with the model's own attack, then takes a gradient step on a robustness-aware
5 loss; the recipes differ in the loss. All run a single forward+backward; the caller does grad-clip
6 + the optimizer step. ``x_clean`` / ``x_adv`` are ndarrays (N, C, H, W); ``y`` is an int (N,).
7
8 pgd_at_loss(model, x_adv, y) Madry PGD-AT: CE on the ADVERSARIAL batch.
9 trades_loss(model, x_clean, x_adv, y, beta) TRADES: CE(clean) + beta*KL(stopgrad(clean)||adv).
10 The clean branch INSIDE the KL is a STOP-GRADIENT
11 target (detached): the KL backprops only through
12 the adversarial branch.
13 mart_loss(model, x_clean, x_adv, y, beta) MART: boosted-CE on the adversarial batch
14 ( CE(adv,y) - mean log(1 - max_{j!=y} p_adv_j) ) +
15 beta * mean_i[ (1 - p_clean_i[y_i]) *
16 KL_i(softmax(adv)||stopgrad softmax(clean)) ].
17 alp_loss(model, x_clean, x_adv, y, lam) Adversarial Logit Pairing:
18 0.5*(CE(clean)+CE(ad
…[truncated 4278 chars]/app/submission/data.py
1 """Data loading + minibatching for the shape-classification set (IMPLEMENT THESE).
2
3 The visible train split ships as ``/app/data/train.npz`` with arrays ``X`` (N, C, H, W) float
4 pixels in [0,1] and ``y`` (N,) int labels. The SEALED held-out split is NOT in the image -- the
5 verifier regenerates it from a secret feature seed and runs its own attack on it.
6
7 Contract:
8 load_npz(path) -> (X float64 (N,C,H,W), y int64 (N,))
9 train_val_split(X, y, val_frac, rng) -> ((Xtr,ytr),(Xval,yval)) random disjoint split (val slice
10 is a held-BACK slice of the VISIBLE train data you may use for best-checkpoint selection --
11 it is NOT the verifier's sealed held-out set)
12 iter_batches(X, y, batch_size, rng) -> yields (xb, yb) random-permutation minibatches
13 get_batch(X, y, batch_size, rng) -> a single random minibatch
14 to_onehot(y, n_classes) -> (N, n_classes) one-hot float matrix
15 clip01(X) -> X clamped into the [0,1] pixel domain
16 """
17 from __future__ import annotations
18
19 from typing import Iterator, Tuple
20
21 import numpy as np
22
23
24 def load_npz(path: str) -> Tuple[np.ndarray, np.ndarray]:
25 raise NotImplementedError("implement load_npz")
26
27
28 def train_val_split(X: np.ndarray, y: np.ndarray, val_frac: float,
29 rng: np.random.Generator):
30 raise NotImplementedError("implement train_val_split")
31
32
33 def iter_batches(X: np.ndarray, y: np.ndarray, batch_size: int,
34
…[truncated 814 chars]/app/submission/train.py
1 """Adversarial-training loop for the small CNN, using the from-scratch numpy framework 2 (IMPLEMENT THIS). 3 4 Standard (clean) training reaches ~99% CLEAN accuracy but ~chance ROBUST accuracy -- it is broken 5 by the verifier's STRONG multi-restart L-inf PGD attack. WEAK robust training is not enough either: 6 single-step (FGSM) adversarial training suffers "catastrophic overfitting" and is shattered by the 7 multi-step / multi-restart eval attack, and adversarial training at a SMALLER perturbation budget 8 than the eval budget leaves the model fragile exactly where it is attacked. The effective recipe is 9 full multi-step PGD ADVERSARIAL TRAINING (Madry et al. 2018) with the perturbation budget MATCHED 10 to the (larger) eval budget: 11 12 * on every minibatch, craft an inner k-step L-inf PGD adversarial batch against the CURRENT model 13 (attack.pgd_attack), at the eps the eval uses, then take the AdamW step on advtrain.pgd_at_loss 14 (cross-entropy on the adversarial batch); 15 * train long enough for robustness to converge (a few epochs is not enough at this eps); 16 * stability details that materially raise the achieved robust accuracy and make it reproducible: 17 (a) exclude biases (1-D params) from weight decay (AdamW no_decay_ndim=1); (b) clip the global 18 gradient norm (the adversarial loss surface is sharp); (c) keep the BEST-by-robust-accuracy 19 checkpoint, evaluated each epoch with the model's own multi-step PGD on a held-BACK slic …[truncated 2473 chars]
wc -l run_checks.py && grep -n "detach\|stop_grad\|stopgrad\|\.detach\|requires_grad" run_checks.py | head -50
1187 run_checks.py
139: t = T(x0.copy(), requires_grad=True)
217: lt = T(x0.copy(), requires_grad=True)
226: lt = T(x0.copy(), requires_grad=True)
235: lt = T(x0.copy(), requires_grad=True)
244: lt = T(x0.copy(), requires_grad=True)
253: wt = T(w0.copy(), requires_grad=True)
263: lt = T(x0.copy(), requires_grad=True)
274: pt = T(p0.copy(), requires_grad=True)
279: qt = T(q0.copy(), requires_grad=True)
290: xt = T(x.copy(), requires_grad=True)
295: Wt = T(W.copy(), requires_grad=True)
300: bt = T(b.copy(), requires_grad=True)
312: xt = T(x0.copy(), requires_grad=True)
323: xt = T(x0.copy(), requires_grad=True)
352: xt = T(x0.copy(), requires_grad=True)
421: xt = T(x0.copy(), requires_grad=True)
596: return [T(rng.standard_normal(s), requires_grad=True) for s in shapes]
872: lt = ag.Tensor(x0.copy(), requires_grad=True)
970: lt = ag.Tensor(x0.copy(), requires_grad=True)
976: # TRADES stop-gradient: agent TRADES grad must equal a hand-built detached-target reference.
977: def trades_stopgrad():
990: prop("trades_stopgrad", trades_stopgrad)
1009: # CLP stop-gradient (pairing target detached): agent CLP grad equals a detached-target reference.
1010: def clp_stopgrad():
1025: prop("clp_stopgrad", clp_stopgrad)
1027: # KL-AT stop-gradient + adv-as-p argument order: agent grad equals the detached-target refer
…[truncated 84 chars]/app/run_checks.py
960 prop("alp_param_grad", lambda: param_grad("alp", lambda m: at.alp_loss(m, Xc, Xa, y, lam=0.7), "conv2.weight", 64))
961 prop("robust_ce_param_grad", lambda: param_grad("rce", lambda m: at.robust_ce_loss(m, Xc, Xa, y, lam=0.5), "fc2.weight", 65))
962 prop("clp_param_grad", lambda: param_grad("clp", lambda m: at.clp_loss(m, Xc, Xa, y, lam=0.7), "fc1.weight", 80))
963 prop("kl_at_param_grad", lambda: param_grad("klat", lambda m: at.kl_at_loss(m, Xc, Xa, y, beta=6.0), "conv2.weight", 81))
964 prop("logit_squeeze_param_grad", lambda: param_grad("lsq", lambda m: at.logit_squeeze_at_loss(m, Xa, y, lam=1e-2), "fc2.weight", 82))
965 prop("ls_at_param_grad", lambda: param_grad("lsat", lambda m: at.ls_at_loss(m, Xa, y, eps_ls=0.1), "fc1.weight", 83))
966
967 def ls_ce_grad():
968 rng2 = np.random.default_rng(sb + 66)
969 x0 = rng2.standard_normal((5, 4)); tgt = rng2.integers(0, 4, size=5)
970 lt = ag.Tensor(x0.copy(), requires_grad=True)
971 at.label_smoothed_ce(lt, tgt, 0.1).backward()
972 gnum = _num_grad_input(lambda xv: np.array(float(at.label_smoothed_ce(ag.Tensor(xv), tgt, 0.1).data)), x0.copy())
973 return _max_abs(lt.grad, gnum) < TOL_GRAD, ""
974 prop("label_smoothed_ce_grad", ls_ce_grad)
975
976 # TRADES stop-gradient: agent TRADES grad must equal a hand-built detached-target reference.
977 def trades_stopgrad():
978 m = _m(71); key = "fc1.weight"; beta = 5.0
979 for p
…[truncated 5435 chars]/app/run_checks.py
1 #!/usr/bin/env python3 2 """PUBLIC component check runner for the from-scratch numpy framework + the adversarial machinery. 3 4 Run this AS OFTEN AS YOU LIKE while you implement to get a per-check progress signal: 5 6 python3 /app/run_checks.py # check the framework in /app/submission 7 python3 /app/run_checks.py --submission /some/dir 8 python3 /app/run_checks.py --only attack # focus a single milestone 9 10 It imports YOUR modules from /app/submission (autograd.py / nn.py / optim.py / data.py / attack.py 11 / advtrain.py), exactly as the grader does, and runs a PUBLIC portion of the component conformance 12 suite, printing a clear per-check report. Each FAIL line names the exact op / layer / optimizer / 13 attack / adversarial-training property that is wrong. 14 15 HOW THIS RELATES TO YOUR GRADE 16 ------------------------------ 17 This runner is a DEBUGGING AID, not the grader. It checks YOUR framework against self-consistent 18 references it computes on its OWN: 19 * autograd_grads : central FINITE-DIFFERENCE of YOUR forward vs YOUR analytic backward (every op, 20 incl. the convolution input-gradient, the pools, and the full SmallCNN -- both 21 grad-wrt-PARAMS and grad-wrt-INPUT, the attack gradient). 22 * nn_forward : mathematical PROPERTIES your forward must satisfy (relu/softmax/conv arithmetic 23 /SmallCNN shape). 24 * optim : YOUR optimize …[truncated 4027 chars]
/app/run_checks.py
130 ag = fw["autograd"]
131 nn = fw["nn"]
132 T = ag.Tensor
133 results = []
134
135 def case(name, build, shape, seed, fdfun=None):
136 try:
137 rng = np.random.default_rng(sb + seed)
138 x0 = rng.standard_normal(shape)
139 t = T(x0.copy(), requires_grad=True)
140 ag.sum(build(t)).backward()
141 gan = np.asarray(t.grad, np.float64)
142 ffun = fdfun or (lambda xv: build(T(xv)).data)
143 gnum = _num_grad_input(ffun, x0.copy())
144 err = _max_abs(gan, gnum)
145 results.append((f"grad/{name}", err < TOL_GRAD, f"max_abs={err:.2e}"))
146 except Exception as e: # noqa: BLE001
147 results.append((f"grad/{name}", False, f"raised {type(e).__name__}: {e}"))
148
149 def guard(name, fn):
150 try:
151 fn()
152 except Exception as e: # noqa: BLE001
153 results.append((f"grad/{name}", False, f"raised {type(e).__name__}: {e}"))
154
155 case("add_bcast", lambda t: ag.add(t, T(np.arange(t.shape[-1], dtype=float) + 1.0)), (4, 5), 1)
156 case("sub_bcast", lambda t: ag.sub(t, T(np.arange(t.shape[-1], dtype=float) + 1.0)), (4, 5), 2)
157 case("mul_bcast", lambda t: ag.mul(t, T(np.arange(t.shape[-1], dtype=float) + 1.0)), (4, 5), 3)
158 case("div", lambda t: ag.div(t, T(np.full((4, 5), 2.0))), (4, 5), 4)
159 case("power3", lambda t: ag.power(t, 3.0), (4, 5), 5)
160 case("ma
…[truncated 17325 chars]/app/run_checks.py
449 450 def leaky_def(): 451 x = np.random.default_rng(sb + 2).standard_normal((4, 5)) 452 return _max_abs(ag.leaky_relu(T(x), 0.1).data, np.where(x > 0, x, 0.1 * x)) < TOL_PROP, "" 453 454 def sigmoid_def(): 455 x = np.random.default_rng(sb + 3).standard_normal((4, 5)) 456 return _max_abs(ag.sigmoid(T(x)).data, 1.0 / (1.0 + np.exp(-x))) < TOL_PROP, "" 457 458 def tanh_def(): 459 x = np.random.default_rng(sb + 4).standard_normal((4, 5)) 460 return _max_abs(ag.tanh(T(x)).data, np.tanh(x)) < TOL_PROP, "" 461 462 def gelu_def(): 463 x = np.random.default_rng(sb + 5).standard_normal((4, 5)) 464 return _max_abs(ag.gelu(T(x)).data, x * 0.5 * (1.0 + erf(x / np.sqrt(2.0)))) < 1e-6, "" 465 466 def softmax_rows(): 467 x = np.random.default_rng(sb + 6).standard_normal((4, 5)) 468 s = ag.softmax(T(x)).data 469 return abs(s.sum(axis=-1) - 1.0).max() < 1e-9 and (s >= 0).all(), "" 470 471 def ce_value(): 472 x = np.random.default_rng(sb + 7).standard_normal((5, 4)); tgt = np.array([0, 1, 2, 3, 0]) 473 logp = x - np.log(np.exp(x - x.max(-1, keepdims=True)).sum(-1, keepdims=True)) - x.max(-1, keepdims=True) 474 ref = float(-logp[np.arange(5), tgt].mean()) 475 return abs(float(ag.cross_entropy(T(x), tgt).data) - ref) < 1e-6, "" 476 477 def kl_nonneg(): 478 x = np.random.default_rng(sb + 8).standard_normal((4, 5)) 479 return f …[truncated 11937 chars]
/app/run_checks.py
729 lion_step(1e-3, 0.9, 0.99, 0.05), 8, sb + 10, SH)
730 run("Adadelta_8step", lambda p: opt.Adadelta(p, lr=1.0, rho=0.9, weight_decay=1e-3),
731 adadelta_step(1.0, 0.9, 1e-6, 1e-3), 8, sb + 11, SH)
732
733 def clip_norm_case(name, scale_in, max_norm):
734 try:
735 ps = mk(sb + 600, [(4, 3), (3,)])
736 grng = np.random.default_rng(sb + 12)
737 gs = [grng.standard_normal(p.data.shape) * scale_in for p in ps]
738 for p, g in zip(ps, gs):
739 p.grad = g.copy()
740 opt.clip_grad_norm(ps, max_norm)
741 total = float(np.sqrt(sum(float((g ** 2).sum()) for g in gs)))
742 ref = [g * (max_norm / (total + 1e-6)) if total > max_norm else g for g in gs]
743 err = max(_max_abs(p.grad, ref[i]) for i, p in enumerate(ps))
744 results.append((f"optim/{name}", err < TOL_OPT, f"max_abs={err:.1e}"))
745 except Exception as e: # noqa: BLE001
746 results.append((f"optim/{name}", False, f"raised {type(e).__name__}: {e}"))
747 clip_norm_case("clip_grad_norm_clips", 10.0, 1.0)
748 clip_norm_case("clip_grad_norm_noop", 0.01, 1.0)
749
750 def clip_value_case():
751 try:
752 ps = mk(sb + 610, [(4, 3), (3,)])
753 grng = np.random.default_rng(sb + 13)
754 gs = [grng.standard_normal(p.data.shape) * 3.0 for p in ps]
755 for p, g in zip(ps, gs):
756
…[truncated 7384 chars]/app/run_checks.py
888 xf = atk.fgsm(m, x, y, eps); xb = atk.bim(m, x, y, eps, 15, 0.025)
889 lf = float(ag.cross_entropy(m(xf), y).data); lb = float(ag.cross_entropy(m(xb), y).data)
890 return lb >= lf - 1e-6, f"fgsm={lf:.3f} bim={lb:.3f}"
891
892 def restarts_worst_case():
893 m = _model(69)
894 x = np.clip(np.random.default_rng(sb + 70).random((8, 1, 8, 8)), 0, 1); y = np.array([0, 1, 2, 3, 0, 1, 2, 3]); eps = 0.12
895 x1 = atk.pgd_attack(m, x, y, eps, 10, 0.03, rng=np.random.default_rng(sb + 71))
896 xr = atk.pgd_restarts(m, x, y, eps, 10, 0.03, restarts=4, rng=np.random.default_rng(sb + 72))
897 l1 = float(ag.cross_entropy(m(x1), y).data); lr = float(ag.cross_entropy(m(xr), y).data)
898 return lr >= l1 - 1e-6, f"single={l1:.3f} restarts={lr:.3f}"
899
900 prop("input_grad_fd", input_grad_fd)
901 prop("cw_loss_input_grad_fd", cw_input_grad_fd)
902 prop("dlr_loss_grad", dlr_loss_grad)
903 prop("dlr_loss_input_grad_fd", dlr_input_grad_fd)
904 prop("fgsm_step", fgsm_step)
905 prop("pgd_projection", lambda: proj("pgd", lambda m, x, y, e: atk.pgd_attack(m, x, y, e, 10, 0.03, rng=np.random.default_rng(sb + 22)), 0.1))
906 prop("mi_fgsm_projection", lambda: proj("mi", lambda m, x, y, e: atk.mi_fgsm(m, x, y, e, 10, 0.03, mu=1.0, rng=np.random.default_rng(sb + 23)), 0.1))
907 prop("cw_pgd_projection", lambda: proj("cw", lambda m, x, y, e: atk.cw_pgd(m, x, y, e, 10, 0.03, rng=np.random.default
…[truncated 4366 chars]grep -n "def check_data\|mart\|p_clean\|max_{j" run_checks.py | head; sed -n '1080,1187p' run_checks.py28: * advtrain : pgd_at / trades / mart / alp / robust_ce / label_smoothed_ce forward+grad
959: prop("mart_param_grad", lambda: param_grad("mart", lambda m: at.mart_loss(m, Xc, Xa, y, beta=5.0), "fc1.weight", 63))
1089:def check_data(fw, sb):
run("pgd_at", "at")
run("trades", "trades")
npass = builtin_sum(1 for _, ok, _ in results if ok)
return npass, len(results), results
# ======================================================================= data (smoke)
def check_data(fw, sb):
data = fw["data"]
results = []
def prop(name, fn):
try:
ok, info = fn()
results.append((f"data/{name}", ok, info))
except Exception as e: # noqa: BLE001
results.append((f"data/{name}", False, f"raised {type(e).__name__}: {e}"))
def batch_shape():
rng = np.random.default_rng(sb)
X = rng.standard_normal((50, 1, 8, 8)); y = rng.integers(0, 4, 50)
bx, by = data.get_batch(X, y, 16, rng)
return bx.shape == (16, 1, 8, 8) and by.shape == (16,), f"{bx.shape},{by.shape}"
def split_shape():
rng = np.random.default_rng(sb + 1)
X = rng.standard_normal((40, 1, 8, 8)); y = rng.integers(0, 4, 40)
(Xtr, ytr), (Xval, yval) = data.train_val_split(X, y, 0.25, rng)
return len(Xtr) + len(Xval) == 40 and len(Xval) == 10, f"{len(Xtr)}/{len(Xval)}"
def onehot():
oh = data.to_onehot(np.array([0, 2, 1]), 3)
return oh.shape == (3, 3) and
…[truncated 2840 chars]"""Reverse-mode automatic differentiation over numpy arrays."""
from __future__ import annotations
import math
from typing import Callable, Iterable, List, Optional
import numpy as np
_erf = np.vectorize(math.erf)
_SQRT2 = math.sqrt(2.0)
_SQRT2PI = math.sqrt(2.0 * math.pi)
def _as_f64(x) -> np.ndarray:
return np.asarray(x, dtype=np.float64)
def _unbroadcast(grad: np.ndarray, shape: tuple) -> np.ndarray:
grad = np.asarray(grad, dtype=np.float64)
while grad.ndim > len(shape):
grad = grad.sum(axis=0)
for i, s in enumerate(shape):
if s == 1 and grad.shape[i] != 1:
grad = grad.sum(axis=i, keepdims=True)
return grad
def _expand(g, shape, axis, keepdims):
"""Broadcast a reduced gradient ``g`` back to ``shape`` (axis can be None/int/tuple)."""
g = np.asarray(g, dtype=np.float64)
if axis is None:
return np.broadcast_to(g, shape)
if not keepdims:
ax = axis if isinstance(axis, tuple) else (axis,)
ax = tuple(a % len(shape) for a in ax)
g = np.expand_dims(g, ax)
return np.broadcast_to(g, shape)
def _count(shape, axis):
if axis is None:
n = 1
for s in shape:
n *= s
return n
ax = axis if isinstance(axis, tuple) else (axis,)
n = 1
for a in ax:
n *= shape[a]
return n
class Tensor:
__slots__ = ("data", "grad", "requires_grad", "_backward", "_parents")
def __init__(self, data, requires_grad: bool = False, _paren
…[truncated 27580 chars]The file /app/submission/autograd.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/autograd.py
def bw():
g = out.grad
sa = np.where(a.data > b.data, 1.0, np.where(a.data == b.data, 0.5, 0.0))
if a.requires_grad:
a._accum(_unbroadcast(g * sa, a.data.shape))
if b.requires_grad:
b._accum(_unbroadcast(g * (1.0 - sa) if False else g * np.where(b.data > a.data, 1.0, np.where(a.data == b.data, 0.5, 0.0)), b.data.shape))
out._backward = bw
return out
def minimum(a, b) -> Tensor: def bw():
g = out.grad
sa = np.where(a.data > b.data, 1.0, np.where(a.data == b.data, 0.5, 0.0))
sb = np.where(b.data > a.data, 1.0, np.where(a.data == b.data, 0.5, 0.0))
if a.requires_grad:
a._accum(_unbroadcast(g * sa, a.data.shape))
if b.requires_grad:
b._accum(_unbroadcast(g * sb, b.data.shape))
out._backward = bw
return out
def minimum(a, b) -> Tensor:The file /app/submission/autograd.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/nn.py
def forward(self, x: Tensor) -> Tensor:
"""ag.conv2d(x, weight, bias, pad)."""
raise NotImplementedError("implement Conv2d.forward") def forward(self, x: Tensor) -> Tensor:
"""ag.conv2d(x, weight, bias, pad)."""
return ag.conv2d(x, self.weight, self.bias, pad=self.pad)The file /app/submission/nn.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/nn.py
def forward(self, x: Tensor) -> Tensor:
"""ag.maxpool2d(x, k)."""
raise NotImplementedError("implement MaxPool2d.forward") def forward(self, x: Tensor) -> Tensor:
"""ag.maxpool2d(x, k)."""
return ag.maxpool2d(x, self.k)The file /app/submission/nn.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/nn.py
def forward(self, x: Tensor) -> Tensor:
"""ag.avgpool2d(x, k)."""
raise NotImplementedError("implement AvgPool2d.forward") def forward(self, x: Tensor) -> Tensor:
"""ag.avgpool2d(x, k)."""
return ag.avgpool2d(x, self.k)The file /app/submission/nn.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/nn.py
def forward(self, x: Tensor) -> Tensor:
"""ag.matmul(x, weight) + bias."""
raise NotImplementedError("implement Linear.forward") def forward(self, x: Tensor) -> Tensor:
"""ag.matmul(x, weight) + bias."""
return ag.add(ag.matmul(x, self.weight), self.bias)The file /app/submission/nn.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/nn.py
def forward(self, x: Tensor) -> Tensor:
"""ag.layernorm(x, weight, bias, eps)."""
raise NotImplementedError("implement LayerNorm.forward") def forward(self, x: Tensor) -> Tensor:
"""ag.layernorm(x, weight, bias, eps)."""
return ag.layernorm(x, self.weight, self.bias, self.eps)The file /app/submission/nn.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/nn.py
def forward(self, x: Tensor) -> Tensor:
"""ag.batchnorm(x, weight, bias, eps)."""
raise NotImplementedError("implement BatchNorm1d.forward") def forward(self, x: Tensor) -> Tensor:
"""ag.batchnorm(x, weight, bias, eps)."""
return ag.batchnorm(x, self.weight, self.bias, self.eps)The file /app/submission/nn.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/nn.py
def forward(self, x):
"""linear -> relu (between layers) -> ... -> linear (no final activation)."""
raise NotImplementedError("implement MLP.forward") def forward(self, x):
"""linear -> relu (between layers) -> ... -> linear (no final activation)."""
if not isinstance(x, Tensor):
x = Tensor(x)
for i, lin in enumerate(self.layers):
x = lin(x)
if i < len(self.layers) - 1:
x = ag.relu(x)
return xThe file /app/submission/nn.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/nn.py
def forward(self, x):
"""for each conv: pool(relu(conv(x))); then flatten -> relu(fc1) -> fc2."""
raise NotImplementedError("implement ConvNet.forward") def forward(self, x):
"""for each conv: pool(relu(conv(x))); then flatten -> relu(fc1) -> fc2."""
if not isinstance(x, Tensor):
x = Tensor(x)
for conv in self.convs:
x = self.pool(ag.relu(conv(x)))
n = x.shape[0]
x = ag.reshape(x, (n, -1))
x = ag.relu(self.fc1(x))
return self.fc2(x)The file /app/submission/nn.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/nn.py
def forward(self, x: Tensor) -> Tensor:
"""ag.groupnorm(x, weight, bias, num_groups, eps)."""
raise NotImplementedError("implement GroupNorm.forward") def forward(self, x: Tensor) -> Tensor:
"""ag.groupnorm(x, weight, bias, num_groups, eps)."""
return ag.groupnorm(x, self.weight, self.bias, self.num_groups, self.eps)The file /app/submission/nn.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/nn.py
def forward(self, x: Tensor) -> Tensor:
"""ag.rmsnorm(x, weight, eps)."""
raise NotImplementedError("implement RMSNorm.forward") def forward(self, x: Tensor) -> Tensor:
"""ag.rmsnorm(x, weight, eps)."""
return ag.rmsnorm(x, self.weight, self.eps)The file /app/submission/nn.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/nn.py
def forward(self, x: Tensor, h: Tensor) -> Tensor:
"""h' = tanh(x @ weight_ih^T + bias_ih + h @ weight_hh^T + bias_hh)."""
raise NotImplementedError("implement RNNCell.forward") def forward(self, x: Tensor, h: Tensor) -> Tensor:
"""h' = tanh(x @ weight_ih^T + bias_ih + h @ weight_hh^T + bias_hh)."""
if not isinstance(x, Tensor):
x = Tensor(x)
if not isinstance(h, Tensor):
h = Tensor(h)
ih = ag.add(ag.matmul(x, ag.transpose(self.weight_ih)), self.bias_ih)
hh = ag.add(ag.matmul(h, ag.transpose(self.weight_hh)), self.bias_hh)
return ag.tanh(ag.add(ih, hh))The file /app/submission/nn.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/nn.py
def forward(self, x: Tensor, h: Tensor) -> Tensor:
"""the GRU update above (slice the 3 gates out of the (N,3H) pre-activations)."""
raise NotImplementedError("implement GRUCell.forward") def forward(self, x: Tensor, h: Tensor) -> Tensor:
"""the GRU update above (slice the 3 gates out of the (N,3H) pre-activations)."""
if not isinstance(x, Tensor):
x = Tensor(x)
if not isinstance(h, Tensor):
h = Tensor(h)
H = self.hidden_size
gi = ag.add(ag.matmul(x, ag.transpose(self.weight_ih)), self.bias_ih) # (N,3H)
gh = ag.add(ag.matmul(h, ag.transpose(self.weight_hh)), self.bias_hh) # (N,3H)
i_r, i_z, i_n = gi[:, 0:H], gi[:, H:2 * H], gi[:, 2 * H:3 * H]
h_r, h_z, h_n = gh[:, 0:H], gh[:, H:2 * H], gh[:, 2 * H:3 * H]
r = ag.sigmoid(ag.add(i_r, h_r))
z = ag.sigmoid(ag.add(i_z, h_z))
n = ag.tanh(ag.add(i_n, ag.mul(r, h_n)))
one_minus_z = ag.sub(1.0, z)
return ag.add(ag.mul(one_minus_z, n), ag.mul(z, h))The file /app/submission/nn.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/nn.py
def forward(self, x: Tensor, h: Tensor, c: Tensor):
"""the LSTM update above; return (h', c')."""
raise NotImplementedError("implement LSTMCell.forward") def forward(self, x: Tensor, h: Tensor, c: Tensor):
"""the LSTM update above; return (h', c')."""
if not isinstance(x, Tensor):
x = Tensor(x)
if not isinstance(h, Tensor):
h = Tensor(h)
if not isinstance(c, Tensor):
c = Tensor(c)
H = self.hidden_size
g = ag.add(ag.add(ag.matmul(x, ag.transpose(self.weight_ih)), self.bias_ih),
ag.add(ag.matmul(h, ag.transpose(self.weight_hh)), self.bias_hh)) # (N,4H)
i = ag.sigmoid(g[:, 0:H])
f = ag.sigmoid(g[:, H:2 * H])
gg = ag.tanh(g[:, 2 * H:3 * H])
o = ag.sigmoid(g[:, 3 * H:4 * H])
c2 = ag.add(ag.mul(f, c), ag.mul(i, gg))
h2 = ag.mul(o, ag.tanh(c2))
return h2, c2The file /app/submission/nn.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/nn.py
def forward(self, x):
"""h = pool(relu(conv1(x))); res = conv2b(relu(conv2a(h))); h = relu(h + res); flatten -> fc."""
raise NotImplementedError("implement SmallResCNN.forward") def forward(self, x):
"""h = pool(relu(conv1(x))); res = conv2b(relu(conv2a(h))); h = relu(h + res); flatten -> fc."""
if not isinstance(x, Tensor):
x = Tensor(x)
h = self.pool(ag.relu(self.conv1(x)))
res = self.conv2b(ag.relu(self.conv2a(h)))
h = ag.relu(ag.add(h, res))
n = h.shape[0]
h = ag.reshape(h, (n, -1))
return self.fc(h)The file /app/submission/nn.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/nn.py
def forward(self, x) -> Tensor:
"""conv1 -> relu -> pool -> conv2 -> relu -> pool -> flatten -> fc1 -> relu -> fc2."""
raise NotImplementedError("implement SmallCNN.forward") def forward(self, x) -> Tensor:
"""conv1 -> relu -> pool -> conv2 -> relu -> pool -> flatten -> fc1 -> relu -> fc2."""
if not isinstance(x, Tensor):
x = Tensor(x)
x = self.pool(ag.relu(self.conv1(x)))
x = self.pool(ag.relu(self.conv2(x)))
n = x.shape[0]
x = ag.reshape(x, (n, -1))
x = ag.relu(self.fc1(x))
return self.fc2(x)The file /app/submission/nn.py has been updated successfully. (file state is current in your context , no need to Read it back)
python3 run_checks.py --only autograd_grads 2>&1 | tail -40
grad/prod_axis OK (max_abs=5.65e-10) grad/cumsum_ax1 OK (max_abs=3.79e-11) grad/logsumexp_ax1 OK (max_abs=4.93e-11) grad/pad2d OK (max_abs=5.10e-11) grad/groupnorm_x OK grad/rmsnorm_x OK grad/layernorm_x OK grad/batchnorm_x OK grad/embedding OK grad/mse_loss OK grad/cross_entropy OK grad/kl_div_q OK grad/kl_div_p OK grad/conv2d_input OK (max_abs=1.09e-09) grad/conv2d_weight OK (max_abs=3.38e-09) grad/conv2d_bias OK grad/conv2d_pad0_input OK (max_abs=7.79e-10) grad/maxpool2d OK grad/avgpool2d OK grad/nn.Conv2d_x OK grad/nn.Linear_x OK grad/nn.LayerNorm_x OK grad/nn.BatchNorm1d_x OK grad/cnn_grad_fc2.bias OK (max_abs=1.21e-11) grad/cnn_grad_conv1.weight OK (max_abs=2.55e-11) grad/cnn_grad_conv2.weight OK (max_abs=2.61e-11) grad/cnn_grad_fc1.weight OK (ma …[truncated 815 chars]
/app/submission/optim.py
def step(self):
raise NotImplementedError("implement SGD.step") def step(self):
for i, p in enumerate(self.params):
if p.grad is None:
continue
g = p.grad + self.weight_decay * p.data
self._v[i] = self.momentum * self._v[i] + g
v = self._v[i]
step = (g + self.momentum * v) if self.nesterov else v
p.data -= self.lr * stepThe file /app/submission/optim.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/optim.py
def step(self):
raise NotImplementedError("implement Adagrad.step") def step(self):
for i, p in enumerate(self.params):
if p.grad is None:
continue
g = p.grad + self.weight_decay * p.data
self._s[i] = self._s[i] + g * g
p.data -= self.lr * g / (np.sqrt(self._s[i]) + self.eps)The file /app/submission/optim.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/optim.py
def step(self):
raise NotImplementedError("implement RMSprop.step") def step(self):
for i, p in enumerate(self.params):
if p.grad is None:
continue
g = p.grad + self.weight_decay * p.data
self._s[i] = self.alpha * self._s[i] + (1 - self.alpha) * (g * g)
p.data -= self.lr * g / (np.sqrt(self._s[i]) + self.eps)The file /app/submission/optim.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/optim.py
def step(self):
raise NotImplementedError("implement Adam.step") def step(self):
self.t += 1
t = self.t
for i, p in enumerate(self.params):
if p.grad is None:
continue
g = p.grad + self.weight_decay * p.data
self._m[i] = self.b1 * self._m[i] + (1 - self.b1) * g
self._v[i] = self.b2 * self._v[i] + (1 - self.b2) * (g * g)
mhat = self._m[i] / (1 - self.b1 ** t)
vhat = self._v[i] / (1 - self.b2 ** t)
p.data -= self.lr * mhat / (np.sqrt(vhat) + self.eps)The file /app/submission/optim.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/optim.py
def step(self):
raise NotImplementedError("implement AdamW.step") def step(self):
self.t += 1
t = self.t
for i, p in enumerate(self.params):
if p.grad is None:
continue
g = p.grad
self._m[i] = self.b1 * self._m[i] + (1 - self.b1) * g
self._v[i] = self.b2 * self._v[i] + (1 - self.b2) * (g * g)
mhat = self._m[i] / (1 - self.b1 ** t)
vhat = self._v[i] / (1 - self.b2 ** t)
wd_eff = 0.0 if p.data.ndim <= self.no_decay_ndim else self.weight_decay
p.data -= self.lr * (mhat / (np.sqrt(vhat) + self.eps) + wd_eff * p.data)The file /app/submission/optim.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/optim.py
def step(self):
raise NotImplementedError("implement Adamax.step") def step(self):
self.t += 1
t = self.t
for i, p in enumerate(self.params):
if p.grad is None:
continue
g = p.grad + self.weight_decay * p.data
self._m[i] = self.b1 * self._m[i] + (1 - self.b1) * g
self._u[i] = np.maximum(self.b2 * self._u[i], np.abs(g))
p.data -= (self.lr / (1 - self.b1 ** t)) * self._m[i] / (self._u[i] + self.eps)The file /app/submission/optim.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/optim.py
def step(self):
raise NotImplementedError("implement NAdam.step") def step(self):
self.t += 1
t = self.t
for i, p in enumerate(self.params):
if p.grad is None:
continue
g = p.grad + self.weight_decay * p.data
self._m[i] = self.b1 * self._m[i] + (1 - self.b1) * g
self._v[i] = self.b2 * self._v[i] + (1 - self.b2) * (g * g)
mhat = self._m[i] / (1 - self.b1 ** t)
vhat = self._v[i] / (1 - self.b2 ** t)
mnes = self.b1 * mhat + (1 - self.b1) * g / (1 - self.b1 ** t)
p.data -= self.lr * mnes / (np.sqrt(vhat) + self.eps)The file /app/submission/optim.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/optim.py
def step(self):
raise NotImplementedError("implement Lion.step") def step(self):
for i, p in enumerate(self.params):
if p.grad is None:
continue
g = p.grad
c = np.sign(self.b1 * self._m[i] + (1 - self.b1) * g)
p.data -= self.lr * (c + self.weight_decay * p.data)
self._m[i] = self.b2 * self._m[i] + (1 - self.b2) * gThe file /app/submission/optim.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/optim.py
def step(self):
raise NotImplementedError("implement Adadelta.step") def step(self):
for i, p in enumerate(self.params):
if p.grad is None:
continue
g = p.grad + self.weight_decay * p.data
self._s[i] = self.rho * self._s[i] + (1 - self.rho) * (g * g)
delta = np.sqrt(self._d[i] + self.eps) / np.sqrt(self._s[i] + self.eps) * g
p.data -= self.lr * delta
self._d[i] = self.rho * self._d[i] + (1 - self.rho) * (delta * delta)The file /app/submission/optim.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/optim.py
If total > max_norm, scale
every grad by max_norm/(total+1e-6)."""
raise NotImplementedError("implement clip_grad_norm") If total > max_norm, scale
every grad by max_norm/(total+1e-6)."""
total_sq = 0.0
for p in params:
if p.grad is not None:
total_sq += float((p.grad ** 2).sum())
total = math.sqrt(total_sq)
if total > max_norm:
scale = max_norm / (total + 1e-6)
for p in params:
if p.grad is not None:
p.grad = p.grad * scale
return total<tool_use_error>String to replace not found in file.
String: If total > max_norm, scale
every grad by max_norm/(total+1e-6)."""
raise NotImplementedError("implement clip_grad_norm")</tool_use_error>/app/submission/optim.py
raise NotImplementedError("implement clip_grad_norm") total_sq = 0.0
for p in params:
if p.grad is not None:
total_sq += float((p.grad ** 2).sum())
total = math.sqrt(total_sq)
if total > max_norm:
scale = max_norm / (total + 1e-6)
for p in params:
if p.grad is not None:
p.grad = p.grad * scale
return totalThe file /app/submission/optim.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/optim.py
raise NotImplementedError("implement clip_grad_value") for p in params:
if p.grad is not None:
p.grad = np.clip(p.grad, -clip_value, clip_value)The file /app/submission/optim.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/optim.py
raise NotImplementedError("implement cosine_lr") if warmup > 0 and step < warmup:
return base_lr * (step + 1) / warmup
prog = min(1.0, max(0.0, (step - warmup) / max(1, total - warmup)))
return min_lr + 0.5 * (base_lr - min_lr) * (1 + math.cos(math.pi * prog))The file /app/submission/optim.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/optim.py
raise NotImplementedError("implement warmup_lr")return base_lr * (step + 1) / warmup if step < warmup else base_lr
The file /app/submission/optim.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/optim.py
raise NotImplementedError("implement step_lr")return base_lr * gamma ** (step // step_size)
The file /app/submission/optim.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/optim.py
raise NotImplementedError("implement exponential_lr")return base_lr * gamma ** step
The file /app/submission/optim.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/optim.py
raise NotImplementedError("implement polynomial_lr") prog = min(1.0, max(0.0, step / total))
return (base_lr - min_lr) * ((1.0 - prog) ** power) + min_lrThe file /app/submission/optim.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/optim.py
raise NotImplementedError("implement linear_lr") prog = min(1.0, max(0.0, step / total))
return base_lr + (min_lr - base_lr) * progThe file /app/submission/optim.py has been updated successfully. (file state is current in your context , no need to Read it back)
python3 run_checks.py --only optim 2>&1 | tail -35 && python3 run_checks.py --only nn_forward 2>&1 | tail -5
[optim] 20/20 optim/SGD_1step OK (max_abs=0.0e+00) optim/SGD_momentum_5step OK (max_abs=0.0e+00) optim/SGD_nesterov_5step OK (max_abs=0.0e+00) optim/Adagrad_5step OK (max_abs=0.0e+00) optim/RMSprop_5step OK (max_abs=0.0e+00) optim/Adam_10step_wd OK (max_abs=0.0e+00) optim/AdamW_10step_wd OK (max_abs=0.0e+00) optim/Adamax_8step OK (max_abs=0.0e+00) optim/NAdam_8step OK (max_abs=0.0e+00) optim/Lion_8step_wd OK (max_abs=0.0e+00) optim/Adadelta_8step OK (max_abs=0.0e+00) optim/clip_grad_norm_clips OK (max_abs=0.0e+00) optim/clip_grad_norm_noop OK (max_abs=0.0e+00) optim/clip_grad_value OK (max_abs=0.0e+00) optim/sched_cosine_lr OK (match) optim/sched_warmup_lr OK (match) optim/sched_step_lr OK (match) optim/sched_exponential_lr OK (match) optim/sched_polynomial_lr OK (match) optim/sched_linear_lr OK (match) ------------------------------------------------------------------------ optim 20/20 TOTAL 20/20 public checks passing All public checks pass. Now make sure model.npz clears the held-out ROBUST-accuracy …[truncated 373 chars]
/app/submission/data.py
def load_npz(path: str) -> Tuple[np.ndarray, np.ndarray]:
raise NotImplementedError("implement load_npz")
def train_val_split(X: np.ndarray, y: np.ndarray, val_frac: float,
rng: np.random.Generator):
raise NotImplementedError("implement train_val_split")
def iter_batches(X: np.ndarray, y: np.ndarray, batch_size: int,
rng: np.random.Generator) -> Iterator[Tuple[np.ndarray, np.ndarray]]:
raise NotImplementedError("implement iter_batches")
def get_batch(X: np.ndarray, y: np.ndarray, batch_size: int,
rng: np.random.Generator) -> Tuple[np.ndarray, np.ndarray]:
"""A single random minibatch (without replacement if possible). Shape-preserving."""
raise NotImplementedError("implement get_batch")
def to_onehot(y: np.ndarray, n_classes: int) -> np.ndarray:
"""(N, n_classes) one-hot float matrix from integer labels y."""
raise NotImplementedError("implement to_onehot")
def clip01(X: np.ndarray) -> np.ndarray:
"""Clamp X into the [0,1] pixel domain (the valid attack range)."""
raise NotImplementedError("implement clip01")def load_npz(path: str) -> Tuple[np.ndarray, np.ndarray]:
d = np.load(path)
X = np.asarray(d["X"], dtype=np.float64)
y = np.asarray(d["y"], dtype=np.int64)
return X, y
def train_val_split(X: np.ndarray, y: np.ndarray, val_frac: float,
rng: np.random.Generator):
N = X.shape[0]
perm = rng.permutation(N)
n_val = int(round(val_frac * N))
val_idx = perm[:n_val]
tr_idx = perm[n_val:]
return (X[tr_idx], y[tr_idx]), (X[val_idx], y[val_idx])
def iter_batches(X: np.ndarray, y: np.ndarray, batch_size: int,
rng: np.random.Generator) -> Iterator[Tuple[np.ndarray, np.ndarray]]:
N = X.shape[0]
perm = rng.permutation(N)
for s in range(0, N, batch_size):
idx = perm[s:s + batch_size]
yield X[idx], y[idx]
def get_batch(X: np.ndarray, y: np.ndarray, batch_size: int,
rng: np.random.Generator) -> Tuple[np.ndarray, np.ndarray]:
"""A single random minibatch (without replacement if possible). Shape-preserving."""
N = X.shape[0]
if batch_size <= N:
idx = rng.choice(N, size=batch_size, replace=False)
else:
idx = rng.choice(N, size=batch_size, replace=True)
return X[idx], y[idx]
def to_onehot(y: np.ndarray, n_classes: int) -> np.ndarray:
"""(N, n_classes) one-hot float matrix from integer labels y."""
y = np.asarray(y)
oh = np.zeros((y.shape[0], n_classes), dtype=np.float64)
oh[np.arange(y.shape[0]), y] = 1.0
return oh
de
…[truncated 142 chars]The file /app/submission/data.py has been updated successfully. (file state is current in your context , no need to Read it back)
"""White-box evasion attacks built on the from-scratch autograd engine."""
from __future__ import annotations
from typing import Callable, Optional, Tuple
import numpy as np
import autograd as ag
from autograd import Tensor
def _default_rng(rng):
return np.random.default_rng() if rng is None else rng
def loss_input_grad(model, x: np.ndarray, y: np.ndarray,
loss_fn: Callable[[Tensor, np.ndarray], Tensor]) -> np.ndarray:
xt = Tensor(np.asarray(x, dtype=np.float64), requires_grad=True)
logits = model(xt)
loss = loss_fn(logits, y)
loss.backward()
return np.asarray(xt.grad, dtype=np.float64)
def input_grad(model, x: np.ndarray, y: np.ndarray) -> np.ndarray:
return loss_input_grad(model, x, y, lambda lg, t: ag.cross_entropy(lg, t))
def _onehot(y, C):
y = np.asarray(y)
oh = np.zeros((y.shape[0], C), dtype=np.float64)
oh[np.arange(y.shape[0]), y] = 1.0
return oh
def cw_margin_loss(logits, y, kappa: float = 0.0) -> Tensor:
logits = ag._ensure(logits)
C = logits.shape[-1]
oh = _onehot(y, C)
z_y = ag.sum(ag.mul(logits, Tensor(oh)), axis=1)
masked = ag.add(logits, Tensor(oh * -1e9))
other = ag.max(masked, axis=1)
margin = ag.sub(z_y, other)
return ag.mean(ag.maximum(ag.mul(margin, -1.0), -kappa))
def dlr_loss(logits, y, eps: float = 1e-12) -> Tensor:
logits = ag._ensure(logits)
C = logits.shape[-1]
oh = _onehot(y, C)
z_y = ag.sum(ag.mul(logits, Tensor(oh)), axis=
…[truncated 7792 chars]The file /app/submission/attack.py has been updated successfully. (file state is current in your context , no need to Read it back)
python3 run_checks.py --only attack 2>&1 | tail -25
[attack] 18/18 attack/input_grad_fd OK (max_abs=2.73e-11) attack/cw_loss_input_grad_fd OK (max_abs=4.13e-12) attack/dlr_loss_grad OK (max_abs=1.04e-09) attack/dlr_loss_input_grad_fd OK (max_abs=3.51e-11) attack/fgsm_step OK attack/pgd_projection OK attack/mi_fgsm_projection OK attack/cw_pgd_projection OK attack/pgd_l2_projection OK attack/bim_projection OK attack/rfgsm_projection OK attack/ni_fgsm_projection OK attack/pgd_restarts_projection OK attack/dlr_pgd_projection OK attack/pgd_stronger_than_fgsm OK (fgsm=1.450 pgd=1.469) attack/bim_stronger_than_fgsm OK (fgsm=1.411 bim=1.423) attack/pgd_restarts_worst_case OK (single=1.521 restarts=1.524) attack/targeted_pgd_lowers_target_ce OK (1.388->1.333) ------------------------------------------------------------------------ attack 18/18 TOTAL 18/18 public checks passing All public checks pass. Now make sure model.npz clears the held-out ROBUST-accuracy threshold; the grader re-checks with DIFFERENT seeds/shapes + its OWN strong PGD.
/app/submission/advtrain.py
def pgd_at_loss(model, x_adv: np.ndarray, y: np.ndarray) -> Tensor:
"""Madry PGD-AT loss: cross-entropy on the adversarial batch (trains parameters)."""
raise NotImplementedError("implement pgd_at_loss")
def trades_loss(model, x_clean: np.ndarray, x_adv: np.ndarray, y: np.ndarray,
beta: float = 6.0) -> Tuple[Tensor, Dict[str, float]]:
"""TRADES loss = CE(clean, y) + beta * KL(stopgrad(softmax(clean)) || softmax(adv))."""
raise NotImplementedError("implement trades_loss")
def mart_loss(model, x_clean: np.ndarray, x_adv: np.ndarray, y: np.ndarray,
beta: float = 5.0) -> Tuple[Tensor, Dict[str, float]]:
"""MART loss (boosted CE on adv + misclassification-aware weighted KL with the clean target
DETACHED); see the module docstring for the exact form."""
raise NotImplementedError("implement mart_loss")
def alp_loss(model, x_clean: np.ndarray, x_adv: np.ndarray, y: np.ndarray,
lam: float = 0.5) -> Tuple[Tensor, Dict[str, float]]:
"""Adversarial Logit Pairing: 0.5*(CE(clean)+CE(adv)) + lam*mean||z_clean - z_adv||^2 (no detach)."""
raise NotImplementedError("implement alp_loss")
def label_smoothed_ce(logits, y, eps_ls: float = 0.1, n_classes: int = None) -> Tensor:
"""CE against a label-smoothed target ((1-eps_ls)*onehot + eps_ls/C*uniform), via log_softmax."""
raise NotImplementedError("implement label_smoothed_ce")
def robust_ce_loss(model, x_clean: np.ndarray, x_adv: np.ndarray, y: np.nd
…[truncated 1782 chars]def _detach(t: Tensor) -> Tensor:
return Tensor(t.data.copy())
def _onehot(y, C):
y = np.asarray(y)
oh = np.zeros((y.shape[0], C), dtype=np.float64)
oh[np.arange(y.shape[0]), y] = 1.0
return oh
def pgd_at_loss(model, x_adv: np.ndarray, y: np.ndarray) -> Tensor:
"""Madry PGD-AT loss: cross-entropy on the adversarial batch (trains parameters)."""
return ag.cross_entropy(model(x_adv), y)
def trades_loss(model, x_clean: np.ndarray, x_adv: np.ndarray, y: np.ndarray,
beta: float = 6.0) -> Tuple[Tensor, Dict[str, float]]:
"""TRADES loss = CE(clean, y) + beta * KL(stopgrad(softmax(clean)) || softmax(adv))."""
cl = model(x_clean)
ad = model(x_adv)
ce = ag.cross_entropy(cl, y)
tgt = _detach(cl)
kl = ag.kl_div(tgt, ad)
loss = ag.add(ce, ag.mul(kl, float(beta)))
return loss, {"ce": float(ce.data), "kl": float(kl.data), "loss": float(loss.data)}
def mart_loss(model, x_clean: np.ndarray, x_adv: np.ndarray, y: np.ndarray,
beta: float = 5.0) -> Tuple[Tensor, Dict[str, float]]:
"""MART loss (boosted CE on adv + misclassification-aware weighted KL with the clean target
DETACHED)."""
ad = model(x_adv)
C = ad.shape[-1]
oh = _onehot(y, C)
ce_adv = ag.cross_entropy(ad, y)
p_adv = ag.softmax(ad)
masked = ag.add(p_adv, Tensor(oh * -1e9))
m = ag.max(masked, axis=1) # max_{j!=y} p_adv_j (N,)
boost = ag.mul(ag.mean(ag.log(ag.add(ag.sub(1.0, m),
…[truncated 4429 chars]The file /app/submission/advtrain.py has been updated successfully. (file state is current in your context , no need to Read it back)
python3 run_checks.py --only advtrain 2>&1 | tail -20 && python3 run_checks.py --only data 2>&1 | tail -6 && python3 run_checks.py --only integration 2>&1 | tail -8
[advtrain] 14/14 advtrain/at_param_grad OK (max_abs=2.56e-11) advtrain/trades_param_grad OK (max_abs=5.66e-04) advtrain/mart_param_grad OK (max_abs=1.14e-04) advtrain/alp_param_grad OK (max_abs=2.60e-11) advtrain/robust_ce_param_grad OK (max_abs=5.12e-11) advtrain/clp_param_grad OK (max_abs=2.84e-05) advtrain/kl_at_param_grad OK (max_abs=1.62e-03) advtrain/logit_squeeze_param_grad OK (max_abs=4.80e-11) advtrain/ls_at_param_grad OK (max_abs=2.14e-11) advtrain/label_smoothed_ce_grad OK advtrain/trades_stopgrad OK (max_abs=0.00e+00) advtrain/alp_pairing OK (max_abs=0.00e+00) advtrain/clp_stopgrad OK (max_abs=0.00e+00) advtrain/kl_at_stopgrad OK (max_abs=0.00e+00) ------------------------------------------------------------------------ advtrain 14/14 TOTAL 14/14 public checks passing All public checks pass. Now make sure model.npz clears the held-out ROBUST-accuracy threshold; the grader re-checks with DIFFERENT seeds/shapes + its OWN strong PGD. data/to_onehot OK ------------------------------------------------------------------------ data 3/3 TOTAL 3/3 public checks passing All public checks pass. Now make sure model.npz clears the held-out ROBUST-accuracy threshold; t …[truncated 554 chars]
python3 run_checks.py 2>&1 | tail -4 && echo "=== SMOKE ===" && cat test.sh
------------------------------------------------------------------------
autograd_grads 82/82 | nn_forward 22/22 | optim 20/20 | attack 18/18 | advtrain 14/14 | integration 4/4 | data 3/3
TOTAL 163/163 public checks passing
All public checks pass. Now make sure model.npz clears the held-out ROBUST-accuracy threshold; the grader re-checks with DIFFERENT seeds/shapes + its OWN strong PGD.
=== SMOKE ===
#!/usr/bin/env bash
# Smoke test (NOT the grader): confirms the environment is wired -- numpy imports, the training
# split loads, and the submission stubs are present. It does NOT check correctness (the stubs raise
# NotImplementedError until you implement them).
set -uo pipefail
python3 - <<'PY'
import numpy as np, os
p = "/app/data/train.npz"
assert os.path.exists(p), "missing train.npz"
d = np.load(p)
print(f"train.npz: X{d['X'].shape} {d['X'].dtype} y{d['y'].shape} classes={len(set(d['y'].tolist()))}")
for f in ("autograd.py", "nn.py", "optim.py", "data.py", "attack.py", "advtrain.py", "train.py"):
assert os.path.exists(f"/app/submission/{f}"), f"missing /app/submission/{f}"
assert os.path.exists("/app/run_checks.py"), "missing /app/run_checks.py (public component runner)"
print("submission stubs present:", sorted(os.listdir("/app/submission")))
print("numpy", np.__version__)
PY
echo "app_test smoke OK (run 'python3 /app/run_checks.py' for the per-check progress report)"/app/submission/train.py
def train(train_path, out_path, epochs=12, batch_size=128, lr=1.2e-3, eps=0.12,
at_steps=7, alpha=0.03, grad_clip=1.0, weight_decay=5e-4, val_frac=0.15,
sel_steps=7, seed=0, log_every=1):
"""Run multi-step PGD adversarial training and save the best-by-robust-val checkpoint to
``out_path``. See the module docstring for the recipe."""
raise NotImplementedError("implement the adversarial-training loop")def _accuracy(model, X, y, bs=256):
correct = 0
for s in range(0, X.shape[0], bs):
logits = model(X[s:s + bs]).data
correct += int((logits.argmax(axis=1) == y[s:s + bs]).sum())
return correct / X.shape[0]
def _robust_accuracy(model, X, y, eps, steps, alpha, restarts, rng, bs=256):
"""Fraction correct cleanly AND surviving every PGD restart (worst-case)."""
robust = 0
total = X.shape[0]
for s in range(0, total, bs):
xb = X[s:s + bs]
yb = y[s:s + bs]
clean_pred = model(xb).data.argmax(axis=1)
surv = clean_pred == yb
for _ in range(restarts):
xa = A.pgd_attack(model, xb, yb, eps, steps, alpha,
rng=np.random.default_rng(rng.integers(0, 2 ** 31 - 1)))
adv_pred = model(xa).data.argmax(axis=1)
surv = surv & (adv_pred == yb)
robust += int(surv.sum())
return robust / total
def train(train_path, out_path, epochs=25, batch_size=128, lr=1.2e-3, eps=0.12,
at_steps=10, alpha=0.031, grad_clip=1.0, weight_decay=5e-4, val_frac=0.12,
sel_steps=20, seed=0, log_every=1):
"""Run multi-step PGD adversarial training and save the best-by-robust-val checkpoint."""
rng = np.random.default_rng(seed)
X, y = D.load_npz(train_path)
n_classes = int(y.max()) + 1
c_in = X.shape[1]
img = X.shape[2]
(Xtr, ytr), (Xval, yval) = D.train_val_split(X, y, val_frac, rng)
model = SmallCNN(n_classes=n_cl
…[truncated 1752 chars]The file /app/submission/train.py has been updated successfully. (file state is current in your context , no need to Read it back)
cd /app/submission && time python3 -c "
import train
sd, rob = train.train('/app/data/train.npz', '/tmp/test_model.npz', epochs=2, at_steps=7, sel_steps=10)
" 2>&1 | tail -10real 0m5.632s user 0m1.753s sys 0m1.350s
python3 -c "
import train
sd, rob = train.train('/app/data/train.npz', '/tmp/test_model.npz', epochs=2, at_steps=7, sel_steps=10)
" 2>&1Exit code 137
/bin/bash: line 7: 1584 Killed python3 -c "
import train
sd, rob = train.train('/app/data/train.npz', '/tmp/test_model.npz', epochs=2, at_steps=7, sel_steps=10)
" 2>&1python3 -c "
import numpy as np, resource, data as D, attack as A, advtrain as AT, optim as O
from nn import SmallCNN
X,y=D.load_npz('/app/data/train.npz')
m=SmallCNN(n_classes=6,c_in=1,img=16,c1=14,c2=28,ff=96,seed=0)
xb,yb=X[:128],y[:128]
xa=A.pgd_attack(m,xb,yb,0.12,7,0.031,rng=np.random.default_rng(0))
print('pgd ok', xa.shape)
loss=AT.pgd_at_loss(m,xa,yb);
o=O.AdamW(m.params()); o.zero_grad(); loss.backward(); O.clip_grad_norm(m.params(),1.0); o.step()
print('step ok loss', float(loss.data))
print('peak MB', resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024)
" 2>&1 | tailpgd ok (128, 1, 16, 16) step ok loss 1.8639379739369182 peak MB 202.30078125
python3 -c "
import numpy as np, resource, gc, data as D, attack as A, advtrain as AT, optim as O
from nn import SmallCNN
X,y=D.load_npz('/app/data/train.npz')
m=SmallCNN(n_classes=6,c_in=1,img=16,c1=14,c2=28,ff=96,seed=0)
o=O.AdamW(m.params(),lr=1e-3)
rng=np.random.default_rng(0)
import time; t=time.time()
for i in range(50):
idx=rng.integers(0,X.shape[0],128); xb,yb=X[idx],y[idx]
xa=A.pgd_attack(m,xb,yb,0.12,10,0.031,rng=rng)
loss=AT.pgd_at_loss(m,xa,yb); o.zero_grad(); loss.backward(); O.clip_grad_norm(m.params(),1.0); o.step()
if i%10==0: print(i,'MB',round(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024),'t',round(time.time()-t,1),flush=True)
print('done MB',round(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024))
" 2>&1 | tail(Bash completed with no output)
python3 -u -c "
import numpy as np, resource, data as D, attack as A, advtrain as AT, optim as O
from nn import SmallCNN
X,y=D.load_npz('/app/data/train.npz')
m=SmallCNN(n_classes=6,c_in=1,img=16,c1=14,c2=28,ff=96,seed=0)
o=O.AdamW(m.params(),lr=1e-3)
rng=np.random.default_rng(0)
for i in range(50):
idx=rng.integers(0,X.shape[0],128); xb,yb=X[idx],y[idx]
xa=A.pgd_attack(m,xb,yb,0.12,10,0.031,rng=rng)
loss=AT.pgd_at_loss(m,xa,yb); o.zero_grad(); loss.backward(); O.clip_grad_norm(m.params(),1.0); o.step()
print(i,'MB',round(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024),flush=True)
"; echo "EXIT $?"/bin/bash: line 25: 1599 Killed python3 -u -c "
import numpy as np, resource, data as D, attack as A, advtrain as AT, optim as O
from nn import SmallCNN
X,y=D.load_npz('/app/data/train.npz')
m=SmallCNN(n_classes=6,c_in=1,img=16,c1=14,c2=28,ff=96,seed=0)
o=O.AdamW(m.params(),lr=1e-3)
rng=np.random.default_rng(0)
for i in range(50):
idx=rng.integers(0,X.shape[0],128); xb,yb=X[idx],y[idx]
xa=A.pgd_attack(m,xb,yb,0.12,10,0.031,rng=rng)
loss=AT.pgd_at_loss(m,xa,yb); o.zero_grad(); loss.backward(); O.clip_grad_norm(m.params(),1.0); o.step()
print(i,'MB',round(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024),flush=True)
"
EXIT 137python3 -u -c "
import numpy as np, resource, data as D, attack as A, advtrain as AT, optim as O
from nn import SmallCNN
X,y=D.load_npz('/app/data/train.npz')
m=SmallCNN(n_classes=6,c_in=1,img=16,c1=14,c2=28,ff=96,seed=0)
o=O.AdamW(m.params(),lr=1e-3)
rng=np.random.default_rng(0)
idx=rng.integers(0,X.shape[0],128); xb,yb=X[idx],y[idx]
print('start',flush=True)
xa=A.pgd_attack(m,xb,yb,0.12,10,0.031,rng=rng)
print('after pgd MB',round(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024),flush=True)
"; echo "EXIT $?"start
/bin/bash: line 23: 1605 Killed python3 -u -c "
import numpy as np, resource, data as D, attack as A, advtrain as AT, optim as O
from nn import SmallCNN
X,y=D.load_npz('/app/data/train.npz')
m=SmallCNN(n_classes=6,c_in=1,img=16,c1=14,c2=28,ff=96,seed=0)
o=O.AdamW(m.params(),lr=1e-3)
rng=np.random.default_rng(0)
idx=rng.integers(0,X.shape[0],128); xb,yb=X[idx],y[idx]
print('start',flush=True)
xa=A.pgd_attack(m,xb,yb,0.12,10,0.031,rng=rng)
print('after pgd MB',round(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024),flush=True)
"
EXIT 137python3 -u -c "
import numpy as np, resource, gc, data as D, attack as A
from nn import SmallCNN
X,y=D.load_npz('/app/data/train.npz')
m=SmallCNN(n_classes=6,c_in=1,img=16,c1=14,c2=28,ff=96,seed=0)
rng=np.random.default_rng(0)
idx=rng.integers(0,X.shape[0],128); xb,yb=X[idx],y[idx]
for s in range(10):
g=A.input_grad(m,xb,yb); gc.collect()
print(s,'MB',round(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024),flush=True)
"; echo EXIT $?0 MB 82 1 MB 83 2 MB 85 3 MB 85 4 MB 85 5 MB 85 6 MB 85 7 MB 85 8 MB 85 9 MB 85 EXIT 0
python3 - <<'PY'
import re
s=open('autograd.py').read()
# closures: take g param
s=s.replace('def bw():','def bw(g):')
s=s.replace('def bw_id():','def bw_id(g):')
# replace out.grad usages inside closures with g
s=s.replace('out.grad','g')
# default backward + dispatch
s=s.replace('self._backward: Callable[[], None] = lambda: None','self._backward: Callable = lambda g: None')
s=s.replace(' t._backward()',' t._backward(t.grad)')
open('autograd.py','w').write(s)
print('done; remaining out.data refs:')
import subprocess
print(subprocess.run(['grep','-n','out.data', 'autograd.py'],capture_output=True,text=True).stdout)
print('g = g lines:', s.count('g = g'))
PYdone; remaining out.data refs: 298: a._accum(g * out.data) 320: a._accum(g * 0.5 / out.data) g = g lines: 17
/app/submission/autograd.py
def exp(a) -> Tensor:
a = _ensure(a)
out = Tensor(np.exp(a.data), requires_grad=_rg(a), _parents=(a,))
def bw(g):
if a.requires_grad:
a._accum(g * out.data)
out._backward = bw
return outdef exp(a) -> Tensor:
a = _ensure(a)
e = np.exp(a.data)
out = Tensor(e, requires_grad=_rg(a), _parents=(a,))
def bw(g):
if a.requires_grad:
a._accum(g * e)
out._backward = bw
return outThe file /app/submission/autograd.py has been updated successfully. (file state is current in your context , no need to Read it back)
/app/submission/autograd.py
def sqrt(a) -> Tensor:
a = _ensure(a)
out = Tensor(np.sqrt(a.data), requires_grad=_rg(a), _parents=(a,))
def bw(g):
if a.requires_grad:
a._accum(g * 0.5 / out.data)
out._backward = bw
return outdef sqrt(a) -> Tensor:
a = _ensure(a)
r = np.sqrt(a.data)
out = Tensor(r, requires_grad=_rg(a), _parents=(a,))
def bw(g):
if a.requires_grad:
a._accum(g * 0.5 / r)
out._backward = bw
return outThe file /app/submission/autograd.py has been updated successfully. (file state is current in your context , no need to Read it back)
cd /app && grep -n "out.grad\|out.data" submission/autograd.py; echo "---grep done---"; python3 run_checks.py 2>&1 | tail -3
---grep done--- autograd_grads 77/82 | nn_forward 22/22 | optim 20/20 | attack 18/18 | advtrain 14/14 | integration 4/4 | data 3/3 TOTAL 158/163 public checks passing Fix the FAIL lines above, then re-run. Each names a backward/forward/optimizer/attack/adversarial-training bug.
python3 run_checks.py --only autograd_grads 2>&1 | grep FAIL
grad/getitem_row FAIL (raised ValueError: array is not broadcastable to correct shape) grad/getitem_slice FAIL (raised ValueError: array is not broadcastable to correct shape) grad/embedding FAIL (raised ValueError: array is not broadcastable to correct shape) grad/grucell FAIL (raised ValueError: array is not broadcastable to correct shape) grad/lstmcell FAIL (raised ValueError: array is not broadcastable to correct shape) Fix the FAIL lines above, then re-run. Each names a backward/forward/optimizer/attack/adversarial-training bug.
/app/submission/autograd.py
out = Tensor(a.data[idx], requires_grad=_rg(a), _parents=(a,))
def bw(g):
if a.requires_grad:
g = np.zeros_like(a.data)
np.add.at(g, idx, g)
a._accum(g)
out._backward = bw
return out out = Tensor(a.data[idx], requires_grad=_rg(a), _parents=(a,))
def bw(g):
if a.requires_grad:
ga = np.zeros_like(a.data)
np.add.at(ga, idx, g)
a._accum(ga)
out._backward = bw
return outThe file /app/submission/autograd.py has been updated successfully. (file state is current in your context , no need to Read it back)
No file changes, the agent left the workspace untouched.
=== SyncVals verifier (local re-grade of the agent's own checkpoint) === COMPONENT CONFORMANCE SUITE: 200/201 cases passed (all milestones pass: False) failing milestones: autograd_grads (86/87) FINAL METRIC: PGD robust accuracy = 0.58 < threshold 0.6 REWARD = 0 (1 iff every component milestone passes AND the sealed held-out metric clears its threshold) NOTE: the in-sandbox training in the 481MB e2b box was OOM-killed (0-byte checkpoint), so the raw in-sandbox reward was an infrastructure artifact. This reward is from a faithful LOCAL re-train of the agent's OWN train.py (24GB, no OOM) with its own default hyperparameters, then re-graded by the real verifier.
Reproduce this trial: git checkout 2f94510 && PYTHONPATH=src python3 scripts/build_site.py , then open trial/trial_5c08b25117294d2b. Re-running the agent live requires EVAL_PLATFORM_ENABLE_OAUTH_SMOKE=1 and is non-deterministic.
Trial trial_5c08b25117294d2b · verifier authoritative; classifier explanatory.