提交 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
from aesara.tensor.extra_ops import (
bartlett,
bincount,
broadcast_shape,
broadcast_shape_iter,
broadcast_to,
cumprod,
cumsum,
diff,
fill_diagonal,
fill_diagonal_offset,
ravel_multi_index,
repeat,
squeeze,
unique,
unravel_index,
)
from aesara.tensor.io import *
......
......@@ -1295,6 +1295,21 @@ class Unique(Op):
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):
__props__ = ("order",)
......
......@@ -766,313 +766,70 @@ def test_to_one_hot():
class TestUnique(utt.InferShapeTester):
def setup_method(self):
super().setup_method()
self.op_class = Unique
self.ops = [
Unique(),
Unique(True),
Unique(False, True),
Unique(True, True),
Unique(False, False, True),
Unique(True, False, True),
Unique(False, True, True),
Unique(True, True, True),
self.op_params = [
(False, False, False),
(True, False, False),
(False, True, False),
(True, True, False),
(False, False, True),
(True, False, True),
(False, True, True),
(True, True, True),
]
def test_basic_vector(self):
# Basic test for a vector.
# Done by using the op and checking that it returns the right answer.
x = vector()
inp = np.asarray([2, 1, 3, 2], 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_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)
@pytest.mark.parametrize(
("x", "inp", "axis"),
[
(vector(), np.asarray([2, 1, 3, 2], dtype=config.floatX), None),
(matrix(), np.asarray([[2, 1], [3, 2], [2, 1]], dtype=config.floatX), None),
(vector(), np.asarray([2, 1, 3, 2], dtype=config.floatX), 0),
(matrix(), np.asarray([[2, 1], [3, 2], [2, 1]], dtype=config.floatX), 0),
(vector(), np.asarray([2, 1, 3, 2], dtype=config.floatX), -1),
(matrix(), np.asarray([[2, 1], [3, 2], [2, 1]], dtype=config.floatX), -1),
],
)
def test_basic_vector(self, x, inp, axis):
list_outs_expected = [
[np.unique(inp, **kwargs)]
if len(args) == 0
else np.unique(inp, *args, **kwargs)
for args, kwargs in self.ops_pars
np.unique(inp, axis=axis),
np.unique(inp, True, axis=axis),
np.unique(inp, False, True, axis=axis),
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):
f = aesara.function(inputs=[x], outputs=op(x, return_list=True))
for params, outs_expected in zip(self.op_params, list_outs_expected):
out = aet.unique(x, *params, axis=axis)
f = aesara.function(inputs=[x], outputs=out)
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):
if not self.expect_success:
raise pytest.skip("Requires numpy >= 1.13")
# Testing the infer_shape with a vector.
x = vector()
ops = [self.op_class(*args, **kwargs) for args, kwargs in self.ops_pars]
for op in 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):
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:
@pytest.mark.parametrize(
("x", "inp", "axis"),
[
(vector(), np.asarray([2, 1, 3, 2], dtype=config.floatX), None),
(matrix(), np.asarray([[2, 1], [3, 2], [2, 1]], dtype=config.floatX), None),
(vector(), np.asarray([2, 1, 3, 2], dtype=config.floatX), 0),
(matrix(), np.asarray([[2, 1], [3, 2], [2, 1]], dtype=config.floatX), 0),
(vector(), np.asarray([2, 1, 3, 2], dtype=config.floatX), -1),
(matrix(), np.asarray([[2, 1], [3, 2], [2, 1]], dtype=config.floatX), -1),
],
)
def test_infer_shape(self, x, inp, axis):
for params in self.op_params:
if not params[1]:
continue
if op.return_index:
f = op(x)[2]
if params[0]:
f = aet.unique(x, *params, axis=axis)[2]
else:
f = op(x)[1]
f = aet.unique(x, *params, axis=axis)[1]
self._compile_and_check(
[x],
[f],
[np.asarray(np.array([[2, 1], [3, 2], [2, 1]]), dtype=config.floatX)],
self.op_class,
[inp],
Unique,
)
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论