Download model.py from Phase-Technologies/two-tower-feed-recsys: direct link, hf CLI and curl.
- Browser
- Download file 1.34 kB
-
https://huggingface.co/Phase-Technologies/two-tower-feed-recsys/resolve/main/model.py
- Command line
-
hf download hf://Phase-Technologies/two-tower-feed-recsys/model.py
-
curl -L -o model.py https://huggingface.co/Phase-Technologies/two-tower-feed-recsys/resolve/main/model.py
1.34 kB
| import torch, torch.nn as nn, torch.nn.functional as nnf | |
| mlp = lambda i, h, o: nn.Sequential(nn.Linear(i, h), nn.ReLU(), nn.Linear(h, o)) | |
| class ItemTower(nn.Module): | |
| def __init__(s, item_in=389, out=128): | |
| super().__init__(); s.net = mlp(item_in, 256, out) | |
| def forward(s, x): return nnf.normalize(s.net(x), dim=-1) | |
| class UserTower(nn.Module): | |
| def __init__(s, item_in=389, aff=15, demo=4, out=128): | |
| super().__init__(); s.net = mlp(item_in + aff + demo, 256, out) | |
| def forward(s, aff, hist, demo): | |
| return nnf.normalize(s.net(torch.cat([aff, hist, demo], -1)), dim=-1) | |
| class TwoTower(nn.Module): | |
| def __init__(s): | |
| super().__init__() | |
| s.user, s.item = UserTower(), ItemTower() | |
| s.log_scale = nn.Parameter(torch.tensor(2.64)) # learned temperature | |
| def loss(s, aff, hist, demo, pid, nid, w, F): | |
| u = s.user(aff, hist, demo) # B x 128 | |
| ids = torch.cat([pid, nid]) | |
| lg = (u @ s.item(F[ids]).T) * s.log_scale.exp() # B x 2B: in-batch + logged skips | |
| dup = ids[None] == pid[:, None] # same post = not a negative | |
| r = torch.arange(len(u)); dup[r, r] = False | |
| ce = nnf.cross_entropy(lg.masked_fill(dup, -1e4), r, reduction="none") | |
| return (ce * w).sum() / w.sum() | |