Delete tests
Browse files- tests/test_examples.py +0 -97
tests/test_examples.py
DELETED
|
@@ -1,97 +0,0 @@
|
|
| 1 |
-
"""Offline unit checks for the Lecture 3 examples."""
|
| 2 |
-
import csv
|
| 3 |
-
import itertools
|
| 4 |
-
from pathlib import Path
|
| 5 |
-
import sys
|
| 6 |
-
from types import SimpleNamespace
|
| 7 |
-
import unittest
|
| 8 |
-
|
| 9 |
-
import torch
|
| 10 |
-
|
| 11 |
-
ROOT = Path(__file__).resolve().parents[1]
|
| 12 |
-
sys.path.insert(0, str(ROOT / "lecture_3"))
|
| 13 |
-
import esm2_flow_guidance as flow
|
| 14 |
-
import esm2_diffusion_guidance as diffusion
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
class GuidanceTests(unittest.TestCase):
|
| 18 |
-
@classmethod
|
| 19 |
-
def setUpClass(cls):
|
| 20 |
-
torch.set_num_threads(2)
|
| 21 |
-
|
| 22 |
-
def test_example_annotations(self):
|
| 23 |
-
with (ROOT / "lecture_3" / "esm2_example.csv").open(newline="") as handle:
|
| 24 |
-
rows = list(csv.DictReader(handle))
|
| 25 |
-
self.assertEqual(len(rows), 64)
|
| 26 |
-
self.assertEqual({len(row["sequence"]) for row in rows}, {24})
|
| 27 |
-
labels = torch.tensor([[float(row["r1"]), float(row["r2"])] for row in rows])
|
| 28 |
-
for module in (flow, diffusion):
|
| 29 |
-
computed = module.composition_proxies([row["sequence"] for row in rows])
|
| 30 |
-
torch.testing.assert_close(computed, labels, atol=1e-7, rtol=0)
|
| 31 |
-
for row in rows:
|
| 32 |
-
self.assertEqual(int(row["c"]), int(float(row["r1"]) > 0))
|
| 33 |
-
|
| 34 |
-
def test_scalarization_weights(self):
|
| 35 |
-
for module in (flow, diffusion):
|
| 36 |
-
with self.subTest(module=module.__name__):
|
| 37 |
-
weights = module.normalize_weights((7, 3)).cpu()
|
| 38 |
-
torch.testing.assert_close(weights, torch.tensor([0.7, 0.3]))
|
| 39 |
-
for invalid in ((0, 0), (-1, 2), (1,), (float("nan"), 1)):
|
| 40 |
-
with self.assertRaises(ValueError):
|
| 41 |
-
module.normalize_weights(invalid)
|
| 42 |
-
|
| 43 |
-
def test_reward_gradient_without_weight_updates(self):
|
| 44 |
-
for module in (flow, diffusion):
|
| 45 |
-
with self.subTest(module=module.__name__):
|
| 46 |
-
torch.manual_seed(3)
|
| 47 |
-
reward = module.RewardModel(4, 5).to(module.DEVICE)
|
| 48 |
-
reward.eval().requires_grad_(False)
|
| 49 |
-
state = torch.randn(2, 4, 5, device=module.DEVICE)
|
| 50 |
-
time = torch.tensor([0.3, 0.7], device=module.DEVICE)
|
| 51 |
-
weights = module.normalize_weights((0.7, 0.3))
|
| 52 |
-
gradient = module.reward_gradient(reward, state, time, weights)
|
| 53 |
-
delta = torch.zeros_like(state)
|
| 54 |
-
delta[0, 1, 2] = 1e-3
|
| 55 |
-
difference = reward(state + delta, time) - reward(state - delta, time)
|
| 56 |
-
estimate = (difference * weights).sum() / (2e-3)
|
| 57 |
-
torch.testing.assert_close(gradient[0, 1, 2], estimate, atol=3e-5, rtol=3e-3)
|
| 58 |
-
self.assertFalse(gradient.requires_grad)
|
| 59 |
-
self.assertTrue(torch.isfinite(gradient).all())
|
| 60 |
-
self.assertTrue(all(p.grad is None for p in reward.parameters()))
|
| 61 |
-
|
| 62 |
-
def test_ddpm_schedule(self):
|
| 63 |
-
self.assertEqual(diffusion.alpha_bars[0].item(), 1.0)
|
| 64 |
-
self.assertLess(diffusion.alpha_bars[-1].item(), 1e-4)
|
| 65 |
-
self.assertEqual(diffusion.posterior_variances[1].item(), 0.0)
|
| 66 |
-
self.assertTrue((diffusion.posterior_variances >= 0).all())
|
| 67 |
-
self.assertTrue(torch.isfinite(diffusion.posterior_variances).all())
|
| 68 |
-
|
| 69 |
-
def test_constrained_decoder_against_exhaustive_search(self):
|
| 70 |
-
torch.manual_seed(11)
|
| 71 |
-
scores = torch.randn(3, 4, 20)
|
| 72 |
-
tokenizer = SimpleNamespace(convert_tokens_to_ids=lambda tokens: list(range(20)))
|
| 73 |
-
esm = SimpleNamespace(lm_head=torch.nn.Identity())
|
| 74 |
-
stats = {"z_mean": torch.zeros(1, 1, 20), "z_std": torch.ones(1, 1, 20)}
|
| 75 |
-
for module in (flow, diffusion):
|
| 76 |
-
polar = [i for i, a in enumerate(module.AMINO_ACIDS) if a in module.POLAR_RESIDUES]
|
| 77 |
-
nonpolar = [i for i in range(20) if i not in polar]
|
| 78 |
-
for minimum in range(5):
|
| 79 |
-
sequences = module.decode(scores, esm, tokenizer, stats, min_polar=minimum)
|
| 80 |
-
for batch, sequence in enumerate(sequences):
|
| 81 |
-
count = sum(a in module.POLAR_RESIDUES for a in sequence)
|
| 82 |
-
self.assertGreaterEqual(count, minimum)
|
| 83 |
-
actual = sum(float(scores[batch, j, module.AMINO_ACIDS.index(a)])
|
| 84 |
-
for j, a in enumerate(sequence))
|
| 85 |
-
optimal = max(
|
| 86 |
-
sum(float(scores[batch, j, polar if flag else nonpolar].max())
|
| 87 |
-
for j, flag in enumerate(assignment))
|
| 88 |
-
for assignment in itertools.product((0, 1), repeat=4)
|
| 89 |
-
if sum(assignment) >= minimum
|
| 90 |
-
)
|
| 91 |
-
self.assertAlmostEqual(actual, optimal, places=5)
|
| 92 |
-
with self.assertRaises(ValueError):
|
| 93 |
-
module.decode(scores, esm, tokenizer, stats, min_polar=5)
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
if __name__ == "__main__":
|
| 97 |
-
unittest.main()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|