python - Scanning without sequences in theano? (emulating range()) -


theano newbie here. doing experiments in order generate variable length sequences. started simplest thing coming mind: emulating range(). here simple code wrote:

from theano import scan theano import function theano import tensor  t  x = t.iscalar('x') step = t.iscalar('step') max_length = 1024  # or othe large value  def fstep(i, x, t):     n = * t     return n, until(n >= x)  t_fwd_range, _ = scan(     fn=fstep,     sequences=t.arange(max_length),     non_sequences=[x, step] )  getrange = function(     inputs=[x, param(step, 1, 'step')],     outputs=t_fwd_range )  getrange(x, step) print list(f) assert list(f[:-1]) == list(range(0, x, step)) 

so had use max_length length of range used input of fstep theano scan. so, main question this: there way use scan without input sequence? and, suppose answer no, next question is: correct (most efficient, ecc) way traying do?

there no need provide input sequence scan. can instead specify number of iterations via scan's n_steps parameter. optionally, can specify condition under scan should stop via theano.scan_module.until.

so python's range function can emulated using theano's scan without specifying input sequence figuring out how many iterations required construct requested sequence.

here's implementation of range function based on theano's scan. complicated part figuring out how many steps required.

import numpy import theano import theano.tensor tt import theano.ifelse   def scan_range_step(x_tm1, step):     return x_tm1 + step   def compile_theano_range():     tt.arange     symbolic_start = tt.lscalar()     symbolic_stop = tt.lscalar()     symbolic_step = tt.lscalar()     n_steps = tt.cast(         tt.ceil(tt.abs_(symbolic_stop - symbolic_start) / tt.cast(tt.abs_(symbolic_step), theano.config.floatx)),         'int64') - 1     outputs, _ = theano.scan(scan_range_step, outputs_info=[symbolic_start], n_steps=n_steps,                              non_sequences=[symbolic_step], strict=true)     outputs = theano.ifelse.ifelse(tt.eq(n_steps, 0), tt.stack(symbolic_start), outputs)     f = theano.function([symbolic_start, symbolic_stop, symbolic_step],                         outputs=tt.concatenate([[symbolic_start], outputs]))      def theano_range(start, stop=none, step=1):         assert isinstance(start, int)         assert isinstance(step, int)         if step == 0:             raise valueerror()         if stop none:             stop = start             start = 0         else:             assert isinstance(stop, int)         if start == stop:             return []         if stop < start , step > 0:             return []         if stop > start , step < 0:             return []         return f(start, stop, step)      return theano_range   def main():     theano_range = compile_theano_range()     python_range = range      start in [-10, -5, -1, 0, 1, 5, 10]:         stop in [-10, -5, -1, 0, 1, 5, 10]:             step in [-3, -2, -1, 1, 2, 3]:                 = theano_range(start, stop, step)                 b = python_range(start, stop, step)                 assert numpy.all(numpy.equal(a, b)), (start, stop, step, a, b)   main() 

clearly daft thing do/use real since theano provides symbolic version of python's range function, i.e. theano.tensor.arange. built in implementation far more efficient our scan version because doesn't use scan, uses custom operation instead.

as rule of thumb: have to set maximum number of iteration steps via range or the n_steps argument. can set large number , use theano.scan_module.until stop iteration @ earlier stage if stop condition met.


Comments

Popular posts from this blog

html - Outlook 2010 Anchor (url/address/link) -

javascript - Why does running this loop 9 times take 100x longer than running it 8 times? -

Getting gateway time-out Rails app with Nginx + Puma running on Digital Ocean -