anzhi2710gmailcom's picture
Upload folder using huggingface_hub
d766458 verified
Raw
History Blame Contribute Delete
3.29 kB
import jax
import jax.numpy as jnp
import haiku as hk
import numpy as np
from .utils import cat_neighbors_nodes, get_ar_mask
class mpnn_sample:
def sample(self, I):
"""
I = {
[[required]]
'X' = (L,4,3)
'mask' = (L,)
'residue_index' = (L,)
'chain_idx' = (L,)
'decoding_order' = (L,)
[[optional]]
'ar_mask' = (L,L)
'bias' = (L,21)
'temperature' = 1.0
}
"""
key = hk.next_rng_key()
L = I["X"].shape[0]
temperature = I.get("temperature",1.0)
# prepare node and edge embeddings
E, E_idx = self.features(I)
h_V = jnp.zeros((E.shape[0], E.shape[-1]))
h_E = self.W_e(E)
##############
# encoder
##############
mask_attend = jnp.take_along_axis(I["mask"][:,None] * I["mask"][None,:], E_idx, 1)
for layer in self.encoder_layers:
h_V, h_E = layer(h_V, h_E, E_idx, I["mask"], mask_attend)
# get autoregressive mask
ar_mask = I.get("ar_mask",get_ar_mask(I["decoding_order"]))
mask_attend = jnp.take_along_axis(ar_mask, E_idx, 1)
mask_1D = I["mask"][:,None]
mask_bw = mask_1D * mask_attend
mask_fw = mask_1D * (1 - mask_attend)
h_EX_encoder = cat_neighbors_nodes(jnp.zeros_like(h_V), h_E, E_idx)
h_EXV_encoder = cat_neighbors_nodes(h_V, h_EX_encoder, E_idx)
h_EXV_encoder = mask_fw[...,None] * h_EXV_encoder
def fwd(x, t, key):
h_EXV_encoder_t = h_EXV_encoder[t]
E_idx_t = E_idx[t]
mask_t = I["mask"][t]
mask_bw_t = mask_bw[t]
h_ES_t = cat_neighbors_nodes(x["h_S"], h_E[t], E_idx_t)
##############
# decoder
##############
for l,layer in enumerate(self.decoder_layers):
h_V = x["h_V"][l]
h_ESV_decoder_t = cat_neighbors_nodes(h_V, h_ES_t, E_idx_t)
h_ESV_t = mask_bw_t[...,None] * h_ESV_decoder_t + h_EXV_encoder_t
h_V_t = layer(h_V[t], h_ESV_t, mask_V=mask_t)
# update
x["h_V"] = x["h_V"].at[l+1,t].set(h_V_t)
logits_t = self.W_out(h_V_t)
x["logits"] = x["logits"].at[t].set(logits_t)
##############
# sample
##############
# add bias
if "bias" in I: logits_t += I["bias"][t]
# sample character
logits_t = logits_t/temperature + jax.random.gumbel(key, logits_t.shape)
# tie positions
logits_t = logits_t.mean(0, keepdims=True)
S_t = jax.nn.one_hot(logits_t[...,:20].argmax(-1), 21)
# update
x["h_S"] = x["h_S"].at[t].set(self.W_s(S_t))
x["S"] = x["S"].at[t].set(S_t)
return x, None
# initial values
X = {"h_S": jnp.zeros_like(h_V),
"h_V": jnp.array([h_V] + [jnp.zeros_like(h_V)] * len(self.decoder_layers)),
"S": jnp.zeros((L,21)),
"logits": jnp.zeros((L,21))}
# scan over decoding order
t = I["decoding_order"]
if t.ndim == 1: t = t[:,None]
XS = {"t":t, "key":jax.random.split(key,t.shape[0])}
X = hk.scan(lambda x, xs: fwd(x, xs["t"], xs["key"]), X, XS)[0]
return {"S":X["S"], "logits":X["logits"], "decoding_order":t}