def test_expm(self): def f(x): x = x.reshape((2,2)) return sum(expm(x)) x = numpy.random.random(2*2) # forward mode ax = UTPM.init_jacobian(x) ay = f(ax) g1 = UTPM.extract_jacobian(ay) # reverse mode cg = CGraph() ax = Function(x) ay = f(ax) cg.independentFunctionList = [ax] cg.dependentFunctionList = [ay] g2 = cg.gradient(x) assert_array_almost_equal(g1, g2)
def test_tracer_on_mixed_utpm_ndarray_mul(self): D, P = 1, 1 A = numpy.arange(2 * 2, dtype=float).reshape(2, 2) x = UTPM(numpy.zeros((D, P, 2, 2))) def f(x): return sum(A * x) cg = CGraph() ax = Function(x) ay = f(ax) cg.independentFunctionList = [ax] cg.dependentFunctionList = [ay] assert_array_almost_equal(A, cg.gradient(x))
def test_expm(self): def f(x): x = x.reshape((2, 2)) return sum(expm(x)) x = numpy.random.random(2 * 2) # forward mode ax = UTPM.init_jacobian(x) ay = f(ax) g1 = UTPM.extract_jacobian(ay) # reverse mode cg = CGraph() ax = Function(x) ay = f(ax) cg.independentFunctionList = [ax] cg.dependentFunctionList = [ay] g2 = cg.gradient(x) assert_array_almost_equal(g1, g2)
x.data[1, :, :, 0] = numpy.eye(P) y = x[N:] x = x[:N] # wrap the UTPM instance in a Function instance to trace all operations # that have x as an argument # create a CGraph instance that to store the computational trace cg = CGraph().trace_on() x = Function(x) y = Function(y) z = f(x, y) cg.trace_off() # define dependent and independent variables in the computational procedure cg.independentFunctionList = [x, y] cg.dependentFunctionList = [z] # Since the UTPM instrance is wrapped in a Function instance we have to access it # by y.x. That means the Jacobian is grad1 = z.x.data[1, :, 0] print('forward gradient g(x) = \n', grad1) # Now we want to compute the same Jacobian in the reverse mode of AD # before we do that we have a look what the computational graph looks like: # print 'Computational graph is', cg # the reverse mode is called by cg.pullback([ybar]) # it is a little hard to explain what's going on here. Suffice to say that we # now compute one row of the Jacobian instead of one column as in the forward mode
V = solve(R.T, Q2) return dot(V.T, V) # dimensions of the involved matrices D, P, M, N, K, Nx = 2, 1, 5, 3, 1, 1 # trace the function evaluation of METHOD 1: nullspace method cg1 = CGraph() J1 = Function(UTPM(numpy.random.rand(*(D, P, M, N)))) J2 = Function(UTPM(numpy.random.rand(*(D, P, K, N)))) C = eval_covariance_matrix_qr(J1, J2) y = C[0, 0] cg1.trace_off() cg1.independentFunctionList = [J1, J2] cg1.dependentFunctionList = [y] print('covariance matrix: C =\n', C) # trace the function evaluation of METHOD 2: naive method (potentially numerically unstable) cg2 = CGraph() J1 = Function(J1.x) J2 = Function(J2.x) C2 = eval_covariance_matrix_naive(J1, J2) y = C2[0, 0] cg2.trace_off() cg2.independentFunctionList = [J1, J2] cg2.dependentFunctionList = [y] print('covariance matrix: C =\n', C2) # check that both algorithms returns the same result print('difference between naive and nullspace method:\n', C - C2)
""" This example shows that most computations can be performed by numpy functions on arrays of UTPM objects. Just bear in mind that is much faster use UTPM instances of matrices than numpy.ndarrays with UTPM elements. """ import numpy, os from algopy import CGraph, Function, UTPM, dot, qr, eigh, inv N, D, P = 2, 2, 1 cg = CGraph() x = numpy.array([Function(UTPM(numpy.random.rand(*(D, P)))) for n in range(N)]) A = numpy.outer(x, x) A = numpy.exp(A) y = numpy.dot(A, x) cg.independentFunctionList = list(x) cg.dependentFunctionList = list(y) cg.plot(os.path.join(os.path.dirname(__file__), 'numpy_dot_graph.svg'))
retval = algopy.zeros(3, dtype=x) retval[0] = algopy.sin(x**2 + y) retval[1] = algopy.cos(x+y) - x retval[2] = algopy.sin(x)**2 + algopy.cos(x)**2 return retval # trace the function evaluation # and store the computational graph in cg cg = CGraph() ax = 3. ay = 5. fx = Function(ax) fy = Function(ay) fz = eval_g(fx, fy) cg.independentFunctionList = [fx, fy] cg.dependentFunctionList = [fz] # compute Taylor series # # Jx( 1. + 2.*t + 3.*t**2 + 4.*t**3 + 5.*t**5, # 6. + 7.*t + 8.*t**2 + 9.*t**3 + 10.*t**5 ) # Jy( 1. + 2.*t + 3.*t**2 + 4.*t**3 + 5.*t**5, # 6. + 7.*t + 8.*t**2 + 9.*t**3 + 10.*t**5 ) # # where # # Jx = dg/dx # Jy = dg/dy # setup input Taylor polynomials
V = solve(R.T, Q2) return dot(V.T,V) # dimensions of the involved matrices D,P,M,N,K,Nx = 2,1,5,3,1,1 # trace the function evaluation of METHOD 1: nullspace method cg1 = CGraph() J1 = Function(UTPM(numpy.random.rand(*(D,P,M,N)))) J2 = Function(UTPM(numpy.random.rand(*(D,P,K,N)))) C = eval_covariance_matrix_qr(J1, J2) y = C[0,0] cg1.trace_off() cg1.independentFunctionList = [J1, J2] cg1.dependentFunctionList = [y] print('covariance matrix: C =\n',C) # trace the function evaluation of METHOD 2: naive method (potentially numerically unstable) cg2 = CGraph() J1 = Function(J1.x) J2 = Function(J2.x) C2 = eval_covariance_matrix_naive(J1, J2) y = C2[0,0] cg2.trace_off() cg2.independentFunctionList = [J1, J2] cg2.dependentFunctionList = [y] print('covariance matrix: C =\n',C2) # check that both algorithms returns the same result print('difference between naive and nullspace method:\n',C - C2)
n_p = 512 # Datenpunkte pro Periode t = np.arange(n * n_p) / (n_p * f) # Zeitvektor current = i_hat * (np.sin(2 * np.pi * f * t) + 0.7 * np.sin(6 * np.pi * f * t + 1)) # Stromvorgabe H = current / (2 * np.pi * r) # Resultierende Feldvorgabe graph = CGraph() graph.trace_on() x = Function([alpha, a, k, c, Msat]) # Parametervektor p = {'alpha': x[0], 'a': x[1], 'k': x[2], 'c': x[3], 'm_sat': x[4]} model = JilesAthertonModel.from_dict(p) M = model.integrate_rk4(t, H) H = H[::2] t = t[::2] B = mu_0 * (H + M) dB_dt = np.zeros(np.size(B)) new = np.append([0.0], (B[1:] - B[0:-1]) / (t[1:] - t[0:-1])) P = np.sum(0.5 * H * new) graph.trace_off() graph.independentFunctionList = [x] graph.dependentFunctionList = [P] a = graph.gradient([alpha, a, k, c, Msat]) print(a)
cg1 = CGraph() J1 = Function(UTPM(numpy.random.rand(*(D, P, M, N)))) J2 = Function(UTPM(numpy.random.rand(*(D, P, K, N)))) Q, R = Function.qr_full(J2.T) Q2 = Q[:, K:].T J1_tilde = dot(J1, Q2.T) Q, R = qr(J1_tilde) V = solve(R.T, Q2) C = dot(V.T, V) cg1.trace_off() cg1.independentFunctionList = [J1, J2] cg1.dependentFunctionList = [C] print('covariance matrix: C =\n', C) print('check that Q2.T spans the nullspace of J2:\n', dot(J2, Q2.T)) # METHOD 2: image space method (potentially numerically unstable) cg2 = CGraph() J1 = Function(J1.x) J2 = Function(J2.x) M = Function(UTPM(numpy.zeros((D, P, N + K, N + K)))) M[:N, :N] = dot(J1.T, J1) M[:N, N:] = J2.T M[N:, :N] = J2 C2 = inv(M)[:N, :N]
""" This example shows that most computations can be performed by numpy functions on arrays of UTPM objects. Just bear in mind that is much faster use UTPM instances of matrices than numpy.ndarrays with UTPM elements. """ import numpy, os from algopy import CGraph, Function, UTPM, dot, qr, eigh, inv N,D,P = 2,2,1 cg = CGraph() x = numpy.array([ Function(UTPM(numpy.random.rand(*(D,P)))) for n in range(N)]) A = numpy.outer(x,x) A = numpy.exp(A) y = numpy.dot(A,x) cg.independentFunctionList = list(x) cg.dependentFunctionList = list(y) cg.plot(os.path.join(os.path.dirname(__file__),'numpy_dot_graph.svg'))
print 'function evaluation =\n',logp(x,3.5,sigma) # forward mode with ALGOPY utp = logp(x, mu, sigma).data[:,0] print 'function evaluation = %f\n1st directional derivative = %f\n2nd directional derivative = %f'%(utp[0], 1.*utp[1], 2.*utp[2]) # finite differences solution: print 'finite differences derivative =\n',(logp(x,3.5+10**-8,sigma) - logp(x, 3.5, sigma))/10**-8 # trace function evaluation cg = CGraph() mu = Function(UTPM([[3.5],[1],[0]])) #unknown variable out = logp(x, mu, sigma) cg.trace_off() cg.independentFunctionList = [mu] cg.dependentFunctionList = [out] cg.plot(os.path.join(os.path.dirname(os.path.realpath(__file__)),'posterior_log_probability_cgraph.png')) # reverse mode with ALGOPY outbar = UTPM([[1.],[0],[0]]) cg.pullback([outbar]) gradient = mu.xbar.data[0,0] Hess_vec = mu.xbar.data[1,0] print 'gradient = ', gradient print 'Hessian vector product = ', Hess_vec
J1 = Function(UTPM(numpy.random.rand(*(D,P,M,N)))) J2 = Function(UTPM(numpy.random.rand(*(D,P,K,N)))) Q,R = Function.qr_full(J2.T) Q2 = Q[:,K:].T J1_tilde = dot(J1,Q2.T) Q,R = qr(J1_tilde) V = solve(R.T, Q2) C = dot(V.T,V) cg1.trace_off() cg1.independentFunctionList = [J1, J2] cg1.dependentFunctionList = [C] print('covariance matrix: C =\n',C) print('check that Q2.T spans the nullspace of J2:\n', dot(J2,Q2.T)) # METHOD 2: image space method (potentially numerically unstable) cg2 = CGraph() J1 = Function(J1.x) J2 = Function(J2.x) M = Function(UTPM(numpy.zeros((D,P,N+K,N+K)))) M[:N,:N] = dot(J1.T,J1) M[:N,N:] = J2.T M[N:,:N] = J2 C2 = inv(M)[:N,:N]