In [1]:
# derivative easy example
import theano
import theano.tensor as T
from theano import pp
x = T.dscalar('x')
y = x ** 2
gy = T.grad(y, x)
f = theano.function([x], gy)
In [3]:
f(8)
f(16)
Out[3]:
In [4]:
# derivative logistic function
x = T.dmatrix('x')
s = T.sum(1 / (1 + T.exp(-x)))
gs = T.grad(s, x)
dlogistic = theano.function([x], gs)
In [5]:
dlogistic([[0,1], [12, 7]])
Out[5]:
In [6]:
# scan function
# easy example
import theano
import theano.tensor as T
k = T.iscalar("k")
A = T.vector("A")
# Symbolic description of the result
result, updates = theano.scan(fn=lambda prior_result, A: prior_result * A,
outputs_info=T.ones_like(A),
non_sequences=A,
n_steps=k)
# We only care about A**k, but scan has provided us with A**1 through A**k.
# Discard the values that we don't care about. Scan is smart enough to
# notice this and not waste memory saving them.
final_result = result[-1]
# compiled function that returns A**k
power = theano.function(inputs=[A,k], outputs=final_result, updates=updates)
print power(range(10),2)
In [21]:
# computing jacobian
# manually do it as follows
import theano
import theano.tensor as T
x = T.dvector('x')
y = x ** 2
J, updates = theano.scan(lambda i, y, x : T.grad(y[i], x), sequences = T.arange(y.shape[0]), non_sequences = [y, x])
f = theano.function([x], J, updates = updates)
f([4,4])
Out[21]:
In [20]:
# computing hessian
# manually do it as follows
y = x ** 2
cost = y.sum()
gy = T.grad(cost, x)
H, updates = theano.scan(lambda i, gy,x : T.grad(gy[i], x), sequences=T.arange(gy.shape[0]), non_sequences=[gy, x])
f = theano.function([x], H, updates = updates)
f([4,4])
Out[20]:
In [22]:
# jacobian times vector -> R-operator
# vector times jacobian -> L-operator
# both of these can be used to Hessian
W = T.dmatrix('W')
V = T.dmatrix('V')
x = T.dvector('x')
y = T.dot(x, W)
JV = T.Rop(y, W, V) # R-operator
f = theano.function([W, V, x], JV)
f([[1, 1], [1, 1]], [[2, 2], [2, 2]], [0,1])
Out[22]:
In [ ]: