def test_ifelse(self): config1 = theano.config.profile config2 = theano.config.profile_memory try: theano.config.profile = True theano.config.profile_memory = True a, b = T.scalars('a', 'b') x, y = T.scalars('x', 'y') z = ifelse(T.lt(a, b), x * 2, y * 2) p = theano.ProfileStats(False) if theano.config.mode in ["DebugMode", "DEBUG_MODE", "FAST_COMPILE"]: m = "FAST_RUN" else: m = None f_ifelse = theano.function([a, b, x, y], z, profile=p, name="test_ifelse", mode=m) val1 = 0. val2 = 1. big_mat1 = 10 big_mat2 = 11 out = f_ifelse(val1, val2, big_mat1, big_mat2) finally: theano.config.profile = config1 theano.config.profile_memory = config2
def test_pickle(self): a = T.scalar() # the a is for 'anonymous' (un-named). x, s = T.scalars('xs') f = function([x, In(a, value=1.0, name='a'), In(s, value=0.0, update=s+a*x, mutable=True)], s+a*x) try: # Note that here we also test protocol 0 on purpose, since it # should work (even though one should not use it). g = pickle.loads(pickle.dumps(f, protocol=0)) g = pickle.loads(pickle.dumps(f, protocol=-1)) except NotImplementedError as e: if e[0].startswith('DebugMode is not picklable'): return else: raise # if they both return, assume that they return equivalent things. # print [(k,id(k)) for k in f.finder.keys()] # print [(k,id(k)) for k in g.finder.keys()] self.assertFalse(g.container[0].storage is f.container[0].storage) self.assertFalse(g.container[1].storage is f.container[1].storage) self.assertFalse(g.container[2].storage is f.container[2].storage) self.assertFalse(x in g.container) self.assertFalse(x in g.value) self.assertFalse(g.value[1] is f.value[1]) # should not have been copied self.assertFalse(g.value[2] is f.value[2]) # should have been copied because it is mutable. self.assertFalse((g.value[2] != f.value[2]).any()) # its contents should be identical self.assertTrue(f(2, 1) == g(2)) # they should be in sync, default value should be copied. self.assertTrue(f(2, 1) == g(2)) # they should be in sync, default value should be copied. f(1, 2) # put them out of sync self.assertFalse(f(1, 2) == g(1, 2)) # they should not be equal anymore.
def test_multiple_functions(self): a = T.scalar() # the a is for 'anonymous' (un-named). x, s = T.scalars('xs') v = T.vector('v') # put in some inputs list_of_things = [s, x, v] # some derived thing, whose inputs aren't all in the list list_of_things.append(a * x + s ) f1 = function([x, In(a, value=1.0, name='a'), In(s, value=0.0, update=s+a*x, mutable=True)], s+a*x) list_of_things.append(f1) # now put in a function sharing container with the previous one f2 = function([x, In(a, value=1.0, name='a'), In(s, value=f1.container[s], update=s+a*x, mutable=True)], s+a*x) list_of_things.append(f2) assert isinstance(f2.container[s].storage, list) assert f2.container[s].storage is f1.container[s].storage # now put in a function with non-scalar v_value = numpy.asarray([2, 3, 4.], dtype=config.floatX) f3 = function([x, In(v, value=v_value)], x+v) list_of_things.append(f3) # try to pickle the entire things try: saved_format = cPickle.dumps(list_of_things, protocol=-1) new_list_of_things = cPickle.loads(saved_format) except NotImplementedError, e: if e[0].startswith('DebugMode is not picklable'): return else: raise
def __init__(self): x, y, z = T.scalars('xyz') e = T.nnet.sigmoid((x + y + z)**2) op = th.OpFromGraph([x, y, z], [e]) e2 = op(x, y, z) + op(z, y, x) self.inputs = [x, y, z] self.outputs = [e2]
def test_callback_with_ifelse(self): a, b, c = tensor.scalars("abc") f = function( [a, b, c], ifelse(a, 2 * b, 2 * c), mode=Mode(optimizer=None, linker=vm.VM_Linker(callback=self.callback)) ) f(1, 2, 3) assert self.n_callbacks["IfElse"] == 2
def test_callback(self): a, b, c = tensor.scalars("abc") f = function([a, b, c], (a + b) + c, mode=Mode(optimizer=None, linker=vm.VM_Linker(callback=self.callback))) f(1, 2, 3) assert sum(self.n_callbacks.values()) == len(f.maker.fgraph.toposort()) f(1, 2, 3) assert sum(self.n_callbacks.values()) == len(f.maker.fgraph.toposort()) * 2
def test_naming_rule1(self): a = T.scalar() # the a is for 'anonymous' (un-named). x, s = T.scalars('xs') f = function([a, s], a/s) self.assertTrue(f(1, 2) == 0.5) self.assertTrue(f(2, 1) == 2.0) self.assertTrue(f(2, s=1) == 2.0) checkfor(self, lambda: f(q=2, s=1), TypeError) # got unexpected keyword argument 'q' checkfor(self, lambda: f(a=2, s=1), TypeError) # got unexpected keyword argument 'a'
def test_weird_names(self): a, x, s = T.scalars('xxx') checkfor(self, lambda: function([In(a, name=[])], []), TypeError) def t(): f = function([In(a, name=set(['adsf', ()]), value=1.0), In(x, name=(), value=2.0), In(s, name=T.scalar(), value=3.0)], a+x+s) checkfor(self, t, TypeError)
def __init__(self): x, y, z = T.scalars('xyz') e = x * y op = th.OpFromGraph([x, y], [e]) e2 = op(x, y) + z op2 = th.OpFromGraph([x, y, z], [e2]) e3 = op2(x, y, z) + z self.inputs = [x, y, z] self.outputs = [e3]
def test_naming_rule2(self): a = T.scalar() # the a is for 'anonymous' (un-named). x,s = T.scalars('xs') #x's name is ignored because it is followed by anonymous parameter a. f = function([x, a, s], a/s) self.assertTrue(f(9,1,2) == 0.5) self.assertTrue(f(9,2,1) == 2.0) self.assertTrue(f(9,2, s=1) == 2.0) checkfor(self, lambda:f(x=9,a=2,s=1), TypeError) #got unexpected keyword argument 'x' checkfor(self, lambda:f(5.0,x=9), TypeError) #got unexpected keyword argument 'x'
def test_naming_rule0(self): x, s = T.scalars('xs') f = function([x, s], x/s) self.assertTrue(f(1, 2) == 0.5) self.assertTrue(f(2, 1) == 2.0) self.assertTrue(f(s=2, x=1) == 0.5) self.assertTrue(f(x=2, s=1) == 2.0) self.assertTrue(f(2, s=1) == 2.0) checkfor(self, lambda : f(2, x=2.0), TypeError) # got multiple values for keyword argument 'x' checkfor(self, lambda : f(x=1), TypeError) # takes exactly 2 non-keyword arguments (1 given) checkfor(self, lambda : f(s=1), TypeError) # takes exactly 2 non-keyword arguments (0 given)
def test_deepcopy(self): a = T.scalar() # the a is for 'anonymous' (un-named). x,s = T.scalars('xs') f = function([x, In(a, value=1.0,name='a'), In(s, value=0.0, update=s+a*x, mutable=True)], s+a*x) try: g = copy.deepcopy(f) except NotImplementedError, e: if e[0].startswith('DebugMode is not picklable'): return else: raise
def test_naming_rule3(self): a = T.scalar() # the a is for 'anonymous' (un-named). x, s = T.scalars('xs') # x's name is not ignored (as in test_naming_rule2) because a has a default value. f = function([x, In(a, value=1.0), s], a/s+x) self.assertTrue(f(9, 2, 4) == 9.5) # can specify all args in order self.assertTrue(f(9, 2, s=4) == 9.5) # can give s as kwarg self.assertTrue(f(9, s=4) == 9.25) # can give s as kwarg, get default a self.assertTrue(f(x=9, s=4) == 9.25) # can give s as kwarg, omit a, x as kw checkfor(self, lambda: f(x=9, a=2, s=4), TypeError) # got unexpected keyword argument 'a' checkfor(self, lambda: f(), TypeError) # takes exactly 3 non-keyword arguments (0 given) checkfor(self, lambda: f(x=9), TypeError) # takes exactly 3 non-keyword arguments (1 given)
def test_shared_state0(self): a = T.scalar() # the a is for 'anonymous' (un-named). x, s = T.scalars('xs') f = function([x, In(a, value=1.0, name='a'), In(s, value=0.0, update=s+a*x, mutable=True)], s+a*x) g = function([x, In(a, value=1.0, name='a'), In(s, value=f.container[s], update=s-a*x, mutable=True)], s+a*x) f(1, 2) self.assertTrue(f[s] == 2) self.assertTrue(g[s] == 2) g(1, 2) self.assertTrue(f[s] == 0) self.assertTrue(g[s] == 0)
def __init__(self): a = T.scalar() # the a is for 'anonymous' (un-named). x, s = T.scalars('xs') v = T.vector('v') self.s = s self.x = x self.v = v self.e = a * x + s self.f1 = function([x, In(a, value=1.0, name='a'), In(s, value=0.0, update=s+a*x, mutable=True)], s+a*x) self.f2 = function([x, In(a, value=1.0, name='a'), In(s, value=self.f1.container[s], update=s+a*x, mutable=True)], s+a*x)
def test_naming_rule4(self): a = T.scalar() # the a is for 'anonymous' (un-named). x, s = T.scalars('xs') f = function([x, In(a, value=1.0, name='a'), s], a/s+x) self.assertTrue(f(9, 2, 4) == 9.5) # can specify all args in order self.assertTrue(f(9, 2, s=4) == 9.5) # can give s as kwarg self.assertTrue(f(9, s=4) == 9.25) # can give s as kwarg, get default a self.assertTrue(f(9, a=2, s=4) == 9.5) # can give s as kwarg, a as kwarg self.assertTrue(f(x=9, a=2, s=4) == 9.5) # can give all kwargs self.assertTrue(f(x=9, s=4) == 9.25) # can give all kwargs checkfor(self, lambda: f(), TypeError) # takes exactly 3 non-keyword arguments (0 given) checkfor(self, lambda: f(5.0, x=9), TypeError) # got multiple values for keyword argument 'x'
def test_pickle(self): a = T.scalar() # the a is for 'anonymous' (un-named). x,s = T.scalars('xs') f = function([x, In(a, value=1.0,name='a'), In(s, value=0.0, update=s+a*x, mutable=True)], s+a*x) try: # Note that here we also test protocol 0 on purpose, since it # should work (even though one should not use it). g = cPickle.loads(cPickle.dumps(f, protocol=0)) g = cPickle.loads(cPickle.dumps(f, protocol=-1)) except NotImplementedError, e: if e[0].startswith('DebugMode is not picklable'): return else: raise
def test_c_thunks(): a = tensor.scalars('a') b, c = tensor.vectors('bc') cases = [False] if theano.config.cxx: cases.append(True) for c_thunks in cases: f = function([a, b, c], ifelse(a, a * b, b * c), mode=Mode( optimizer=None, linker=vm.VM_Linker(c_thunks=c_thunks, use_cloop=False))) f(1, [2], [3, 2]) from nose.tools import assert_raises assert_raises(ValueError, f, 0, [2], [3, 4]) assert any([hasattr(t, 'cthunk') for t in f.fn.thunks]) == c_thunks
def _policy_function(self): epoch, gm, powr, step = T.scalars('epoch', 'gm', 'powr', 'step') if self.lr_policy == 'inv': decay = T.power(1.0+gm*epoch, -powr) elif self.lr_policy == 'exp': decay = gm ** epoch elif self.lr_policy == 'step': decay = T.switch(T.eq(T.mod_check(epoch, step), 0.0), T.power(gm, T.floor_div(epoch, step)), 1.0) elif self.lr_policy == 'fixed': decay = T.constant(1.0, name='fixed', dtype=theano.config.floatX) return theano.function([gm, epoch, powr, step], decay, allow_input_downcast=True, on_unused_input='ignore')
def test_shared_state_not_implicit(self): # This test is taken from the documentation in # doc/topics/function.txt. If it does not pass anymore and yet the # behavior is still intended the doc and the test should both be # updated accordingly. x, s = T.scalars('xs') inc = function([x, In(s, update=(s+x), value=10.0)], []) dec = function([x, In(s, update=(s-x), value=inc.container[s], implicit=False)], []) self.assertTrue(dec[s] is inc[s]) inc[s] = 2 self.assertTrue(dec[s] == 2) dec(1) self.assertTrue(inc[s] == 1) dec(1, 0) self.assertTrue(inc[s] == -1) self.assertTrue(dec[s] == -1)
def policy_update(self, lr_policy): epoch, gm, powr, step = T.scalars('epoch', 'gm', 'powr', 'step') if lr_policy == 'inv': decay = T.power(1+gm*epoch, -powr) elif lr_policy == 'exp': decay = gm ** epoch elif lr_policy == 'step': decay = T.switch(T.eq(T.mod_check(epoch, step), 0), T.power(gm, T.floor_div(epoch, step)), 1.0) elif lr_policy == 'fixed': decay = T.constant(1.0, name='fixed', dtype='float32') return theano.function([gm, epoch, powr, step], decay, updates=[(self.shared_lr, self.shared_lr * decay)], on_unused_input='ignore')
def test_deepcopy(self): a = T.scalar() # the a is for 'anonymous' (un-named). x, s = T.scalars('xs') f = function([x, In(a, value=1.0, name='a'), In(s, value=0.0, update=s + a * x, mutable=True)], s + a * x) try: g = copy.deepcopy(f) except NotImplementedError as e: if e[0].startswith('DebugMode is not picklable'): return else: raise # if they both return, assume that they return equivalent things. # print [(k,id(k)) for k in f.finder.keys()] # print [(k,id(k)) for k in g.finder.keys()] self.assertFalse(g.container[0].storage is f.container[0].storage) self.assertFalse(g.container[1].storage is f.container[1].storage) self.assertFalse(g.container[2].storage is f.container[2].storage) self.assertFalse(x in g.container) self.assertFalse(x in g.value) self.assertTrue(len(f.defaults) == len(g.defaults)) self.assertTrue(f._check_for_aliased_inputs is g._check_for_aliased_inputs) self.assertTrue(f.name == g.name) self.assertTrue(f.maker.fgraph.name == g.maker.fgraph.name) # print 'f.defaults = %s' % (f.defaults, ) # print 'g.defaults = %s' % (g.defaults, ) self.assertTrue(all([f_req == g_req and f_feed == g_feed and f_val == g_val for ((f_req, f_feed, f_val), (g_req, g_feed, g_val)) in zip( f.defaults, g.defaults)])) self.assertFalse(g.value[1] is f.value[1]) # should not have been copied self.assertFalse(g.value[2] is f.value[2]) # should have been copied because it is mutable. self.assertFalse((g.value[2] != f.value[2]).any()) # its contents should be identical self.assertTrue(f(2, 1) == g(2)) # they should be in sync, default value should be copied. self.assertTrue(f(2, 1) == g(2)) # they should be in sync, default value should be copied. f(1, 2) # put them out of sync self.assertFalse(f(1, 2) == g(1, 2)) # they should not be equal anymore. g(1, 2) # put them back in sync self.assertTrue(f(3) == g(3)) # They should be in sync again.
def test_deepcopy_shared_container(self): # Ensure that shared containers remain shared after a deep copy. a, x = T.scalars('ax') h = function([In(a, value = 0.0)], a) f = function([x, In(a, value=h.container[a], implicit = True)], x + a) try: memo = {} ac = copy.deepcopy(a) memo.update({id(a): ac}) hc = copy.deepcopy(h, memo = memo) memo.update({id(h): hc}) fc = copy.deepcopy(f, memo = memo) except NotImplementedError, e: if e[0].startswith('DebugMode is not picklable'): return else: raise
def test_state_access(self): a = T.scalar() # the a is for 'anonymous' (un-named). x, s = T.scalars('xs') f = function([x, In(a, value=1.0, name='a'), In(s, value=0.0, update=s+a*x)], s+a*x) self.assertTrue(f[a] == 1.0) self.assertTrue(f[s] == 0.0) self.assertTrue(f(3.0) == 3.0) self.assertTrue(f(3.0, a=2.0) == 9.0) # 3.0 + 2*3.0 self.assertTrue(f[a] == 1.0) # state hasn't changed permanently, we just overrode it last line self.assertTrue(f[s] == 9.0) f[a] = 5.0 self.assertTrue(f[a] == 5.0) self.assertTrue(f(3.0) == 24.0) # 9 + 3*5 self.assertTrue(f[s] == 24.0)
def test_4_conditionals(): a, b = T.scalars('a', 'b') x, y = T.matrices('x', 'y') f_switch = theano.function([a, b, x, y], T.switch(T.lt(a, b), T.mean(x), T.mean(y))) f_lazy_ifelse = theano.function([a, b, x, y], ifelse(T.lt(a, b), T.mean(x), T.mean(y))) x_val = np.ones((100, 100), dtype=theano.config.floatX)*1 y_val = np.ones((100, 100), dtype=theano.config.floatX)*2 # vectorized switch is going to evaluate both options np.testing.assert_almost_equal( f_switch(1, 2, x_val, y_val), 1 ) # lazy evaluation is going to evaluate only single option np.testing.assert_almost_equal( f_lazy_ifelse(2, 1, x_val, y_val), 2 )
def test_copy(self): a = T.scalar() # the a is for 'anonymous' (un-named). x, s = T.scalars('xs') f = function([x, In(a, value=1.0, name='a'), In(s, value=0.0, update=s+a*x, mutable=True)], s+a*x) g = copy.copy(f) # if they both return, assume that they return equivalent things. self.assertFalse(g.container[x].storage is f.container[x].storage) self.assertFalse(g.container[a].storage is f.container[a].storage) self.assertFalse(g.container[s].storage is f.container[s].storage) self.assertFalse(g.value[a] is not f.value[a]) # should not have been copied self.assertFalse(g.value[s] is f.value[s]) # should have been copied because it is mutable. self.assertFalse((g.value[s] != f.value[s]).any()) # its contents should be identical self.assertTrue(f(2, 1) == g(2)) # they should be in sync, default value should be copied. self.assertTrue(f(2, 1) == g(2)) # they should be in sync, default value should be copied. f(1, 2) # put them out of sync self.assertFalse(f(1, 2) == g(1, 2)) # they should not be equal anymore.
def learning_updates(model, details, inputs): # create a list of all model parameters to be fit by gradient descent params = [] for i in xrange(len(model.params_to_train)): for j in model.params_to_train[i]: params.append(model.params[i][j]) updates = [] # list of gradients for all model parameters grads = T.grad(model.cost, params) # theano variables for input (learning hyperparameters) l_r, mom = T.scalars('l_r', 'mom') #initialize parameter updates for momentum param_updates = [] for i in xrange(len(params)): param = params[i] init = np.zeros(param.get_value(borrow=True).shape, dtype=theano.config.floatX) param_updates.append(theano.shared(init)) # build updates pairs for param_i, grad_i, prev in zip(params, grads, param_updates): upd = mom * prev - l_r * grad_i upd_param = param_i + upd upd_param = regularize_weights(details['regularizer'], param_i, upd, upd_param) updates.append((param_i, upd_param)) inputs += [l_r, mom] return inputs, params, updates
def test_input_anon_singleton(self): x, s = T.scalars('xs') fn = function([s, x], [x + s]) self.assertTrue(fn(2, 3) == [5]) # no state self.assertTrue(fn(2, 3) == [5])
def test_input_anon_unpack(self): x, s = T.scalars('xs') fn = function([s, x], x + s) self.assertTrue(fn(2, 3) == 5)
def test_same_names(self): a, x, s = T.scalars('xxx') # implicit names would cause error. What do we do? f = function([a, x, s], a + x + s) self.assertTrue(f(1, 2, 3) == 6) checkfor(self, lambda: f(1, 2, x=3), TypeError)
def test_extra_inputs(self): x, s = T.scalars('xs') fn = function([x], [x]) self.assertRaises(TypeError, fn, 1, 2)
def fn(): x, s = T.scalars('xs') # Ignore unused input s, as it hides the other error function([s], [x], on_unused_input='ignore')
def test_multiple_functions(self): a = T.scalar() # the a is for 'anonymous' (un-named). x, s = T.scalars('xs') v = T.vector('v') # put in some inputs list_of_things = [s, x, v] # some derived thing, whose inputs aren't all in the list list_of_things.append(a * x + s) f1 = function([x, In(a, value=1.0, name='a'), In(s, value=0.0, update=s + a * x, mutable=True)], s + a * x) list_of_things.append(f1) # now put in a function sharing container with the previous one f2 = function([x, In(a, value=1.0, name='a'), In(s, value=f1.container[s], update=s + a * x, mutable=True)], s + a * x) list_of_things.append(f2) assert isinstance(f2.container[s].storage, list) assert f2.container[s].storage is f1.container[s].storage # now put in a function with non-scalar v_value = numpy.asarray([2, 3, 4.], dtype=config.floatX) f3 = function([x, In(v, value=v_value)], x + v) list_of_things.append(f3) # try to pickle the entire things try: saved_format = pickle.dumps(list_of_things, protocol=-1) new_list_of_things = pickle.loads(saved_format) except NotImplementedError as e: if e[0].startswith('DebugMode is not picklable'): return else: raise # now test our recovered new_list_of_things # it should be totally unrelated to the original # it should be interdependent in the same way as the original ol = list_of_things nl = new_list_of_things for i in range(4): assert nl[i] != ol[i] assert nl[i].type == ol[i].type assert nl[i].type is not ol[i].type # see if the implicit input got stored assert ol[3].owner.inputs[1] is s assert nl[3].owner.inputs[1] is not s assert nl[3].owner.inputs[1].type == s.type # moving on to the functions... for i in range(4, 7): assert nl[i] != ol[i] # looking at function number 1, input 's' assert nl[4][nl[0]] is not ol[4][ol[0]] assert nl[4][nl[0]] == ol[4][ol[0]] assert nl[4](3) == ol[4](3) # looking at function number 2, input 's' # make sure it's shared with the first function assert ol[4].container[ol[0]].storage is ol[5].container[ol[0]].storage assert nl[4].container[nl[0]].storage is nl[5].container[nl[0]].storage assert nl[5](3) == ol[5](3) assert nl[4].value[nl[0]] == 6 assert numpy.all(nl[6][nl[2]] == numpy.asarray([2, 3., 4]))
def fn(): x, s = T.scalars('xs') function([In(x, update=s + x)], x)
def fn(): x, s = T.scalars('xs') function([In(x, update=((s * s) + x))], x)
def fn(): x, s = T.scalars('xs') function([s], [x])
def setUp(self): self.x, self.y = tensor.scalars("x", "y") self.z = self.x + self.y self.w = 2 * self.z
def fn(): x,s = T.scalars('xs') fn = function([], [x])
def setUp(self): self.x, self.y = tensor.scalars('x', 'y') self.z = self.x + self.y self.w = 2 * self.z
def setup_method(self): self.x, self.y = tensor.scalars("x", "y") self.z = self.x + self.y self.w = 2 * self.z
def fn(): x, s = T.scalars('xs') fn = function([In(x, update=s+x)], x)
def fn(): x,s = T.scalars('xs') fn = function([s], Out(x))
from __future__ import absolute_import, print_function, division import time import numpy import theano from theano import tensor as tt from six.moves import xrange from theano.ifelse import ifelse a, b = tt.scalars('a', 'b') x, y = tt.matrices('x', 'y') z_switch = tt.switch(tt.lt(a, b), tt.mean(x), tt.mean(y)) z_lazy = ifelse(tt.lt(a, b), tt.mean(x), tt.mean(y)) f_switch = theano.function([a, b, x, y], z_switch) f_lazyifelse = theano.function([a, b, x, y], z_lazy) val1 = 0. val2 = 1. big_mat1 = numpy.ones((10000, 1000)) big_mat2 = numpy.ones((10000, 1000)) n_times = 10 tic = time.clock() for i in xrange(n_times): f_switch(val1, val2, big_mat1, big_mat2) print('time spent evaluating both values %f sec' % (time.clock() - tic))
from theano import tensor as T from theano.ifelse import ifelse import theano, time, numpy a, b = T.scalars('a', 'b') x, y = T.matrices('x', 'y') z_switch = T.switch(T.lt(a, b), T.mean(x), T.mean(y)) z_lazy = ifelse(T.lt(a, b), T.mean(x), T.mean(y)) f_switch = theano.function([a, b, x, y], z_switch, mode=theano.Mode(linker='vm')) f_lazyifelse = theano.function([a, b, x, y], z_lazy, mode=theano.Mode(linker='vm')) val1 = 0. val2 = 1. big_mat1 = numpy.ones((10000, 1000)) big_mat2 = numpy.ones((10000, 1000)) n_times = 10 tic = time.clock() for i in xrange(n_times): f_switch(val1, val2, big_mat1, big_mat2) print 'time spent evaluating both values %f sec' % (time.clock() - tic) tic = time.clock() for i in xrange(n_times):