maya2-native-fast / tests /test_maya_fast_sampling.py
mrwine's picture
Initial release: optimized CPU runtime and converted weights of maya2-native
4f5f309 verified
Raw History Blame Contribute Delete
2.43 kB
import math
import unittest
import numpy as np
from src.maya_fast.sampling import gumbel, topk_gumbel_argmax
def _gammp(a: float, x: float) -> float:
if x <= 0:
return 0.0
if x < a + 1.0:
ap = a
sum_val = 1.0 / a
del_val = sum_val
for _ in range(1, 300):
ap += 1.0
del_val *= x / ap
sum_val += del_val
if abs(del_val) < abs(sum_val) * 1e-12:
break
return sum_val * math.exp(-x + a * math.log(x) - math.lgamma(a))
else:
b = x + 1.0 - a
c = 1.0 / 1e-30
d = 1.0 / b
h = d
for i in range(1, 300):
an = -i * (i - a)
b += 2.0
d = an * d + b
if abs(d) < 1e-30:
d = 1e-30
c = b + an / c
if abs(c) < 1e-30:
c = 1e-30
d = 1.0 / d
del_h = d * c
h *= del_h
if abs(del_h - 1.0) < 1e-12:
break
q = math.exp(-x + a * math.log(x) - math.lgamma(a)) * h
return 1.0 - q
def _chi2_pvalue(stat: float, df: int) -> float:
return max(0.0, min(1.0, 1.0 - _gammp(df / 2.0, stat / 2.0)))
class TestMayaFastSampling(unittest.TestCase):
def test_topk_gumbel_matches_multinomial(self):
# numpy: fixed 2048-logit vector, 40 000 draws, chi-square p > 0.01 against softmax(topk_masked(logits) / 0.7)
np.random.seed(42)
vocab_size = 2048
logits = np.random.randn(vocab_size).astype(np.float32)
temp = 0.7
top_k = 64
topk_indices = np.argpartition(logits, -top_k)[-top_k:]
scaled = logits[topk_indices] / temp
exp_scaled = np.exp(scaled - np.max(scaled))
probs = exp_scaled / np.sum(exp_scaled)
n_draws = 40000
rng = np.random.default_rng(12345)
counts = np.zeros(vocab_size, dtype=np.int64)
for _ in range(n_draws):
noise = gumbel(rng, (vocab_size,))
sample = topk_gumbel_argmax(logits, temp=temp, top_k=top_k, noise=noise)
counts[sample] += 1
obs = counts[topk_indices].astype(np.float64)
exp = (probs * n_draws).astype(np.float64)
chi2_stat = float(np.sum((obs - exp) ** 2 / exp))
p_val = _chi2_pvalue(chi2_stat, df=top_k - 1)
self.assertGreater(p_val, 0.01)
if __name__ == "__main__":
unittest.main()