def __init__(self, imshp=None, kshp=None, border_mode="valid", subsample=(1, 1), filter_flip=True, filter_dilation=(1, 1)): if isinstance(border_mode, integer_types): border_mode = (border_mode, border_mode) if isinstance(border_mode, tuple): pad_h, pad_w = map(int, border_mode) border_mode = (pad_h, pad_w) if border_mode == (0, 0): border_mode = 'valid' if not ((isinstance(border_mode, tuple) and min(border_mode) >= 0) or border_mode in ('valid', 'full', 'half')): raise ValueError( 'invalid border_mode {}, which must be either ' '"valid", "full", "half", an integer or a pair of' ' integers'.format(border_mode)) self.imshp = tuple(imshp) if imshp else (None,) * 4 for imshp_i in self.imshp: if imshp_i is not None: # Components of imshp should be constant or ints try: get_scalar_constant_value(imshp_i, only_process_constants=True) except NotScalarConstantError: reraise(ValueError, ValueError("imshp should be None or a tuple of " "constant int values"), sys.exc_info()[2]) self.kshp = tuple(kshp) if kshp else (None,) * 4 for kshp_i in self.kshp: if kshp_i is not None: # Components of kshp should be constant or ints try: get_scalar_constant_value(kshp_i, only_process_constants=True) except NotScalarConstantError: reraise(ValueError, ValueError("kshp should be None or a tuple of " "constant int values"), sys.exc_info()[2]) self.border_mode = border_mode self.filter_flip = filter_flip if len(subsample) != 2: raise ValueError("subsample must have two elements") self.subsample = tuple(subsample) if len(filter_dilation) != 2: raise ValueError("filter_dilation must have two elements") self.filter_dilation = tuple(filter_dilation)
def opt(node): if (isinstance(node.op, GpuElemwise) and node.op.scalar_op == scal.mul and node.nin == 2): targ = find_node(node.inputs[0], cls) if targ is None: targ = find_node(node.inputs[1], cls) if targ is None: return lr = grab_cpu_scalar(node.inputs[0], nd=targ.outputs[0].ndim) else: lr = grab_cpu_scalar(node.inputs[1], nd=targ.outputs[0].ndim) if lr is None or lr.dtype != targ.outputs[0].dtype: return None inputs = list(targ.inputs) try: c = get_scalar_constant_value(lr) if c == 0: inputs[alpha_in] = lr inputs[beta_in] = lr elif c == 1: inputs[alpha_in] = targ.inputs[alpha_in] inputs[beta_in] = targ.inputs[beta_in] else: inputs[alpha_in] = lr * targ.inputs[alpha_in] inputs[beta_in] = lr * targ.inputs[beta_in] except NotScalarConstantError: inputs[alpha_in] = lr * targ.inputs[alpha_in] inputs[beta_in] = lr * targ.inputs[beta_in] return maker(targ, *inputs)
def is_equal(var, val): # Returns True if var is always equal to val (python value), False # otherwise (including if var is not constant) try: v = get_scalar_constant_value(var) return v == val except NotScalarConstantError: return False
def local_gpu_multinomial(node): # TODO : need description for function if type(node.op) is MultinomialFromUniform: if len(node.inputs) == 2: p, u = node.inputs n_samples = 1 else: p, u, n_samples = node.inputs try: if get_scalar_constant_value(n_samples) != 1: return None except NotScalarConstantError: return None m, = node.outputs if (p.dtype == u.dtype == m.dtype == 'float32' and any([i.owner and isinstance(i.owner.op, theano.sandbox.cuda.HostFromGpu) for i in node.inputs])): gpu_op = GpuMultinomialFromUniform(node.op.odtype) return [host_from_gpu(gpu_op(*[gpu_from_host(i) for i in [p, u]])).T] if (isinstance(node.op, theano.sandbox.cuda.GpuFromHost) and node.inputs[0].owner and type(node.inputs[0].owner.op) is MultinomialFromUniform): multi = node.inputs[0].owner if len(node.inputs) == 2: p, u = node.inputs n_samples = 1 else: p, u, n_samples = node.inputs try: if get_scalar_constant_value(n_samples) != 1: return None except NotScalarConstantError: return None m, = multi.outputs if (p.dtype == u.dtype == m.dtype == 'float32'): gpu_op = GpuMultinomialFromUniform(multi.op.odtype) ret = gpu_op(*[gpu_from_host(i) for i in [p, u]]).T # The dimshuffle is on the cpu, but will be moved to the # gpu by an opt. return [gpu_from_host(ret)]
def make_node(self, n, m, k): n = tensor.as_tensor_variable(n) m = tensor.as_tensor_variable(m) k = tensor.as_tensor_variable(k) assert n.ndim == 0 assert m.ndim == 0 assert k.ndim == 0 otype = GpuArrayType(dtype=self.dtype, broadcastable=(False, False), context_name=self.context_name) # k != 0 isn't implemented on the GPU yet. assert tensor.get_scalar_constant_value(k) == 0 return Apply(self, [n, m], [otype()])
def is_positive(v): if hints(v).get('positive', False): return True # TODO: how to handle this - a registry? # infer_hints on Ops? logger.debug('is_positive: %s' % str(v)) if v.owner and v.owner.op == tensor.pow: try: exponent = tensor.get_scalar_constant_value(v.owner.inputs[1]) except tensor.basic.NotScalarConstantError: return False if 0 == exponent % 2: return True return False
def make_node(self, images, maxout, gz): images = as_cuda_ndarray_variable(images) maxout = as_cuda_ndarray_variable(maxout) gz = as_cuda_ndarray_variable(gz) assert images.ndim == 4 assert maxout.ndim == 4 assert gz.ndim == 4 try: # Note : `get_scalar_constant_value` returns a ndarray not a # int nb_channel = int(get_scalar_constant_value(images.shape[0])) assert nb_channel % 16 == 0 except NotScalarConstantError: pass return Apply(self, [images, maxout, gz], [images.type()])
def make_node(self, p, h, gp, gh): p = as_cuda_ndarray_variable(p) h = as_cuda_ndarray_variable(h) gp = as_cuda_ndarray_variable(gp) gh = as_cuda_ndarray_variable(gh) assert p.ndim == 4 assert h.ndim == 4 assert gp.ndim == 4 assert gh.ndim == 4 try: nb_channel = int(get_scalar_constant_value(h.shape[0])) assert nb_channel % 16 == 0 except NotScalarConstantError: pass return Apply(self, [p, h, gp, gh], [p.type(), h.type()])
def local_gpua_multinomial(op, context_name, inputs, outputs): # TODO : need description for function if len(inputs) == 2: p, u = inputs n_samples = 1 else: p, u, n_samples = inputs try: if get_scalar_constant_value(n_samples) != 1: return None except NotScalarConstantError: return None m, = outputs gpu_op = GPUAMultinomialFromUniform(op.odtype) return GpuDimShuffle([False, False], [1, 0])( gpu_op(p, u))
def local_gpua_multinomial(node, context_name): # TODO : need description for function if len(node.inputs) == 2: p, u = node.inputs n_samples = 1 else: p, u, n_samples = node.inputs try: if get_scalar_constant_value(n_samples) != 1: return None except NotScalarConstantError: return None m, = node.outputs if p.dtype == u.dtype == m.dtype == "float32": gpu_op = GPUAMultinomialFromUniform(node.op.odtype) return gpuarray.elemwise.GpuDimShuffle([False, False], [1, 0])(gpu_op(p, u))
def make_node(self, value, *shape): v = as_gpuarray_variable(value) sh = [tensor.as_tensor_variable(s) for s in shape] bcast = [] if v.ndim > len(shape): raise TypeError( 'GpuAlloc value has more dimensions than arguments', value.ndim, len(shape)) for i, s in enumerate(sh): if s.type.dtype[:3] not in ('int', 'uint'): raise TypeError('Shape arguments must be integers', s) try: const_shp = tensor.get_scalar_constant_value(s) except tensor.NotScalarConstantError: const_shp = None bcast.append(numpy.all(1 == const_shp)) otype = GpuArrayType(dtype=v.dtype, broadcastable=bcast) return Apply(self, [v] + sh, [otype()])
def convert_rv_to_dist(node, obs): if not isinstance(node.op, RandomVariable): raise TypeError(f"{node} is not of type `RandomVariable`") rv = node.default_output() if hasattr(node, "fgraph") and hasattr(node.fgraph, "shape_feature"): shape = list(node.fgraph.shape_feature.shape_tuple(rv)) else: shape = list(rv.shape) for i, s in enumerate(shape): try: shape[i] = tt.get_scalar_constant_value(s) except tt.NotScalarConstantError: shape[i] = s.tag.test_value dist_type, dist_params = _convert_rv_to_dist(node.op, node) return dist_type(rv.name, shape=shape, observed=obs, **dist_params)
def is_equal(var, val): """ Returns True if `var` is always equal to `val`. This will only return True if the variable will always be equal to the value. If it might not be true in some cases then it returns False. Parameters ---------- var Variable to compare val Python value """ try: v = get_scalar_constant_value(var) return v == val except NotScalarConstantError: return False
def make_node(self, images, maxout, gz): """ .. todo:: WRITEME """ images = as_cuda_ndarray_variable(images) maxout = as_cuda_ndarray_variable(maxout) gz = as_cuda_ndarray_variable(gz) assert images.ndim == 4 assert maxout.ndim == 4 assert gz.ndim == 4 try: # Note : `get_scalar_constant_value` returns a ndarray not a # int nb_channel = int(get_scalar_constant_value(images.shape[0])) assert nb_channel % 16 == 0 except NotScalarConstantError: pass return Apply(self, [images, maxout, gz], [images.type()])
def make_node(self, p, h, gp, gh, gp_iszero, gh_iszero): """ .. todo:: WRITEME """ p = as_cuda_ndarray_variable(p) h = as_cuda_ndarray_variable(h) gp = as_cuda_ndarray_variable(gp) gh = as_cuda_ndarray_variable(gh) assert p.ndim == 4 assert h.ndim == 4 assert gp.ndim == 4 assert gh.ndim == 4 try: nb_channel = int(get_scalar_constant_value(h.shape[0])) assert nb_channel % 16 == 0 except NotScalarConstantError: pass return Apply(self, [p, h, gp, gh, gp_iszero, gh_iszero], [p.type(), h.type()])
def validate( self, image_shape, filter_shape, border_mode="valid", subsample=(1, 1, 1), input=None, filters=None, verify_grad=True, non_contiguous=False, filter_dilation=(1, 1, 1), ): """ :param image_shape: The constant shape info passed to corr3dMM. :param filter_shape: The constant shape info passed to corr3dMM. """ if not theano.config.cxx: pytest.skip("Need cxx for this test") N_image_shape = [ T.get_scalar_constant_value(T.as_tensor_variable(x)) for x in image_shape ] N_filter_shape = [ T.get_scalar_constant_value(T.as_tensor_variable(x)) for x in filter_shape ] if input is None: input = self.input if filters is None: filters = self.filters # THEANO IMPLEMENTATION # we create a symbolic function so that verify_grad can work def sym_Corr3dMM(input, filters): # define theano graph and function input.name = "input" filters.name = "filters" rval = corr3d.Corr3dMM(border_mode, subsample, filter_dilation)(input, filters) rval.name = "corr_output" return rval output = sym_Corr3dMM(input, filters) output.name = "Corr3dMM()(%s,%s)" % (input.name, filters.name) theano_corr = theano.function([input, filters], output, mode=self.mode) # initialize input and compute result image_data = np.random.random(N_image_shape).astype(self.dtype) filter_data = np.random.random(N_filter_shape).astype(self.dtype) image_data /= 10 filter_data /= 10 if non_contiguous: image_data = np.transpose(image_data, axes=(0, 1, 4, 3, 2)) image_data = image_data.copy() image_data = np.transpose(image_data, axes=(0, 1, 4, 3, 2)) filter_data = np.transpose(filter_data, axes=(0, 1, 4, 3, 2)) filter_data = filter_data.copy() filter_data = np.transpose(filter_data, axes=(0, 1, 4, 3, 2)) assert not image_data.flags["CONTIGUOUS"] assert not filter_data.flags["CONTIGUOUS"] theano_output = theano_corr(image_data, filter_data) # REFERENCE IMPLEMENTATION # Testing correlation, not convolution. Reverse filters. filter_data_corr = np.array(filter_data[:, :, ::-1, ::-1, ::-1], copy=True, order="C") orig_image_data = image_data img_shape3d = np.array(N_image_shape[-3:]) fil_shape3d = np.array(N_filter_shape[-3:]) dil_shape3d = np.array(filter_dilation) dil_fil_shape3d = (fil_shape3d - 1) * dil_shape3d + 1 subsample3d = np.array(subsample) if border_mode == "full": padHWD = dil_fil_shape3d - 1 elif border_mode == "valid": padHWD = np.array([0, 0, 0]) elif border_mode == "half": padHWD = np.floor(dil_fil_shape3d / 2).astype("int32") elif isinstance(border_mode, tuple): padHWD = np.array(border_mode) elif isinstance(border_mode, integer_types): padHWD = np.array([border_mode, border_mode, border_mode]) else: raise NotImplementedError( "Unsupported border_mode {}".format(border_mode)) out_shape3d = (np.floor( (img_shape3d + 2 * (padHWD) - dil_fil_shape3d) / subsample3d) + 1) # avoid numpy deprecation out_shape3d = out_shape3d.astype("int32") out_shape = (N_image_shape[0], N_filter_shape[0]) + tuple(out_shape3d) ref_output = np.zeros(out_shape) # loop over output feature maps ref_output.fill(0) image_data2 = np.zeros(( N_image_shape[0], N_image_shape[1], N_image_shape[2] + 2 * padHWD[0], N_image_shape[3] + 2 * padHWD[1], N_image_shape[4] + 2 * padHWD[2], )) image_data2[:, :, padHWD[0]:padHWD[0] + N_image_shape[2], padHWD[1]:padHWD[1] + N_image_shape[3], padHWD[2]:padHWD[2] + N_image_shape[4], ] = image_data image_data = image_data2 N_image_shape = image_data.shape for bb in range(N_image_shape[0]): for nn in range(N_filter_shape[0]): for im0 in range(N_image_shape[1]): filter3d = filter_data_corr[nn, im0, :, :, :] image3d = image_data[bb, im0, :, :, :] for row in range(ref_output.shape[2]): irow = row * subsample[0] # image row for col in range(ref_output.shape[3]): icol = col * subsample[1] # image col for slc in range(ref_output.shape[4]): islc = slc * subsample[2] # image slice ref_output[bb, nn, row, col, slc] += ( image3d[ irow:irow + dil_fil_shape3d[0]:filter_dilation[0], icol:icol + dil_fil_shape3d[1]:filter_dilation[1], islc:islc + dil_fil_shape3d[2]: filter_dilation[2], ] * filter3d[::-1, ::-1, ::-1]).sum() utt.assert_allclose(theano_output, ref_output) # TEST GRADIENT if verify_grad: utt.verify_grad(sym_Corr3dMM, [orig_image_data, filter_data], mode=self.mode)
def validate(self, image_shape, filter_shape, border_mode='valid', subsample=(1, 1), input=None, filters=None, verify_grad=True, non_contiguous=False, filter_dilation=(1, 1)): """ :param image_shape: The constant shape info passed to corrMM. :param filter_shape: The constant shape info passed to corrMM. """ N_image_shape = [T.get_scalar_constant_value(T.as_tensor_variable(x)) for x in image_shape] N_filter_shape = [T.get_scalar_constant_value(T.as_tensor_variable(x)) for x in filter_shape] if input is None: input = self.input if filters is None: filters = self.filters # THEANO IMPLEMENTATION # we create a symbolic function so that verify_grad can work def sym_CorrMM(input, filters): # define theano graph and function input.name = 'input' filters.name = 'filters' rval = corr.CorrMM(border_mode, subsample, filter_dilation)(input, filters) rval.name = 'corr_output' return rval output = sym_CorrMM(input, filters) output.name = 'CorrMM()(%s,%s)' % (input.name, filters.name) theano_corr = theano.function([input, filters], output, mode=self.mode) # initialize input and compute result image_data = numpy.random.random(N_image_shape).astype(self.dtype) filter_data = numpy.random.random(N_filter_shape).astype(self.dtype) if non_contiguous: image_data = numpy.transpose(image_data, axes=(0, 1, 3, 2)) image_data = image_data.copy() image_data = numpy.transpose(image_data, axes=(0, 1, 3, 2)) filter_data = numpy.transpose(filter_data, axes=(0, 1, 3, 2)) filter_data = filter_data.copy() filter_data = numpy.transpose(filter_data, axes=(0, 1, 3, 2)) assert not image_data.flags['CONTIGUOUS'] assert not filter_data.flags['CONTIGUOUS'] theano_output = theano_corr(image_data, filter_data) # REFERENCE IMPLEMENTATION # Testing correlation, not convolution. Reverse filters. filter_data_corr = numpy.array(filter_data[:, :, ::-1, ::-1], copy=True, order='C') orig_image_data = image_data img_shape2d = numpy.array(N_image_shape[-2:]) fil_shape2d = numpy.array(N_filter_shape[-2:]) dil_shape2d = numpy.array(filter_dilation) dil_fil_shape2d = (fil_shape2d - 1) * dil_shape2d + 1 subsample2d = numpy.array(subsample) if border_mode == 'full': padHW = (dil_fil_shape2d - 1) elif border_mode == 'valid': padHW = numpy.array([0, 0]) elif border_mode == 'half': padHW = numpy.floor(dil_fil_shape2d / 2).astype('int32') elif isinstance(border_mode, tuple): padHW = numpy.array(border_mode) elif isinstance(border_mode, integer_types): padHW = numpy.array([border_mode, border_mode]) else: raise NotImplementedError('Unsupported border_mode {}'.format(border_mode)) out_shape2d = numpy.floor((img_shape2d + 2 * (padHW) - dil_fil_shape2d) / subsample2d) + 1 # avoid numpy deprecation out_shape2d = out_shape2d.astype('int32') out_shape = (N_image_shape[0], N_filter_shape[0]) + tuple(out_shape2d) ref_output = numpy.zeros(out_shape) # loop over output feature maps ref_output.fill(0) image_data2 = numpy.zeros((N_image_shape[0], N_image_shape[1], N_image_shape[2] + 2 * padHW[0], N_image_shape[3] + 2 * padHW[1])) image_data2[:, :, padHW[0]:padHW[0] + N_image_shape[2], padHW[1]:padHW[1] + N_image_shape[3]] = image_data image_data = image_data2 N_image_shape = image_data.shape for bb in range(N_image_shape[0]): for nn in range(N_filter_shape[0]): for im0 in range(N_image_shape[1]): filter2d = filter_data_corr[nn, im0, :, :] image2d = image_data[bb, im0, :, :] for row in range(ref_output.shape[2]): irow = row * subsample[0] # image row for col in range(ref_output.shape[3]): icol = col * subsample[1] # image col ref_output[bb, nn, row, col] += (image2d[ irow:irow + dil_fil_shape2d[0]:filter_dilation[0], icol:icol + dil_fil_shape2d[1]:filter_dilation[1]] * filter2d[::-1, ::-1] ).sum() self.assertTrue(_allclose(theano_output, ref_output)) # TEST GRADIENT if verify_grad: utt.verify_grad(sym_CorrMM, [orig_image_data, filter_data], mode=self.mode)
def process_shape_info(cls, output, pstate): using_latex = getattr(pstate, "latex", False) if output.dtype in tt.int_dtypes: sspace_char = "Z" elif output.dtype in tt.uint_dtypes: sspace_char = "N" elif output.dtype in tt.float_dtypes: sspace_char = "R" else: sspace_char = "?" fgraph = getattr(output, "fgraph", None) shape_feature = None if fgraph: if not hasattr(fgraph, "shape_feature"): fgraph.attach_feature(tt.opt.ShapeFeature()) shape_feature = fgraph.shape_feature shape_dims = [] for i in range(output.ndim): s_i_out = None if using_latex: s_i_pat = "N^{%s}" + ("_{%s}" % i) else: s_i_pat = "N^%s" + ("_%s" % i) if shape_feature: new_precedence = -1000 try: old_precedence = getattr(pstate, "precedence", None) pstate.precedence = new_precedence _s_i_out = shape_feature.get_shape(output, i) if not isinstance(_s_i_out, (tt.Constant, tt.TensorVariable)): s_i_out = pstate.pprinter.process(_s_i_out, pstate) else: s_i_out = str(tt.get_scalar_constant_value(_s_i_out)) except (KeyError, IndexError, ValueError, tt.NotScalarConstantError): # Ugh, most of these exception types are just for # `get_scalar_constant_value`! # TODO: The design of that function contract could use some # serious reconsideration. pass finally: pstate.precedence = old_precedence if not s_i_out: s_i_out = cls.process_variable_name(output, pstate) s_i_out = s_i_pat % s_i_out shape_dims += [s_i_out] shape_info = cls.process_variable_name(output, pstate) if using_latex: shape_info += " \\in \\mathbb{%s}" % sspace_char shape_dims = " \\times ".join(shape_dims) if shape_dims: shape_info += "^{%s}" % shape_dims else: shape_info += " in %s" % sspace_char shape_dims = " x ".join(shape_dims) if shape_dims: shape_info += "**(%s)" % shape_dims return shape_info
def validate(self, image_shape, filter_shape, border_mode='valid', subsample=(1, 1), N_image_shape=None, N_filter_shape=None, input=None, filters=None, unroll_batch=None, unroll_kern=None, unroll_patch=None, verify_grad=True, should_raise=False): """ :param image_shape: The constant shape info passed to conv2d. :param filter_shape: The constant shape info passed to conv2d. :param N_image_shape: None(default to image_shape) or tuple of 4 elements with the shape of the input image :param N_filter_shape: None(default to filter_shape) or tuple of 4 elements with the shape of the input filter """ if N_image_shape is None: N_image_shape = [T.get_scalar_constant_value(T. as_tensor_variable(x)) for x in image_shape] if N_filter_shape is None: N_filter_shape = [T.get_scalar_constant_value(T. as_tensor_variable(x)) for x in filter_shape] if input is None: input = self.input if not filters: filters = self.filters ############# THEANO IMPLEMENTATION ############ # we create a symbolic function so that verify_grad can work def sym_conv2d(input, filters): # define theano graph and function input.name = 'input' filters.name = 'filters' rval = conv.conv2d(input, filters, image_shape, filter_shape, border_mode, subsample, unroll_batch=unroll_batch, unroll_kern=unroll_kern, unroll_patch=unroll_patch) rval.name = 'conv_output' return rval output = sym_conv2d(input, filters) output.name = 'conv2d(%s,%s)' % (input.name, filters.name) theano_conv = theano.function([input, filters], output) # initialize input and compute result image_data = numpy.random.random(N_image_shape) filter_data = numpy.random.random(N_filter_shape) try: theano_output = theano_conv(image_data, filter_data) except ValueError: if not should_raise: raise return else: if should_raise: raise Exception( "ConvOp should have generated an error") ############# REFERENCE IMPLEMENTATION ############ s = 1. orig_image_data = image_data if border_mode is not 'full': s = -1. out_shape2d = numpy.array(N_image_shape[-2:]) +\ s * numpy.array(N_filter_shape[-2:]) - s out_shape2d = numpy.ceil(out_shape2d / numpy.array(subsample)) out_shape = (N_image_shape[0], N_filter_shape[0]) + tuple(out_shape2d) ref_output = numpy.zeros(out_shape) # loop over output feature maps ref_output.fill(0) if border_mode == 'full': image_data2 = numpy.zeros((N_image_shape[0], N_image_shape[1], N_image_shape[2] + 2 * N_filter_shape[2] - 2, N_image_shape[3] + 2 * N_filter_shape[3] - 2)) image_data2[:, :, N_filter_shape[2] - 1:N_filter_shape[2] - 1 + N_image_shape[2], N_filter_shape[3] - 1:N_filter_shape[3] - 1 + N_image_shape[3]] = image_data image_data = image_data2 N_image_shape = image_data.shape for bb in range(N_image_shape[0]): for nn in range(N_filter_shape[0]): for im0 in range(N_image_shape[1]): filter2d = filter_data[nn, im0, :, :] image2d = image_data[bb, im0, :, :] for row in range(ref_output.shape[2]): irow = row * subsample[0] # image row for col in range(ref_output.shape[3]): icol = col * subsample[1] # image col ref_output[bb, nn, row, col] += (image2d[ irow:irow + N_filter_shape[2], icol:icol + N_filter_shape[3]] * filter2d[::-1,::-1] ).sum() self.assertTrue(_allclose(theano_output, ref_output)) ############# TEST GRADIENT ############ if verify_grad: utt.verify_grad(sym_conv2d, [orig_image_data, filter_data])
def validate(self, image_shape, filter_shape, border_mode='valid', subsample=(1, 1), N_image_shape=None, N_filter_shape=None, input=None, filters=None, unroll_batch=None, unroll_kern=None, unroll_patch=None, verify_grad=True, should_raise=False): """ :param image_shape: The constant shape info passed to conv2d. :param filter_shape: The constant shape info passed to conv2d. :param N_image_shape: None(default to image_shape) or tuple of 4 elements with the shape of the input image :param N_filter_shape: None(default to filter_shape) or tuple of 4 elements with the shape of the input filter """ if N_image_shape is None: N_image_shape = [T.get_scalar_constant_value( T.as_tensor_variable(x)) for x in image_shape] if N_filter_shape is None: N_filter_shape = [T.get_scalar_constant_value( T.as_tensor_variable(x)) for x in filter_shape] if input is None: input = self.input if not filters: filters = self.filters # THEANO IMPLEMENTATION # we create a symbolic function so that verify_grad can work def sym_conv2d(input, filters): # define theano graph and function input.name = 'input' filters.name = 'filters' rval = conv.conv2d( input, filters, image_shape, filter_shape, border_mode, subsample, unroll_batch=unroll_batch, unroll_kern=unroll_kern, unroll_patch=unroll_patch) rval.name = 'conv_output' return rval output = sym_conv2d(input, filters) output.name = 'conv2d(%s,%s)' % (input.name, filters.name) theano_conv = theano.function([input, filters], output, mode=self.mode) # initialize input and compute result image_data = numpy.random.random(N_image_shape).astype(self.dtype) filter_data = numpy.random.random(N_filter_shape).astype(self.dtype) try: theano_output = theano_conv(image_data, filter_data) except ValueError: if not should_raise: raise return else: if should_raise: raise Exception( "ConvOp should have generated an error") # REFERENCE IMPLEMENTATION s = 1. orig_image_data = image_data if border_mode is not 'full': s = -1. out_shape2d = numpy.array(N_image_shape[-2:]) +\ s * numpy.array(N_filter_shape[-2:]) - s out_shape2d = numpy.ceil(out_shape2d / numpy.array(subsample)) # avoid numpy deprecation out_shape2d = out_shape2d.astype('int32') out_shape = (N_image_shape[0], N_filter_shape[0]) + tuple(out_shape2d) ref_output = numpy.zeros(out_shape) # loop over output feature maps ref_output.fill(0) if border_mode == 'full': image_data2 = numpy.zeros((N_image_shape[0], N_image_shape[1], N_image_shape[2] + 2 * N_filter_shape[2] - 2, N_image_shape[3] + 2 * N_filter_shape[3] - 2)) image_data2[ :, :, N_filter_shape[2] - 1:N_filter_shape[2] - 1 + N_image_shape[2], N_filter_shape[3] - 1:N_filter_shape[3] - 1 + N_image_shape[3]] = image_data image_data = image_data2 N_image_shape = image_data.shape for bb in range(N_image_shape[0]): for nn in range(N_filter_shape[0]): for im0 in range(N_image_shape[1]): filter2d = filter_data[nn, im0, :, :] image2d = image_data[bb, im0, :, :] for row in range(ref_output.shape[2]): irow = row * subsample[0] # image row for col in range(ref_output.shape[3]): icol = col * subsample[1] # image col ref_output[bb, nn, row, col] += (image2d[ irow:irow + N_filter_shape[2], icol:icol + N_filter_shape[3]] * filter2d[::-1, ::-1] ).sum() self.assertTrue(_allclose(theano_output, ref_output)) # TEST GRADIENT if verify_grad: utt.verify_grad(sym_conv2d, [orig_image_data, filter_data])
def validate(self, image_shape, filter_shape, border_mode='valid', subsample=(1, 1), input=None, filters=None, verify_grad=True, non_contiguous=False): """ :param image_shape: The constant shape info passed to corrMM. :param filter_shape: The constant shape info passed to corrMM. """ N_image_shape = [ T.get_scalar_constant_value(T.as_tensor_variable(x)) for x in image_shape ] N_filter_shape = [ T.get_scalar_constant_value(T.as_tensor_variable(x)) for x in filter_shape ] if input is None: input = self.input if filters is None: filters = self.filters # THEANO IMPLEMENTATION # we create a symbolic function so that verify_grad can work def sym_CorrMM(input, filters): # define theano graph and function input.name = 'input' filters.name = 'filters' rval = corr.CorrMM(border_mode, subsample)(input, filters) rval.name = 'corr_output' return rval output = sym_CorrMM(input, filters) output.name = 'CorrMM()(%s,%s)' % (input.name, filters.name) theano_corr = theano.function([input, filters], output, mode=self.mode) # initialize input and compute result image_data = numpy.random.random(N_image_shape).astype(self.dtype) filter_data = numpy.random.random(N_filter_shape).astype(self.dtype) if non_contiguous: image_data = numpy.transpose(image_data, axes=(0, 1, 3, 2)) image_data = image_data.copy() image_data = numpy.transpose(image_data, axes=(0, 1, 3, 2)) filter_data = numpy.transpose(filter_data, axes=(0, 1, 3, 2)) filter_data = filter_data.copy() filter_data = numpy.transpose(filter_data, axes=(0, 1, 3, 2)) assert not image_data.flags['CONTIGUOUS'] assert not filter_data.flags['CONTIGUOUS'] theano_output = theano_corr(image_data, filter_data) # REFERENCE IMPLEMENTATION # Testing correlation, not convolution. Reverse filters. filter_data_corr = numpy.array(filter_data[:, :, ::-1, ::-1], copy=True, order='C') orig_image_data = image_data img_shape2d = numpy.array(N_image_shape[-2:]) fil_shape2d = numpy.array(N_filter_shape[-2:]) subsample2d = numpy.array(subsample) if border_mode == 'full': padHW = (fil_shape2d - 1) elif border_mode == 'valid': padHW = numpy.array([0, 0]) elif border_mode == 'half': padHW = numpy.floor(fil_shape2d / 2) elif isinstance(border_mode, tuple): padHW = numpy.array(border_mode) elif isinstance(border_mode, int): padHW = numpy.array([border_mode, border_mode]) else: raise NotImplementedError( 'Unsupported border_mode {}'.format(border_mode)) out_shape2d = numpy.floor( (img_shape2d + 2 * (padHW) - fil_shape2d) / subsample2d) + 1 out_shape = (N_image_shape[0], N_filter_shape[0]) + tuple(out_shape2d) ref_output = numpy.zeros(out_shape) # loop over output feature maps ref_output.fill(0) image_data2 = numpy.zeros( (N_image_shape[0], N_image_shape[1], N_image_shape[2] + 2 * padHW[0], N_image_shape[3] + 2 * padHW[1])) image_data2[:, :, padHW[0]:padHW[0] + N_image_shape[2], padHW[1]:padHW[1] + N_image_shape[3]] = image_data image_data = image_data2 N_image_shape = image_data.shape for bb in range(N_image_shape[0]): for nn in range(N_filter_shape[0]): for im0 in range(N_image_shape[1]): filter2d = filter_data_corr[nn, im0, :, :] image2d = image_data[bb, im0, :, :] for row in range(ref_output.shape[2]): irow = row * subsample[0] # image row for col in range(ref_output.shape[3]): icol = col * subsample[1] # image col ref_output[bb, nn, row, col] += ( image2d[irow:irow + N_filter_shape[2], icol:icol + N_filter_shape[3]] * filter2d[::-1, ::-1]).sum() self.assertTrue(_allclose(theano_output, ref_output)) # TEST GRADIENT if verify_grad: utt.verify_grad(sym_CorrMM, [orig_image_data, filter_data])