Incidence-Matrix Structured Action Head / custom_incidence_actions.py

✓✓ Beats tuned baseline

Raw ⬇ ZIP
 1import numpy as np
 2import torch
 3
 4META = {
 5    "name": "incidence_actions",
 6    "domain": "structured_action_classification",
 7    "description": "Variable-size atomic entities and legal composite actions represented by an instance-specific binary incidence matrix; labels are noisy utility-maximizing legal actions."
 8}
 9D = 4
10MAX_ATOMS = 24
11MAX_ACTIONS = 48
12
13def get_dataset(seed, n_train, n_test):
14    rng = np.random.default_rng(int(seed))
15    true_w = np.array([1.2, -0.9, 0.65, 0.35], dtype=np.float32)
16    def make(n):
17        X = np.zeros((n, MAX_ATOMS * D + MAX_ACTIONS * MAX_ATOMS), dtype=np.float32)
18        y = np.zeros(n, dtype=np.int64)
19        for b in range(n):
20            na = int(rng.integers(5, MAX_ATOMS + 1))
21            pa = int(rng.integers(5, MAX_ACTIONS + 1))
22            atoms = rng.normal(size=(na, D)).astype(np.float32)
23            A = np.zeros((pa, na), dtype=np.float32)
24            for p in range(pa):
25                k = int(rng.integers(1, min(6, na) + 1))
26                A[p, rng.choice(na, size=k, replace=False)] = 1.0
27            utilities = A @ (atoms @ true_w) + 0.08 * rng.normal(size=pa)
28            y[b] = int(np.argmax(utilities))
29            X[b, :na * D] = atoms.reshape(-1)
30            packed = np.pad(A, ((0, 0), (0, MAX_ATOMS-na))).reshape(-1)
31            X[b, MAX_ATOMS * D:MAX_ATOMS * D + pa * MAX_ATOMS] = packed
32        return X, y
33    xtr, ytr = make(n_train)
34    xte, yte = make(n_test)
35    return {"xtr": torch.from_numpy(xtr), "ytr": torch.from_numpy(ytr),
36            "xte": torch.from_numpy(xte), "yte": torch.from_numpy(yte),
37            "input_shape": (xtr.shape[1],), "out_dim": MAX_ACTIONS,
38            "task": "classification", "metric": "cross_entropy"}