Upload folder using huggingface_hub
Browse files- README.md +9 -0
- config.json +1 -0
- model.pt +3 -0
- modeling.py +73 -0
- vocab.json +1 -0
README.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Atomight-V1-GRAFT-0.8M
|
| 2 |
+
|
| 3 |
+
Custom from-scratch hybrid discriminative+generative model for abstract reasoning (RAVEN / PGM / I-RAVEN-X style matrix puzzles).
|
| 4 |
+
|
| 5 |
+
Architecture: GRAFT (Grid Relational Attention Fusion Transformer), ~0.79M params.
|
| 6 |
+
|
| 7 |
+
Narration is templated (captions the classifier's decision, not an independent derivation from ground-truth attribute labels).
|
| 8 |
+
|
| 9 |
+
Load with the GRAFT class definition (see modeling.py) + model.pt state_dict.
|
config.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"D": 128, "D2": 96, "vocab_size": 49, "architecture": "GRAFT"}
|
model.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:a3c126b5fdfecb5dbf8d8ed177005fa6d843ac03c759697281a84d1c63fb1c13
|
| 3 |
+
size 3173304
|
modeling.py
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
import torch.nn as nn
|
| 3 |
+
import torch.nn.functional as F
|
| 4 |
+
|
| 5 |
+
D = 128
|
| 6 |
+
D2 = 96
|
| 7 |
+
|
| 8 |
+
class DepthwiseSeparableConv(nn.Module):
|
| 9 |
+
def __init__(self, in_ch, out_ch):
|
| 10 |
+
super().__init__()
|
| 11 |
+
self.dw = nn.Conv2d(in_ch, in_ch, 3, padding=1, groups=in_ch)
|
| 12 |
+
self.pw = nn.Conv2d(in_ch, out_ch, 1)
|
| 13 |
+
def forward(self, x):
|
| 14 |
+
return self.pw(self.dw(x))
|
| 15 |
+
|
| 16 |
+
class AtomEncoder(nn.Module):
|
| 17 |
+
def __init__(self, embed_dim=D):
|
| 18 |
+
super().__init__()
|
| 19 |
+
self.net = nn.Sequential(
|
| 20 |
+
nn.Conv2d(1, 16, 3, stride=2, padding=1), nn.GELU(),
|
| 21 |
+
nn.Conv2d(16, 32, 3, stride=2, padding=1), nn.GELU(),
|
| 22 |
+
DepthwiseSeparableConv(32, 64), nn.GELU(),
|
| 23 |
+
nn.AdaptiveAvgPool2d(1),
|
| 24 |
+
)
|
| 25 |
+
self.proj = nn.Linear(64, embed_dim)
|
| 26 |
+
def forward(self, x):
|
| 27 |
+
return self.proj(self.net(x).flatten(1))
|
| 28 |
+
|
| 29 |
+
class GridRelationalAttention(nn.Module):
|
| 30 |
+
def __init__(self, dim=D, heads=4, n_relations=4):
|
| 31 |
+
super().__init__()
|
| 32 |
+
self.missing_token = nn.Parameter(torch.randn(dim) * 0.02)
|
| 33 |
+
self.row_attn = nn.MultiheadAttention(dim, heads, batch_first=True)
|
| 34 |
+
self.col_attn = nn.MultiheadAttention(dim, heads, batch_first=True)
|
| 35 |
+
self.relation_queries = nn.Parameter(torch.randn(n_relations, dim) * 0.02)
|
| 36 |
+
self.cross_attn = nn.MultiheadAttention(dim, heads, batch_first=True)
|
| 37 |
+
self.rule_proj = nn.Linear(n_relations * dim, dim)
|
| 38 |
+
self.n_relations, self.dim = n_relations, dim
|
| 39 |
+
|
| 40 |
+
def forward(self, context_panels):
|
| 41 |
+
B = context_panels.shape[0]
|
| 42 |
+
missing = self.missing_token.expand(B, 1, self.dim)
|
| 43 |
+
grid = torch.cat([context_panels, missing], dim=1)
|
| 44 |
+
rows_idx = [[0,1,2],[3,4,5],[6,7,8]]
|
| 45 |
+
cols_idx = [[0,3,6],[1,4,7],[2,5,8]]
|
| 46 |
+
row_vecs = torch.cat([
|
| 47 |
+
self.row_attn(grid[:, idx, :], grid[:, idx, :], grid[:, idx, :])[0].mean(1, keepdim=True)
|
| 48 |
+
for idx in rows_idx
|
| 49 |
+
], dim=1)
|
| 50 |
+
col_vecs = torch.cat([
|
| 51 |
+
self.col_attn(grid[:, idx, :], grid[:, idx, :], grid[:, idx, :])[0].mean(1, keepdim=True)
|
| 52 |
+
for idx in cols_idx
|
| 53 |
+
], dim=1)
|
| 54 |
+
combined_ctx = torch.cat([row_vecs, col_vecs], dim=1)
|
| 55 |
+
rq = self.relation_queries.unsqueeze(0).expand(B, -1, -1)
|
| 56 |
+
rel_out, _ = self.cross_attn(rq, combined_ctx, combined_ctx)
|
| 57 |
+
return self.rule_proj(rel_out.flatten(1))
|
| 58 |
+
|
| 59 |
+
class CandidateScorer(nn.Module):
|
| 60 |
+
def __init__(self, dim=D):
|
| 61 |
+
super().__init__()
|
| 62 |
+
self.score_proj = nn.Linear(dim, dim)
|
| 63 |
+
def forward(self, rule_embedding, candidate_embeds):
|
| 64 |
+
proj_rule = self.score_proj(rule_embedding)
|
| 65 |
+
return torch.einsum("bd,bkd->bk", proj_rule, candidate_embeds)
|
| 66 |
+
|
| 67 |
+
class GRAFT(nn.Module):
|
| 68 |
+
def __init__(self, vocab_size, narrator_cls):
|
| 69 |
+
super().__init__()
|
| 70 |
+
self.encoder = AtomEncoder()
|
| 71 |
+
self.gra = GridRelationalAttention()
|
| 72 |
+
self.scorer = CandidateScorer()
|
| 73 |
+
self.narrator = narrator_cls(vocab_size=vocab_size)
|
vocab.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
["<pad>", "<bos>", "<eos>", " ", "'", "(", ")", ",", "-", ".", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", "?", "_", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
|