Skip to content

Commit

Permalink
Move the exercies from the basic tutorial to a ipython notebook.
Browse files Browse the repository at this point in the history
  • Loading branch information
abergeron committed Jan 31, 2017
1 parent b22999e commit 0f3741d
Show file tree
Hide file tree
Showing 10 changed files with 972 additions and 0 deletions.
39 changes: 39 additions & 0 deletions ipnb/01_scalar_soln.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import numpy as np
from theano import function
import theano.tensor as T


def make_scalar():
"""
Returns a new Theano scalar.
"""

return T.scalar()


def log(x):
"""
Returns the logarithm of a Theano scalar x.
"""

return T.log(x)


def add(x, y):
"""
Adds two theano scalars together and returns the result.
"""

return x + y

a = make_scalar()
b = make_scalar()
c = log(b)
d = add(a, c)
f = function([a, b], d)
a = np.cast[a.dtype](1.)
b = np.cast[b.dtype](2.)
actual = f(a, b)
expected = 1. + np.log(2.)
assert np.allclose(actual, expected)
print "SUCCESS!"
59 changes: 59 additions & 0 deletions ipnb/02_vector_mat_soln.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import numpy as np
from theano import function
import theano.tensor as T


def make_vector():
"""
Returns a new Theano vector.
"""

return T.vector()


def make_matrix():
"""
Returns a new Theano matrix.
"""

return T.matrix()


def elemwise_mul(a, b):
"""
a: A theano matrix
b: A theano matrix
Returns the elementwise product of a and b
"""

return a * b


def matrix_vector_mul(a, b):
"""
a: A theano matrix
b: A theano vector
Returns the matrix-vector product of a and b
"""

return T.dot(a, b)

a = make_vector()
b = make_vector()
c = elemwise_mul(a, b)
d = make_matrix()
e = matrix_vector_mul(d, c)

f = function([a, b, d], e)

rng = np.random.RandomState([1, 2, 3])
a_value = rng.randn(5).astype(a.dtype)
b_value = rng.rand(5).astype(b.dtype)
c_value = a_value * b_value
d_value = rng.randn(5, 5).astype(d.dtype)
expected = np.dot(d_value, c_value)

actual = f(a_value, b_value, d_value)

assert np.allclose(actual, expected)
print "SUCCESS!"
58 changes: 58 additions & 0 deletions ipnb/03_tensor_soln.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import numpy as np
from theano import function
import theano.tensor as T


def make_tensor(dim):
"""
Returns a new Theano tensor with no broadcastable dimensions.
dim: the total number of dimensions of the tensor.
"""

return T.TensorType(broadcastable=tuple([False] * dim), dtype='float32')()


def broadcasted_add(a, b):
"""
a: a 3D theano tensor
b: a 4D theano tensor
Returns c, a 4D theano tensor, where
c[i, j, k, l] = a[l, k, i] + b[i, j, k, l]
for all i, j, k, l
"""

return a.dimshuffle(2, 'x', 1, 0) + b


def partial_max(a):
"""
a: a 4D theano tensor
Returns b, a theano matrix, where
b[i, j] = max_{k,l} a[i, k, l, j]
for all i, j
"""

return a.max(axis=(1, 2))

a = make_tensor(3)
b = make_tensor(4)
c = broadcasted_add(a, b)
d = partial_max(c)

f = function([a, b], d)

rng = np.random.RandomState([1, 2, 3])
a_value = rng.randn(2, 2, 2).astype(a.dtype)
b_value = rng.rand(2, 2, 2, 2).astype(b.dtype)
c_value = np.transpose(a_value, (2, 1, 0))[:, None, :, :] + b_value
expected = c_value.max(axis=1).max(axis=1)

actual = f(a_value, b_value)

assert np.allclose(actual, expected), (actual, expected)
print "SUCCESS!"
24 changes: 24 additions & 0 deletions ipnb/11_function_soln.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from theano import tensor as T
from theano import function


def evaluate(x, y, expr, x_value, y_value):
"""
x: A theano variable
y: A theano variable
expr: A theano expression involving x and y
x_value: A numpy value
y_value: A numpy value
Returns the value of expr when x_value is substituted for x
and y_value is substituted for y
"""

return function([x, y], expr)(x_value, y_value)


x = T.iscalar()
y = T.iscalar()
z = x + y
assert evaluate(x, y, z, 1, 2) == 3
print "SUCCESS!"
60 changes: 60 additions & 0 deletions ipnb/12_shared_soln.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import numpy as np
from theano.compat.python2x import OrderedDict
from theano import function
from theano import shared


