def bincount(x, weights=None, minlength=None, assert_nonneg=False): """Count number of occurrences of each value in array of ints. The number of bins (of size 1) is one larger than the largest value in x. If minlength is specified, there will be at least this number of bins in the output array (though it will be longer if necessary, depending on the contents of x). Each bin gives the number of occurrences of its index value in x. If weights is specified the input array is weighted by it, i.e. if a value n is found at position i, out[n] += weight[i] instead of out[n] += 1. Parameters ---------- x : 1 dimension, nonnegative ints weights : array of the same shape as x with corresponding weights. Optional. minlength : A minimum number of bins for the output array. Optional. assert_nonneg : A flag that inserts an assert_op to check if every input x is nonnegative. Optional. .. versionadded:: 0.6 """ compatible_type = ('int8', 'int16', 'int32', 'int64', 'uint8', 'uint16', 'uint32') unsupported_dtypes = ('uint64',) if x.dtype in unsupported_dtypes: raise TypeError( ("Input dtype %s is not supported, " % unsupported_dtypes), x.dtype) if x.dtype not in compatible_type: raise TypeError("Inputs dtype must be an integer.") if x.ndim != 1: raise TypeError("Inputs must be of dimension 1.") if assert_nonneg: from theano.tensor.opt import Assert assert_op = Assert('Input to bincount has negative values!') x = assert_op(x, theano.tensor.all(x >= 0)) max_value = theano.tensor.cast(x.max() + 1, 'int64') if minlength is not None: max_value = theano.tensor.maximum(max_value, minlength) if weights is None: out = theano.tensor.zeros([max_value], dtype=x.dtype) out = theano.tensor.inc_subtensor(out[x], 1) else: out = theano.tensor.zeros([max_value], dtype=weights.dtype) out = theano.tensor.inc_subtensor(out[x], weights) return out
def bincount(x, weights=None, minlength=None, assert_nonneg=False): """Count number of occurrences of each value in array of ints. The number of bins (of size 1) is one larger than the largest value in x. If minlength is specified, there will be at least this number of bins in the output array (though it will be longer if necessary, depending on the contents of x). Each bin gives the number of occurrences of its index value in x. If weights is specified the input array is weighted by it, i.e. if a value n is found at position i, out[n] += weight[i] instead of out[n] += 1. Parameters ---------- x : 1 dimension, nonnegative ints weights : array of the same shape as x with corresponding weights. Optional. minlength : A minimum number of bins for the output array. Optional. assert_nonneg : A flag that inserts an assert_op to check if every input x is nonnegative. Optional. .. versionadded:: 0.6 """ if x.ndim != 1: raise TypeError("Inputs must be of dimension 1.") if assert_nonneg: from theano.tensor.opt import Assert assert_op = Assert("Input to bincount has negative values!") x = assert_op(x, theano.tensor.all(x >= 0)) max_value = theano.tensor.cast(x.max() + 1, "int64") if minlength is not None: max_value = theano.tensor.maximum(max_value, minlength) # Note: we do not use inc_subtensor(out[x], ...) in the following lines, # since out[x] raises an exception if the indices (x) are int8. if weights is None: out = theano.tensor.zeros([max_value], dtype=x.dtype) out = theano.tensor.advanced_inc_subtensor1(out, 1, x) else: out = theano.tensor.zeros([max_value], dtype=weights.dtype) out = theano.tensor.advanced_inc_subtensor1(out, weights, x) return out
def test_RandomVariable(): str_res = str( RandomVariable( "normal", 0, [0, 0], "normal", inplace=True, ) ) assert str_res == "normal_rv" # `ndims_params` should be a `Sequence` type with raises(TypeError, match="^Parameter ndims_params*"): RandomVariable( "normal", 0, 0, config.floatX, inplace=True, ) # `size` should be a `Sequence` type with raises(TypeError, match="^Parameter size*"): RandomVariable( "normal", 0, [0, 0], config.floatX, inplace=True, )(0, 1, size={1, 2}) # No dtype with raises(TypeError, match="^dtype*"): RandomVariable( "normal", 0, [0, 0], inplace=True, )(0, 1) # Confirm that `inplace` works rv = RandomVariable( "normal", 0, [0, 0], "normal", inplace=True, ) assert rv.inplace assert rv.destroy_map == {0: [3]} # A no-params `RandomVariable` rv = RandomVariable(name="test_rv", ndim_supp=0, ndims_params=()) with raises(TypeError): rv.make_node(rng=1) # `RandomVariable._infer_shape` should handle no parameters rv_shape = rv._infer_shape(tt.constant([]), (), []) assert rv_shape.equals(tt.constant([], dtype="int64")) # Integer-specificed `dtype` dtype_1 = tt.all_dtypes[1] rv_node = rv.make_node(None, None, 1) rv_out = rv_node.outputs[1] rv_out.tag.test_value = 1 assert rv_out.dtype == dtype_1 with raises(NullTypeGradError): tt.grad(rv_out, [rv_node.inputs[0]]) rv = RandomVariable("normal", 0, [0, 0], config.floatX, inplace=True) mu = tt.tensor(config.floatX, [True, False, False]) mu.tag.test_value = np.zeros((1, 2, 3)).astype(config.floatX) sd = tt.tensor(config.floatX, [False, False]) sd.tag.test_value = np.ones((2, 3)).astype(config.floatX) s1 = tt.iscalar() s1.tag.test_value = 1 s2 = tt.iscalar() s2.tag.test_value = 2 s3 = tt.iscalar() s3.tag.test_value = 3 s3 = Assert("testing")(s3, tt.eq(s1, 1)) res = rv.compute_bcast([mu, sd], (s1, s2, s3)) assert res == [False] * 3
def broadcast_shape_iter(arrays, **kwargs): """Compute the shape resulting from broadcasting arrays. Parameters ---------- arrays: Iterable[TensorVariable] or Iterable[Tuple[Variable]] An iterable of tensors, or a tuple of shapes (as tuples), for which the broadcast shape is computed. XXX: Do not call this with a generator/iterator; this function will not make copies! arrays_are_shapes: bool (Optional) Indicates whether or not the `arrays` contains shape tuples. If you use this approach, make sure that the broadcastable dimensions are (scalar) constants with the value `1` or `1` exactly. """ one = theano.scalar.ScalarConstant(theano.scalar.int64, 1) arrays_are_shapes = kwargs.pop("arrays_are_shapes", False) if arrays_are_shapes: max_dims = max(len(a) for a in arrays) array_shapes = [(one, ) * (max_dims - len(a)) + tuple(one if getattr(sh, "value", sh) == 1 else sh for sh in a) for a in arrays] else: max_dims = max(a.ndim for a in arrays) array_shapes = [(one, ) * (max_dims - a.ndim) + tuple(one if bcast else sh for sh, bcast in zip(a.shape, a.broadcastable)) for a in arrays] result_dims = [] for dim_shapes in zip(*array_shapes): non_bcast_shapes = [shape for shape in dim_shapes if shape != one] if len(non_bcast_shapes) > 0: # Either there's only one non-broadcastable dimensions--and that's # what determines the dimension size, or there are multiple # non-broadcastable dimensions that must be equal i_dim = non_bcast_shapes.pop() potentially_unequal_dims = [ dim for dim in non_bcast_shapes # TODO FIXME: This is a largely deficient means of comparing graphs # (and especially shapes) if not theano.gof.graph.equal_computations([i_dim], [dim]) ] if potentially_unequal_dims: from theano.tensor.opt import Assert # In this case, we can't tell whether or not the dimensions are # equal, so we'll need to assert their equality and move the error # handling to evaluation time. assert_dim = Assert("Could not broadcast dimensions") eq_condition = basic.all([ basic.or_(basic.eq(dim, one), basic.eq(i_dim, dim)) for dim in potentially_unequal_dims ]) eq_condition = basic.or_(basic.eq(i_dim, one), eq_condition) result_dims.append(assert_dim(i_dim, eq_condition)) else: result_dims.append(i_dim) else: # Every array was broadcastable in this dimension result_dims.append(one) return tuple(result_dims)