def __call__(self, x): """Implements the chain rule. INPUTS ======= x: autodiff.Variable holding a val and grad RETURNS ======== autodiff.Variable: updated Variable after chain rule was applied """ # if autodiff.config.mode == 'forward': if isinstance(x, Variable): out_val = self.get_val(x.val) out_grad = np.dot(self.get_grad(x.val), x.grad) # out_grad = np.dot(self.get_grad(x.val), x.grad) return Variable(val=out_val, grad=out_grad) elif isinstance(x, ReverseVariable): out_val = self.get_val(x.val) res = ReverseVariable(out_val) x.children.append(res) res.left = x res.leftgrad = self.get_grad(x.val) return res else: raise ValueError("Not a variable!")
def test_rpow_exception(): x = ReverseVariable([1, 3]) y = ReverseVariable([3, 1]) z = ReverseVariable(2) a = x + y with pytest.raises(TypeError): b = "g"**y with pytest.raises(ValueError): b = 2**a
def test_mul_exception(): x = ReverseVariable([1, 2]) y = ReverseVariable([2, 1]) z = ReverseVariable(4) a = x + y with pytest.raises(TypeError): b = a * "g" with pytest.raises(TypeError): b = False * y
def test_sub_exception(): x = ReverseVariable([1, 2]) y = ReverseVariable([2, 1]) z = y + x a = z + [4.4, 3.3] b = a + z with pytest.raises(TypeError): c = b - "g" with pytest.raises(TypeError): c = True - b
def test_neg(): x = ReverseVariable([1, 3]) y = ReverseVariable([3, 1]) z = ReverseVariable(4) a = x + y b = a / z c = -b c.reverse() assert close(c.val, -np.asarray([[1], [1]])) assert close(x.grad, np.eye(2) * -0.25) assert close(y.grad, np.eye(2) * -0.25) assert close(z.grad, np.asarray([[0.25], [0.25]]))
def test_pow_exception(): x = ReverseVariable([1, 3]) y = ReverseVariable([3, 1]) z = ReverseVariable(2) a = x + y with pytest.raises(TypeError): b = a**"g" with pytest.raises(ValueError): b = a**[3, 3] with pytest.raises(ValueError): b = a**z with pytest.raises(ValueError): b = z**a
def test_create_function_exception(): with pytest.raises(NotImplementedError): f = F.Function() x = ReverseVariable([1, 2, 3]) y = f(x) with pytest.raises(NotImplementedError): f = F.Function() x = ReverseVariable([1, 2, 3]) y = f.get_grad(x) with pytest.raises(NotImplementedError): f = F.Function() x = ReverseVariable([1, 2, 3]) y = f.get_val(x)
def test_arccos(): x = ReverseVariable(0.5) arccos = F.Arccos() y = arccos(x) y.reverse() assert close(y.val, np.pi / 3) and close(x.grad, -1.0 / np.sqrt(1.0 - 0.5**2))
def test_arcsin(): x = ReverseVariable(0.5) arcsin = F.Arcsin() y = arcsin(x) y.reverse() assert close(y.val, np.pi / 6) and close(x.grad, 1.0 / np.sqrt(1.0 - 0.5**2))
def test_dot(): x = ReverseVariable([1, 1]) M = np.asarray(([2, 2], [1, 1])) dotm = F.Dot(M) y = dotm(x) y.reverse() assert close(y.val, np.asarray([[4], [2]])) and close(x.grad, M)
def test_exp(): x = ReverseVariable(2) exp = F.Exponent() y = exp(x) y.reverse() assert close(y.val, np.exp(2)) assert close(x.grad, np.exp(2))
def test_tanh(): x = ReverseVariable(1) tanh = F.Tanh() y = tanh(x) y.reverse() assert close(y.val, np.tanh(1)) and close(x.grad, (np.cosh(1)**2 - np.sinh(1)**2) / (np.cosh(1)**2))
def test_logistic(): x = ReverseVariable(2) logi = F.Logistic() y = logi(x) y.reverse() assert close(y.val, 1.0 / (1.0 + np.exp(-(2)))) and close( x.grad, (1.0 / (1.0 + np.exp(-(2)))) * (1.0 - (1.0 / (1.0 + np.exp(-(2))))))
def test_add(): x = ReverseVariable([1, 2]) y = ReverseVariable([2, 1]) z = x + y z.reverse() assert close(z.val, np.asarray([[3], [3]])) assert close(x.grad, np.eye(2)) assert close(y.grad, np.eye(2)) a = z + [4.4, 3.3] b = a + z b.reverse() assert close(b.val, np.asarray([[10.4], [9.3]])) assert close(x.grad, np.eye(2) * 2) assert close(y.grad, np.eye(2) * 2) c = [4.4, 3.3] + b c.reverse() assert close(c.val, np.asarray([[14.8], [12.6]])) assert close(x.grad, np.eye(2) * 2) assert close(y.grad, np.eye(2) * 2)
def test_log(): x = ReverseVariable(2) log = F.Log() y = log(x) y.reverse() assert close(y.val, np.log(2)) and close(x.grad, 0.5) log2 = F.Log(2) y = log2(x) y.reverse() assert close(y.val, 1) assert close(x.grad, 0.5 / np.log(2))
def test_pow(): x = ReverseVariable([1, 3]) y = ReverseVariable([3, 1]) z = ReverseVariable(2) a = x + y b = z**2 b.reverse() assert close(b.val, 4) assert close(z.grad, 4) b = a**2 b.reverse() assert close(b.val, np.asarray([[16], [16]])) assert close(x.grad, np.eye(2) * 8) assert close(y.grad, np.eye(2) * 8) c = z d = z**c d.reverse() assert close(d.val, 4) print(z.grad) assert close(z.grad, 4 * (np.log(2) + 1))
def test_sub(): x = ReverseVariable([1, 2]) y = ReverseVariable([2, 1]) z = y + x a = z + [4.4, 3.3] b = a + z c = b - x c.reverse() assert close(c.val, np.asarray([[9.4], [7.3]])) assert close(x.grad, np.eye(2)) assert close(y.grad, np.eye(2) * 2) d = 3 - c d.reverse() assert close(d.val, np.asarray([[-6.4], [-4.3]])) assert close(x.grad, np.eye(2) * -1) assert close(y.grad, np.eye(2) * -2) e = c - 2.1 e.reverse() assert close(e.val, np.asarray([[7.3], [5.2]])) assert close(x.grad, np.eye(2)) assert close(y.grad, np.eye(2) * 2)
def test_div_exception(): x = ReverseVariable([1, 3]) y = ReverseVariable([3, 1]) z = ReverseVariable(0) a = x + y with pytest.raises(ValueError): b = a / x with pytest.raises(ValueError): b = a / z with pytest.raises(ValueError): b = 4.0 / z with pytest.raises(ValueError): b = a / 0.0 with pytest.raises(ValueError): b = a / np.asarray([1, 1]) with pytest.raises(ValueError): b = 4.0 / x with pytest.raises(TypeError): b = a / "g" with pytest.raises(TypeError): a = True / y
def test_div(): x = ReverseVariable([1, 3]) y = ReverseVariable([3, 1]) z = ReverseVariable(4) a = x + y b = a / z b.reverse() assert close(b.val, np.asarray([[1], [1]])) assert close(x.grad, np.eye(2) * 0.25) assert close(y.grad, np.eye(2) * 0.25) assert close(z.grad, np.asarray([[-0.25], [-0.25]])) c = b / 0.25 c.reverse() assert close(c.val, np.asarray([[4], [4]])) assert close(x.grad, np.eye(2)) assert close(y.grad, np.eye(2)) assert close(z.grad, np.asarray([[-1], [-1]])) d = 4 / z d.reverse() assert close(d.val, 1) assert close(z.grad, -0.25)
def test_mul(): x = ReverseVariable([1, 2]) y = ReverseVariable([2, 1]) z = ReverseVariable(4) a = x + y b = a * z b.reverse() assert close(b.val, np.asarray([[12], [12]])) assert close(x.grad, np.eye(2) * 4) assert close(y.grad, np.eye(2) * 4) assert close(z.grad, np.asarray([[3], [3]])) c = b * 4 c.reverse() assert close(c.val, np.asarray([[48], [48]])) assert close(x.grad, np.eye(2) * 16) assert close(y.grad, np.eye(2) * 16) assert close(z.grad, np.asarray([[12], [12]])) d = 2 * b d.reverse() assert close(d.val, np.asarray([[24], [24]])) assert close(x.grad, np.eye(2) * 8) assert close(y.grad, np.eye(2) * 8) assert close(z.grad, np.asarray([[6], [6]]))
def test_arctan(): x = ReverseVariable(1) arctan = F.Arctan() y = arctan(x) y.reverse() assert close(y.val, np.pi / 4) and close(x.grad, 0.5)
def test_add_exception(): x = ReverseVariable([1, 2, 3]) with pytest.raises(TypeError): y = x + "g" with pytest.raises(TypeError): y = True + x
def test_exp_exception(): x = ReverseVariable([1, 2, 3]) exp = F.Exponent() with pytest.raises(ValueError): y = exp(x)
def test_sin(): x = ReverseVariable(np.pi / 6) sin = F.Sinus() y = sin(x) y.reverse() assert abs(y.val - 0.5) < 1e-4 and abs(x.grad - np.sqrt(3) / 2) < 1e-4
def test_rpow(): z = ReverseVariable(2) b = 2**z b.reverse() assert close(b.val, 4) assert close(z.grad, np.log(2) * 4)
def test_cos(): x = ReverseVariable(np.pi / 3) cos = F.Cosinus() y = cos(x) y.reverse() assert abs(y.val - 0.5) < 1e-4 and abs(x.grad + np.sqrt(3) / 2) < 1e-4
def test_tan(): x = ReverseVariable(np.pi / 4) tan = F.Tangent() y = tan(x) y.reverse() assert abs(y.val - 1) < 1e-4 and abs(x.grad - 2) < 1e-4
def test_tan_exception(): x = ReverseVariable(np.pi / 2) tan = F.Tangent() with pytest.raises(ValueError): y = tan(x)
def test_create_variable(): X = ReverseVariable([1, 2, 3]) assert close(X.val, np.asarray([[1], [2], [3]])) y = ReverseVariable(1) assert close(y.val, 1)
def test_sinh(): x = ReverseVariable(1) sinh = F.Sinh() y = sinh(x) y.reverse() assert close(y.val, np.sinh(1)) and close(x.grad, np.cosh(1))