提交 6a0852fd authored 作者: Olivier Breuleux's avatar Olivier Breuleux

ported dot, gemm

上级 2fd6ea22
......@@ -52,7 +52,7 @@ def make_tester(name, op, expected, checks = {}, good = {}, bad_build = {}, bad_
raise type, value, traceback
try:
f = Function(node.inputs, node.outputs,
f = Function(inputrs, node.outputs,
linker_cls = lambda env: gof.DualLinker(env, checker = _numpy_checker),
unpack_single = False,
optimizer = None)
......@@ -111,7 +111,7 @@ def make_tester(name, op, expected, checks = {}, good = {}, bad_build = {}, bad_
raise type, value, traceback
try:
f = Function(node.inputs, node.outputs,
f = Function(inputrs, node.outputs,
linker_cls = lambda env: gof.DualLinker(env, checker = _numpy_checker),
unpack_single = False,
optimizer = None)
......@@ -175,6 +175,7 @@ def make_broadcast_tester(op, expected, checks = {}, **kwargs):
_good_broadcast_binary_normal = dict(same_shapes = (rand(2, 3), rand(2, 3)),
not_same_dimensions = (rand(2, 2), rand(2)),
scalar = (rand(2, 3), rand(1, 1)),
row = (rand(2, 3), rand(1, 3)),
column = (rand(2, 3), rand(2, 1)),
......@@ -182,7 +183,7 @@ _good_broadcast_binary_normal = dict(same_shapes = (rand(2, 3), rand(2, 3)),
dtype_mixup_1 = (rand(2, 3), randint(2, 3)),
dtype_mixup_2 = (randint(2, 3), rand(2, 3)))
_bad_build_broadcast_binary_normal = dict(not_same_dimensions = (rand(2), rand(2, 2)))
_bad_build_broadcast_binary_normal = dict()#not_same_dimensions = (rand(2), rand(2, 2)))
_bad_runtime_broadcast_binary_normal = dict(bad_shapes = (rand(2, 3), rand(3, 2)),
bad_row = (rand(2, 3), rand(1, 2)))
......@@ -193,280 +194,280 @@ _grad_broadcast_binary_normal = dict(same_shapes = (rand(2, 3), rand(2, 3)),
column = (rand(2, 3), rand(2, 1)))
AddTester = make_broadcast_tester(op = add,
expected = lambda *inputs: reduce(lambda x, y: x + y, inputs),
good = dict(three_inputs_same_shapes = (rand(2, 3), rand(2, 3), rand(2, 3)),
four_inputs_broadcast = (rand(2, 3), rand(1, 3), rand(2, 1), rand(1, 1)),
**_good_broadcast_binary_normal),
bad_build = _bad_build_broadcast_binary_normal,
bad_runtime = _bad_runtime_broadcast_binary_normal)
AddInplaceTester = make_broadcast_tester(op = add_inplace,
expected = lambda x, y: x + y,
good = _good_broadcast_binary_normal,
bad_build = _bad_build_broadcast_binary_normal,
bad_runtime = _bad_runtime_broadcast_binary_normal,
inplace = True)
SubTester = make_broadcast_tester(op = sub,
expected = lambda x, y: x - y,
good = _good_broadcast_binary_normal,
bad_build = _bad_build_broadcast_binary_normal,
bad_runtime = _bad_runtime_broadcast_binary_normal,
grad = _grad_broadcast_binary_normal)
SubInplaceTester = make_broadcast_tester(op = sub_inplace,
expected = lambda x, y: x - y,
good = _good_broadcast_binary_normal,
bad_build = _bad_build_broadcast_binary_normal,
bad_runtime = _bad_runtime_broadcast_binary_normal,
grad = _grad_broadcast_binary_normal,
inplace = True)
MulTester = make_broadcast_tester(op = mul,
expected = lambda *inputs: reduce(lambda x, y: x * y, inputs),
good = dict(three_inputs_same_shapes = (rand(2, 3), rand(2, 3), rand(2, 3)),
four_inputs_broadcast = (rand(2, 3), rand(1, 3), rand(2, 1), rand(1, 1)),
**_good_broadcast_binary_normal),
bad_build = _bad_build_broadcast_binary_normal,
bad_runtime = _bad_runtime_broadcast_binary_normal,
grad = dict(three_inputs_same_shapes = (rand(2, 3), rand(2, 3), rand(2, 3)),
four_inputs_broadcast = (rand(2, 3), rand(1, 3), rand(2, 1), rand(1, 1)),
**_grad_broadcast_binary_normal))
MulInplaceTester = make_broadcast_tester(op = mul_inplace,
expected = lambda x, y: x * y,
good = _good_broadcast_binary_normal,
bad_build = _bad_build_broadcast_binary_normal,
bad_runtime = _bad_runtime_broadcast_binary_normal,
grad = _grad_broadcast_binary_normal,
inplace = True)
DivTester = make_broadcast_tester(op = div,
expected = lambda x, y: x / y,
good = dict(same_shapes = (rand(2, 3), rand(2, 3)),
scalar = (rand(2, 3), rand(1, 1)),
row = (rand(2, 3), rand(1, 3)),
column = (rand(2, 3), rand(2, 1)),
dtype_mixup_1 = (rand(2, 3), randint_nonzero(2, 3)),
dtype_mixup_2 = (randint_nonzero(2, 3), rand(2, 3)),
# integers_positive = (randint_ranged(4, 10, (2, 3)), randint_ranged(1, 6, (2, 3))),
# integers_known_to_fail = (numpy.array(-1), numpy.array(5))
),
# integers = (randint(2, 3), randint_nonzero(2, 3)),
# AddTester = make_broadcast_tester(op = add,
# expected = lambda *inputs: reduce(lambda x, y: x + y, inputs),
# good = dict(three_inputs_same_shapes = (rand(2, 3), rand(2, 3), rand(2, 3)),
# four_inputs_broadcast = (rand(2, 3), rand(1, 3), rand(2, 1), rand(1, 1)),
# **_good_broadcast_binary_normal),
# bad_build = _bad_build_broadcast_binary_normal,
# bad_runtime = _bad_runtime_broadcast_binary_normal)
# AddInplaceTester = make_broadcast_tester(op = add_inplace,
# expected = lambda x, y: x + y,
# good = _good_broadcast_binary_normal,
# bad_build = _bad_build_broadcast_binary_normal,
# bad_runtime = _bad_runtime_broadcast_binary_normal,
# inplace = True)
# SubTester = make_broadcast_tester(op = sub,
# expected = lambda x, y: x - y,
# good = _good_broadcast_binary_normal,
# bad_build = _bad_build_broadcast_binary_normal,
# bad_runtime = _bad_runtime_broadcast_binary_normal,
# grad = _grad_broadcast_binary_normal)
# SubInplaceTester = make_broadcast_tester(op = sub_inplace,
# expected = lambda x, y: x - y,
# good = _good_broadcast_binary_normal,
# bad_build = _bad_build_broadcast_binary_normal,
# bad_runtime = _bad_runtime_broadcast_binary_normal,
# grad = _grad_broadcast_binary_normal,
# inplace = True)
# MulTester = make_broadcast_tester(op = mul,
# expected = lambda *inputs: reduce(lambda x, y: x * y, inputs),
# good = dict(three_inputs_same_shapes = (rand(2, 3), rand(2, 3), rand(2, 3)),
# four_inputs_broadcast = (rand(2, 3), rand(1, 3), rand(2, 1), rand(1, 1)),
# **_good_broadcast_binary_normal),
# bad_build = _bad_build_broadcast_binary_normal,
# bad_runtime = _bad_runtime_broadcast_binary_normal,
# grad = dict(three_inputs_same_shapes = (rand(2, 3), rand(2, 3), rand(2, 3)),
# four_inputs_broadcast = (rand(2, 3), rand(1, 3), rand(2, 1), rand(1, 1)),
# **_grad_broadcast_binary_normal))
# MulInplaceTester = make_broadcast_tester(op = mul_inplace,
# expected = lambda x, y: x * y,
# good = _good_broadcast_binary_normal,
# bad_build = _bad_build_broadcast_binary_normal,
# bad_runtime = _bad_runtime_broadcast_binary_normal,
# grad = _grad_broadcast_binary_normal,
# inplace = True)
# DivTester = make_broadcast_tester(op = div,
# expected = lambda x, y: x / y,
# good = dict(same_shapes = (rand(2, 3), rand(2, 3)),
# scalar = (rand(2, 3), rand(1, 1)),
# row = (rand(2, 3), rand(1, 3)),
# column = (rand(2, 3), rand(2, 1)),
# dtype_mixup_1 = (rand(2, 3), randint_nonzero(2, 3)),
# dtype_mixup_2 = (randint_nonzero(2, 3), rand(2, 3))),
grad = dict(same_shapes = (rand(2, 3), rand(2, 3)),
scalar = (rand(2, 3), rand(1, 1)),
row = (rand(2, 3), rand(1, 3)),
column = (rand(2, 3), rand(2, 1))))
DivInplaceTester = make_broadcast_tester(op = div_inplace,
expected = lambda x, y: x / y,
good = dict(same_shapes = (rand(2, 3), rand(2, 3)),
scalar = (rand(2, 3), rand(1, 1)),
row = (rand(2, 3), rand(1, 3)),
column = (rand(2, 3), rand(2, 1)),
dtype_mixup_1 = (rand(2, 3), randint_nonzero(2, 3)),
dtype_mixup_2 = (randint_nonzero(2, 3), rand(2, 3))
),
grad = dict(same_shapes = (rand(2, 3), rand(2, 3)),
scalar = (rand(2, 3), rand(1, 1)),
row = (rand(2, 3), rand(1, 3)),
column = (rand(2, 3), rand(2, 1))),
inplace = True)
PowTester = make_broadcast_tester(op = pow,
expected = lambda x, y: x ** y,
good = dict(same_shapes = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (2, 3))),
scalar = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (1, 1))),
row = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (1, 3))),
column = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (2, 1))),
dtype_mixup = (rand_ranged(-3, 3, (2, 3)), randint_ranged(-3, 3, (2, 3)))),
grad = dict(same_shapes = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (2, 3))),
scalar = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (1, 1))),
row = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (1, 3))),
column = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (2, 1))))
)
PowInplaceTester = make_broadcast_tester(op = pow_inplace,
expected = lambda x, y: x ** y,
good = dict(same_shapes = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (2, 3))),
scalar = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (1, 1))),
row = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (1, 3))),
column = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (2, 1))),
dtype_mixup = (rand_ranged(-3, 3, (2, 3)), randint_ranged(-3, 3, (2, 3)))),
grad = dict(same_shapes = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (2, 3))),
scalar = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (1, 1))),
row = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (1, 3))),
column = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (2, 1)))),
inplace = True)
_good_broadcast_unary_normal = dict(normal = (rand_ranged(-5, 5, (2, 3)),),
integers = (randint_ranged(-5, 5, (2, 3)),))
_grad_broadcast_unary_normal = dict(normal = (rand_ranged(-5, 5, (2, 3)),))
AbsTester = make_broadcast_tester(op = tensor._abs,
expected = lambda x: abs(x),
good = _good_broadcast_unary_normal,
grad = _grad_broadcast_unary_normal)
AbsInplaceTester = make_broadcast_tester(op = abs_inplace,
expected = lambda x: abs(x),
good = _good_broadcast_unary_normal,
grad = _grad_broadcast_unary_normal,
inplace = True)
NegTester = make_broadcast_tester(op = neg,
expected = lambda x: -x,
good = _good_broadcast_unary_normal,
grad = _grad_broadcast_unary_normal)
NegInplaceTester = make_broadcast_tester(op = neg_inplace,
expected = lambda x: -x,
good = _good_broadcast_unary_normal,
grad = _grad_broadcast_unary_normal,
inplace = True)
SgnTester = make_broadcast_tester(op = sgn,
expected = numpy.sign,
good = _good_broadcast_unary_normal)
SgnInplaceTester = make_broadcast_tester(op = sgn_inplace,
expected = numpy.sign,
good = _good_broadcast_unary_normal,
inplace = True)
SqrTester = make_broadcast_tester(op = sqr,
expected = numpy.square,
good = _good_broadcast_unary_normal,
grad = _grad_broadcast_unary_normal)
SqrInplaceTester = make_broadcast_tester(op = sqr_inplace,
expected = numpy.square,
good = _good_broadcast_unary_normal,
grad = _grad_broadcast_unary_normal,
inplace = True)
ExpTester = make_broadcast_tester(op = exp,
expected = numpy.exp,
good = _good_broadcast_unary_normal,
grad = _grad_broadcast_unary_normal)
ExpInplaceTester = make_broadcast_tester(op = exp_inplace,
expected = numpy.exp,
good = _good_broadcast_unary_normal,
grad = _grad_broadcast_unary_normal,
inplace = True)
_good_broadcast_unary_positive = dict(normal = (rand_ranged(0.001, 5, (2, 3)),),
integers = (randint_ranged(1, 5, (2, 3)),))
_grad_broadcast_unary_positive = dict(normal = (rand_ranged(0.001, 5, (2, 3)),))
LogTester = make_broadcast_tester(op = log,
expected = numpy.log,
good = _good_broadcast_unary_positive,
grad = _grad_broadcast_unary_positive)
LogInplaceTester = make_broadcast_tester(op = log_inplace,
expected = numpy.log,
good = _good_broadcast_unary_positive,
grad = _grad_broadcast_unary_positive,
inplace = True)
Log2Tester = make_broadcast_tester(op = log2,
expected = numpy.log2,
good = _good_broadcast_unary_positive,
grad = _grad_broadcast_unary_positive)
Log2InplaceTester = make_broadcast_tester(op = log2_inplace,
expected = numpy.log2,
good = _good_broadcast_unary_positive,
grad = _grad_broadcast_unary_positive,
inplace = True)
SqrtTester = make_broadcast_tester(op = sqrt,
expected = numpy.sqrt,
good = _good_broadcast_unary_positive,
grad = _grad_broadcast_unary_positive)
SqrtInplaceTester = make_broadcast_tester(op = sqrt_inplace,
expected = numpy.sqrt,
good = _good_broadcast_unary_positive,
grad = _grad_broadcast_unary_positive,
inplace = True)
_good_broadcast_unary_wide = dict(normal = (rand_ranged(-1000, 1000, (2, 3)),),
integers = (randint_ranged(-1000, 1000, (2, 3)),))
_grad_broadcast_unary_wide = dict(normal = (rand_ranged(-1000, 1000, (2, 3)),))
SinTester = make_broadcast_tester(op = sin,
expected = numpy.sin,
good = _good_broadcast_unary_wide,
grad = _grad_broadcast_unary_wide)
SinInplaceTester = make_broadcast_tester(op = sin_inplace,
expected = numpy.sin,
good = _good_broadcast_unary_wide,
grad = _grad_broadcast_unary_wide,
inplace = True)
CosTester = make_broadcast_tester(op = cos,
expected = numpy.cos,
good = _good_broadcast_unary_wide,
grad = _grad_broadcast_unary_wide)
CosInplaceTester = make_broadcast_tester(op = cos_inplace,
expected = numpy.cos,
good = _good_broadcast_unary_wide,
grad = _grad_broadcast_unary_wide,
inplace = True)
TanTester = make_broadcast_tester(op = tan,
expected = numpy.tan,
good = dict(normal = (rand_ranged(-3.14, 3.14, (2, 3)),),
shifted = (rand_ranged(3.15, 6.28, (2, 3)),)),
grad = dict(normal = (rand_ranged(-3.14, 3.14, (2, 3)),),
shifted = (rand_ranged(3.15, 6.28, (2, 3)),)))
TanInplaceTester = make_broadcast_tester(op = tan_inplace,
expected = numpy.tan,
good = dict(normal = (rand_ranged(-3.14, 3.14, (2, 3)),),
shifted = (rand_ranged(3.15, 6.28, (2, 3)),)),
grad = dict(normal = (rand_ranged(-3.14, 3.14, (2, 3)),),
shifted = (rand_ranged(3.15, 6.28, (2, 3)),)),
inplace = True)
CoshTester = make_broadcast_tester(op = cosh,
expected = numpy.cosh,
good = _good_broadcast_unary_normal,
grad = _grad_broadcast_unary_normal)
CoshInplaceTester = make_broadcast_tester(op = cosh_inplace,
expected = numpy.cosh,
good = _good_broadcast_unary_normal,
grad = _grad_broadcast_unary_normal,
inplace = True)
SinhTester = make_broadcast_tester(op = sinh,
expected = numpy.sinh,
good = _good_broadcast_unary_normal,
grad = _grad_broadcast_unary_normal)
SinhInplaceTester = make_broadcast_tester(op = sinh_inplace,
expected = numpy.sinh,
good = _good_broadcast_unary_normal,
grad = _grad_broadcast_unary_normal,
inplace = True)
TanhTester = make_broadcast_tester(op = tanh,
expected = numpy.tanh,
good = _good_broadcast_unary_normal,
grad = _grad_broadcast_unary_normal)
TanhInplaceTester = make_broadcast_tester(op = tanh_inplace,
expected = numpy.tanh,
good = _good_broadcast_unary_normal,
grad = _grad_broadcast_unary_normal,
inplace = True)
# dtype_mixup_2 = (randint_nonzero(2, 3), rand(2, 3)),
# # integers_positive = (randint_ranged(4, 10, (2, 3)), randint_ranged(1, 6, (2, 3))),
# # integers_known_to_fail = (numpy.array(-1), numpy.array(5))
# ),
# # integers = (randint(2, 3), randint_nonzero(2, 3)),
# # dtype_mixup_1 = (rand(2, 3), randint_nonzero(2, 3)),
# # dtype_mixup_2 = (randint_nonzero(2, 3), rand(2, 3))),
# grad = dict(same_shapes = (rand(2, 3), rand(2, 3)),
# scalar = (rand(2, 3), rand(1, 1)),
# row = (rand(2, 3), rand(1, 3)),
# column = (rand(2, 3), rand(2, 1))))
# DivInplaceTester = make_broadcast_tester(op = div_inplace,
# expected = lambda x, y: x / y,
# good = dict(same_shapes = (rand(2, 3), rand(2, 3)),
# scalar = (rand(2, 3), rand(1, 1)),
# row = (rand(2, 3), rand(1, 3)),
# column = (rand(2, 3), rand(2, 1)),
# dtype_mixup_1 = (rand(2, 3), randint_nonzero(2, 3)),
# dtype_mixup_2 = (randint_nonzero(2, 3), rand(2, 3))
# ),
# grad = dict(same_shapes = (rand(2, 3), rand(2, 3)),
# scalar = (rand(2, 3), rand(1, 1)),
# row = (rand(2, 3), rand(1, 3)),
# column = (rand(2, 3), rand(2, 1))),
# inplace = True)
# PowTester = make_broadcast_tester(op = pow,
# expected = lambda x, y: x ** y,
# good = dict(same_shapes = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (2, 3))),
# scalar = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (1, 1))),
# row = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (1, 3))),
# column = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (2, 1))),
# dtype_mixup = (rand_ranged(-3, 3, (2, 3)), randint_ranged(-3, 3, (2, 3)))),
# grad = dict(same_shapes = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (2, 3))),
# scalar = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (1, 1))),
# row = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (1, 3))),
# column = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (2, 1))))
# )
# PowInplaceTester = make_broadcast_tester(op = pow_inplace,
# expected = lambda x, y: x ** y,
# good = dict(same_shapes = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (2, 3))),
# scalar = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (1, 1))),
# row = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (1, 3))),
# column = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (2, 1))),
# dtype_mixup = (rand_ranged(-3, 3, (2, 3)), randint_ranged(-3, 3, (2, 3)))),
# grad = dict(same_shapes = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (2, 3))),
# scalar = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (1, 1))),
# row = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (1, 3))),
# column = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (2, 1)))),
# inplace = True)
# _good_broadcast_unary_normal = dict(normal = (rand_ranged(-5, 5, (2, 3)),),
# integers = (randint_ranged(-5, 5, (2, 3)),))
# _grad_broadcast_unary_normal = dict(normal = (rand_ranged(-5, 5, (2, 3)),))
# AbsTester = make_broadcast_tester(op = tensor._abs,
# expected = lambda x: abs(x),
# good = _good_broadcast_unary_normal,
# grad = _grad_broadcast_unary_normal)
# AbsInplaceTester = make_broadcast_tester(op = abs_inplace,
# expected = lambda x: abs(x),
# good = _good_broadcast_unary_normal,
# grad = _grad_broadcast_unary_normal,
# inplace = True)
# NegTester = make_broadcast_tester(op = neg,
# expected = lambda x: -x,
# good = _good_broadcast_unary_normal,
# grad = _grad_broadcast_unary_normal)
# NegInplaceTester = make_broadcast_tester(op = neg_inplace,
# expected = lambda x: -x,
# good = _good_broadcast_unary_normal,
# grad = _grad_broadcast_unary_normal,
# inplace = True)
# SgnTester = make_broadcast_tester(op = sgn,
# expected = numpy.sign,
# good = _good_broadcast_unary_normal)
# SgnInplaceTester = make_broadcast_tester(op = sgn_inplace,
# expected = numpy.sign,
# good = _good_broadcast_unary_normal,
# inplace = True)
# SqrTester = make_broadcast_tester(op = sqr,
# expected = numpy.square,
# good = _good_broadcast_unary_normal,
# grad = _grad_broadcast_unary_normal)
# SqrInplaceTester = make_broadcast_tester(op = sqr_inplace,
# expected = numpy.square,
# good = _good_broadcast_unary_normal,
# grad = _grad_broadcast_unary_normal,
# inplace = True)
# ExpTester = make_broadcast_tester(op = exp,
# expected = numpy.exp,
# good = _good_broadcast_unary_normal,
# grad = _grad_broadcast_unary_normal)
# ExpInplaceTester = make_broadcast_tester(op = exp_inplace,
# expected = numpy.exp,
# good = _good_broadcast_unary_normal,
# grad = _grad_broadcast_unary_normal,
# inplace = True)
# _good_broadcast_unary_positive = dict(normal = (rand_ranged(0.001, 5, (2, 3)),),
# integers = (randint_ranged(1, 5, (2, 3)),))
# _grad_broadcast_unary_positive = dict(normal = (rand_ranged(0.001, 5, (2, 3)),))
# LogTester = make_broadcast_tester(op = log,
# expected = numpy.log,
# good = _good_broadcast_unary_positive,
# grad = _grad_broadcast_unary_positive)
# LogInplaceTester = make_broadcast_tester(op = log_inplace,
# expected = numpy.log,
# good = _good_broadcast_unary_positive,
# grad = _grad_broadcast_unary_positive,
# inplace = True)
# Log2Tester = make_broadcast_tester(op = log2,
# expected = numpy.log2,
# good = _good_broadcast_unary_positive,
# grad = _grad_broadcast_unary_positive)
# Log2InplaceTester = make_broadcast_tester(op = log2_inplace,
# expected = numpy.log2,
# good = _good_broadcast_unary_positive,
# grad = _grad_broadcast_unary_positive,
# inplace = True)
# SqrtTester = make_broadcast_tester(op = sqrt,
# expected = numpy.sqrt,
# good = _good_broadcast_unary_positive,
# grad = _grad_broadcast_unary_positive)
# SqrtInplaceTester = make_broadcast_tester(op = sqrt_inplace,
# expected = numpy.sqrt,
# good = _good_broadcast_unary_positive,
# grad = _grad_broadcast_unary_positive,
# inplace = True)
# _good_broadcast_unary_wide = dict(normal = (rand_ranged(-1000, 1000, (2, 3)),),
# integers = (randint_ranged(-1000, 1000, (2, 3)),))
# _grad_broadcast_unary_wide = dict(normal = (rand_ranged(-1000, 1000, (2, 3)),))
# SinTester = make_broadcast_tester(op = sin,
# expected = numpy.sin,
# good = _good_broadcast_unary_wide,
# grad = _grad_broadcast_unary_wide)
# SinInplaceTester = make_broadcast_tester(op = sin_inplace,
# expected = numpy.sin,
# good = _good_broadcast_unary_wide,
# grad = _grad_broadcast_unary_wide,
# inplace = True)
# CosTester = make_broadcast_tester(op = cos,
# expected = numpy.cos,
# good = _good_broadcast_unary_wide,
# grad = _grad_broadcast_unary_wide)
# CosInplaceTester = make_broadcast_tester(op = cos_inplace,
# expected = numpy.cos,
# good = _good_broadcast_unary_wide,
# grad = _grad_broadcast_unary_wide,
# inplace = True)
# TanTester = make_broadcast_tester(op = tan,
# expected = numpy.tan,
# good = dict(normal = (rand_ranged(-3.14, 3.14, (2, 3)),),
# shifted = (rand_ranged(3.15, 6.28, (2, 3)),)),
# grad = dict(normal = (rand_ranged(-3.14, 3.14, (2, 3)),),
# shifted = (rand_ranged(3.15, 6.28, (2, 3)),)))
# TanInplaceTester = make_broadcast_tester(op = tan_inplace,
# expected = numpy.tan,
# good = dict(normal = (rand_ranged(-3.14, 3.14, (2, 3)),),
# shifted = (rand_ranged(3.15, 6.28, (2, 3)),)),
# grad = dict(normal = (rand_ranged(-3.14, 3.14, (2, 3)),),
# shifted = (rand_ranged(3.15, 6.28, (2, 3)),)),
# inplace = True)
# CoshTester = make_broadcast_tester(op = cosh,
# expected = numpy.cosh,
# good = _good_broadcast_unary_normal,
# grad = _grad_broadcast_unary_normal)
# CoshInplaceTester = make_broadcast_tester(op = cosh_inplace,
# expected = numpy.cosh,
# good = _good_broadcast_unary_normal,
# grad = _grad_broadcast_unary_normal,
# inplace = True)
# SinhTester = make_broadcast_tester(op = sinh,
# expected = numpy.sinh,
# good = _good_broadcast_unary_normal,
# grad = _grad_broadcast_unary_normal)
# SinhInplaceTester = make_broadcast_tester(op = sinh_inplace,
# expected = numpy.sinh,
# good = _good_broadcast_unary_normal,
# grad = _grad_broadcast_unary_normal,
# inplace = True)
# TanhTester = make_broadcast_tester(op = tanh,
# expected = numpy.tanh,
# good = _good_broadcast_unary_normal,
# grad = _grad_broadcast_unary_normal)
# TanhInplaceTester = make_broadcast_tester(op = tanh_inplace,
# expected = numpy.tanh,
# good = _good_broadcast_unary_normal,
# grad = _grad_broadcast_unary_normal,
# inplace = True)
# DotTester = make_tester(name = 'DotTester',
# op = Dot,
# op = dot,
# expected = lambda x, y: numpy.dot(x, y),
# checks = {},
# good = dict(correct1 = (rand(5, 7), rand(7, 5)),
......@@ -537,147 +538,147 @@ def verify_grad(testcase, op, pt, n_tests=1, rng=numpy.random, eps=0.0000001, to
verify_grad.E_grad = 'gradient error exceeded tolerance'
# #useful mostly for unit tests
# def _approx_eq(a,b,eps=1.0e-9):
# a = numpy.asarray(a)
# b = numpy.asarray(b)
# if a.shape != b.shape:
# if _approx_eq.debug:
# print a.shape, b.shape
# return False
# if numpy.max(numpy.abs(a-b)) >= eps:
# if _approx_eq.debug:
# print a, b
# return False
# return True
# _approx_eq.debug = 0
# def check_eq(self, node_in, node_out, arg_in, arg_out):
# fn = Function([node_in], [node_out])
# self.failUnless( numpy.all(fn(arg_in) == arg_out), (arg_in, arg_out))
# def check_eq2(self, inputs, output, args_in, arg_out):
# fn = Function(inputs, [output])
# val = fn(*args_in)
# self.failUnless( numpy.all(val == arg_out), (val, arg_out))
# def check_eq2_c(self, inputs, output, args_in, arg_out):
# fn = Function(inputs, [output], linker_cls = gof.CLinker)
# val = fn(*args_in)
# self.failUnless( numpy.all(val == arg_out), (val, arg_out))
# def check_eq2_both(self, inputs, output, args_in, arg_out):
# fn = Function(inputs, [output], linker_cls = lambda env: gof.DualLinker(env, _numpy_checker))
# val = fn(*args_in)
# self.failUnless( numpy.all(val == arg_out), (val, arg_out))
# class T_argmax(unittest.TestCase):
# def setUp(self):
# numpy.random.seed(123784)
# Argmax.debug = 0
# def test0(self):
# n = astensor(5.0)
# v,i = eval_outputs(argmax(n))
# self.failUnless(v == 5.0)
# self.failUnless(i == 0)
# def test1(self):
# n = astensor([1,2,3,2,-6])
# v,i = eval_outputs(argmax(n))
# self.failUnless(v == 3)
# self.failUnless(i == 2)
# def test2(self):
# n = astensor(numpy.random.rand(2,3))
# v,i = eval_outputs(argmax(n))
# self.failUnless(numpy.all(i == [0,1]))
# def test2b(self):
# n = astensor(numpy.random.rand(2,3))
# v,i = eval_outputs(argmax(n,axis=0))
# self.failUnless(numpy.all(i == [0,1,1]))
# def test2_invalid(self):
# n = astensor(numpy.random.rand(2,3))
# try:
# eval_outputs(argmax(n,axis=3))
# except ValueError, e:
# return
# self.fail()
# def test2_invalid_neg(self):
# n = astensor(numpy.random.rand(2,3))
# try:
# eval_outputs(argmax(n,axis=-3))
# except ValueError, e:
# return
# self.fail()
# def test2_valid_neg(self):
# n = astensor(numpy.random.rand(2,3))
# v,i = eval_outputs(argmax(n,axis=-1))
# self.failUnless(v.shape == (2,))
# v,i = eval_outputs(argmax(n,axis=-2))
# self.failUnless(v.shape == (3,))
# def test3(self):
# n = astensor(numpy.random.rand(2,3,4))
# v,i = eval_outputs(argmax(n,axis=0))
# self.failUnless(v.shape == (3,4))
# self.failUnless(i.shape == (3,4))
# v,i = eval_outputs(argmax(n,axis=1))
# self.failUnless(v.shape == (2,4))
# self.failUnless(i.shape == (2,4))
# v,i = eval_outputs(argmax(n,axis=2))
# self.failUnless(v.shape == (2,3))
# self.failUnless(i.shape == (2,3))
# class T_transpose(unittest.TestCase):
# def test0(self):
# n = astensor(numpy.ones(()))
# t = transpose(n)
# self.failUnless(t.owner.__class__ is TransposeInplace)
# f = Function([n], [t])
# tval = f(n.data)
# self.failUnless(tval.shape == n.data.shape)
# #test aliasing
# tval += 55.0
# self.failUnless(n.data == 1.0)
#useful mostly for unit tests
def _approx_eq(a,b,eps=1.0e-9):
a = numpy.asarray(a)
b = numpy.asarray(b)
if a.shape != b.shape:
if _approx_eq.debug:
print a.shape, b.shape
return False
if numpy.max(numpy.abs(a-b)) >= eps:
if _approx_eq.debug:
print a, b
return False
return True
_approx_eq.debug = 0
def check_eq(self, node_in, node_out, arg_in, arg_out):
fn = Function([node_in], [node_out])
self.failUnless( numpy.all(fn(arg_in) == arg_out), (arg_in, arg_out))
def check_eq2(self, inputs, output, args_in, arg_out):
fn = Function(inputs, [output])
val = fn(*args_in)
self.failUnless( numpy.all(val == arg_out), (val, arg_out))
def check_eq2_c(self, inputs, output, args_in, arg_out):
fn = Function(inputs, [output], linker_cls = gof.CLinker)
val = fn(*args_in)
self.failUnless( numpy.all(val == arg_out), (val, arg_out))
def check_eq2_both(self, inputs, output, args_in, arg_out):
fn = Function(inputs, [output], linker_cls = lambda env: gof.DualLinker(env, _numpy_checker))
val = fn(*args_in)
self.failUnless( numpy.all(val == arg_out), (val, arg_out))
class T_argmax(unittest.TestCase):
def setUp(self):
numpy.random.seed(123784)
Argmax.debug = 0
def test0(self):
n = as_tensor(5.0)
v,i = eval_outputs(argmax(n))
self.failUnless(v == 5.0)
self.failUnless(i == 0)
def test1(self):
n = as_tensor([1,2,3,2,-6])
v,i = eval_outputs(argmax(n))
self.failUnless(v == 3)
self.failUnless(i == 2)
def test2(self):
n = as_tensor(numpy.random.rand(2,3))
v,i = eval_outputs(argmax(n))
self.failUnless(numpy.all(i == [0,1]))
def test2b(self):
n = as_tensor(numpy.random.rand(2,3))
v,i = eval_outputs(argmax(n,0))
self.failUnless(numpy.all(i == [0,1,1]))
def test2_invalid(self):
n = as_tensor(numpy.random.rand(2,3))
try:
eval_outputs(argmax(n,3))
except ValueError, e:
return
self.fail()
def test2_invalid_neg(self):
n = as_tensor(numpy.random.rand(2,3))
try:
eval_outputs(argmax(n,-3))
except ValueError, e:
return
self.fail()
def test2_valid_neg(self):
n = as_tensor(numpy.random.rand(2,3))
v,i = eval_outputs(argmax(n,-1))
self.failUnless(v.shape == (2,))
v,i = eval_outputs(argmax(n,-2))
self.failUnless(v.shape == (3,))
def test3(self):
n = as_tensor(numpy.random.rand(2,3,4))
v,i = eval_outputs(argmax(n,0))
self.failUnless(v.shape == (3,4))
self.failUnless(i.shape == (3,4))
v,i = eval_outputs(argmax(n,1))
self.failUnless(v.shape == (2,4))
self.failUnless(i.shape == (2,4))
v,i = eval_outputs(argmax(n,2))
self.failUnless(v.shape == (2,3))
self.failUnless(i.shape == (2,3))
class T_transpose(unittest.TestCase):
def test0(self):
n = as_tensor(numpy.ones(()))
t = transpose(n)
self.failUnless(t.owner.op == transpose_inplace)
f = Function([n], [t])
tval = f(n.data)
self.failUnless(tval.shape == n.data.shape)
#test aliasing
tval += 55.0
self.failUnless(n.data == 1.0)
# def test1(self):
# n = astensor(numpy.ones(5))
# t = transpose(n)
# self.failUnless(t.owner.__class__ is TransposeInplace)
# f = Function([n], [t])
# tval = f(n.data)
# self.failUnless(tval.shape == n.data.shape)
# #test aliasing
# tval += 55.0
# self.failUnless(n.data[0] == 1.0)
def test1(self):
n = as_tensor(numpy.ones(5))
t = transpose(n)
self.failUnless(t.owner.op == transpose_inplace)
f = Function([n], [t])
tval = f(n.data)
self.failUnless(tval.shape == n.data.shape)
#test aliasing
tval += 55.0
self.failUnless(n.data[0] == 1.0)
# def test2(self):
# n = astensor(numpy.ones((5,3)))
# t = transpose(n)
# self.failUnless(t.owner.__class__ is TransposeInplace)
# f = Function([n], [t])
# tval = f(n.data)
# self.failUnless(tval.shape == (3,5))
# #test aliasing
# tval += 55.0
# self.failUnless(n.data[0,0] == 1.0)
# def test3(self):
# """Test transpose of tensor, inplace version"""
# n = astensor(numpy.ones((5,3,2)))
# t = transpose_inplace(n)
# self.failUnless(t.owner.__class__ is TransposeInplace)
# f = Function([n], [t])
# tval = f(n.data)
# self.failUnless(tval.shape == (2,3,5))
# #test aliasing
# tval += 55.0
# self.failUnless(n.data[0,0,0] == 56.0)
# def test_grad(self):
# verify_grad(self, TransposeInplace, [numpy.random.rand(2, 3)])
# verify_grad(self, TransposeInplace, [numpy.ones(3)])
def test2(self):
n = as_tensor(numpy.ones((5,3)))
t = transpose(n)
self.failUnless(t.owner.op == transpose_inplace)
f = Function([n], [t])
tval = f(n.data)
self.failUnless(tval.shape == (3,5))
#test aliasing
tval += 55.0
self.failUnless(n.data[0,0] == 1.0)
def test3(self):
"""Test transpose of tensor, inplace version"""
n = as_tensor(numpy.ones((5,3,2)))
t = transpose_inplace(n)
self.failUnless(t.owner.op == transpose_inplace)
f = Function([n], [t])
tval = f(n.data)
self.failUnless(tval.shape == (2,3,5))
#test aliasing
tval += 55.0
self.failUnless(n.data[0,0,0] == 56.0)
def test_grad(self):
verify_grad(self, transpose_inplace, [numpy.random.rand(2, 3)])
verify_grad(self, transpose_inplace, [numpy.ones(3)])
# class T_subtensor(unittest.TestCase):
# def test0_err_invalid(self):
......@@ -1013,276 +1014,275 @@ verify_grad.E_grad = 'gradient error exceeded tolerance'
# def test_col(self):
# verify_grad(self, Pow, [numpy.random.rand(3, 5), numpy.random.rand(3, 1)])
# class _testCase_matinv(unittest.TestCase):
# def setUp(self):
# numpy.random.seed(1)
# def mat_reciprocal(self,dim):
# # symbolic program
# # broadcastable=[False,False] means that the shape of matrix is two dimensional,
# # and none of the dimensions are constrained to have length 1.
# # Note that Tensor's constructor does not actually allocate any memory.
# # TODO: Make Tensor syntax more explicit, and maybe give shape or number of dimensions.
# a = Tensor('float64', broadcastable=[False,False], name='a')
# b = Tensor('float64', broadcastable=[False,False], name='b')
# ab = a*b
# # Here, astensor actually uses the data allocated by numpy.
# diff = ab - astensor(numpy.ones((dim,dim)))
# # Sum of squared errors
# ssdiff = sum((diff**2.0))
# g_b = gradient.grad(ssdiff, b)
# # compilation to function
# # [a,b] are the inputs, [ssdiff,g_b] are the outputs
# fn = Function([a,b], [ssdiff,g_b])
# # use the function
# x = numpy.random.rand(dim,dim)+0.1 # Initialized s.t. x is not too tiny
# w = numpy.random.rand(dim,dim)
# for i in xrange(300):
# ssd, gw = fn(x,w)
# #print ssd, x*w, x, w
# if i == 0:
# str0 = str(ssd)
# w -= 0.4 * gw
# return str0, str(ssd)
# def test_reciprocal(self):
# """Matrix reciprocal by gradient descent"""
# self.assertEqual(('6.10141615619', '0.00703816291711'), self.mat_reciprocal(3))
# class t_dot(unittest.TestCase):
# def setUp(self):
# numpy.random.seed(44)
# @staticmethod
# def rand(*args):
# return numpy.random.rand(*args)
# def cmp_dot(self,x,y):
# #x, y are matrices or numbers
# def spec(x):
# x = numpy.asarray(x)
# return type(x), x.dtype, x.shape
# nz = numpy.dot(x,y)
# tz = eval_outputs([dot(astensor(x), astensor(y))])
# self.failUnless(tz.dtype == nz.dtype)
# self.failUnless(tz.shape == nz.shape)
# self.failUnless(_approx_eq(nz, tz))
# def test_dot_0d_0d(self): self.cmp_dot(1.1, 2.2)
# def test_dot_0d_1d(self): self.cmp_dot(1.1, self.rand(5))
# def test_dot_0d_2d(self): self.cmp_dot(3.0, self.rand(6,7))
# def test_dot_0d_3d(self): self.cmp_dot(3.0, self.rand(8,6,7))
# def test_dot_1d_0d(self): self.cmp_dot(self.rand(5), 1.1 )
# def test_dot_1d_1d(self): self.cmp_dot(self.rand(5), self.rand(5))
# def test_dot_1d_2d(self): self.cmp_dot(self.rand(6), self.rand(6,7))
# def test_dot_1d_3d(self): self.cmp_dot(self.rand(6), self.rand(8,6,7))
# def test_dot_2d_0d(self): self.cmp_dot(self.rand(5,6), 1.0)
# def test_dot_2d_1d(self): self.cmp_dot(self.rand(5,6), self.rand(6))
# def test_dot_2d_2d(self): self.cmp_dot(self.rand(5,6), self.rand(6,7))
# def test_dot_2d_3d(self): self.cmp_dot(self.rand(5,6), self.rand(8,6,7))
# def test_dot_3d_0d(self): self.cmp_dot(self.rand(4,5,6), 1.0)
# def test_dot_3d_1d(self): self.cmp_dot(self.rand(4,5,6), self.rand(6))
# def test_dot_3d_2d(self): self.cmp_dot(self.rand(4,5,6), self.rand(6,7))
# def test_dot_3d_3d(self): self.cmp_dot(self.rand(4,5,6), self.rand(8,6,7))
# def not_aligned(self, x, y):
# z = dot(x,y)
# try:
# tz = eval_outputs([z])
# except ValueError, e:
# self.failUnless(e[0].split()[1:4] == ['are', 'not', 'aligned'], e)
# return
# self.fail()
# def test_align_1_1(self): self.not_aligned(self.rand(5), self.rand(6))
# def test_align_1_2(self): self.not_aligned(self.rand(5), self.rand(6,4))
# def test_align_1_3(self): self.not_aligned(self.rand(5), self.rand(6,4,7))
# def test_align_2_1(self): self.not_aligned(self.rand(5,4), self.rand(6))
# def test_align_2_1(self): self.not_aligned(self.rand(5,4), self.rand(6,7))
# def test_align_2_3(self): self.not_aligned(self.rand(5,4), self.rand(6,7,8))
# def test_align_3_1(self): self.not_aligned(self.rand(5,4,3), self.rand(6))
# def test_align_3_2(self): self.not_aligned(self.rand(5,4,3), self.rand(6,7))
# def test_align_3_3(self): self.not_aligned(self.rand(5,4,3), self.rand(6,7,8))
# def test_grad(self):
# verify_grad(self, Dot, [self.rand(2,3), self.rand(3,2)])
# class t_gemm(unittest.TestCase):
# def setUp(self):
# numpy.random.seed(44)
# _approx_eq.debug = 0
# Gemm.debug = False
# @staticmethod
# def _gemm(z,a,x,y,b):
# assert a.shape == ()
# assert b.shape == ()
# return b * z + a * numpy.dot(x,y)
# @staticmethod
# def rand(*args):
# return numpy.random.rand(*args)
# def cmp(self, z, a, x, y, b):
# def cmp_linker(z, a, x, y, b, l):
# z,a,x,y,b = [numpy.asarray(p) for p in z,a,x,y,b]
# z_orig = z.copy()
# tz,ta,tx,ty,tb = [astensor(p) for p in z,a,x,y,b]
# f = Function([tz,ta,tx,ty,tb], [gemm(tz,ta,tx,ty,tb)], linker_cls=l)
# new_z = f(z,a,x,y,b)
# z_after = self._gemm(z_orig, a, x, y, b)
# self.failUnless(z is new_z)
# #print z_orig, z_after, z, type(z_orig), type(z_after), type(z)
# #_approx_eq.debug = 1
# self.failUnless(_approx_eq(z_after, z))
# if a == 0.0 and b == 1.0:
# return
# else:
# self.failIf(numpy.all(z_orig == z))
# cmp_linker(copy(z), a, x, y, b, gof.cc.OpWiseCLinker)
# #cmp_linker(copy(z), a, x, y, b, gof.cc.CLinker)
# cmp_linker(copy(z), a, x, y, b, gof.link.PerformLinker)
# def test0a(self):
# Gemm.debug = True
# try:
# g = gemm([1.], 1., [1.], [1.], 1.)
# except ValueError, e:
# if e[0] is Gemm.E_rank:
# return
# self.fail()
# def test0(self):
# try:
# self.cmp(1., 0., 1.0, 1.0, 1.0)
# except ValueError, e:
# if e[0] is Gemm.E_rank:
# return
# self.fail()
# def test2(self):
# try:
# self.cmp(2., 1.0, [3,2,1.], [[1],[2],[3.]], 1.0)
# except ValueError, e:
# self.failUnless(e[0] == Gemm.E_rank)
# return
# self.fail()
# def test4(self):
# self.cmp(self.rand(3,4), 1.0, self.rand(3,5), self.rand(5,4), 0.0)
# def test5(self): self.cmp(self.rand(3,4), 1.0,
# self.rand(3,5), self.rand(5,4), 1.0)
# def test6(self): self.cmp(self.rand(3,4), 1.0,
# self.rand(3,5), self.rand(5,4), -1.0)
# def test7(self): self.cmp(self.rand(3,4), 0.0,
# self.rand(3,5), self.rand(5,4), 0.0)
# def test8(self): self.cmp(self.rand(3,4), 0.0,
# self.rand(3,5), self.rand(5,4), 0.6)
# def test9(self): self.cmp(self.rand(3,4), 0.0,
# self.rand(3,5), self.rand(5,4), -1.0)
# def test10(self):
# _approx_eq.debug = 1
# self.cmp(self.rand(3,4), -1.0, self.rand(3,5), self.rand(5,4), 0.0)
# def test11(self): self.cmp(self.rand(3,4), -1.0,
# self.rand(3,5), self.rand(5,4), 1.0)
# def test12(self): self.cmp(self.rand(3,4), -1.0,
# self.rand(3,5), self.rand(5,4), -1.0)
# def test_destroy_map0(self):
# """test that only first input can be overwritten"""
# Z = astensor(self.rand(2,2))
# try:
# gemm(Z, 1.0, Z, Z, 1.0)
# except ValueError, e:
# if e[0] == Gemm.E_z_uniq:
# return
# self.fail()
# def test_destroy_map1(self):
# """test that only first input can be overwritten"""
# Z = astensor(self.rand(2,2))
# A = astensor(self.rand(2,2))
# try:
# gemm(Z, 1.0, A, transpose_inplace(Z), 1.0)
# except ValueError, e:
# if e[0] == Gemm.E_z_uniq:
# return
# self.fail()
# def test_destroy_map2(self):
# """test that only first input can be overwritten"""
# Z = astensor(self.rand(2,2))
# A = astensor(self.rand(2,2))
# try:
# gemm(Z, 1.0, transpose_inplace(Z), A, 1.0)
# except ValueError, e:
# if e[0] == Gemm.E_z_uniq:
# return
# self.fail()
# def test_destroy_map3(self):
# """test that only first input can be overwritten"""
# Z = astensor(self.rand(2,2))
# A = astensor(self.rand(2,2))
# try:
# gemm(Z, 1.0, Z, A, 1.0)
# except ValueError, e:
# if e[0] == Gemm.E_z_uniq:
# return
# self.fail()
# def test_destroy_map4(self):
# """test that dot args can be aliased"""
# Z = astensor(self.rand(2,2))
# A = astensor(self.rand(2,2))
# eval_outputs([gemm(Z, 1.0, A, A, 1.0)])
# eval_outputs([gemm(Z, 1.0, A, A.T, 1.0)])
# def test_transposes(self):
# # three square matrices which are not contiguous
# A = self.rand(4,5)[:,:4]
# B = self.rand(4,5)[:,:4]
# C = self.rand(4,5)[:,:4]
class _testCase_matinv(unittest.TestCase):
def setUp(self):
numpy.random.seed(1)
def mat_reciprocal(self,dim):
# symbolic program
# broadcastable=[False,False] means that the shape of matrix is two dimensional,
# and none of the dimensions are constrained to have length 1.
# Note that Tensor's constructor does not actually allocate any memory.
# TODO: Make Tensor syntax more explicit, and maybe give shape or number of dimensions.
a, b = matrices('ab')
ab = a*b
# Here, as_tensor actually uses the data allocated by numpy.
diff = ab - as_tensor(numpy.ones((dim,dim)))
# Sum of squared errors
ssdiff = sum((diff**2.0))
g_b = gradient.grad(ssdiff, b)
# compilation to function
# [a,b] are the inputs, [ssdiff,g_b] are the outputs
fn = Function([a,b], [ssdiff,g_b])
# use the function
x = numpy.random.rand(dim,dim)+0.1 # Initialized s.t. x is not too tiny
w = numpy.random.rand(dim,dim)
for i in xrange(300):
ssd, gw = fn(x,w)
#print ssd, x*w, x, w
if i == 0:
str0 = str(ssd)
w -= 0.4 * gw
return str0, str(ssd)
def test_reciprocal(self):
"""Matrix reciprocal by gradient descent"""
self.assertEqual(('6.10141615619', '0.00703816291711'), self.mat_reciprocal(3))
class t_dot(unittest.TestCase):
def setUp(self):
numpy.random.seed(44)
@staticmethod
def rand(*args):
return numpy.random.rand(*args)
def cmp_dot(self,x,y):
#x, y are matrices or numbers
def spec(x):
x = numpy.asarray(x)
return type(x), x.dtype, x.shape
nz = numpy.dot(x,y)
tz = eval_outputs([dot(as_tensor(x), as_tensor(y))])
self.failUnless(tz.dtype == nz.dtype)
self.failUnless(tz.shape == nz.shape)
self.failUnless(_approx_eq(nz, tz))
def test_dot_0d_0d(self): self.cmp_dot(1.1, 2.2)
def test_dot_0d_1d(self): self.cmp_dot(1.1, self.rand(5))
def test_dot_0d_2d(self): self.cmp_dot(3.0, self.rand(6,7))
def test_dot_0d_3d(self): self.cmp_dot(3.0, self.rand(8,6,7))
def test_dot_1d_0d(self): self.cmp_dot(self.rand(5), 1.1 )
def test_dot_1d_1d(self): self.cmp_dot(self.rand(5), self.rand(5))
def test_dot_1d_2d(self): self.cmp_dot(self.rand(6), self.rand(6,7))
def test_dot_1d_3d(self): self.cmp_dot(self.rand(6), self.rand(8,6,7))
def test_dot_2d_0d(self): self.cmp_dot(self.rand(5,6), 1.0)
def test_dot_2d_1d(self): self.cmp_dot(self.rand(5,6), self.rand(6))
def test_dot_2d_2d(self): self.cmp_dot(self.rand(5,6), self.rand(6,7))
def test_dot_2d_3d(self): self.cmp_dot(self.rand(5,6), self.rand(8,6,7))
def test_dot_3d_0d(self): self.cmp_dot(self.rand(4,5,6), 1.0)
def test_dot_3d_1d(self): self.cmp_dot(self.rand(4,5,6), self.rand(6))
def test_dot_3d_2d(self): self.cmp_dot(self.rand(4,5,6), self.rand(6,7))
def test_dot_3d_3d(self): self.cmp_dot(self.rand(4,5,6), self.rand(8,6,7))
def not_aligned(self, x, y):
z = dot(x,y)
try:
tz = eval_outputs([z])
except ValueError, e:
self.failUnless(e[0].split()[1:4] == ['are', 'not', 'aligned'], e)
return
self.fail()
def test_align_1_1(self): self.not_aligned(self.rand(5), self.rand(6))
def test_align_1_2(self): self.not_aligned(self.rand(5), self.rand(6,4))
def test_align_1_3(self): self.not_aligned(self.rand(5), self.rand(6,4,7))
def test_align_2_1(self): self.not_aligned(self.rand(5,4), self.rand(6))
def test_align_2_1(self): self.not_aligned(self.rand(5,4), self.rand(6,7))
def test_align_2_3(self): self.not_aligned(self.rand(5,4), self.rand(6,7,8))
def test_align_3_1(self): self.not_aligned(self.rand(5,4,3), self.rand(6))
def test_align_3_2(self): self.not_aligned(self.rand(5,4,3), self.rand(6,7))
def test_align_3_3(self): self.not_aligned(self.rand(5,4,3), self.rand(6,7,8))
def test_grad(self):
verify_grad(self, dot, [self.rand(2,3), self.rand(3,2)])
class t_gemm(unittest.TestCase):
def setUp(self):
numpy.random.seed(44)
_approx_eq.debug = 0
Gemm.debug = False
@staticmethod
def _gemm(z,a,x,y,b):
assert a.shape == ()
assert b.shape == ()
return b * z + a * numpy.dot(x,y)
@staticmethod
def rand(*args):
return numpy.random.rand(*args)
def cmp(self, z, a, x, y, b):
def cmp_linker(z, a, x, y, b, l):
z,a,x,y,b = [numpy.asarray(p) for p in z,a,x,y,b]
z_orig = z.copy()
tz,ta,tx,ty,tb = [as_tensor(p).type() for p in z,a,x,y,b]
f = Function([tz,ta,tx,ty,tb], [gemm(tz,ta,tx,ty,tb)], linker_cls=l)
new_z = f(z,a,x,y,b)
z_after = self._gemm(z_orig, a, x, y, b)
self.failUnless(z is new_z)
#print z_orig, z_after, z, type(z_orig), type(z_after), type(z)
#_approx_eq.debug = 1
self.failUnless(_approx_eq(z_after, z))
if a == 0.0 and b == 1.0:
return
else:
self.failIf(numpy.all(z_orig == z))
#cmp_linker(copy(z), a, x, y, b, gof.cc.OpWiseCLinker)
#cmp_linker(copy(z), a, x, y, b, gof.cc.CLinker)
cmp_linker(copy(z), a, x, y, b, gof.link.PerformLinker)
def test0a(self):
Gemm.debug = True
try:
g = gemm([1.], 1., [1.], [1.], 1.)
except ValueError, e:
if e[0] is Gemm.E_rank:
return
self.fail()
def test0(self):
try:
self.cmp(1., 0., 1.0, 1.0, 1.0)
except ValueError, e:
if e[0] is Gemm.E_rank:
return
self.fail()
def test2(self):
try:
self.cmp(2., 1.0, [3,2,1.], [[1],[2],[3.]], 1.0)
except ValueError, e:
self.failUnless(e[0] == Gemm.E_rank)
return
self.fail()
def test4(self):
self.cmp(self.rand(3,4), 1.0, self.rand(3,5), self.rand(5,4), 0.0)
def test5(self): self.cmp(self.rand(3,4), 1.0,
self.rand(3,5), self.rand(5,4), 1.0)
def test6(self): self.cmp(self.rand(3,4), 1.0,
self.rand(3,5), self.rand(5,4), -1.0)
def test7(self): self.cmp(self.rand(3,4), 0.0,
self.rand(3,5), self.rand(5,4), 0.0)
def test8(self): self.cmp(self.rand(3,4), 0.0,
self.rand(3,5), self.rand(5,4), 0.6)
def test9(self): self.cmp(self.rand(3,4), 0.0,
self.rand(3,5), self.rand(5,4), -1.0)
def test10(self):
_approx_eq.debug = 1
self.cmp(self.rand(3,4), -1.0, self.rand(3,5), self.rand(5,4), 0.0)
def test11(self): self.cmp(self.rand(3,4), -1.0,
self.rand(3,5), self.rand(5,4), 1.0)
def test12(self): self.cmp(self.rand(3,4), -1.0,
self.rand(3,5), self.rand(5,4), -1.0)
def test_destroy_map0(self):
"""test that only first input can be overwritten"""
Z = as_tensor(self.rand(2,2))
try:
gemm(Z, 1.0, Z, Z, 1.0)
except ValueError, e:
if e[0] == Gemm.E_z_uniq:
return
self.fail()
def test_destroy_map1(self):
"""test that only first input can be overwritten"""
Z = as_tensor(self.rand(2,2))
A = as_tensor(self.rand(2,2))
try:
gemm(Z, 1.0, A, transpose_inplace(Z), 1.0)
except ValueError, e:
if e[0] == Gemm.E_z_uniq:
return
self.fail()
def test_destroy_map2(self):
"""test that only first input can be overwritten"""
Z = as_tensor(self.rand(2,2))
A = as_tensor(self.rand(2,2))
try:
gemm(Z, 1.0, transpose_inplace(Z), A, 1.0)
except ValueError, e:
if e[0] == Gemm.E_z_uniq:
return
self.fail()
def test_destroy_map3(self):
"""test that only first input can be overwritten"""
Z = as_tensor(self.rand(2,2))
A = as_tensor(self.rand(2,2))
try:
gemm(Z, 1.0, Z, A, 1.0)
except ValueError, e:
if e[0] == Gemm.E_z_uniq:
return
self.fail()
def test_destroy_map4(self):
"""test that dot args can be aliased"""
Z = as_tensor(self.rand(2,2))
A = as_tensor(self.rand(2,2))
eval_outputs([gemm(Z, 1.0, A, A, 1.0)])
eval_outputs([gemm(Z, 1.0, A, A.T, 1.0)])
def test_transposes(self):
# three square matrices which are not contiguous
A = self.rand(4,5)[:,:4]
B = self.rand(4,5)[:,:4]
C = self.rand(4,5)[:,:4]
# def t(z,x,y,a=1.0, b=0.0,l=gof.cc.OpWiseCLinker,dt='float64'):
# z,a,x,y,b = [numpy.asarray(p,dtype=dt) for p in z,a,x,y,b]
# z_orig = z.copy()
# z_after = self._gemm(z, a, x, y, b)
# tz,ta,tx,ty,tb = [astensor(p) for p in z,a,x,y,b]
# f = Function([tz,ta,tx,ty,tb], [gemm(tz,ta,tx,ty,tb)], linker_cls=l)
# f(z, a, x, y, b)
# self.failUnless(_approx_eq(z_after, z), (z_orig, z_after, z))
# f(z.T, a, y.T, x.T, b)
# self.failUnless(_approx_eq(z_after, z))
# t(C,A,B)
# t(C.T, A, B)
# t(C, A.T, B, dt='float32')
# t(C, A, B.T)
# t(C.T, A.T, B)
# t(C, A.T, B.T, dt='float32')
# t(C.T, A, B.T)
# t(C.T, A.T, B.T, dt='float32')
# t(C, A[:,:2], B[:2, :])
# t(C.T, A[:,:2], B[:2, :], dt='float32')
# t(C, A[:2,:].T, B[:2, :])
# t(C.T, A[:2,:].T, B[:2, :], dt='float32')
# t(C, A[:2,:].T, B[:, :2].T)
# t(C.T, A[:2,:].T, B[:, :2].T)
# try:
# t(C.T, A[:2,:], B[:, :2].T)
# except ValueError, e:
# if e[0].find('aligned') >= 0:
# return
# self.fail()
def t(z,x,y,a=1.0, b=0.0,l=gof.cc.OpWiseCLinker,dt='float64'):
z,a,x,y,b = [numpy.asarray(p,dtype=dt) for p in z,a,x,y,b]
z_orig = z.copy()
z_after = self._gemm(z, a, x, y, b)
tz,ta,tx,ty,tb = [as_tensor(p) for p in z,a,x,y,b]
f = Function([tz,ta,tx,ty,tb], [gemm(tz,ta,tx,ty,tb)], linker_cls=l)
f(z, a, x, y, b)
self.failUnless(_approx_eq(z_after, z), (z_orig, z_after, z))
f(z.T, a, y.T, x.T, b)
self.failUnless(_approx_eq(z_after, z))
t(C,A,B)
t(C.T, A, B)
t(C, A.T, B, dt='float32')
t(C, A, B.T)
t(C.T, A.T, B)
t(C, A.T, B.T, dt='float32')
t(C.T, A, B.T)
t(C.T, A.T, B.T, dt='float32')
t(C, A[:,:2], B[:2, :])
t(C.T, A[:,:2], B[:2, :], dt='float32')
t(C, A[:2,:].T, B[:2, :])
t(C.T, A[:2,:].T, B[:2, :], dt='float32')
t(C, A[:2,:].T, B[:, :2].T)
t(C.T, A[:2,:].T, B[:, :2].T)
try:
t(C.T, A[:2,:], B[:, :2].T)
except ValueError, e:
if e[0].find('aligned') >= 0:
return
self.fail()
......
......@@ -12,12 +12,12 @@ import scalar_opt
def inputs(xbc = (0, 0), ybc = (0, 0), zbc = (0, 0)):
x = Tensor(broadcastable = xbc, dtype = 'float64', name = 'x')
y = Tensor(broadcastable = ybc, dtype = 'float64', name = 'y')
z = Tensor(broadcastable = zbc, dtype = 'float64', name = 'z')
x = Tensor(broadcastable = xbc, dtype = 'float64')('x')
y = Tensor(broadcastable = ybc, dtype = 'float64')('y')
z = Tensor(broadcastable = zbc, dtype = 'float64')('z')
return x, y, z
ds = gof.op.constructor(DimShuffle)
ds = DimShuffle
class _test_inplace_opt(unittest.TestCase):
......
......@@ -6,14 +6,6 @@ from copy import copy
from env import InconsistencyError
__all__ = ['Destroyer',
'Viewer',
'view_roots',
'DestroyHandler',
]
class DestroyHandler(Listener, Constraint, Orderings, Tool):
"""
This feature ensures that an env represents a consistent data flow
......@@ -488,13 +480,14 @@ def view_roots(r):
owner = r.owner
if owner is not None:
try:
view_map = owner.view_map()
except AttributeError, AbstractFunctionError:
view_map = owner.op.view_map
view_map = dict([(owner.outputs[o], i) for o, i in view_map.items()])
except AttributeError:
return [r]
if r in view_map:
answer = []
for r2 in view_map[r]:
answer += view_roots(r2)
for i in view_map[r]:
answer += view_roots(owner.inputs[i])
return answer
else:
return [r]
......
......@@ -24,7 +24,11 @@ class Op(object2):
raise AbstractFunctionError()
def __call__(self, *inputs):
return self.make_node(*inputs).out
node = self.make_node(*inputs)
if len(node.outputs) == 1:
return node.outputs[0]
else:
return node.outputs
#########################
......
......@@ -396,8 +396,14 @@ class _metadict:
return self.d[item]
except:
for item2, value in self.l:
if item == item2:
return value
try:
if item == item2:
return value
if item.equals(item2):
return value
except:
if item is item2:
return value
else:
return default
def clear(self):
......
......@@ -36,6 +36,9 @@ def as_tensor(x, name = None):
except TypeError:
raise
raise TypeError("Cannot convert %s to Tensor" % x, type(x))
# this has a different name, because _as_tensor is the function which ops use
# to upcast their arguments... this internal-use function is a good place to put debugging stuff, better than the global astensor.
_as_tensor = as_tensor
def constant(x):
......@@ -226,6 +229,9 @@ class Tensor(Type):
# Easy constructors
def tensor(*args):
return Tensor(*args).make_result()
def _multi(*fns):
def f2(f, names):
if len(names) == 1:
......@@ -347,115 +353,39 @@ s2t.TensorConstant = TensorConstant
# Supporting Ops
############################
# this has a different name, because _as_tensor is the function which ops use
# to upcast their arguments... this internal-use function is a good place to put debugging stuff, better than the global astensor.
_as_tensor = as_tensor
# class _Op(Op):
# """
# A basic L{Op} subclass that can be used to make L{Op}s that operate on L{Tensor}s.
# It is not mandatory to inherit from this class, but it is practical.
# @ivar nin: number of inputs
# @ivar nout: number of outputs
# @ivar out_tensor_class: L{Tensor} subclass used to instantiate the outputs
# - input_wrapper: returns a L{Tensor} from its argument
# - propagate_dtype: returns a list of dtypes corresponding to the
# output dtypes from a list of input dtypes (if an input is not a
# L{Tensor}, the passed value will be None)
# - propagate_broadcastable: returns a list of tuples corresponding
# to the output broadcastable flags from the input broadcastable flags
# (if an input is not a L{Tensor}, the passed value will be None).
# """
# nin = -1 # nin == -1 means: arbitrary number of inputs
# nout = 1
# def __init__(self, *inputs):
# inputs = map(_as_tensor, inputs)
# if self.nin >= 0:
# if len(inputs) != self.nin:
# raise TypeError("Wrong number of inputs for %s (got %i, expected %i)") \
# % (self, len(inputs), self.nin)
# i_broadcastables = [getattr(input, 'broadcastable', None) for input in inputs]
# i_dtypes = [getattr(input, 'dtype', None) for input in inputs]
# o_broadcastables = utils.from_return_values(self.propagate_broadcastable(*i_broadcastables))
# o_dtypes = utils.from_return_values(self.propagate_dtype(*i_dtypes))
# self.inputs = inputs
# self.outputs = [Tensor(dtype, broadcastable) for broadcastable, dtype in zip(o_broadcastables, o_dtypes)]
# def propagate_broadcastable(self, *inputs):
# raise AbstractFunctionError()
# def propagate_dtype(self, *i_dtypes):
# rval = set([dtype for dtype in i_dtypes if dtype is not None])
# if len(rval) == 0:
# raise ValueError("Cannot infer the dtypes of the outputs with no Tensor inputs.")
# elif len(rval) > 1:
# raise ValueError("The dtypes of all inputs should be identical.")
# return [rval.pop()] * self.nout
##########################
# Unary Operations
##########################
class Argmax(Op):
"""Calculate the max and argmax over a given axis"""
nin=2 # tensor, axis
nout=2 # max val, max idx
E_axis = 'invalid axis'
def make_node(self, x, axis=None):
x = _as_tensor(x)
if axis is None:
axis = x.type.ndim - 1
axis = _as_tensor(axis)
inputs = [x, axis]
broadcastable = [False] * (x.type.ndim - 1)
outputs = [tensor(x.type.dtype, broadcastable),
tensor(axis.type.dtype, broadcastable)]
return Apply(self, inputs, outputs)
def perform(self, node, (x, axis), (max, max_idx)):
max[0] = numpy.max(x, axis)
max_idx[0] = numpy.argmax(x, axis)
argmax = Argmax()
# def broadcast(scalar_opclass, name, module_name = None, inplace_versions = True):
# C = s2t.make_broadcast(scalar_opclass, name = name, module_name = module_name) # this returns a class
# C.__module__ = module_name
# c = gof.op.constructor(s2t.wrap_broadcast(C))
# if inplace_versions:
# CInplace = s2t.make_broadcast(scalar_opclass, {0:0}, name = name+"Inplace")
# CInplace.__module__ = module_name
# c_inplace = gof.op.constructor(s2t.wrap_broadcast(CInplace))
# return C, c, CInplace, c_inplace
# else:
# return C, c
# def _broadcast(scalar_opclass, name, inplace_versions = True):
# return broadcast(scalar_opclass, name, 'tensor', inplace_versions)
def max(x, axis=None):
"""Return maximum elements obtained by iterating over given axis
# class Argmax(Op):
# """Calculate the max and argmax over a given axis"""
# nin=2 # tensor, axis
# nout=2 # max val, max idx
# E_axis = 'invalid axis'
# debug = 0
# def __init__(self, x, axis=None):
# x = _as_tensor(x)
# if axis is None:
# axis = len(x.broadcastable) -1
# axis = _as_tensor(axis)
# self.inputs = [x, axis]
# broadcastable = [0] * (len(x.broadcastable) - 1)
# self.outputs = [Tensor(x.dtype, broadcastable),
# Tensor(axis.dtype, broadcastable)]
# def perform(self):
# axis = self.inputs[1].data
# x = self.inputs[0].data
# self.outputs[0].data = numpy.max(x, axis)
# self.outputs[1].data = numpy.argmax(x,axis)
# argmax = gof.op.constructor(Argmax)
# def max(x, axis=None):
# """Return maximum elements obtained by iterating over given axis
# Default axis is the last one.
# """
# # In python (using Argmax.perform()) this leads to an wasteful
# # implementation that goes through the data twice instead of once
# # but when Argmax.c_impl() is in place, it should be fine.
# return argmax(x,axis)[0]
Default axis is the last one.
"""
# In python (using Argmax.perform()) this leads to an wasteful
# implementation that goes through the data twice instead of once
# but when Argmax.c_impl() is in place, it should be fine.
return argmax(x,axis)[0]
def _elemwise(scalar_op, name):
......@@ -508,7 +438,8 @@ pow, pow_inplace = _elemwise(scal.pow, 'pow')
##########################
class TransposeInplace(Op):
view_map = {0: [0]}
def make_node(self, input):
return Apply(self, [input], [input.type()])
......@@ -531,32 +462,24 @@ transpose_inplace = TransposeInplace()
def transpose(x, **kwargs):
return transpose_inplace(tensor_copy(x), **kwargs)
# class Subtensor(Op, Viewer):
# class Subtensor(Op):
# nin = 2
# nout = 1
# e_invalid = 'invalid index'
# debug = 0
# def __init__(self, *args,**kwargs):
# view_map = {0: [0]}
# def make_node(self, *inputs):
# def as_tuple_result(obj):
# if isinstance(obj, Result):
# if isinstance(obj, gof.Result):
# return obj
# r = gof.result.PythonResult(None)
# if isinstance(obj, tuple):
# r.data = obj
# else:
# r.data = (obj,)
# assert isinstance(obj, (list, tuple))
# r = gof.Constant(gof.generic, obj)
# return r
# def pad(tplR, N):
# l = list(tplR.data)
# for i in range(len(l), N):
# l.append(slice(0,sys.maxint,1))
# tplR.data = tuple(l)
# if Subtensor.debug:
# print 'Subtensor.__init__', args, kwargs
# #Olivier says not to call this
# #Op.__init__(self, *args,**kwargs)
# #Viewer.__init__(self, *args,**kwargs)
# # def pad(tplR, N):
# # l = list(tplR.data)
# # for i in range(len(l), N):
# # l.append(slice(0,sys.maxint,1))
# # tplR.data = tuple(l)
# t, coord = args
# t = _as_tensor(t)
# coord = as_tuple_result(coord)
......@@ -564,26 +487,17 @@ def transpose(x, **kwargs):
# raise ValueError(Subtensor.e_invalid)
# # add the implicit extra unbounded slices
# # e.g. n[0] on a 3d tensor pads to n[0,:,:]
# pad(coord, len(t.broadcastable))
# broadcastable = [0 for c in coord.data if isinstance(c, slice)]
# if Subtensor.debug:
# print 'brdcstble', broadcastable
# print 't', t.data
# print 'coord', coord.data
# ###pad(coord, len(t.broadcastable))
# broadcastable = [False for c in coord.data if isinstance(c, slice)]
# self.inputs = [t, coord]
# self.outputs = [Tensor(t.dtype, broadcastable)]
# def view_map(self):
# return {self.out: [self.inputs[0]]}
# def perform(self):
# x = self.inputs[0].data
# c = self.inputs[1].data
# if Subtensor.debug:
# print 'perform: x', x
# print 'perform: c', c
# def perform(self, node, (x, c), (out, )):
# if len(c) == 1:
# self.outputs[0].data = x.__getitem__(c[0])
# out[0] = x.__getitem__(c[0])
# else:
# self.outputs[0].data = x.__getitem__(c)
# out[0] = x.__getitem__(c)
# def grad(self, (x,), (gz,)):
# # - option: allocate a potentially large matrix of zeros, and fill in
# # the appropriate elements from gz
......@@ -591,7 +505,7 @@ def transpose(x, **kwargs):
# # - option: return gz, but think about how to include a special addition
# # function that works on a corresponding view of the original data
# raise NotImplementedError()
# subtensor = gof.op.constructor(Subtensor)
# subtensor = Subtensor()
#########################
......@@ -599,8 +513,6 @@ def transpose(x, **kwargs):
#########################
class Dot(Op):
# nin=2
# nout=1
def make_node(self, *inputs):
inputs = map(as_tensor, inputs)
if len(inputs) != 2:
......@@ -608,9 +520,6 @@ class Dot(Op):
i_broadcastables = [input.type.broadcastable for input in inputs]
i_dtypes = [input.type.dtype for input in inputs]
# o_broadcastables = utils.from_return_values(self.propagate_broadcastable(*i_broadcastables))
# o_dtypes = utils.from_return_values(self.propagate_dtype(*i_dtypes))
bx, by = i_broadcastables
if len(bx) == 0: # x is a scalar
bz = by
......@@ -624,7 +533,7 @@ class Dot(Op):
o_broadcastables = [bz]
o_dtypes = [scal.upcast(*i_dtypes)]
outputs = [Tensor(t, b)() for b, t in zip(o_broadcastables, o_dtypes)]
outputs = [tensor(t, b) for b, t in zip(o_broadcastables, o_dtypes)]
return Apply(self, inputs, outputs)
def perform(self, node, (x, y), (z, )):
......@@ -633,228 +542,222 @@ class Dot(Op):
return dot(gz, y.T), dot(x.T, gz)
dot = Dot()
# class Gemm(_Op):
# nin=5
# nout=1
# E_rank = 'gemm only works for rank 2'
# E_scalar = 'gemm requires scalar argument'
# E_z_uniq = 'argument z aliased to x or y'
# debug = False
# def __init__(self, *args, **kwargs):
# _Op.__init__(self, *args, **kwargs)
# z, a, x, y, b = self.inputs
# zr, xr, yr = [set(gof.view_roots(i)) for i in z,x,y]
# if zr.intersection(xr):
# raise ValueError(Gemm.E_z_uniq, (z, x))
# if zr.intersection(yr):
# raise ValueError(Gemm.E_z_uniq, (z, y))
# def destroy_map(self):
# return {self.out:[self.inputs[0]]}
# def propagate_broadcastable(self, bz, ba, bx, by, bb):
# if len(bz) != 2: raise ValueError(Gemm.E_rank, len(bz))
# if len(bx) != 2: raise ValueError(Gemm.E_rank, len(bx))
# if len(by) != 2: raise ValueError(Gemm.E_rank, len(by))
# if len(ba): raise ValueError(Gemm.E_scalar, ba)
# if len(bb): raise ValueError(Gemm.E_scalar, bb)
# return [bz]
# def impl(self, z, a, x, y, b):
# assert a.shape == ()
# assert b.shape == ()
# if z.shape == ():
# z.itemset(z*a + b*numpy.dot(x,y))
# return z
# else:
# if b == 0.0:
# if a == 1.0:
# z[:] = numpy.dot(x,y)
# elif a == -1.0:
# z[:] = -numpy.dot(x,y)
# else:
# z[:] = a * numpy.dot(x,y)
# elif b == 1.0:
# if a == 1.0:
# z += numpy.dot(x,y)
# elif a == -1.0:
# z -= numpy.dot(x,y)
# else:
# z += a * numpy.dot(x,y)
# else:
# z *= b
# z += a * numpy.dot(x,y)
# return z
# def grad(self, (z, a, x, y, b), (gz,)):
# raise NotImplementedError()
# def c_support_code(self):
# #return blas.cblas_header_text()
# mod_str = """
# #ifndef MOD
# #define MOD %
# #endif
# """
# return blas.blas_proto() + mod_str
# def c_headers(self):
# return ['<iostream>']
# def c_libraries(self):
# return blas.ldflags()
# def c_validate_update(self, *args):
# return ""
# def c_validate_update_cleanup(self, *args):
# return ""
# def c_code(self, (_z, _a, _x, _y, _b), (_zout, ), sub):
# return """
# int unit = 0;
# int type_num = %(_x)s->descr->type_num;
# int type_size = %(_x)s->descr->elsize; // in bytes
# npy_intp* Nx = %(_x)s->dimensions;
# npy_intp* Ny = %(_y)s->dimensions;
# npy_intp* Nz = %(_z)s->dimensions;
# npy_intp* Sx = %(_x)s->strides;
# npy_intp* Sy = %(_y)s->strides;
# npy_intp* Sz = %(_z)s->strides;
# //strides for x, y, z in dimensions 0, 1
# int sx_0, sx_1, sy_0, sy_1, sz_0, sz_1;
# if (%(_zout)s != %(_z)s)
# {
# if (%(_zout)s)
# {
# Py_DECREF(%(_zout)s);
# }
# %(_zout)s = %(_z)s;
# Py_INCREF(%(_zout)s);
# }
# if (%(_x)s->nd != 2) {PyErr_SetString(PyExc_NotImplementedError, "rank(x) != 2"); %(fail)s;}
# if (%(_y)s->nd != 2) {PyErr_SetString(PyExc_NotImplementedError, "rank(y) != 2"); %(fail)s;}
# if (%(_z)s->nd != 2) {PyErr_SetString(PyExc_NotImplementedError, "rank(z) != 2"); %(fail)s;}
# if ((%(_a)s->descr->type_num != PyArray_DOUBLE)
# && (%(_a)s->descr->type_num != PyArray_FLOAT))
# {PyErr_SetString(PyExc_NotImplementedError, "type(a) is not double or float"); %(fail)s;}
# if ((%(_b)s->descr->type_num != PyArray_DOUBLE)
# && (%(_b)s->descr->type_num != PyArray_FLOAT))
# {PyErr_SetString(PyExc_NotImplementedError, "type(b) is not double or float"); %(fail)s;}
# if ((%(_x)s->descr->type_num != PyArray_DOUBLE)
# && (%(_x)s->descr->type_num != PyArray_FLOAT))
# {PyErr_SetString(PyExc_NotImplementedError, "type(x) is not double or float"); %(fail)s;}
# if ((%(_y)s->descr->type_num != PyArray_DOUBLE)
# && (%(_y)s->descr->type_num != PyArray_FLOAT))
# {PyErr_SetString(PyExc_NotImplementedError, "type(y) is not double or float"); %(fail)s;}
# if ((%(_z)s->descr->type_num != PyArray_DOUBLE)
# && (%(_z)s->descr->type_num != PyArray_FLOAT))
# {PyErr_SetString(PyExc_NotImplementedError, "type(z) is not double or float"); %(fail)s;}
# if ((%(_x)s->descr->type_num != %(_y)s->descr->type_num)
# ||(%(_x)s->descr->type_num != %(_z)s->descr->type_num))
# { PyErr_SetString(PyExc_NotImplementedError, "type(z), type(y), type(z) are not all the same"); %(fail)s; }
# if ((Nx[0] != Nz[0]) || (Nx[1] != Ny[0]) || (Ny[1] != Nz[1]))
# {
# PyErr_SetString(PyExc_ValueError, "Input dimensions do not agree");
# %(fail)s;
# }
# if ((Sx[0] < 1) || (Sx[1] < 1) || (Sx[0] MOD type_size) || (Sx[1] MOD type_size)
# || (Sy[0] < 1) || (Sy[1] < 1) || (Sy[0] MOD type_size) || (Sy[1] MOD type_size)
# || (Sz[0] < 1) || (Sz[1] < 1) || (Sz[0] MOD type_size) || (Sz[1] MOD type_size))
# {
# PyErr_SetString(PyExc_ValueError, "stride is not multiple of element size"); %(fail)s;
# }
# /*
# encode the stride structure of _x,_y,_z into a single integer
# */
# unit |= ((Sx[1] == type_size) ? 0x0 : (Sx[0] == type_size) ? 0x1 : 0x2) << 8;
# unit |= ((Sy[1] == type_size) ? 0x0 : (Sy[0] == type_size) ? 0x1 : 0x2) << 4;
# unit |= ((Sz[1] == type_size) ? 0x0 : (Sz[0] == type_size) ? 0x1 : 0x2) << 0;
# /* create appropriate strides for malformed matrices that are row or column
# * vectors
# */
# sx_0 = (Nx[0] > 1) ? Sx[0]/type_size : Nx[1];
# sx_1 = (Nx[1] > 1) ? Sx[1]/type_size : Nx[0];
# sy_0 = (Ny[0] > 1) ? Sy[0]/type_size : Ny[1];
# sy_1 = (Ny[1] > 1) ? Sy[1]/type_size : Ny[0];
# sz_0 = (Nz[0] > 1) ? Sz[0]/type_size : Nz[1];
# sz_1 = (Nz[1] > 1) ? Sz[1]/type_size : Nz[0];
# switch (type_num)
# {
# case PyArray_FLOAT:
# {
# #define REAL float
# float a = (%(_a)s->descr->type_num == PyArray_FLOAT)
# ? (REAL)(((float*)%(_a)s->data)[0])
# : (REAL)(((double*)%(_a)s->data)[0]);
# float b = (%(_b)s->descr->type_num == PyArray_FLOAT) ?
# (REAL)(((float*)%(_b)s->data)[0])
# : (REAL)(((double*)%(_b)s->data)[0]);
# float* x = (float*)PyArray_DATA(%(_x)s);
# float* y = (float*)PyArray_DATA(%(_y)s);
# float* z = (float*)PyArray_DATA(%(_z)s);
# char N = 'N';
# char T = 'T';
# int Nz0 = Nz[0], Nz1 = Nz[1], Nx1 = Nx[1];
# //std::cerr << (unit/256) MOD 16 << (unit / 16) MOD 16 << unit MOD 16<< '\\n';
# switch(unit)
# {
# case 0x000: sgemm_(&N, &N, &Nz1, &Nz0, &Nx1, &a, y, &sy_0, x, &sx_0, &b, z, &sz_0); break;
# case 0x100: sgemm_(&N, &T, &Nz1, &Nz0, &Nx1, &a, y, &sy_0, x, &sx_1, &b, z, &sz_0); break;
# case 0x010: sgemm_(&T, &N, &Nz1, &Nz0, &Nx1, &a, y, &sy_1, x, &sx_0, &b, z, &sz_0); break;
# case 0x110: sgemm_(&T, &T, &Nz1, &Nz0, &Nx1, &a, y, &sy_1, x, &sx_1, &b, z, &sz_0); break;
# case 0x001: sgemm_(&T, &T, &Nz0, &Nz1, &Nx1, &a, x, &sx_0, y, &sy_0, &b, z, &sz_1); break;
# case 0x101: sgemm_(&N, &T, &Nz0, &Nz1, &Nx1, &a, x, &sx_1, y, &sy_0, &b, z, &sz_1); break;
# case 0x011: sgemm_(&T, &N, &Nz0, &Nz1, &Nx1, &a, x, &sx_0, y, &sy_1, &b, z, &sz_1); break;
# case 0x111: sgemm_(&N, &N, &Nz0, &Nz1, &Nx1, &a, x, &sx_1, y, &sy_1, &b, z, &sz_1); break;
# default: PyErr_SetString(PyExc_ValueError, "some matrix has no unit stride"); %(fail)s;
# };
# #undef REAL
# }
# break;
# case PyArray_DOUBLE:
# {
# #define REAL double
# double a = (%(_a)s->descr->type_num == PyArray_FLOAT)
# ? (REAL)(((float*)%(_a)s->data)[0])
# : (REAL)(((double*)%(_a)s->data)[0]);
# double b = (%(_b)s->descr->type_num == PyArray_FLOAT) ?
# (REAL)(((float*)%(_b)s->data)[0])
# : (REAL)(((double*)%(_b)s->data)[0]);
# double* x = (double*)PyArray_DATA(%(_x)s);
# double* y = (double*)PyArray_DATA(%(_y)s);
# double* z = (double*)PyArray_DATA(%(_z)s);
# char N = 'N';
# char T = 'T';
# int Nz0 = Nz[0], Nz1 = Nz[1], Nx1 = Nx[1];
# //std::cerr << (unit/256) MOD 16 << (unit / 16) MOD 16 << unit MOD 16<< '\\n';
# switch(unit)
# {
# case 0x000: dgemm_(&N, &N, &Nz1, &Nz0, &Nx1, &a, y, &sy_0, x, &sx_0, &b, z, &sz_0); break;
# case 0x100: dgemm_(&N, &T, &Nz1, &Nz0, &Nx1, &a, y, &sy_0, x, &sx_1, &b, z, &sz_0); break;
# case 0x010: dgemm_(&T, &N, &Nz1, &Nz0, &Nx1, &a, y, &sy_1, x, &sx_0, &b, z, &sz_0); break;
# case 0x110: dgemm_(&T, &T, &Nz1, &Nz0, &Nx1, &a, y, &sy_1, x, &sx_1, &b, z, &sz_0); break;
# case 0x001: dgemm_(&T, &T, &Nz0, &Nz1, &Nx1, &a, x, &sx_0, y, &sy_0, &b, z, &sz_1); break;
# case 0x101: dgemm_(&N, &T, &Nz0, &Nz1, &Nx1, &a, x, &sx_1, y, &sy_0, &b, z, &sz_1); break;
# case 0x011: dgemm_(&T, &N, &Nz0, &Nz1, &Nx1, &a, x, &sx_0, y, &sy_1, &b, z, &sz_1); break;
# case 0x111: dgemm_(&N, &N, &Nz0, &Nz1, &Nx1, &a, x, &sx_1, y, &sy_1, &b, z, &sz_1); break;
# default: PyErr_SetString(PyExc_ValueError, "some matrix has no unit stride"); %(fail)s;
# };
# #undef REAL
# }
# break;
# }
# """ % dict(locals(), **sub)
# gemm = gof.op.constructor(Gemm)
class Gemm(Op):
E_rank = 'gemm only works for rank 2'
E_scalar = 'gemm requires scalar argument'
E_z_uniq = 'argument z aliased to x or y'
destroy_map = {0: [0]}
def make_node(self, *inputs):
inputs = map(as_tensor, inputs)
if len(inputs) != 5:
raise TypeError("Wrong number of inputs for %s (expected 5, got %s)" % (self, len(inputs)))
z, a, x, y, b = inputs
zr, xr, yr = [set(gof.view_roots(i)) for i in z,x,y]
if zr.intersection(xr):
raise ValueError(Gemm.E_z_uniq, (z, x))
if zr.intersection(yr):
raise ValueError(Gemm.E_z_uniq, (z, y))
bz, ba, bx, by, bb = [r.type.broadcastable for r in inputs]
if len(bz) != 2: raise ValueError(Gemm.E_rank, len(bz))
if len(bx) != 2: raise ValueError(Gemm.E_rank, len(bx))
if len(by) != 2: raise ValueError(Gemm.E_rank, len(by))
if len(ba): raise ValueError(Gemm.E_scalar, ba)
if len(bb): raise ValueError(Gemm.E_scalar, bb)
output = z.type()
return Apply(self, inputs, [output])
def perform(self, node, (z, a, x, y, b), (zout, )):
assert a.shape == ()
assert b.shape == ()
if z.shape == ():
z.itemset(z*a + b*numpy.dot(x,y))
zout[0] = z
else:
if b == 0.0:
if a == 1.0:
z[:] = numpy.dot(x,y)
elif a == -1.0:
z[:] = -numpy.dot(x,y)
else:
z[:] = a * numpy.dot(x,y)
elif b == 1.0:
if a == 1.0:
z += numpy.dot(x,y)
elif a == -1.0:
z -= numpy.dot(x,y)
else:
z += a * numpy.dot(x,y)
else:
z *= b
z += a * numpy.dot(x,y)
zout[0] = z
def grad(self, (z, a, x, y, b), (gz,)):
raise NotImplementedError()
def c_support_code(self):
#return blas.cblas_header_text()
mod_str = """
#ifndef MOD
#define MOD %
#endif
"""
return blas.blas_proto() + mod_str
def c_headers(self):
return ['<iostream>']
def c_libraries(self):
return blas.ldflags()
def c_code(self, node, name, (_z, _a, _x, _y, _b), (_zout, ), sub):
return """
int unit = 0;
int type_num = %(_x)s->descr->type_num;
int type_size = %(_x)s->descr->elsize; // in bytes
npy_intp* Nx = %(_x)s->dimensions;
npy_intp* Ny = %(_y)s->dimensions;
npy_intp* Nz = %(_z)s->dimensions;
npy_intp* Sx = %(_x)s->strides;
npy_intp* Sy = %(_y)s->strides;
npy_intp* Sz = %(_z)s->strides;
//strides for x, y, z in dimensions 0, 1
int sx_0, sx_1, sy_0, sy_1, sz_0, sz_1;
if (%(_zout)s != %(_z)s)
{
if (%(_zout)s)
{
Py_DECREF(%(_zout)s);
}
%(_zout)s = %(_z)s;
Py_INCREF(%(_zout)s);
}
if (%(_x)s->nd != 2) {PyErr_SetString(PyExc_NotImplementedError, "rank(x) != 2"); %(fail)s;}
if (%(_y)s->nd != 2) {PyErr_SetString(PyExc_NotImplementedError, "rank(y) != 2"); %(fail)s;}
if (%(_z)s->nd != 2) {PyErr_SetString(PyExc_NotImplementedError, "rank(z) != 2"); %(fail)s;}
if ((%(_a)s->descr->type_num != PyArray_DOUBLE)
&& (%(_a)s->descr->type_num != PyArray_FLOAT))
{PyErr_SetString(PyExc_NotImplementedError, "type(a) is not double or float"); %(fail)s;}
if ((%(_b)s->descr->type_num != PyArray_DOUBLE)
&& (%(_b)s->descr->type_num != PyArray_FLOAT))
{PyErr_SetString(PyExc_NotImplementedError, "type(b) is not double or float"); %(fail)s;}
if ((%(_x)s->descr->type_num != PyArray_DOUBLE)
&& (%(_x)s->descr->type_num != PyArray_FLOAT))
{PyErr_SetString(PyExc_NotImplementedError, "type(x) is not double or float"); %(fail)s;}
if ((%(_y)s->descr->type_num != PyArray_DOUBLE)
&& (%(_y)s->descr->type_num != PyArray_FLOAT))
{PyErr_SetString(PyExc_NotImplementedError, "type(y) is not double or float"); %(fail)s;}
if ((%(_z)s->descr->type_num != PyArray_DOUBLE)
&& (%(_z)s->descr->type_num != PyArray_FLOAT))
{PyErr_SetString(PyExc_NotImplementedError, "type(z) is not double or float"); %(fail)s;}
if ((%(_x)s->descr->type_num != %(_y)s->descr->type_num)
||(%(_x)s->descr->type_num != %(_z)s->descr->type_num))
{ PyErr_SetString(PyExc_NotImplementedError, "type(z), type(y), type(z) are not all the same"); %(fail)s; }
if ((Nx[0] != Nz[0]) || (Nx[1] != Ny[0]) || (Ny[1] != Nz[1]))
{
PyErr_SetString(PyExc_ValueError, "Input dimensions do not agree");
%(fail)s;
}
if ((Sx[0] < 1) || (Sx[1] < 1) || (Sx[0] MOD type_size) || (Sx[1] MOD type_size)
|| (Sy[0] < 1) || (Sy[1] < 1) || (Sy[0] MOD type_size) || (Sy[1] MOD type_size)
|| (Sz[0] < 1) || (Sz[1] < 1) || (Sz[0] MOD type_size) || (Sz[1] MOD type_size))
{
PyErr_SetString(PyExc_ValueError, "stride is not multiple of element size"); %(fail)s;
}
/*
encode the stride structure of _x,_y,_z into a single integer
*/
unit |= ((Sx[1] == type_size) ? 0x0 : (Sx[0] == type_size) ? 0x1 : 0x2) << 8;
unit |= ((Sy[1] == type_size) ? 0x0 : (Sy[0] == type_size) ? 0x1 : 0x2) << 4;
unit |= ((Sz[1] == type_size) ? 0x0 : (Sz[0] == type_size) ? 0x1 : 0x2) << 0;
/* create appropriate strides for malformed matrices that are row or column
* vectors
*/
sx_0 = (Nx[0] > 1) ? Sx[0]/type_size : Nx[1];
sx_1 = (Nx[1] > 1) ? Sx[1]/type_size : Nx[0];
sy_0 = (Ny[0] > 1) ? Sy[0]/type_size : Ny[1];
sy_1 = (Ny[1] > 1) ? Sy[1]/type_size : Ny[0];
sz_0 = (Nz[0] > 1) ? Sz[0]/type_size : Nz[1];
sz_1 = (Nz[1] > 1) ? Sz[1]/type_size : Nz[0];
switch (type_num)
{
case PyArray_FLOAT:
{
#define REAL float
float a = (%(_a)s->descr->type_num == PyArray_FLOAT)
? (REAL)(((float*)%(_a)s->data)[0])
: (REAL)(((double*)%(_a)s->data)[0]);
float b = (%(_b)s->descr->type_num == PyArray_FLOAT) ?
(REAL)(((float*)%(_b)s->data)[0])
: (REAL)(((double*)%(_b)s->data)[0]);
float* x = (float*)PyArray_DATA(%(_x)s);
float* y = (float*)PyArray_DATA(%(_y)s);
float* z = (float*)PyArray_DATA(%(_z)s);
char N = 'N';
char T = 'T';
int Nz0 = Nz[0], Nz1 = Nz[1], Nx1 = Nx[1];
//std::cerr << (unit/256) MOD 16 << (unit / 16) MOD 16 << unit MOD 16<< '\\n';
switch(unit)
{
case 0x000: sgemm_(&N, &N, &Nz1, &Nz0, &Nx1, &a, y, &sy_0, x, &sx_0, &b, z, &sz_0); break;
case 0x100: sgemm_(&N, &T, &Nz1, &Nz0, &Nx1, &a, y, &sy_0, x, &sx_1, &b, z, &sz_0); break;
case 0x010: sgemm_(&T, &N, &Nz1, &Nz0, &Nx1, &a, y, &sy_1, x, &sx_0, &b, z, &sz_0); break;
case 0x110: sgemm_(&T, &T, &Nz1, &Nz0, &Nx1, &a, y, &sy_1, x, &sx_1, &b, z, &sz_0); break;
case 0x001: sgemm_(&T, &T, &Nz0, &Nz1, &Nx1, &a, x, &sx_0, y, &sy_0, &b, z, &sz_1); break;
case 0x101: sgemm_(&N, &T, &Nz0, &Nz1, &Nx1, &a, x, &sx_1, y, &sy_0, &b, z, &sz_1); break;
case 0x011: sgemm_(&T, &N, &Nz0, &Nz1, &Nx1, &a, x, &sx_0, y, &sy_1, &b, z, &sz_1); break;
case 0x111: sgemm_(&N, &N, &Nz0, &Nz1, &Nx1, &a, x, &sx_1, y, &sy_1, &b, z, &sz_1); break;
default: PyErr_SetString(PyExc_ValueError, "some matrix has no unit stride"); %(fail)s;
};
#undef REAL
}
break;
case PyArray_DOUBLE:
{
#define REAL double
double a = (%(_a)s->descr->type_num == PyArray_FLOAT)
? (REAL)(((float*)%(_a)s->data)[0])
: (REAL)(((double*)%(_a)s->data)[0]);
double b = (%(_b)s->descr->type_num == PyArray_FLOAT) ?
(REAL)(((float*)%(_b)s->data)[0])
: (REAL)(((double*)%(_b)s->data)[0]);
double* x = (double*)PyArray_DATA(%(_x)s);
double* y = (double*)PyArray_DATA(%(_y)s);
double* z = (double*)PyArray_DATA(%(_z)s);
char N = 'N';
char T = 'T';
int Nz0 = Nz[0], Nz1 = Nz[1], Nx1 = Nx[1];
//std::cerr << (unit/256) MOD 16 << (unit / 16) MOD 16 << unit MOD 16<< '\\n';
switch(unit)
{
case 0x000: dgemm_(&N, &N, &Nz1, &Nz0, &Nx1, &a, y, &sy_0, x, &sx_0, &b, z, &sz_0); break;
case 0x100: dgemm_(&N, &T, &Nz1, &Nz0, &Nx1, &a, y, &sy_0, x, &sx_1, &b, z, &sz_0); break;
case 0x010: dgemm_(&T, &N, &Nz1, &Nz0, &Nx1, &a, y, &sy_1, x, &sx_0, &b, z, &sz_0); break;
case 0x110: dgemm_(&T, &T, &Nz1, &Nz0, &Nx1, &a, y, &sy_1, x, &sx_1, &b, z, &sz_0); break;
case 0x001: dgemm_(&T, &T, &Nz0, &Nz1, &Nx1, &a, x, &sx_0, y, &sy_0, &b, z, &sz_1); break;
case 0x101: dgemm_(&N, &T, &Nz0, &Nz1, &Nx1, &a, x, &sx_1, y, &sy_0, &b, z, &sz_1); break;
case 0x011: dgemm_(&T, &N, &Nz0, &Nz1, &Nx1, &a, x, &sx_0, y, &sy_1, &b, z, &sz_1); break;
case 0x111: dgemm_(&N, &N, &Nz0, &Nz1, &Nx1, &a, x, &sx_1, y, &sy_1, &b, z, &sz_1); break;
default: PyErr_SetString(PyExc_ValueError, "some matrix has no unit stride"); %(fail)s;
};
#undef REAL
}
break;
}
""" % dict(locals(), **sub)
gemm = Gemm()
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论