提交 2ac39b3e authored 作者: Pascal Lamblin's avatar Pascal Lamblin

Move Sparse random Ops back to sandbox, see gh-993.

上级 ef44c58e
......@@ -2316,158 +2316,6 @@ class Remove0(gof.Op):
remove0 = Remove0()
# Probability
class Poisson(gof.op.Op):
"""Return a sparse having random values from a Poisson density
with mean from the input.
:param x: Sparse matrix.
:return: A sparse matrix of random integers of a Poisson density
with mean of `x` element wise.
"""
def __eq__(self, other):
return (type(self) == type(other))
def __hash__(self):
return hash(type(self))
def make_node(self, x):
x = as_sparse_variable(x)
return gof.Apply(self, [x], [x.type()])
def perform(self, node, (x, ), (out, )):
assert _is_sparse(x)
out[0] = x.copy()
out[0].data = numpy.asarray(numpy.random.poisson(out[0].data),
dtype=x.dtype)
out[0].eliminate_zeros()
def grad(self, inputs, outputs_gradients):
return [None]
def infer_shape(self, node, ins_shapes):
return ins_shapes
def __str__(self):
return self.__class__.__name__
poisson = Poisson()
class Binomial(gof.op.Op):
"""Return a sparse matrix having random values from a binomial
density having number of experiment `n` and probability of succes
`p`.
:param n: Tensor scalar representing the number of experiment.
:param p: Tensor scalar representing the probability of success.
:param shape: Tensor vector for the output shape.
:return: A sparse matrix of integers representing the number
of success.
"""
def __init__(self, format, dtype):
self.format = format
self.dtype = dtype
def __eq__(self, other):
return ((type(self) == type(other)) and
self.format == other.format and
self.dtype == other.dtype)
def __hash__(self):
return hash(type(self)) ^ hash(self.format) ^ hash(self.dtype)
def make_node(self, n, p, shape):
n = tensor.as_tensor_variable(n)
p = tensor.as_tensor_variable(p)
shape = tensor.as_tensor_variable(shape)
return gof.Apply(self, [n, p, shape], [SparseType(dtype=self.dtype,
format=self.format).make_variable()])
def perform(self, node, (n, p, shape, ), (out, )):
binomial = numpy.random.binomial(n, p, size=shape)
csx_matrix = getattr(scipy.sparse, self.format + '_matrix')
out[0] = csx_matrix(binomial, dtype=self.dtype)
def grad(self, (n, p, shape, ), (gz,)):
return None, None, None
def infer_shape(self, node, ins_shapes):
return [(node.inputs[2][0], node.inputs[2][1])]
def __str__(self):
return self.__class__.__name__
csr_fbinomial = Binomial('csr', 'float32')
csc_fbinomial = Binomial('csc', 'float32')
csr_dbinomial = Binomial('csr', 'float64')
csc_dbinomial = Binomial('csc', 'float64')
class Multinomial(gof.op.Op):
"""Return a sparse matrix having random values from a multinomial
density having number of experiment `n` and probability of succes
`p`.
:param n: Tensor type vector or scalar representing the number of
experiment for each row. If `n` is a scalar, it will be
used for each row.
:param p: Sparse matrix of probability where each row is a probability
vector representing the probability of succes. N.B. Each row
must sum to one.
:return: A sparse matrix of random integers from a multinomial density
for each row.
:note: It will works only if `p` have csr format.
"""
def __eq__(self, other):
return (type(self) == type(other))
def __hash__(self):
return hash(type(self))
def make_node(self, n, p):
n = tensor.as_tensor_variable(n)
p = as_sparse_variable(p)
return gof.Apply(self, [n, p], [p.type()])
def perform(self, node, (n, p), (out, )):
assert _is_sparse(p)
if p.format != 'csr':
raise NotImplemented()
out[0] = p.copy()
if n.ndim == 0:
for i in xrange(p.shape[0]):
k, l = p.indptr[i], p.indptr[i + 1]
out[0].data[k:l] = numpy.random.multinomial(n, p.data[k:l])
elif n.ndim == 1:
if n.shape[0] != p.shape[0]:
raise ValueError('The number of element of n must be '
'the same as the number of row of p.')
for i in xrange(p.shape[0]):
k, l = p.indptr[i], p.indptr[i + 1]
out[0].data[k:l] = numpy.random.multinomial(n[i], p.data[k:l])
def grad(self, inputs, outputs_gradients):
return [None, None]
def infer_shape(self, node, ins_shapes):
return [ins_shapes[1]]
def __str__(self):
return self.__class__.__name__
multinomial = Multinomial()
# Structured monoid
def structured_monoid(tensor_op):
# Generic operation to perform many kinds of monoid element-wise
......
......@@ -18,14 +18,20 @@ from theano.sparse.basic import (
HStack, hstack, VStack, vstack,
AddSSData, add_s_s_data,
MulSV, mul_s_v,
Multinomial, multinomial, Poisson, poisson,
Binomial, csr_fbinomial, csc_fbinomial, csr_dbinomial, csc_dbinomial,
structured_monoid,
structured_sigmoid, structured_exp, structured_log, structured_pow,
structured_minimum, structured_maximum, structured_add,
StructuredAddSV, structured_add_s_v,
SamplingDot, sampling_dot)
# Probability Ops are currently back in sandbox, because they do not respect
# Theano's Op contract, as their behaviour is not reproducible: calling
# the perform() method twice with the same argument will yield different
# results.
#from theano.sparse.basic import (
# Multinomial, multinomial, Poisson, poisson,
# Binomial, csr_fbinomial, csc_fbinomial, csr_dbinomial, csc_dbinomial)
# Also for compatibility
from theano.sparse.opt import (
MulSDCSC, mul_s_d_csc, MulSDCSR, mul_s_d_csr,
......@@ -38,3 +44,167 @@ from theano.sparse.opt import (
# Alias to maintain compatibility
EliminateZeros = Remove0
eliminate_zeros = remove0
# Probability
class Poisson(gof.op.Op):
"""Return a sparse having random values from a Poisson density
with mean from the input.
WARNING: This Op is NOT deterministic, as calling it twice with the
same inputs will NOT give the same result. This is a violation of
Theano's contract for Ops
:param x: Sparse matrix.
:return: A sparse matrix of random integers of a Poisson density
with mean of `x` element wise.
"""
def __eq__(self, other):
return (type(self) == type(other))
def __hash__(self):
return hash(type(self))
def make_node(self, x):
x = as_sparse_variable(x)
return gof.Apply(self, [x], [x.type()])
def perform(self, node, (x, ), (out, )):
assert _is_sparse(x)
out[0] = x.copy()
out[0].data = numpy.asarray(numpy.random.poisson(out[0].data),
dtype=x.dtype)
out[0].eliminate_zeros()
def grad(self, inputs, outputs_gradients):
return [None]
def infer_shape(self, node, ins_shapes):
return ins_shapes
def __str__(self):
return self.__class__.__name__
poisson = Poisson()
class Binomial(gof.op.Op):
"""Return a sparse matrix having random values from a binomial
density having number of experiment `n` and probability of succes
`p`.
WARNING: This Op is NOT deterministic, as calling it twice with the
same inputs will NOT give the same result. This is a violation of
Theano's contract for Ops
:param n: Tensor scalar representing the number of experiment.
:param p: Tensor scalar representing the probability of success.
:param shape: Tensor vector for the output shape.
:return: A sparse matrix of integers representing the number
of success.
"""
def __init__(self, format, dtype):
self.format = format
self.dtype = dtype
def __eq__(self, other):
return ((type(self) == type(other)) and
self.format == other.format and
self.dtype == other.dtype)
def __hash__(self):
return hash(type(self)) ^ hash(self.format) ^ hash(self.dtype)
def make_node(self, n, p, shape):
n = tensor.as_tensor_variable(n)
p = tensor.as_tensor_variable(p)
shape = tensor.as_tensor_variable(shape)
return gof.Apply(self, [n, p, shape], [SparseType(dtype=self.dtype,
format=self.format).make_variable()])
def perform(self, node, (n, p, shape, ), (out, )):
binomial = numpy.random.binomial(n, p, size=shape)
csx_matrix = getattr(scipy.sparse, self.format + '_matrix')
out[0] = csx_matrix(binomial, dtype=self.dtype)
def grad(self, (n, p, shape, ), (gz,)):
return None, None, None
def infer_shape(self, node, ins_shapes):
return [(node.inputs[2][0], node.inputs[2][1])]
def __str__(self):
return self.__class__.__name__
csr_fbinomial = Binomial('csr', 'float32')
csc_fbinomial = Binomial('csc', 'float32')
csr_dbinomial = Binomial('csr', 'float64')
csc_dbinomial = Binomial('csc', 'float64')
class Multinomial(gof.op.Op):
"""Return a sparse matrix having random values from a multinomial
density having number of experiment `n` and probability of succes
`p`.
WARNING: This Op is NOT deterministic, as calling it twice with the
same inputs will NOT give the same result. This is a violation of
Theano's contract for Ops
:param n: Tensor type vector or scalar representing the number of
experiment for each row. If `n` is a scalar, it will be
used for each row.
:param p: Sparse matrix of probability where each row is a probability
vector representing the probability of succes. N.B. Each row
must sum to one.
:return: A sparse matrix of random integers from a multinomial density
for each row.
:note: It will works only if `p` have csr format.
"""
def __eq__(self, other):
return (type(self) == type(other))
def __hash__(self):
return hash(type(self))
def make_node(self, n, p):
n = tensor.as_tensor_variable(n)
p = as_sparse_variable(p)
return gof.Apply(self, [n, p], [p.type()])
def perform(self, node, (n, p), (out, )):
assert _is_sparse(p)
if p.format != 'csr':
raise NotImplemented()
out[0] = p.copy()
if n.ndim == 0:
for i in xrange(p.shape[0]):
k, l = p.indptr[i], p.indptr[i + 1]
out[0].data[k:l] = numpy.random.multinomial(n, p.data[k:l])
elif n.ndim == 1:
if n.shape[0] != p.shape[0]:
raise ValueError('The number of element of n must be '
'the same as the number of row of p.')
for i in xrange(p.shape[0]):
k, l = p.indptr[i], p.indptr[i + 1]
out[0].data[k:l] = numpy.random.multinomial(n[i], p.data[k:l])
def grad(self, inputs, outputs_gradients):
return [None, None]
def infer_shape(self, node, ins_shapes):
return [ins_shapes[1]]
def __str__(self):
return self.__class__.__name__
multinomial = Multinomial()
......@@ -34,7 +34,6 @@ from theano.sparse import (
Dot, Usmm, sp_ones_like, GetItemScalar,
SparseFromDense,
Cast, cast, HStack, VStack, AddSSData, add_s_s_data,
Poisson, poisson, Binomial, Multinomial, multinomial,
structured_sigmoid, structured_exp, structured_log,
structured_pow, structured_minimum, structured_maximum, structured_add,
MulSV, mul_s_v, StructuredAddSV, structured_add_s_v,
......@@ -42,6 +41,10 @@ from theano.sparse import (
Diag, diag, SquareDiagonal, square_diagonal,
EnsureSortedIndices, ensure_sorted_indices, clean)
# Probability distributions are currently tested in test_sp2.py
#from theano.sparse import (
# Poisson, poisson, Binomial, Multinomial, multinomial)
from theano.sparse.opt import (StructuredDotCSC, UsmmCscDense, CSMGradC)
from theano.tests import unittest_tools as utt
......@@ -2141,122 +2144,6 @@ class AddSSDataTester(utt.InferShapeTester):
structured=True)
class PoissonTester(utt.InferShapeTester):
x = {}
a = {}
for format in sparse.sparse_formats:
variable = getattr(theano.sparse, format + '_matrix')
rand = numpy.array(numpy.random.random_integers(3, size=(3, 4)) - 1,
dtype=theano.config.floatX)
x[format] = variable()
a[format] = as_sparse_format(rand, format)
def setUp(self):
super(PoissonTester, self).setUp()
self.op_class = Poisson
def test_op(self):
for format in sparse.sparse_formats:
f = theano.function(
[self.x[format]],
poisson(self.x[format]))
tested = f(self.a[format])
assert tested.format == format
assert tested.dtype == self.a[format].dtype
assert numpy.allclose(numpy.floor(tested.data), tested.data)
assert tested.shape == self.a[format].shape
def test_infer_shape(self):
for format in sparse.sparse_formats:
self._compile_and_check([self.x[format]],
[poisson(self.x[format])],
[self.a[format]],
self.op_class)
class BinomialTester(utt.InferShapeTester):
n = tensor.scalar()
p = tensor.scalar()
shape = tensor.lvector()
_n = 5
_p = .25
_shape = numpy.asarray([3, 5], dtype='int64')
inputs = [n, p, shape]
_inputs = [_n, _p, _shape]
def setUp(self):
super(BinomialTester, self).setUp()
self.op_class = Binomial
def test_op(self):
for sp_format in sparse.sparse_formats:
for o_type in sparse.float_dtypes:
f = theano.function(
self.inputs,
Binomial(sp_format, o_type)(*self.inputs))
tested = f(*self._inputs)
assert tested.shape == tuple(self._shape)
assert tested.format == sp_format
assert tested.dtype == o_type
assert numpy.allclose(numpy.floor(tested.todense()),
tested.todense())
def test_infer_shape(self):
for sp_format in sparse.sparse_formats:
for o_type in sparse.float_dtypes:
self._compile_and_check(
self.inputs,
[Binomial(sp_format, o_type)(*self.inputs)],
self._inputs,
self.op_class)
class MultinomialTester(utt.InferShapeTester):
p = sparse.csr_matrix()
_p = sp.csr_matrix(numpy.asarray([[0.0, 0.5, 0.0, 0.5],
[0.1, 0.2, 0.3, 0.4],
[0.0, 1.0, 0.0, 0.0],
[0.3, 0.3, 0.0, 0.4]],
dtype=config.floatX))
def setUp(self):
super(MultinomialTester, self).setUp()
self.op_class = Multinomial
def test_op(self):
n = tensor.lscalar()
f = theano.function([self.p, n], multinomial(n, self.p))
_n = 5
tested = f(self._p, _n)
assert tested.shape == self._p.shape
assert numpy.allclose(numpy.floor(tested.todense()), tested.todense())
assert tested[2, 1] == _n
n = tensor.lvector()
f = theano.function([self.p, n], multinomial(n, self.p))
_n = numpy.asarray([1, 2, 3, 4], dtype='int64')
tested = f(self._p, _n)
assert tested.shape == self._p.shape
assert numpy.allclose(numpy.floor(tested.todense()), tested.todense())
assert tested[2, 1] == _n[2]
def test_infer_shape(self):
self._compile_and_check([self.p],
[multinomial(5, self.p)],
[self._p],
self.op_class)
def elemwise_checker(op, expected_f, gap=None, test_dtypes=None,
grad_test=True, name=None):
"""Return the appropriate test class for the elemwise on sparse.
......
......@@ -2,7 +2,7 @@ import time
import unittest
from nose.plugins.skip import SkipTest
import numpy as np
import numpy
try:
import scipy.sparse as sp
import scipy.sparse
......@@ -10,16 +10,134 @@ except ImportError:
pass # The variable enable_sparse will be used to disable the test file.
import theano
from theano import config
from theano import tensor
from theano import sparse
if not theano.sparse.enable_sparse:
raise SkipTest('Optional package sparse disabled')
from theano.sparse.sandbox import sp2 as S2
from theano.sparse.sandbox.sp2 import (
Poisson, poisson, Binomial, Multinomial, multinomial)
from theano.tests import unittest_tools as utt
from theano.sparse.basic import verify_grad_sparse
from theano.sparse.tests.test_basic import as_sparse_format
class PoissonTester(utt.InferShapeTester):
x = {}
a = {}
for format in sparse.sparse_formats:
variable = getattr(theano.sparse, format + '_matrix')
rand = numpy.array(numpy.random.random_integers(3, size=(3, 4)) - 1,
dtype=theano.config.floatX)
x[format] = variable()
a[format] = as_sparse_format(rand, format)
def setUp(self):
super(PoissonTester, self).setUp()
self.op_class = Poisson
def test_op(self):
for format in sparse.sparse_formats:
f = theano.function(
[self.x[format]],
poisson(self.x[format]))
tested = f(self.a[format])
assert tested.format == format
assert tested.dtype == self.a[format].dtype
assert numpy.allclose(numpy.floor(tested.data), tested.data)
assert tested.shape == self.a[format].shape
def test_infer_shape(self):
for format in sparse.sparse_formats:
self._compile_and_check([self.x[format]],
[poisson(self.x[format])],
[self.a[format]],
self.op_class)
class BinomialTester(utt.InferShapeTester):
n = tensor.scalar()
p = tensor.scalar()
shape = tensor.lvector()
_n = 5
_p = .25
_shape = numpy.asarray([3, 5], dtype='int64')
inputs = [n, p, shape]
_inputs = [_n, _p, _shape]
def setUp(self):
super(BinomialTester, self).setUp()
self.op_class = Binomial
def test_op(self):
for sp_format in sparse.sparse_formats:
for o_type in sparse.float_dtypes:
f = theano.function(
self.inputs,
Binomial(sp_format, o_type)(*self.inputs))
tested = f(*self._inputs)
assert tested.shape == tuple(self._shape)
assert tested.format == sp_format
assert tested.dtype == o_type
assert numpy.allclose(numpy.floor(tested.todense()),
tested.todense())
def test_infer_shape(self):
for sp_format in sparse.sparse_formats:
for o_type in sparse.float_dtypes:
self._compile_and_check(
self.inputs,
[Binomial(sp_format, o_type)(*self.inputs)],
self._inputs,
self.op_class)
class MultinomialTester(utt.InferShapeTester):
p = sparse.csr_matrix()
_p = sp.csr_matrix(numpy.asarray([[0.0, 0.5, 0.0, 0.5],
[0.1, 0.2, 0.3, 0.4],
[0.0, 1.0, 0.0, 0.0],
[0.3, 0.3, 0.0, 0.4]],
dtype=config.floatX))
def setUp(self):
super(MultinomialTester, self).setUp()
self.op_class = Multinomial
def test_op(self):
n = tensor.lscalar()
f = theano.function([self.p, n], multinomial(n, self.p))
_n = 5
tested = f(self._p, _n)
assert tested.shape == self._p.shape
assert numpy.allclose(numpy.floor(tested.todense()), tested.todense())
assert tested[2, 1] == _n
n = tensor.lvector()
f = theano.function([self.p, n], multinomial(n, self.p))
_n = numpy.asarray([1, 2, 3, 4], dtype='int64')
tested = f(self._p, _n)
assert tested.shape == self._p.shape
assert numpy.allclose(numpy.floor(tested.todense()), tested.todense())
assert tested[2, 1] == _n[2]
def test_infer_shape(self):
self._compile_and_check([self.p],
[multinomial(5, self.p)],
[self._p],
self.op_class)
if __name__ == '__main__':
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论