提交 52bad109 authored 作者: Brandon T. Willard's avatar Brandon T. Willard 提交者: Brandon T. Willard

Add missing NumPy functions to aesara.tensor

上级 06c17926
...@@ -63,13 +63,18 @@ from aesara.tensor.blas import batched_dot, batched_tensordot ...@@ -63,13 +63,18 @@ from aesara.tensor.blas import batched_dot, batched_tensordot
from aesara.tensor.extra_ops import ( from aesara.tensor.extra_ops import (
bartlett, bartlett,
bincount, bincount,
broadcast_shape,
broadcast_shape_iter,
broadcast_to,
cumprod, cumprod,
cumsum, cumsum,
diff,
fill_diagonal, fill_diagonal,
fill_diagonal_offset, fill_diagonal_offset,
ravel_multi_index, ravel_multi_index,
repeat, repeat,
squeeze, squeeze,
unique,
unravel_index, unravel_index,
) )
from aesara.tensor.io import * from aesara.tensor.io import *
......
...@@ -1295,6 +1295,21 @@ class Unique(Op): ...@@ -1295,6 +1295,21 @@ class Unique(Op):
self.axis = None self.axis = None
def unique(
ar, return_index=False, return_inverse=False, return_counts=False, axis=None
):
"""Find the unique elements of an array.
Returns the sorted unique elements of an array. There are three optional
outputs in addition to the unique elements:
* the indices of the input array that give the unique values
* the indices of the unique array that reconstruct the input array
* the number of times each unique value comes up in the input array
"""
return Unique(return_index, return_inverse, return_counts, axis)(ar)
class UnravelIndex(Op): class UnravelIndex(Op):
__props__ = ("order",) __props__ = ("order",)
......
...@@ -766,313 +766,70 @@ def test_to_one_hot(): ...@@ -766,313 +766,70 @@ def test_to_one_hot():
class TestUnique(utt.InferShapeTester): class TestUnique(utt.InferShapeTester):
def setup_method(self): def setup_method(self):
super().setup_method() super().setup_method()
self.op_class = Unique self.op_params = [
self.ops = [ (False, False, False),
Unique(), (True, False, False),
Unique(True), (False, True, False),
Unique(False, True), (True, True, False),
Unique(True, True), (False, False, True),
Unique(False, False, True), (True, False, True),
Unique(True, False, True), (False, True, True),
Unique(False, True, True), (True, True, True),
Unique(True, True, True),
] ]
def test_basic_vector(self): @pytest.mark.parametrize(
# Basic test for a vector. ("x", "inp", "axis"),
# Done by using the op and checking that it returns the right answer. [
(vector(), np.asarray([2, 1, 3, 2], dtype=config.floatX), None),
x = vector() (matrix(), np.asarray([[2, 1], [3, 2], [2, 1]], dtype=config.floatX), None),
inp = np.asarray([2, 1, 3, 2], dtype=config.floatX) (vector(), np.asarray([2, 1, 3, 2], dtype=config.floatX), 0),
list_outs_expected = [ (matrix(), np.asarray([[2, 1], [3, 2], [2, 1]], dtype=config.floatX), 0),
[np.unique(inp)], (vector(), np.asarray([2, 1, 3, 2], dtype=config.floatX), -1),
np.unique(inp, True), (matrix(), np.asarray([[2, 1], [3, 2], [2, 1]], dtype=config.floatX), -1),
np.unique(inp, False, True), ],
np.unique(inp, True, True), )
np.unique(inp, False, False, True), def test_basic_vector(self, x, inp, axis):
np.unique(inp, True, False, True),
np.unique(inp, False, True, True),
np.unique(inp, True, True, True),
]
for op, outs_expected in zip(self.ops, list_outs_expected):
f = aesara.function(inputs=[x], outputs=op(x, return_list=True))
outs = f(inp)
# Compare the result computed to the expected value.
for out, out_exp in zip(outs, outs_expected):
utt.assert_allclose(out, out_exp)
def test_basic_matrix(self):
# Basic test for a matrix.
# Done by using the op and checking that it returns the right answer.
x = matrix()
inp = np.asarray([[2, 1], [3, 2], [2, 1]], dtype=config.floatX)
list_outs_expected = [
[np.unique(inp)],
np.unique(inp, True),
np.unique(inp, False, True),
np.unique(inp, True, True),
np.unique(inp, False, False, True),
np.unique(inp, True, False, True),
np.unique(inp, False, True, True),
np.unique(inp, True, True, True),
]
for op, outs_expected in zip(self.ops, list_outs_expected):
f = aesara.function(inputs=[x], outputs=op(x, return_list=True))
outs = f(inp)
# Compare the result computed to the expected value.
for out, out_exp in zip(outs, outs_expected):
utt.assert_allclose(out, out_exp)
def test_infer_shape_vector(self):
# Testing the infer_shape with a vector.
x = vector()
for op in self.ops:
if not op.return_inverse:
continue
if op.return_index:
f = op(x)[2]
else:
f = op(x)[1]
self._compile_and_check(
[x],
[f],
[np.asarray(np.array([2, 1, 3, 2]), dtype=config.floatX)],
self.op_class,
)
def test_infer_shape_matrix(self):
# Testing the infer_shape with a matrix.
x = matrix()
for op in self.ops:
if not op.return_inverse:
continue
if op.return_index:
f = op(x)[2]
else:
f = op(x)[1]
self._compile_and_check(
[x],
[f],
[np.asarray(np.array([[2, 1], [3, 2], [2, 3]]), dtype=config.floatX)],
self.op_class,
)
class TestUniqueAxis(utt.InferShapeTester):
def setup_method(self):
super().setup_method()
numpy_ver = tuple([int(n) for n in np.__version__.split(".")])
if numpy_ver >= (1, 13):
self.expect_success = True
else:
self.expect_success = False
self.ops_pars = [
(tuple(), {"axis": 0}),
((True,), {"axis": 0}),
(
(
False,
True,
),
{"axis": 0},
),
(
(
True,
True,
),
{"axis": 0},
),
(
(
False,
False,
True,
),
{"axis": 0},
),
(
(
True,
False,
True,
),
{"axis": 0},
),
(
(
False,
True,
True,
),
{"axis": 0},
),
(
(
True,
True,
True,
),
{"axis": 0},
),
(tuple(), {"axis": -1}),
((True,), {"axis": -1}),
(
(
False,
True,
),
{"axis": -1},
),
(
(
True,
True,
),
{"axis": -1},
),
(
(
False,
False,
True,
),
{"axis": -1},
),
(
(
True,
False,
True,
),
{"axis": -1},
),
(
(
False,
True,
True,
),
{"axis": -1},
),
(
(
True,
True,
True,
),
{"axis": -1},
),
]
self.op_class = Unique
def test_op(self):
if self.expect_success:
for args, kwargs in self.ops_pars:
op = self.op_class(*args, **kwargs)
assert isinstance(op, self.op_class)
else:
for args, kwargs in self.ops_pars:
def func():
return self.op_class(*args, **kwargs)
with pytest.raises(RuntimeError):
func()
def test_basic_vector(self):
if not self.expect_success:
raise pytest.skip("Requires numpy >= 1.13")
# Basic test for a vector.
# Done by using the op and checking that it returns the right
# answer.
x = vector()
ops = [self.op_class(*args, **kwargs) for args, kwargs in self.ops_pars]
inp = np.asarray([2, 1, 3, 2], dtype=config.floatX)
list_outs_expected = [
[np.unique(inp, **kwargs)]
if len(args) == 0
else np.unique(inp, *args, **kwargs)
for args, kwargs in self.ops_pars
]
for op, outs_expected in zip(ops, list_outs_expected):
f = aesara.function(inputs=[x], outputs=op(x, return_list=True))
outs = f(inp)
# Compare the result computed to the expected value.
for out, out_exp in zip(outs, outs_expected):
utt.assert_allclose(out, out_exp)
def test_basic_matrix(self):
if not self.expect_success:
raise pytest.skip("Requires numpy >= 1.13")
# Basic test for a matrix.
# Done by using the op and checking that it returns the right
# answer.
x = matrix()
ops = [self.op_class(*args, **kwargs) for args, kwargs in self.ops_pars]
inp = np.asarray([[2, 1], [3, 2], [2, 1]], dtype=config.floatX)
list_outs_expected = [ list_outs_expected = [
[np.unique(inp, **kwargs)] np.unique(inp, axis=axis),
if len(args) == 0 np.unique(inp, True, axis=axis),
else np.unique(inp, *args, **kwargs) np.unique(inp, False, True, axis=axis),
for args, kwargs in self.ops_pars np.unique(inp, True, True, axis=axis),
np.unique(inp, False, False, True, axis=axis),
np.unique(inp, True, False, True, axis=axis),
np.unique(inp, False, True, True, axis=axis),
np.unique(inp, True, True, True, axis=axis),
] ]
for op, outs_expected in zip(ops, list_outs_expected): for params, outs_expected in zip(self.op_params, list_outs_expected):
f = aesara.function(inputs=[x], outputs=op(x, return_list=True)) out = aet.unique(x, *params, axis=axis)
f = aesara.function(inputs=[x], outputs=out)
outs = f(inp) outs = f(inp)
# Compare the result computed to the expected value.
for out, out_exp in zip(outs, outs_expected): for out, out_exp in zip(outs, outs_expected):
utt.assert_allclose(out, out_exp) utt.assert_allclose(out, out_exp)
def test_infer_shape_vector(self): @pytest.mark.parametrize(
if not self.expect_success: ("x", "inp", "axis"),
raise pytest.skip("Requires numpy >= 1.13") [
# Testing the infer_shape with a vector. (vector(), np.asarray([2, 1, 3, 2], dtype=config.floatX), None),
(matrix(), np.asarray([[2, 1], [3, 2], [2, 1]], dtype=config.floatX), None),
x = vector() (vector(), np.asarray([2, 1, 3, 2], dtype=config.floatX), 0),
(matrix(), np.asarray([[2, 1], [3, 2], [2, 1]], dtype=config.floatX), 0),
ops = [self.op_class(*args, **kwargs) for args, kwargs in self.ops_pars] (vector(), np.asarray([2, 1, 3, 2], dtype=config.floatX), -1),
for op in ops: (matrix(), np.asarray([[2, 1], [3, 2], [2, 1]], dtype=config.floatX), -1),
if not op.return_inverse: ],
continue )
if op.return_index: def test_infer_shape(self, x, inp, axis):
f = op(x)[2] for params in self.op_params:
else: if not params[1]:
f = op(x)[1]
self._compile_and_check(
[x],
[f],
[np.asarray(np.array([2, 1, 3, 2]), dtype=config.floatX)],
self.op_class,
)
def test_infer_shape_matrix(self):
if not self.expect_success:
raise pytest.skip("Requires numpy >= 1.13")
# Testing the infer_shape with a matrix.
x = matrix()
ops = [self.op_class(*args, **kwargs) for args, kwargs in self.ops_pars]
for op in ops:
if not op.return_inverse:
continue continue
if op.return_index: if params[0]:
f = op(x)[2] f = aet.unique(x, *params, axis=axis)[2]
else: else:
f = op(x)[1] f = aet.unique(x, *params, axis=axis)[1]
self._compile_and_check( self._compile_and_check(
[x], [x],
[f], [f],
[np.asarray(np.array([[2, 1], [3, 2], [2, 1]]), dtype=config.floatX)], [inp],
self.op_class, Unique,
) )
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论