def make_shared(shape):
"""
Returns a theano shared variable containing a tensor of the specified
shape.
You can use any value you want.
"""
return shared(np.zeros(shape))


def exchange_shared(a, b):
"""
a: a theano shared variable
b: a theano shared variable
Uses get_value and set_value to swap the values stored in a and b
"""
temp = a.get_value()
a.set_value(b.get_value())
b.set_value(temp)


def make_exchange_func(a, b):
"""
a: a theano shared variable
b: a theano shared variable
Returns f
where f is a theano function, that, when called, swaps the
values in a and b
f should not return anything
"""

updates = OrderedDict()
updates[a] = b
updates[b] = a
f = function([], updates=updates)
return f


a = make_shared((5, 4, 3))
assert a.get_value().shape == (5, 4, 3)
b = make_shared((5, 4, 3))
assert a.get_value().shape == (5, 4, 3)
a.set_value(np.zeros((5, 4, 3), dtype=a.dtype))
b.set_value(np.ones((5, 4, 3), dtype=b.dtype))
exchange_shared(a, b)
assert np.all(a.get_value() == 1.)
assert np.all(b.get_value() == 0.)
f = make_exchange_func(a, b)
rval = f()
assert isinstance(rval, list)
assert len(rval) == 0
assert np.all(a.get_value() == 0.)
assert np.all(b.get_value() == 1.)

print "SUCCESS!"
10 changes: 10 additions & 0 deletions ipnb/13_bug_soln.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# The weird thing is that the function succeeds.
#
# This is weird because the two values passed in for x and y do not
# have the same shape, yet x is added with something that has the same
# shape as y (z).
#
# This happens because optimizations realize that z is always zero and
# therefore remove the addition, which removes the error.
#
# The problem is more evident if FAST_COMPILE or DEBUG_MODE is used.
23 changes: 23 additions & 0 deletions ipnb/21_grad_soln.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Fill in the TODOs in this exercise, then run
# python 01_grad.py to see if your solution works!
#
from theano import tensor as T


def grad_sum(x, y, z):
"""
x: A theano variable
y: A theano variable
z: A theano expression involving x and y
Returns dz / dx + dz / dy
"""

return sum(T.grad(z, [x, y]))

x = T.scalar()
y = T.scalar()
z = x + y
s = grad_sum(x, y, z)
assert s.eval({x: 0, y: 0}) == 2
print "SUCCESS!"
59 changes: 59 additions & 0 deletions ipnb/22_traverse_soln.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import numpy as np
from theano.gof import Variable
from theano import tensor as T


def arg_to_softmax(prob):
"""
Oh no! Someone has passed you the probability output,
"prob", of a softmax function, and you want the unnormalized
log probability--the argument to the softmax.
Verify that prob really is the output of a softmax. Raise a
TypeError if it is not.
If it is, return the argument to the softmax.
"""

if not isinstance(prob, Variable):
raise TypeError()

if prob.owner is None:
raise TypeError()

owner = prob.owner

if not isinstance(owner.op, T.nnet.Softmax):
raise TypeError()

rval, = owner.inputs

return rval

if __name__ == "__main__":
x = np.ones((5, 4))
try:
arg_to_softmax(x)
raise Exception("You should have raised an error.")
except TypeError:
pass

x = T.matrix()
try:
arg_to_softmax(x)
raise Exception("You should have raised an error.")
except TypeError:
pass

y = T.nnet.sigmoid(x)
try:
arg_to_softmax(y)
raise Exception("You should have raised an error.")
except TypeError:
pass

y = T.nnet.softmax(x)
rval = arg_to_softmax(y)
assert rval is x

print "SUCCESS!"
17 changes: 17 additions & 0 deletions ipnb/31_debug_soln.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import numpy as np
from theano import function
from theano import tensor as T
from theano import config
config.compute_test_value = 'raise'
a = T.vector()
a.tag.test_value = np.ones((3,)).astype(a.dtype)
b = T.log(a)
c = T.nnet.sigmoid(b)
d = T.sqrt(c)
e = T.concatenate((d, c), axis=0)
f = b * c * d
# This is the first bad line
g = e + f
h = g / c
fn = function([a], h)
fn(np.ones((3,)).astype(a.dtype))
Loading

0 comments on commit 0f3741d

Please sign in to comment.