|
1 | 1 | from itertools import combinations |
2 | | - |
| 2 | +import jax |
3 | 3 | import numpy as np |
4 | 4 | import pytest |
5 | 5 |
|
6 | | -# try: |
7 | | -# import jax |
8 | | -# |
9 | | -# _HAS_JAX = True |
10 | | -# except ImportError: |
11 | | -_HAS_JAX = False |
12 | | - |
13 | 6 | from autofit.mapper.variable import variables |
14 | 7 | from autofit.graphical.factor_graphs import ( |
15 | 8 | Factor, |
16 | 9 | FactorValue, |
17 | 10 | ) |
18 | 11 |
|
19 | 12 |
|
20 | | -def test_jacobian_equiv(): |
21 | | - if not _HAS_JAX: |
22 | | - return |
23 | | - |
24 | | - def linear(x, a, b, c): |
25 | | - z = x.dot(a) + b |
26 | | - return (z**2).sum(), z |
27 | | - |
28 | | - x_, a_, b_, c_, z_ = variables("x, a, b, c, z") |
29 | | - x = np.arange(10.0).reshape(5, 2) |
30 | | - a = np.arange(2.0).reshape(2, 1) |
31 | | - b = np.ones(1) |
32 | | - c = -1.0 |
33 | | - |
34 | | - factors = [ |
35 | | - Factor( |
36 | | - linear, |
37 | | - x_, |
38 | | - a_, |
39 | | - b_, |
40 | | - c_, |
41 | | - factor_out=(FactorValue, z_), |
42 | | - numerical_jacobian=False, |
43 | | - ), |
44 | | - Factor( |
45 | | - linear, |
46 | | - x_, |
47 | | - a_, |
48 | | - b_, |
49 | | - c_, |
50 | | - factor_out=(FactorValue, z_), |
51 | | - numerical_jacobian=False, |
52 | | - jacfwd=False, |
53 | | - ), |
54 | | - Factor( |
55 | | - linear, |
56 | | - x_, |
57 | | - a_, |
58 | | - b_, |
59 | | - c_, |
60 | | - factor_out=(FactorValue, z_), |
61 | | - numerical_jacobian=False, |
62 | | - vjp=True, |
63 | | - ), |
64 | | - Factor( |
65 | | - linear, |
66 | | - x_, |
67 | | - a_, |
68 | | - b_, |
69 | | - c_, |
70 | | - factor_out=(FactorValue, z_), |
71 | | - numerical_jacobian=True, |
72 | | - ), |
73 | | - ] |
74 | | - |
75 | | - values = {x_: x, a_: a, b_: b, c_: c} |
76 | | - outputs = [factor.func_jacobian(values) for factor in factors] |
77 | | - |
78 | | - tol = pytest.approx(0, abs=1e-4) |
79 | | - pairs = combinations(outputs, 2) |
80 | | - g0 = FactorValue(1.0, {z_: np.ones((5, 1))}) |
81 | | - for (val1, jac1), (val2, jac2) in pairs: |
82 | | - assert val1 == val2 |
83 | | - |
84 | | - # test with different ways of calculating gradients |
85 | | - grad1, grad2 = jac1.grad(g0), jac2.grad(g0) |
86 | | - assert (grad1 - grad2).norm() == tol |
87 | | - grad1 = g0.to_dict() * jac1 |
88 | | - assert (grad1 - grad2).norm() == tol |
89 | | - grad2 = g0.to_dict() * jac2 |
90 | | - assert (grad1 - grad2).norm() == tol |
91 | | - |
92 | | - grad1, grad2 = jac1.grad(val1), jac2.grad(val2) |
93 | | - assert (grad1 - grad2).norm() == tol |
94 | | - |
95 | | - # test getting gradient with no args |
96 | | - assert (jac1.grad() - jac2.grad()).norm() == tol |
97 | | - |
98 | | - |
99 | | -def test_jac_model(): |
100 | | - if not _HAS_JAX: |
101 | | - return |
102 | | - |
103 | | - def linear(x, a, b): |
104 | | - z = x.dot(a) + b |
105 | | - return (z**2).sum(), z |
106 | | - |
107 | | - def likelihood(y, z): |
108 | | - return ((y - z) ** 2).sum() |
109 | | - |
110 | | - def combined(x, y, a, b): |
111 | | - like, z = linear(x, a, b) |
112 | | - return like + likelihood(y, z) |
113 | | - |
114 | | - x_, a_, b_, y_, z_ = variables("x, a, b, y, z") |
115 | | - x = np.arange(10.0).reshape(5, 2) |
116 | | - a = np.arange(2.0).reshape(2, 1) |
117 | | - b = np.ones(1) |
118 | | - y = np.arange(0.0, 10.0, 2).reshape(5, 1) |
119 | | - values = {x_: x, y_: y, a_: a, b_: b} |
120 | | - linear_factor = Factor(linear, x_, a_, b_, factor_out=(FactorValue, z_), vjp=True) |
121 | | - like_factor = Factor(likelihood, y_, z_, vjp=True) |
122 | | - full_factor = Factor(combined, x_, y_, a_, b_, vjp=True) |
123 | | - model_factor = like_factor * linear_factor |
124 | | - |
125 | | - x = np.arange(10.0).reshape(5, 2) |
126 | | - a = np.arange(2.0).reshape(2, 1) |
127 | | - b = np.ones(1) |
128 | | - y = np.arange(0.0, 10.0, 2).reshape(5, 1) |
129 | | - values = {x_: x, y_: y, a_: a, b_: b} |
130 | | - |
131 | | - # Fully working problem |
132 | | - fval, jac = full_factor.func_jacobian(values) |
133 | | - grad = jac.grad() |
134 | | - |
135 | | - model_val, model_jac = model_factor.func_jacobian(values) |
136 | | - model_grad = model_jac.grad() |
137 | | - |
138 | | - linear_val, linear_jac = linear_factor.func_jacobian(values) |
139 | | - like_val, like_jac = like_factor.func_jacobian( |
140 | | - {**values, **linear_val.deterministic_values} |
141 | | - ) |
142 | | - combined_val = like_val + linear_val |
143 | | - |
144 | | - # Manually back propagate |
145 | | - combined_grads = linear_jac.grad(like_jac.grad()) |
146 | | - |
147 | | - vals = (fval, model_val, combined_val) |
148 | | - grads = (grad, model_grad, combined_grads) |
149 | | - pairs = combinations(zip(vals, grads), 2) |
150 | | - for (val1, grad1), (val2, grad2) in pairs: |
151 | | - assert val1 == val2 |
152 | | - assert (grad1 - grad2).norm() == pytest.approx(0, 1e-6) |
| 13 | +# def test_jacobian_equiv(): |
| 14 | +# |
| 15 | +# def linear(x, a, b, c): |
| 16 | +# z = x.dot(a) + b |
| 17 | +# return (z**2).sum(), z |
| 18 | +# |
| 19 | +# x_, a_, b_, c_, z_ = variables("x, a, b, c, z") |
| 20 | +# x = np.arange(10.0).reshape(5, 2) |
| 21 | +# a = np.arange(2.0).reshape(2, 1) |
| 22 | +# b = np.ones(1) |
| 23 | +# c = -1.0 |
| 24 | +# |
| 25 | +# factors = [ |
| 26 | +# Factor( |
| 27 | +# linear, |
| 28 | +# x_, |
| 29 | +# a_, |
| 30 | +# b_, |
| 31 | +# c_, |
| 32 | +# factor_out=(FactorValue, z_), |
| 33 | +# numerical_jacobian=False, |
| 34 | +# ), |
| 35 | +# Factor( |
| 36 | +# linear, |
| 37 | +# x_, |
| 38 | +# a_, |
| 39 | +# b_, |
| 40 | +# c_, |
| 41 | +# factor_out=(FactorValue, z_), |
| 42 | +# numerical_jacobian=False, |
| 43 | +# jacfwd=False, |
| 44 | +# ), |
| 45 | +# Factor( |
| 46 | +# linear, |
| 47 | +# x_, |
| 48 | +# a_, |
| 49 | +# b_, |
| 50 | +# c_, |
| 51 | +# factor_out=(FactorValue, z_), |
| 52 | +# numerical_jacobian=False, |
| 53 | +# vjp=True, |
| 54 | +# ), |
| 55 | +# Factor( |
| 56 | +# linear, |
| 57 | +# x_, |
| 58 | +# a_, |
| 59 | +# b_, |
| 60 | +# c_, |
| 61 | +# factor_out=(FactorValue, z_), |
| 62 | +# numerical_jacobian=True, |
| 63 | +# ), |
| 64 | +# ] |
| 65 | +# |
| 66 | +# values = {x_: x, a_: a, b_: b, c_: c} |
| 67 | +# outputs = [factor.func_jacobian(values) for factor in factors] |
| 68 | +# |
| 69 | +# tol = pytest.approx(0, abs=1e-4) |
| 70 | +# pairs = combinations(outputs, 2) |
| 71 | +# g0 = FactorValue(1.0, {z_: np.ones((5, 1))}) |
| 72 | +# for (val1, jac1), (val2, jac2) in pairs: |
| 73 | +# assert val1 == val2 |
| 74 | +# |
| 75 | +# # test with different ways of calculating gradients |
| 76 | +# grad1, grad2 = jac1.grad(g0), jac2.grad(g0) |
| 77 | +# assert (grad1 - grad2).norm() == tol |
| 78 | +# grad1 = g0.to_dict() * jac1 |
| 79 | +# assert (grad1 - grad2).norm() == tol |
| 80 | +# grad2 = g0.to_dict() * jac2 |
| 81 | +# assert (grad1 - grad2).norm() == tol |
| 82 | +# |
| 83 | +# grad1, grad2 = jac1.grad(val1), jac2.grad(val2) |
| 84 | +# assert (grad1 - grad2).norm() == tol |
| 85 | +# |
| 86 | +# # test getting gradient with no args |
| 87 | +# assert (jac1.grad() - jac2.grad()).norm() == tol |
| 88 | +# |
| 89 | +# |
| 90 | +# def test_jac_model(): |
| 91 | +# |
| 92 | +# def linear(x, a, b): |
| 93 | +# z = x.dot(a) + b |
| 94 | +# return (z**2).sum(), z |
| 95 | +# |
| 96 | +# def likelihood(y, z): |
| 97 | +# return ((y - z) ** 2).sum() |
| 98 | +# |
| 99 | +# def combined(x, y, a, b): |
| 100 | +# like, z = linear(x, a, b) |
| 101 | +# return like + likelihood(y, z) |
| 102 | +# |
| 103 | +# x_, a_, b_, y_, z_ = variables("x, a, b, y, z") |
| 104 | +# x = np.arange(10.0).reshape(5, 2) |
| 105 | +# a = np.arange(2.0).reshape(2, 1) |
| 106 | +# b = np.ones(1) |
| 107 | +# y = np.arange(0.0, 10.0, 2).reshape(5, 1) |
| 108 | +# values = {x_: x, y_: y, a_: a, b_: b} |
| 109 | +# linear_factor = Factor(linear, x_, a_, b_, factor_out=(FactorValue, z_), vjp=True) |
| 110 | +# like_factor = Factor(likelihood, y_, z_, vjp=True) |
| 111 | +# full_factor = Factor(combined, x_, y_, a_, b_, vjp=True) |
| 112 | +# model_factor = like_factor * linear_factor |
| 113 | +# |
| 114 | +# x = np.arange(10.0).reshape(5, 2) |
| 115 | +# a = np.arange(2.0).reshape(2, 1) |
| 116 | +# b = np.ones(1) |
| 117 | +# y = np.arange(0.0, 10.0, 2).reshape(5, 1) |
| 118 | +# values = {x_: x, y_: y, a_: a, b_: b} |
| 119 | +# |
| 120 | +# # Fully working problem |
| 121 | +# fval, jac = full_factor.func_jacobian(values) |
| 122 | +# grad = jac.grad() |
| 123 | +# |
| 124 | +# model_val, model_jac = model_factor.func_jacobian(values) |
| 125 | +# model_grad = model_jac.grad() |
| 126 | +# |
| 127 | +# linear_val, linear_jac = linear_factor.func_jacobian(values) |
| 128 | +# like_val, like_jac = like_factor.func_jacobian( |
| 129 | +# {**values, **linear_val.deterministic_values} |
| 130 | +# ) |
| 131 | +# combined_val = like_val + linear_val |
| 132 | +# |
| 133 | +# # Manually back propagate |
| 134 | +# combined_grads = linear_jac.grad(like_jac.grad()) |
| 135 | +# |
| 136 | +# vals = (fval, model_val, combined_val) |
| 137 | +# grads = (grad, model_grad, combined_grads) |
| 138 | +# pairs = combinations(zip(vals, grads), 2) |
| 139 | +# for (val1, grad1), (val2, grad2) in pairs: |
| 140 | +# assert val1 == val2 |
| 141 | +# assert (grad1 - grad2).norm() == pytest.approx(0, 1e-6) |
0 commit comments