def test_autograd(self): # The graph is not retained by default g1 = gtn.scalar_graph(3.0) g2 = gtn.scalar_graph(3.0) result = gtn.add(g1, g2) gtn.backward(result) # Cannot backward twice when graph is cleared. self.assertRaises(ValueError, gtn.backward, result) # Check the graph is retained g1.zero_grad() g2.zero_grad() result = gtn.add(g1, g2) gtn.backward(result, True) result.zero_grad() g1.zero_grad() g2.zero_grad() gtn.backward(result, True) self.assertEqual(g1.grad().item(), 1.0) self.assertEqual(g2.grad().item(), 1.0) # Check that provided input gradients are used. g1.zero_grad() g2.zero_grad() result = gtn.add(g1, g2) deltas = gtn.Graph() deltas.add_node(True) deltas.add_node(False, True) deltas.add_arc(0, 1, 0, 0, 7.0) gtn.backward(result, deltas) self.assertEqual(g1.grad().item(), 7.0) self.assertEqual(g2.grad().item(), 7.0)
def test_backward_calls_once(self): g1 = gtn.scalar_graph(1) g2 = gtn.scalar_graph(1) gout = gtn.add(g1, g2) gtn.backward([gout]) pmap_grad = gout.grad() gout = gtn.add(g1, g2) gtn.backward(gout) grad = gout.grad() self.assertTrue(gtn.equal(pmap_grad, grad))
def test_default_args(self): g1 = gtn.scalar_graph(0) g1.add_arc(0, 1, 0) g2 = gtn.scalar_graph(0) g2.add_arc(0, 1, 0) g_expected = gtn.remove(g1) g_removed = gtn.remove([g1, g2])[0] self.assertTrue(gtn.equal(g_expected, g_removed))
def test_parallel_two_arg(self): inputs1 = [gtn.scalar_graph(k) for k in [1.0, 2.0, 3.0]] inputs2 = [gtn.scalar_graph(k) for k in [1.0, 2.0, 3.0]] outputs = gtn.add(inputs1, inputs2) expected = [] for g1, g2 in zip(inputs1, inputs2): expected.append(gtn.add(g1, g2)) self.assertEqual(len(outputs), len(inputs1), len(inputs2)) for i in range(0, len(expected)): self.assertTrue(gtn.equal(outputs[i], expected[i]))
def test_scalar_ops(self): g1 = gtn.scalar_graph(3.0) result = gtn.negate(g1) self.assertEqual(result.item(), -3.0) g2 = gtn.scalar_graph(4.0) result = gtn.add(g1, g2) self.assertEqual(result.item(), 7.0) result = gtn.subtract(g2, g1) self.assertEqual(result.item(), 1.0)
def test_parallel_vector_arg(self): inputList = [ gtn.scalar_graph(1.0), gtn.scalar_graph(2.0), gtn.scalar_graph(3.0), ] inputs = [inputList, inputList, inputList] outputs = gtn.concat(inputs) expected = [] for gList in inputs: expected.append(gtn.concat(gList)) self.assertEqual(len(outputs), len(inputs)) for i in range(0, len(expected)): self.assertTrue(gtn.equal(outputs[i], expected[i]))
def test_scalar_graph(self): weight = random.random() g = gtn.scalar_graph(weight) self.assertTrue(list_almost_equal(g.weights_to_list(), [weight])) self.assertEqual(g.num_arcs(), 1) self.assertEqual(g.num_nodes(), 2) self.assertEqual(g.labels_to_list(), [gtn.epsilon])
def test_clone_project_grad(self): g1 = gtn.scalar_graph(3.0) g2 = gtn.scalar_graph(4.0) cloned = gtn.clone(g1) result = gtn.add(g1, g2) gtn.backward(result) # Cloned wasn't used in the computation self.assertRaises(RuntimeError, cloned.grad) # Cloned was used in the computation g1.zero_grad() g2.zero_grad() result = gtn.add(cloned, g2) gtn.backward(result) self.assertTrue(gtn.equal(cloned.grad(), g1.grad()))
def test_scalar_creation(self): weight = random.random() g = gtn.scalar_graph(weight, False) self.assertEqual(g.num_arcs(), 1) self.assertEqual(g.labels_to_list(), [gtn.epsilon]) self.assertEqual(g.num_nodes(), 2) self.assertEqual(len(g.weights_to_list()), 1) self.assertAlmostEqual(g.weights_to_list()[0], weight, places=5) self.assertAlmostEqual(g.item(), weight, places=5) self.assertFalse(g.calc_grad)
def test_parallel_one_arg(self): inputs = [gtn.scalar_graph(k) for k in [1.0, 2.0, 3.0]] outputs = gtn.negate(inputs) expected = [] for g in inputs: expected.append(gtn.negate(g)) self.assertEqual(len(outputs), len(inputs)) for i in range(0, len(expected)): self.assertTrue(gtn.equal(outputs[i], expected[i]))
def test_parallel_func(self): B = 3 inputs1 = [gtn.scalar_graph(k) for k in [1.0, 2.0, 3.0]] inputs2 = [gtn.scalar_graph(k) for k in [1.0, 2.0, 3.0]] out = [None] * B def process(b): out[b] = gtn.add(gtn.add(inputs1[b], inputs1[b]), gtn.negate(inputs2[b])) gtn.parallel_for(process, range(B)) expected = [] for b in range(B): expected.append( gtn.add(gtn.add(inputs1[b], inputs1[b]), gtn.negate(inputs2[b]))) self.assertEqual(len(out), len(expected)) for i in range(len(expected)): self.assertTrue(gtn.equal(out[i], expected[i]))
def test_scalar_ops_grad(self): g1 = gtn.scalar_graph(3.0) result = gtn.negate(g1) gtn.backward(result) self.assertEqual(g1.grad().item(), -1.0) g1.zero_grad() g2 = gtn.scalar_graph(4.0) result = gtn.add(g1, g2) gtn.backward(result) self.assertEqual(g1.grad().item(), 1.0) self.assertEqual(g2.grad().item(), 1.0) g1.zero_grad() g2.zero_grad() result = gtn.subtract(g1, g2) gtn.backward(result) self.assertEqual(g1.grad().item(), 1.0) self.assertEqual(g2.grad().item(), -1.0) g1.zero_grad() g2.zero_grad() result = gtn.add(gtn.add(g1, g2), g1) gtn.backward(result) self.assertEqual(g1.grad().item(), 2.0) self.assertEqual(g2.grad().item(), 1.0) g1.zero_grad() g2nograd = gtn.scalar_graph(4.0, False) result = gtn.add(g1, g2nograd) gtn.backward(result) self.assertEqual(g1.grad().item(), 1.0) self.assertRaises(RuntimeError, g2nograd.grad)
def test_parallel_backward(self): inputs1 = [gtn.scalar_graph(k) for k in [1.0, 2.0, 3.0]] inputs2 = [gtn.scalar_graph(k) for k in [1.0, 2.0, 3.0]] outputs = gtn.add(inputs1, inputs2) gtn.backward(outputs) # Test gradients inputs1 = [gtn.scalar_graph(k) for k in [1.0, 2.0, 3.0]] inputs2 = [gtn.scalar_graph(k) for k in [1.0, 2.0, 3.0]] outputs = gtn.add(inputs1, inputs2) gradIn = gtn.scalar_graph(5.0) gtn.backward(outputs, [gradIn], [False]) inputs1Dup = [gtn.scalar_graph(k) for k in [1.0, 2.0, 3.0]] inputs2Dup = [gtn.scalar_graph(k) for k in [1.0, 2.0, 3.0]] expected = [] for g1, g2 in zip(inputs1Dup, inputs2Dup): expected.append(gtn.add(g1, g2)) for g in expected: gtn.backward(g, gtn.scalar_graph(5.0)) for i in range(0, len(expected)): self.assertTrue(gtn.equal(inputs1[i].grad(), inputs1Dup[i].grad())) self.assertTrue(gtn.equal(inputs2[i].grad(), inputs2Dup[i].grad()))