LightNest / tests /test_patch_rl.py
LIghtJUNction's picture
Cursor
Add the October 17 experiment source without the result archives.
3f69d68 verified
Raw History Blame Contribute Delete
3.35 kB
import random
import unittest
import torch
from dataclasses import replace
from lightnest.learned_patch import MAX_WINDOW, PatchNetwork, make_example
from lightnest.train_patch_rl import cases_for, execution_reward, sample_actions, oracle
class PatchRLTests(unittest.TestCase):
def test_execution_reward_not_teacher_fields(self):
rng = random.Random(9)
e = make_example(rng)
while not e.present:
e = make_example(rng)
cases = cases_for(e.target_operation, rng)
self.assertEqual(execution_reward(e.binary, e.pointer, e.replacement, cases), 1)
self.assertEqual(execution_reward(e.binary, MAX_WINDOW, 0, cases), -1)
poisoned = replace(e, pointer=-777, replacement=-99, target=b'bad')
self.assertEqual(execution_reward(poisoned.binary, e.pointer, e.replacement, cases), 1)
def test_negative_requires_none(self):
rng = random.Random(9)
e = make_example(rng)
while e.present:
e = make_example(rng)
cases = cases_for(e.target_operation, rng)
self.assertEqual(execution_reward(e.binary, MAX_WINDOW, 0, cases), 1)
self.assertEqual(execution_reward(e.binary, 0, e.binary[0], cases), -1)
with self.assertRaises(ValueError):
execution_reward(e.binary, MAX_WINDOW, 0, [])
def test_sampling_is_differentiable(self):
torch.set_num_threads(2)
model = PatchNetwork()
es = [make_example(random.Random(i)) for i in range(3)]
pos, byte, logp = sample_actions(model, es)
self.assertEqual(pos.shape, (3,4))
self.assertTrue(bool(((byte >= 0) & (byte <= 255)).all()))
(-logp.mean()).backward()
self.assertIsNotNone(model.pointer.weight.grad)
self.assertIsNotNone(model.replacement.weight.grad)
def test_signed_composed_oracle(self):
self.assertEqual(oracle('add', [2147483647, 1]), -2147483648)
self.assertEqual(oracle('sub', [5, 2], 7), 10)
class PatchRLUpdateTests(unittest.TestCase):
def test_ties_skip_adam_momentum(self):
from lightnest.train_patch_rl import reinforce_step
model = torch.nn.Linear(1,1)
opt = torch.optim.Adam(model.parameters(), lr=.01)
x = torch.ones(1,4,1)
lp = model(x).squeeze(-1)
# First create a nonzero momentum state using nonidentical log-probs.
lp = lp * torch.tensor([[1.,2.,3.,4.]])
stepped, _, groups = reinforce_step(opt, model, lp, torch.tensor([[1.,-1.,1.,-1.]]))
self.assertTrue(stepped); self.assertEqual(groups,1)
before = {k:v.clone() for k,v in model.state_dict().items()}
step_before = opt.state[model.weight]['step'].clone()
stepped, loss, groups = reinforce_step(opt, model, model(x).squeeze(-1), torch.ones(1,4))
self.assertFalse(stepped); self.assertEqual(loss,0); self.assertEqual(groups,0)
self.assertTrue(all(torch.equal(v,model.state_dict()[k]) for k,v in before.items()))
self.assertTrue(torch.equal(step_before,opt.state[model.weight]['step']))
def test_train_templates_disjoint_from_eval_templates(self):
from lightnest.train_patch_rl import RL_TEMPLATES
from lightnest.learned_patch import TRAIN_TEMPLATES, TEST_TEMPLATES
self.assertFalse(set(RL_TEMPLATES) & set(TRAIN_TEMPLATES + TEST_TEMPLATES))