提交 7aebdea8 authored 作者: Amjad Almahairi's avatar Amjad Almahairi

creating a theano graph replacing numpy bincount wrapper

上级 8965b09a
import numpy as np import numpy as np
import numpy import numpy
import warnings
import theano import theano
from theano.tensor import basic from theano.tensor import basic
...@@ -332,8 +332,11 @@ def diff(x, n=1, axis=-1): ...@@ -332,8 +332,11 @@ def diff(x, n=1, axis=-1):
class BinCountOp(theano.Op): class BinCountOp(theano.Op):
# See function bincount for docstring """
DEPRECATED: use bincount() instead.
See function bincount for docstring
"""
compatible_type = ('int8', 'int16', 'int32', 'int64', compatible_type = ('int8', 'int16', 'int32', 'int64',
'uint8', 'uint16', 'uint32', 'uint64') 'uint8', 'uint16', 'uint32', 'uint64')
"""Tuple of all compatible dtype for the parameter of this op.""" """Tuple of all compatible dtype for the parameter of this op."""
...@@ -355,6 +358,10 @@ class BinCountOp(theano.Op): ...@@ -355,6 +358,10 @@ class BinCountOp(theano.Op):
return hash(type(self)) ^ hash(self.minlength) return hash(type(self)) ^ hash(self.minlength)
def make_node(self, x, weights): def make_node(self, x, weights):
warnings.warn((
"Tile op is deprecated, use tile function instead."),
stacklevel=3)
x = basic.as_tensor_variable(x) x = basic.as_tensor_variable(x)
if x.dtype not in BinCountOp.compatible_type: if x.dtype not in BinCountOp.compatible_type:
...@@ -450,39 +457,48 @@ def bincount(x, weights=None, minlength=None): ...@@ -450,39 +457,48 @@ def bincount(x, weights=None, minlength=None):
.. versionadded:: 0.6 .. versionadded:: 0.6
""" """
return BinCountOp(minlength=minlength)(x, weights) compatible_type = ('int8', 'int16', 'int32', 'int64',
'uint8', 'uint16', 'uint32', 'uint64')
def newbincount(x, weights=None, minlength=None): if x.dtype not in compatible_type:
"""Count number of occurrences of each value in array of non-negative ints. raise TypeError("Inputs dtype must be an integer.")
The number of bins (of size 1) is one larger than the largest # Some dtypes are not supported by numpy's implementation of bincount.
value in x. If minlength is specified, there will be at least # Until another one is available, we should fail at graph construction
this number of bins in the output array (though it will be longer # time, not wait for execution.
if necessary, depending on the contents of x). Each bin gives the int_bitwidth = theano.gof.python_int_bitwidth()
number of occurrences of its index value in x. If weights is if int_bitwidth == 64:
specified the input array is weighted by it, i.e. if a value n numpy_unsupported_dtypes = ('uint64',)
is found at position i, out[n] += weight[i] instead of out[n] += 1. if int_bitwidth == 32:
Wraping of numpy.bincount numpy_unsupported_dtypes = ('uint32', 'int64', 'uint64')
:param x: 1 dimension, nonnegative ints intp_bitwidth = theano.gof.local_bitwidth()
if intp_bitwidth == 32:
:param weights: array of the same shape as x with corresponding weights. out_type = basic.ivector()
Optional. elif intp_bitwidth == 64:
:param minlength: A minimum number of bins for the output array. out_type = basic.lvector()
Optional.
if x.dtype in numpy_unsupported_dtypes:
.. versionadded:: 0.6 raise TypeError(
""" ("Input dtypes %s are not supported by numpy.bincount, "
# do checks ... % numpy_unsupported_dtypes), x.dtype)
if x.ndim != 1:
raise TypeError("Inputs must be of dimension 1.")
# general case...
max_value = x.max() + 1 max_value = x.max() + 1
out_dtype = x.dtype # out_dtype = x.dtype
out = theano.tensor.zeros(max_value, dtype=out_dtype) if minlength is not None:
out = theano.tensor.inc_subtensor(out[x], 1) max_value = theano.tensor.maximum(max_value, minlength)
if weights is None:
out = theano.tensor.zeros([max_value], dtype=out_type.dtype)
out = theano.tensor.inc_subtensor(out[x], 1)
else:
out_type = basic.dvector()
out = theano.tensor.zeros([max_value], dtype=out_type.dtype)
out = theano.tensor.inc_subtensor(out[x], weights)
return out return out
......
...@@ -161,12 +161,12 @@ class TestBinCountOp(utt.InferShapeTester): ...@@ -161,12 +161,12 @@ class TestBinCountOp(utt.InferShapeTester):
x = T.vector('x', dtype=dtype) x = T.vector('x', dtype=dtype)
if dtype in numpy_unsupported_dtypes: if dtype in numpy_unsupported_dtypes:
self.assertRaises(TypeError, bincount, x) self.assertRaises(TypeError, BinCountOp(), x)
else: else:
self._compile_and_check( self._compile_and_check(
[x], [x],
[bincount(x)], [BinCountOp()(x,None)],
[np.random.random_integers( [np.random.random_integers(
50, size=(25,)).astype(dtype)], 50, size=(25,)).astype(dtype)],
self.op_class) self.op_class)
...@@ -174,7 +174,7 @@ class TestBinCountOp(utt.InferShapeTester): ...@@ -174,7 +174,7 @@ class TestBinCountOp(utt.InferShapeTester):
weights = np.random.random((25,)).astype(config.floatX) weights = np.random.random((25,)).astype(config.floatX)
self._compile_and_check( self._compile_and_check(
[x], [x],
[bincount(x, weights=weights)], [BinCountOp()(x, weights=weights)],
[np.random.random_integers( [np.random.random_integers(
50, size=(25,)).astype(dtype)], 50, size=(25,)).astype(dtype)],
self.op_class) self.op_class)
...@@ -183,14 +183,14 @@ class TestBinCountOp(utt.InferShapeTester): ...@@ -183,14 +183,14 @@ class TestBinCountOp(utt.InferShapeTester):
continue continue
self._compile_and_check( self._compile_and_check(
[x], [x],
[bincount(x, minlength=60)], [BinCountOp(minlength=60)(x, weights=weights)],
[np.random.random_integers( [np.random.random_integers(
50, size=(25,)).astype(dtype)], 50, size=(25,)).astype(dtype)],
self.op_class) self.op_class)
self._compile_and_check( self._compile_and_check(
[x], [x],
[bincount(x, minlength=5)], [BinCountOp(minlength=5)(x, weights=weights)],
[np.random.random_integers( [np.random.random_integers(
50, size=(25,)).astype(dtype)], 50, size=(25,)).astype(dtype)],
self.op_class) self.op_class)
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论