tensor test added, Dot and Gemm added. tensor_ops removed. Fixed a bug in some…

tensor test added, Dot and Gemm added. tensor_ops removed. Fixed a bug in some tests which causes them now to fail :(
上级 0bb9219e
import unittest
from core import build_mode, pop_mode
from ops import *
class _testCase_add_build_mode(unittest.TestCase):
def setUp(self):
build_mode()
numpy.random.seed(44)
def tearDown(self):
pop_mode()
class _testCase_dot(unittest.TestCase):
def setUp(self):
build_eval_mode()
numpy.random.seed(44)
def tearDown(self):
pop_mode()
@staticmethod
def rand(*args):
return numpy.random.rand(*args)
def cmp_dot(self,x,y):
if 0:
def spec(x):
x = numpy.asarray(x)
return type(x), x.dtype, x.shape
zspec = dot.specs(spec(x), spec(y))
nz = numpy.dot(x,y)
self.failUnless(zspec == spec(nz))
self.failUnless(_approx_eq(dot(x,y), numpy.dot(x,y)))
def cmp_dot_comp(self, x,y):
x = numpy.asarray(x)
y = numpy.asarray(y)
z = dot(x,y)
p = compile.single(z)
if len(x.shape):
x[:] = numpy.random.rand(*x.shape)
else:
x.fill(numpy.random.rand(*x.shape))
if len(y.shape):
y[:] = numpy.random.rand(*y.shape)
else:
y.fill(numpy.random.rand(*y.shape))
p() # recalculate z
self.failUnless(_approx_eq(z, numpy.dot(x,y)))
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 test_dot_0d_0d_(self): self.cmp_dot_comp(1.1, 2.2)
def test_dot_0d_1d_(self): self.cmp_dot_comp(1.1, self.rand(5))
def test_dot_0d_2d_(self): self.cmp_dot_comp(3.0, self.rand(6,7))
def test_dot_0d_3d_(self): self.cmp_dot_comp(3.0, self.rand(8,6,7))
def test_dot_1d_0d_(self): self.cmp_dot_comp(self.rand(5), 1.1 )
def test_dot_1d_1d_(self): self.cmp_dot_comp(self.rand(5), self.rand(5))
def test_dot_1d_2d_(self): self.cmp_dot_comp(self.rand(6), self.rand(6,7))
def test_dot_1d_3d_(self): self.cmp_dot_comp(self.rand(6), self.rand(8,6,7))
def test_dot_2d_0d_(self): self.cmp_dot_comp(self.rand(5,6), 1.0)
def test_dot_2d_1d_(self): self.cmp_dot_comp(self.rand(5,6), self.rand(6))
def test_dot_2d_2d_(self): self.cmp_dot_comp(self.rand(5,6), self.rand(6,7))
def test_dot_2d_3d_(self): self.cmp_dot_comp(self.rand(5,6), self.rand(8,6,7))
def test_dot_3d_0d_(self): self.cmp_dot_comp(self.rand(4,5,6), 1.0)
def test_dot_3d_1d_(self): self.cmp_dot_comp(self.rand(4,5,6), self.rand(6))
def test_dot_3d_2d_(self): self.cmp_dot_comp(self.rand(4,5,6), self.rand(6,7))
def test_dot_3d_3d_(self): self.cmp_dot_comp(self.rand(4,5,6), self.rand(8,6,7))
def test_dot_fail_1_1(self):
x = numpy.random.rand(5)
y = numpy.random.rand(6)
try:
z = dot(x,y)
except ValueError, e:
self.failUnless(str(e) == 'objects are not aligned', e)
return
self.fail()
def test_dot_fail_1_2(self):
x = numpy.random.rand(5)
y = numpy.random.rand(6,4)
try:
z = dot(x,y)
except ValueError, e:
self.failUnless(str(e) == 'objects are not aligned', e)
return
self.fail()
def test_dot_fail_1_3(self):
x = numpy.random.rand(5)
y = numpy.random.rand(6,4,7)
try:
z = dot(x,y)
except ValueError, e:
self.failUnless(str(e) == 'objects are not aligned', e)
return
self.fail()
def test_dot_fail_2_1(self):
x = numpy.random.rand(5,4)
y = numpy.random.rand(6)
try:
z = dot(x,y)
except ValueError, e:
self.failUnless(str(e) == 'objects are not aligned', e)
return
self.fail()
def test_dot_fail_2_2(self):
x = numpy.random.rand(5,4)
y = numpy.random.rand(6,7)
try:
z = dot(x,y)
except ValueError, e:
self.failUnless(str(e) == 'objects are not aligned', e)
return
self.fail()
def test_dot_fail_2_3(self):
x = numpy.random.rand(5,4)
y = numpy.random.rand(6,7,8)
try:
z = dot(x,y)
except ValueError, e:
self.failUnless(str(e) == 'objects are not aligned', e)
return
self.fail()
def test_dot_fail_3_1(self):
x = numpy.random.rand(5,4,3)
y = numpy.random.rand(6)
try:
z = dot(x,y)
except ValueError, e:
self.failUnless(str(e) == 'objects are not aligned', e)
return
self.fail()
def test_dot_fail_3_2(self):
x = numpy.random.rand(5,4,3)
y = numpy.random.rand(6,7)
try:
z = dot(x,y)
except ValueError, e:
self.failUnless(str(e) == 'objects are not aligned', e)
return
self.fail()
def test_dot_fail_3_3(self):
x = numpy.random.rand(5,4,3)
y = numpy.random.rand(6,7,8)
try:
z = dot(x,y)
except ValueError, e:
self.failUnless(str(e) == 'objects are not aligned', e)
return
self.fail()
class gemm(omega_op):
def destroy_map(self):
return {self.out:[self.inputs[0]]}
def impl(z, a, x, y, b):
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(z, a, x, y, b, gz):
raise NotImplemented
def refresh(self, alloc = False):
z,a,x,y,b = self.inputs
self.out.shape = z.shape
self.out.dtype = z.dtype
if alloc:
self.out.data = z.data
def c_support_code(self):
return blas.cblas_header_text()
def c_libs(self):
return blas.ldflags()
def c_impl((_zin, _a, _x, _y, _b), (_z,)):
check_ab = """
{
if ((_a->descr->type_num != PyArray_DOUBLE)
&& (_a->descr->type_num != PyArray_FLOAT))
goto _dot_execute_fallback;
if ((_b->descr->type_num != PyArray_DOUBLE)
&& (_b->descr->type_num != PyArray_FLOAT))
goto _dot_execute_fallback;
}
"""
return blas.gemm_code( check_ab,
'(_a->descr->type_num == PyArray_FLOAT) ? (REAL)(((float*)_a->data)[0]) : (REAL)(((double*)_a->data)[0])',
'(_b->descr->type_num == PyArray_FLOAT) ? (REAL)(((float*)_b->data)[0]) : (REAL)(((double*)_b->data)[0])')
if __name__ == '__main__':
unittest.main()
...@@ -53,6 +53,20 @@ def verify_grad(testcase, op_cls, pt, n_tests=1, rng=numpy.random, eps=0.0000001 ...@@ -53,6 +53,20 @@ def verify_grad(testcase, op_cls, pt, n_tests=1, rng=numpy.random, eps=0.0000001
verify_grad.E_grad = 'gradient error exceeded tolerance' 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): def check_eq(self, node_in, node_out, arg_in, arg_out):
fn = Function([node_in], [node_out]) fn = Function([node_in], [node_out])
...@@ -97,16 +111,16 @@ class T_argmax(unittest.TestCase): ...@@ -97,16 +111,16 @@ class T_argmax(unittest.TestCase):
n = tinit(numpy.random.rand(2,3)) n = tinit(numpy.random.rand(2,3))
try: try:
eval_outputs(argmax(n,axis=3)) eval_outputs(argmax(n,axis=3))
self.fail()
except ValueError, e: except ValueError, e:
return return
self.fail()
def test2_invalid_neg(self): def test2_invalid_neg(self):
n = tinit(numpy.random.rand(2,3)) n = tinit(numpy.random.rand(2,3))
try: try:
eval_outputs(argmax(n,axis=-3)) eval_outputs(argmax(n,axis=-3))
self.fail()
except ValueError, e: except ValueError, e:
return return
self.fail()
def test2_valid_neg(self): def test2_valid_neg(self):
n = tinit(numpy.random.rand(2,3)) n = tinit(numpy.random.rand(2,3))
v,i = eval_outputs(argmax(n,axis=-1)) v,i = eval_outputs(argmax(n,axis=-1))
...@@ -178,19 +192,19 @@ class T_subtensor(unittest.TestCase): ...@@ -178,19 +192,19 @@ class T_subtensor(unittest.TestCase):
n = tinit(numpy.ones(())) n = tinit(numpy.ones(()))
try: try:
t = n[0] t = n[0]
self.fail()
except ValueError, e: except ValueError, e:
self.failUnless(e[0] is Subtensor.e_invalid) self.failUnless(e[0] is Subtensor.e_invalid)
self.fail()
def test1_err_bounds(self): def test1_err_bounds(self):
n = tinit(numpy.ones(3)) n = tinit(numpy.ones(3))
t = n[7] t = n[7]
self.failUnless(t.owner.__class__ is Subtensor) self.failUnless(t.owner.__class__ is Subtensor)
try: try:
tval = eval_outputs([t]) tval = eval_outputs([t])
self.fail()
except Exception, e: except Exception, e:
if e[0] != 'index out of bounds': if e[0] != 'index out of bounds':
raise raise
self.fail()
def test1_ok_range_finite(self): def test1_ok_range_finite(self):
n = tinit(numpy.ones(3)*5) n = tinit(numpy.ones(3)*5)
t = n[0:2] t = n[0:2]
...@@ -209,9 +223,9 @@ class T_subtensor(unittest.TestCase): ...@@ -209,9 +223,9 @@ class T_subtensor(unittest.TestCase):
n = tinit(numpy.ones(1)) n = tinit(numpy.ones(1))
try: try:
t = n[0,0] t = n[0,0]
self.fail()
except ValueError, e: except ValueError, e:
self.failUnless(e[0] is Subtensor.e_invalid) self.failUnless(e[0] is Subtensor.e_invalid)
self.fail()
def test1_ok_elem(self): def test1_ok_elem(self):
n = tinit(numpy.ones(1)*5) n = tinit(numpy.ones(1)*5)
t = n[0] t = n[0]
...@@ -244,9 +258,9 @@ class T_subtensor(unittest.TestCase): ...@@ -244,9 +258,9 @@ class T_subtensor(unittest.TestCase):
self.failUnless(t.owner.__class__ is Subtensor) self.failUnless(t.owner.__class__ is Subtensor)
try: try:
tval = eval_outputs([t]) tval = eval_outputs([t])
self.fail()
except IndexError, e: except IndexError, e:
return return
self.fail()
def test2_err_bounds1(self): def test2_err_bounds1(self):
n = tinit(numpy.ones((2,3))*5) n = tinit(numpy.ones((2,3))*5)
t = n[4:5,2] t = n[4:5,2]
...@@ -356,9 +370,9 @@ class T_abs(unittest.TestCase): ...@@ -356,9 +370,9 @@ class T_abs(unittest.TestCase):
def test_badgrad(self): def test_badgrad(self):
try: try:
verify_grad(self, T_abs.AbsBadGrad, [numpy.ones(())]) verify_grad(self, T_abs.AbsBadGrad, [numpy.ones(())])
self.fail()
except Exception, e: except Exception, e:
self.failUnless(str(e) == verify_grad.E_grad, str(e)) self.failUnless(str(e) == verify_grad.E_grad, str(e))
self.fail()
class T_fill(unittest.TestCase): class T_fill(unittest.TestCase):
def test0(self): def test0(self):
...@@ -425,9 +439,9 @@ class T_mul(unittest.TestCase): ...@@ -425,9 +439,9 @@ class T_mul(unittest.TestCase):
try: try:
check_eq2(self, [a,b], MulElemwise(a,b).out, check_eq2(self, [a,b], MulElemwise(a,b).out,
[numpy.ones(3), numpy.ones(4)], 1.0) [numpy.ones(3), numpy.ones(4)], 1.0)
self.fail()
except ValueError, e: except ValueError, e:
self.failUnless(e[0] is tensor._assert_same_shapes.E_shape) self.failUnless(e[0] is tensor._assert_same_shapes.E_shape)
self.fail()
class T_div(unittest.TestCase): class T_div(unittest.TestCase):
def setUp(self): def setUp(self):
...@@ -490,5 +504,124 @@ class _testCase_matinv:#(unittest.TestCase): ...@@ -490,5 +504,124 @@ class _testCase_matinv:#(unittest.TestCase):
"""Matrix reciprocal by gradient descent""" """Matrix reciprocal by gradient descent"""
self.assertEqual(('2.67327580893', '0.000438649434819'), self.mat_recip(3)) self.assertEqual(('2.67327580893', '0.000438649434819'), self.mat_recip(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(tinit(x), tinit(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] == 'objects 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))
class t_gemm(unittest.TestCase):
def setUp(self):
numpy.random.seed(44)
_approx_eq.debug = 0
@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):
z,a,x,y,b = [numpy.asarray(p) for p in z,a,x,y,b]
cz = z.copy()
tz,ta,tx,ty,tb = [tinit(p) for p in z,a,x,y,b]
f = Function([tz,ta,tx,ty,tb], [gemm(tz,ta,tx,ty,tb)])
new_z = f(z,a,x,y,b)
_z = self._gemm(cz, a, x, y, b)
self.failUnless(z is new_z)
#print cz, _z, z, type(cz), type(_z), type(z)
#_approx_eq.debug = 1
self.failUnless(_approx_eq(_z, z))
if a == 0.0 and b == 1.0:
return
else:
self.failIf(numpy.all(cz == z))
def test0(self): self.cmp(1., 0., 1.0, 1.0, 1.0)
def test1(self): self.cmp(2., 0., 1.0, 1.0, 0.0)
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_bcast)
return
self.fail()
def test3(self): self.cmp([2.], 1.,[3,2,1.], [[1],[2],[3.]], 1.0)
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)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
import unittest
from gof import ResultBase, Op, Env, modes
import gof
from tensor import *
from tensor_ops import *
import numpy
import sys
from scipy import weave
def inputs():
l1 = [[1.0, 2.0], [3.0, 4.0]]
l2 = [[3.0, 4.0], [1.0, 2.0]]
l3 = numpy.ones((2, 3))
x = modes.build(tensor(l1, 'x'))
y = modes.build(tensor(l2, 'y'))
z = modes.build(tensor(l3, 'z'))
return x, y, z
def env(inputs, outputs, validate = True, features = []):
return Env(inputs, outputs, features = features, consistency_check = validate)
class _test_TensorOps(unittest.TestCase):
def test_0(self):
x, y, z = inputs()
# e = mul(add(x, y), 2)
e = (x + y) * 2
fn, i, o = gof.PerformLinker(env([x, y], [e])).make_thunk(True)
fn()
assert (e.data == numpy.array([[8, 12], [8, 12]])).all()
def test_1(self):
x, y, z = inputs()
e = dot(x, z).T
fn, i, o = gof.PerformLinker(env([x, z], [e])).make_thunk(True)
fn()
assert (e.data == numpy.array([[3, 3, 3], [7, 7, 7]]).T).all()
def test_2(self):
x, y, z = inputs()
x = x.data
y = weave.inline("""
PyObject* p = PyArray_Transpose(x_array, NULL);
return_val = p;
""", ['x'])
print y
# def test_0(self):
# x, y, z = inputs()
# e = transpose(x)
# g = env([x], [e])
# fn, (i, ), (o, ) = gof.cc.CLinker(g).make_thunk()
# # print sys.getrefcount(i.data)
# for blah in xrange(10000):
# i.data = numpy.ones((1000, 1000)) # [[1.0, 2.0], [3.0, 4.0]]
# fn()
# # print sys.getrefcount(i.data)
# # print sys.getrefcount(o.data)
# print o.data
# # assert res == numpy.asarray(arr)
# # def test_1(self):
# # x, y, z = inputs()
# # e = mul(add(x, y), div(x, y))
# # g = env([x, y], [e])
# # fn = gof.cc.CLinker(g).make_function()
# # assert fn(1.0, 2.0) == 1.5
# # assert e.data == 1.5
from core import *
import unittest
import gradient
#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:
return False
return numpy.max(numpy.abs(a-b)) < eps
if 1: # run gradient tests
def _scalar(x):
rval = numpy.zeros(())
rval.itemset(x)
return rval
def _test_grad(self, op_cls, args, n_tests=1,eps=0.0000001, tol=0.0001):
"""unittest.TestCase.failUnless( analytic gradient matches finite-diff gradient )
The criterion is that every input gradient must match every
finite-difference gradient (using stepsize of eps) to relative precision
tol.
"""
def _finite_diff1(f, x, eps, f_of_x = None):
if f_of_x is None: f_of_x = f(x)
y_eps = f(x+eps)
return (y_eps - f_of_x) / eps
def _scalar_f(op_cls, args, R, arg_idx, coord=None):
m = args[arg_idx].data
if () == m.shape:
def rval(x):
old_x = float(m)
m.itemset(x)
y = float(sum(mul_elemwise(R, op_cls(*args))).data)
m.itemset(old_x)
return y
return rval
else:
def rval(x):
old_x = m.__getitem__(coord)
#print old_x.shape
#print x.shape
m.__setitem__(coord, x)
y = float(sum(mul_elemwise(R, op_cls(*args))).data)
m.__setitem__(coord, old_x)
return y
return rval
self.failUnless(hasattr(op_cls, 'update_gradient'), op_cls)
op_out = op_cls(*args)
if len(op_out.owner.outputs) > 1:
raise NotImplementedError('cant autotest gradient of op with multiple outputs')
# we could make loop over outputs making random projections R for each,
# but this doesn't handle the case where not all the outputs are
# differentiable... so I leave this as TODO for now -jsb.
R = numpy.random.rand(*op_out.shape)
y = sum(mul_elemwise(R, op_out))
g = gradient.grad(y)
def abs_rel_err(a,b):
return abs( (a-b) / (a+b+eps))
for idx in range(len(args)):
#print 'aaaaaaa', op_cls, [i.shape for i in args]
g_i = g(args[idx])
if g_i is gradient.Undefined:
continue
if args[idx].shape == ():
fd_grad = _finite_diff1(_scalar_f(op_cls, args, R, idx),
args[idx].data, eps, y.data)
err = abs_rel_err(fd_grad,g_i.data)
self.failUnless( err < tol, (err, op_cls, idx))
elif len(args[idx].shape) == 1:
for i in xrange(args[idx].shape[0]):
fd_grad = _finite_diff1(_scalar_f(op_cls, args, R, idx, (i,)),
args[idx].data[i], eps, y.data)
err = abs_rel_err(fd_grad,g_i.data[i])
self.failUnless( abs(err) < tol, (err, op_cls, idx, i))
elif len(args[idx].shape) == 2:
for i in xrange(args[idx].shape[0]):
for j in xrange(args[idx].shape[1]):
fd_grad = _finite_diff1(_scalar_f(op_cls, args, R, idx, (i,j)),
args[idx].data[i,j], eps, y.data)
err = abs_rel_err(fd_grad,g_i.data[i,j])
self.failUnless( abs(err) < tol, (err, op_cls, idx, i, j))
else:
raise NotImplementedError()
def _testgrad_unary_elemwise_randnearzero(op_cls, n_tests=1,eps=0.000001, tol=0.0001):
class test_some_op_gradient(unittest.TestCase):
def setUp(self):
gof.lib.build_eval_mode()
numpy.random.seed([234,234,23333])
def tearDown(self):
gof.lib.pop_mode()
def test0(self):
"""Gradient Test with a small scalar"""
_test_grad(self, op_cls,
(Numpy2(data=(numpy.ones(()))*0.03),),
n_tests, eps, tol)
def test1(self):
"""Gradient Test with a medium scalar"""
_test_grad(self, op_cls,
(Numpy2(data=(numpy.ones(()))*1.03),),
n_tests, eps, tol)
def test2(self):
"""Gradient Test with a big scalar"""
_test_grad(self, op_cls,
(Numpy2(data=(numpy.ones(()))*90.03),),
n_tests, eps, tol)
def test3(self):
"""Gradient Test with a vector"""
_test_grad(self, op_cls,
(Numpy2(data=numpy.random.rand(3)+0.01),),
n_tests, eps, tol)
def test4(self):
"""Gradient Test with a matrix"""
_test_grad(self, op_cls,
(Numpy2(data=numpy.random.rand(2,3)*4),),
n_tests, eps, tol)
return test_some_op_gradient
neg_test = _testgrad_unary_elemwise_randnearzero(neg)
twice_test = _testgrad_unary_elemwise_randnearzero(twice)
exp_test = _testgrad_unary_elemwise_randnearzero(exp)
sqr_test = _testgrad_unary_elemwise_randnearzero(sqr)
sqrt_test = _testgrad_unary_elemwise_randnearzero(sqrt)
inv_test = _testgrad_unary_elemwise_randnearzero(inv_elemwise)
transpose_test = _testgrad_unary_elemwise_randnearzero(transpose)
def _testgrad_unary_elemwise_randpositive(op_cls, n_tests=1,eps=0.000001, tol=0.0001):
class test_some_op_gradient(unittest.TestCase):
def setUp(self):
gof.lib.build_eval_mode()
numpy.random.seed([234,234,23333])
def tearDown(self):
gof.lib.pop_mode()
def test0(self):
"""Gradient Test with a small scalar"""
_test_grad(self, op_cls,
(Numpy2(data=numpy.ones(())*0.03),),
n_tests, eps, tol)
def test1(self):
"""Gradient Test with a medium scalar"""
_test_grad(self, op_cls,
(Numpy2(data=numpy.ones(())*1.03),),
n_tests, eps, tol)
def test2(self):
"""Gradient Test with a big scalar"""
_test_grad(self, op_cls,
(Numpy2(data=numpy.ones(())*90.03),),
n_tests, eps, tol)
def test3(self):
"""Gradient Test with a vector"""
_test_grad(self, op_cls,
(Numpy2(data=numpy.random.rand(3)+0.01),),
n_tests, eps, tol)
def test4(self):
"""Gradient Test with a matrix"""
_test_grad(self, op_cls,
(Numpy2(data=numpy.random.rand(2,3)*4),),
n_tests, eps, tol)
return test_some_op_gradient
log_test = _testgrad_unary_elemwise_randpositive(log)
log2_test = _testgrad_unary_elemwise_randpositive(log2)
sqrt_test = _testgrad_unary_elemwise_randpositive(sqrt)
def _testgrad_binary_elemwise(op_cls, domain, n_tests=1,eps=0.000001, tol=0.0001):
class test_some_op_gradient(unittest.TestCase):
def setUp(self):
gof.lib.build_eval_mode()
numpy.random.seed([234,234,23333])
def tearDown(self):
gof.lib.pop_mode()
def mytest(self, *raw_args):
args = [Numpy2(data=d(a)) for a,d in zip(raw_args,domain)]
_test_grad(self, op_cls, args, n_tests, eps, tol)
def test0(self):
"""Gradient test low"""
self.mytest(numpy.zeros(()), numpy.zeros(()))
def test1(self):
"""Gradient test middle"""
self.mytest(numpy.ones(())*.5, numpy.ones(())*0.5)
def test2(self):
"""Gradient test high"""
self.mytest(numpy.ones(()), numpy.ones(()))
def test3(self):
"""Gradient test with a vector"""
self.mytest(numpy.random.rand(4),numpy.random.rand(4))
def test4(self):
"""Gradient test with a matrix"""
self.mytest(numpy.random.rand(3,2),numpy.random.rand(3,2))
return test_some_op_gradient
add_test = _testgrad_binary_elemwise(add_elemwise, [lambda x:(x-0.5)*50]*2)
sub_test = _testgrad_binary_elemwise(sub_elemwise, [lambda x:(x-0.5)*50]*2)
mul_test = _testgrad_binary_elemwise(mul_elemwise, [lambda x:(x-0.5)*50]*2)
div_test = _testgrad_binary_elemwise(div_elemwise, [lambda x:(x-0.4)*50]*2)
pow_test = _testgrad_binary_elemwise(pow_elemwise, [lambda x:x*10+0.01, lambda x:(x-0.5)*4])
def _testgrad_binary_scalar(op_cls, domain, n_tests=1,eps=0.000001, tol=0.0001):
class test_some_op_gradient(unittest.TestCase):
def setUp(self):
gof.lib.build_eval_mode()
numpy.random.seed([234,234,23333])
def tearDown(self):
gof.lib.pop_mode()
def mytest(self, *raw_args):
args = [Numpy2(data=domain[0](raw_args[0])),
Numpy2(data=_scalar(domain[1](raw_args[1])))]
#print repr(args[0].data), repr(args[1].data)
_test_grad(self, op_cls, args, n_tests, eps, tol)
def test0_low(self):
self.mytest(numpy.zeros(()), _scalar(0))
def test1_middle(self):
self.mytest(numpy.ones(())*.5, _scalar(0.5))
def test2_high(self):
self.mytest(numpy.ones(()), _scalar(1.0))
def test3_vector(self):
self.mytest(numpy.random.rand(4),_scalar(numpy.random.rand()))
def test4_matrix(self):
self.mytest(numpy.random.rand(3,2),_scalar(numpy.random.rand()))
test_some_op_gradient.__name__ = str(op_cls.__name__) + '_test'
return test_some_op_gradient
add_scalar_test = _testgrad_binary_scalar(add_scalar, [lambda x:(x-0.5)*50]*2)
mul_scalar_test = _testgrad_binary_scalar(mul_scalar, [lambda x:(x-0.5)*50]*2)
pow_scalar_l_test = _testgrad_binary_scalar(pow_scalar_l,
[lambda x:(x-0.5)*10, lambda x:(x+0.01)*10.0])
pow_scalar_r_test = _testgrad_binary_scalar(pow_scalar_r,
[lambda x:(x+0.01)*10, lambda x:(x-0.5)*10.0])
fill_test = _testgrad_binary_scalar(fill, [lambda x:(x-0.5)*50]*2)
class test_some_op_gradient(unittest.TestCase):
def setUp(self):
gof.lib.build_eval_mode()
numpy.random.seed([234,234,23333])
def tearDown(self):
gof.lib.pop_mode()
def mytest(self, *raw_args):
n_tests = 1
eps = 0.000001
tol=0.00001
args = [Numpy2(data=raw_args[0]),
Numpy2(data=raw_args[1])]
#print repr(args[0].data), repr(args[1].data)
_test_grad(self, dot, args, n_tests, eps, tol)
def test0(self):
"""Gradient test low"""
self.mytest(numpy.zeros(()), _scalar(0))
def test1(self):
"""Gradient test middle"""
self.mytest(_scalar(0.5), _scalar(0.5))
def test2(self):
"""Gradient test high"""
self.mytest(numpy.ones(()), _scalar(1.0))
def test3(self):
"""Gradient test dot with vectors"""
self.mytest(numpy.random.rand(4),numpy.random.rand(4))
def test4(self):
"""Gradient test dot with matrices"""
self.mytest(numpy.random.rand(3,2),numpy.random.rand(2,4))
def _notyet_test5(self):
"""Gradient test dot with 3d-tensor on left"""
self.mytest(numpy.random.rand(3,4,2),numpy.random.rand(2,5))
def _notyet_test6(self):
"""Gradient test dot with 3d-tensor on right"""
self.mytest(numpy.random.rand(4,2),numpy.random.rand(3,2,5))
class testCase_slicing(unittest.TestCase):
def setUp(self):
build_eval_mode()
def tearDown(self):
pop_mode()
def test_getitem0(self):
a = numpy.ones((4,4))
wa1 = wrap(a)[:,1]
try:
err = wa1 + a
except ValueError, e:
self.failUnless(str(e) == \
'The dimensions of the inputs do not match.',
'Wrong ValueError')
return
self.fail('add should not have succeeded')
def test_getitem1(self):
a = numpy.ones((4,4))
wa1 = wrap(a)[1]
self.failUnless(wa1.data.shape == (4,))
def test_getslice_0d_all(self):
"""Test getslice does not work on 0d array """
a = numpy.ones(())
try:
wa1 = wrap(a)[:]
except IndexError, e:
self.failUnless(str(e) == "0-d arrays can't be indexed.")
return
self.fail()
def test_getslice_1d_all(self):
"""Test getslice on 1d array"""
a = numpy.ones(4)
wa1 = wrap(a)[:]
self.failUnless(wa1.data.shape == (4,), 'wrong shape')
self.failUnless(numpy.all(wa1.data == a), 'unequal value')
a[1] = 3.4
self.failUnless(wa1.data[1] == 3.4, 'not a view')
try:
wa1[2] = 2.5
except TypeError, e:
self.failUnless("object does not support item assignment" in str(e))
return
self.fail()
def test_getslice_3d_all(self):
"""Test getslice on 3d array"""
a = numpy.ones((4,5,6))
wa1 = wrap(a)[:]
self.failUnless(wa1.data.shape == (4,5,6), 'wrong shape')
self.failUnless(numpy.all(wa1.data == a), 'unequal value')
a[1,1,1] = 3.4
self.failUnless(wa1.data[1,1,1] == 3.4, 'not a view')
def test_getslice_1d_some(self):
"""Test getslice on 1d array"""
a = numpy.ones(5)
wa1 = wrap(a)[1:3]
a[2] = 5.0
a[3] = 2.5
self.failUnless(wa1.data.shape == (2,))
self.failUnless(a[1] == wa1.data[0])
self.failUnless(a[2] == wa1.data[1])
def test_getslice_1d_step(self):
"""Test getslice on 1d array"""
a = numpy.ones(8)
wa1 = wrap(a)[0:8:2]
for i in xrange(8): a[i] = i
self.failUnless(wa1.shape == (4,))
for i in xrange(4):
self.failUnless(a[i*2] == wa1.data[i])
def test_getslice_3d_float(self):
"""Test getslice on 3d array"""
a = numpy.asarray(range(4*5*6))
a.resize((4,5,6))
wa1 = wrap(a)[1:3]
self.failUnless(wa1.shape == (2,5,6))
self.failUnless(numpy.all(a[1:3] == wa1.data))
a[1] *= -1.0
self.failUnless(numpy.all(a[1:3] == wa1.data))
def test_getslice_3d_one(self):
"""Test getslice on 3d array"""
a = numpy.asarray(range(4*5*6))
a.resize((4,5,6))
wa = wrap(a)
wa_123 = wa[1,2,3]
self.failUnless(wa_123.shape == (), wa_123.shape)
class test_Numpy2(unittest.TestCase):
def setUp(self):
build_eval_mode()
numpy.random.seed(44)
def tearDown(self):
pop_mode()
def test_0(self):
r = Numpy2()
def test_1(self):
o = numpy.ones((3,3))
r = Numpy2(data=o)
self.failUnless(r.data is o)
self.failUnless(r.shape == (3,3))
self.failUnless(str(r.dtype) == 'float64')
def test_2(self):
r = Numpy2(data=[(3,3),'int32'])
self.failUnless(r.data is None)
self.failUnless(r.shape == (3,3))
self.failUnless(str(r.dtype) == 'int32')
r.alloc()
self.failUnless(isinstance(r.data, numpy.ndarray))
self.failUnless(r.shape == (3,3))
self.failUnless(str(r.dtype) == 'int32')
def test_3(self):
a = Numpy2(data=numpy.ones((2,2)))
b = Numpy2(data=numpy.ones((2,2)))
c = add(a,b)
self.failUnless(_approx_eq(c, numpy.ones((2,2))*2))
def test_4(self):
ones = numpy.ones((2,2))
a = Numpy2(data=ones)
o = numpy.asarray(a)
self.failUnless((ones == o).all())
def test_5(self):
ones = numpy.ones((2,2))
self.failUnless(_approx_eq(Numpy2(data=ones), Numpy2(data=ones)))
class testCase_producer_build_mode(unittest.TestCase):
def test_0(self):
"""producer in build mode"""
build_mode()
a = ones(4)
self.failUnless(a.data is None, a.data)
self.failUnless(a.state is gof.result.Empty, a.state)
self.failUnless(a.shape == 4, a.shape)
self.failUnless(str(a.dtype) == 'float64', a.dtype)
pop_mode()
def test_1(self):
"""producer in build_eval mode"""
build_eval_mode()
a = ones(4)
self.failUnless((a.data == numpy.ones(4)).all(), a.data)
self.failUnless(a.state is gof.result.Computed, a.state)
self.failUnless(a.shape == (4,), a.shape)
self.failUnless(str(a.dtype) == 'float64', a.dtype)
pop_mode()
class testCase_add_build_mode(unittest.TestCase):
def setUp(self):
build_mode()
numpy.random.seed(44)
def tearDown(self):
pop_mode()
class testCase_dot(unittest.TestCase):
def setUp(self):
build_eval_mode()
numpy.random.seed(44)
def tearDown(self):
pop_mode()
@staticmethod
def rand(*args):
return numpy.random.rand(*args)
def cmp_dot(self,x,y):
def spec(x):
x = numpy.asarray(x)
return type(x), x.dtype, x.shape
zspec = dot.specs(spec(x), spec(y))
nz = numpy.dot(x,y)
self.failUnless(zspec == spec(nz))
self.failUnless(_approx_eq(dot(x,y), numpy.dot(x,y)))
def cmp_dot_comp(self, x,y):
x = numpy.asarray(x)
y = numpy.asarray(y)
z = dot(x,y)
p = compile.single(z)
if len(x.shape):
x[:] = numpy.random.rand(*x.shape)
else:
x.fill(numpy.random.rand(*x.shape))
if len(y.shape):
y[:] = numpy.random.rand(*y.shape)
else:
y.fill(numpy.random.rand(*y.shape))
p() # recalculate z
self.failUnless(_approx_eq(z, numpy.dot(x,y)))
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 test_dot_0d_0d_(self): self.cmp_dot_comp(1.1, 2.2)
def test_dot_0d_1d_(self): self.cmp_dot_comp(1.1, self.rand(5))
def test_dot_0d_2d_(self): self.cmp_dot_comp(3.0, self.rand(6,7))
def test_dot_0d_3d_(self): self.cmp_dot_comp(3.0, self.rand(8,6,7))
def test_dot_1d_0d_(self): self.cmp_dot_comp(self.rand(5), 1.1 )
def test_dot_1d_1d_(self): self.cmp_dot_comp(self.rand(5), self.rand(5))
def test_dot_1d_2d_(self): self.cmp_dot_comp(self.rand(6), self.rand(6,7))
def test_dot_1d_3d_(self): self.cmp_dot_comp(self.rand(6), self.rand(8,6,7))
def test_dot_2d_0d_(self): self.cmp_dot_comp(self.rand(5,6), 1.0)
def test_dot_2d_1d_(self): self.cmp_dot_comp(self.rand(5,6), self.rand(6))
def test_dot_2d_2d_(self): self.cmp_dot_comp(self.rand(5,6), self.rand(6,7))
def test_dot_2d_3d_(self): self.cmp_dot_comp(self.rand(5,6), self.rand(8,6,7))
def test_dot_3d_0d_(self): self.cmp_dot_comp(self.rand(4,5,6), 1.0)
def test_dot_3d_1d_(self): self.cmp_dot_comp(self.rand(4,5,6), self.rand(6))
def test_dot_3d_2d_(self): self.cmp_dot_comp(self.rand(4,5,6), self.rand(6,7))
def test_dot_3d_3d_(self): self.cmp_dot_comp(self.rand(4,5,6), self.rand(8,6,7))
def test_dot_fail_1_1(self):
x = numpy.random.rand(5)
y = numpy.random.rand(6)
try:
z = dot(x,y)
except ValueError, e:
self.failUnless(str(e) == 'objects are not aligned', e)
return
self.fail()
def test_dot_fail_1_2(self):
x = numpy.random.rand(5)
y = numpy.random.rand(6,4)
try:
z = dot(x,y)
except ValueError, e:
self.failUnless(str(e) == 'objects are not aligned', e)
return
self.fail()
def test_dot_fail_1_3(self):
x = numpy.random.rand(5)
y = numpy.random.rand(6,4,7)
try:
z = dot(x,y)
except ValueError, e:
self.failUnless(str(e) == 'objects are not aligned', e)
return
self.fail()
def test_dot_fail_2_1(self):
x = numpy.random.rand(5,4)
y = numpy.random.rand(6)
try:
z = dot(x,y)
except ValueError, e:
self.failUnless(str(e) == 'objects are not aligned', e)
return
self.fail()
def test_dot_fail_2_2(self):
x = numpy.random.rand(5,4)
y = numpy.random.rand(6,7)
try:
z = dot(x,y)
except ValueError, e:
self.failUnless(str(e) == 'objects are not aligned', e)
return
self.fail()
def test_dot_fail_2_3(self):
x = numpy.random.rand(5,4)
y = numpy.random.rand(6,7,8)
try:
z = dot(x,y)
except ValueError, e:
self.failUnless(str(e) == 'objects are not aligned', e)
return
self.fail()
def test_dot_fail_3_1(self):
x = numpy.random.rand(5,4,3)
y = numpy.random.rand(6)
try:
z = dot(x,y)
except ValueError, e:
self.failUnless(str(e) == 'objects are not aligned', e)
return
self.fail()
def test_dot_fail_3_2(self):
x = numpy.random.rand(5,4,3)
y = numpy.random.rand(6,7)
try:
z = dot(x,y)
except ValueError, e:
self.failUnless(str(e) == 'objects are not aligned', e)
return
self.fail()
def test_dot_fail_3_3(self):
x = numpy.random.rand(5,4,3)
y = numpy.random.rand(6,7,8)
try:
z = dot(x,y)
except ValueError, e:
self.failUnless(str(e) == 'objects are not aligned', e)
return
self.fail()
class testCase_transpose(unittest.TestCase):
def setUp(self):
build_eval_mode()
def tearDown(self):
pop_mode()
def test_1d_alias(self):
a = numpy.ones(10)
ta = transpose(a)
self.failUnless(ta.data.shape == a.shape)
self.failUnless(numpy.all(ta.data == a))
a[3] *= -1.0
self.failUnless(numpy.all(ta.data == a))
def test_1d_copy(self):
a = numpy.ones(10)
ta = transpose_copy(a)
self.failUnless(ta.data.shape == a.shape)
self.failUnless(numpy.all(ta.data == a))
a[3] *= -1.0
self.failIf(numpy.all(ta.data == a))
def test_2d_alias(self):
a = numpy.ones((10,3))
ta = transpose(a)
self.failUnless(ta.data.shape == (3,10))
def test_3d_alias(self):
a = numpy.ones((10,3,5))
ta = transpose(a)
self.failUnless(ta.data.shape == (5,3,10))
a[9,0,0] = 5.0
self.failUnless(ta.data[0,0,9] == 5.0)
def test_3d_copy(self):
a = numpy.ones((10,3,5))
ta = transpose_copy(a)
self.failUnless(ta.data.shape == (5,3,10))
a[9,0,0] = 5.0
self.failUnless(ta.data[0,0,9] == 1.0)
class testCase_power(unittest.TestCase):
def setUp(self):
build_eval_mode()
numpy.random.seed(44)
def tearDown(self):
pop_mode()
def test1(self):
r = numpy.random.rand(50)
exp_r = exp(r)
self.failUnless(exp_r.__array__().__class__ is numpy.ndarray)
def test_0(self):
r = numpy.random.rand(50)
exp_r = exp(r)
n_exp_r = numpy.exp(r)
self.failUnless( _approx_eq(exp_r, n_exp_r),
(exp_r, exp_r.data, n_exp_r,
numpy.max(numpy.abs(n_exp_r.__sub__(exp_r.__array__())))))
log_exp_r = log(exp_r)
self.failUnless( _approx_eq(log_exp_r, r), log_exp_r)
def test_1(self):
r = numpy.random.rand(50)
r2 = pow(r,2)
self.failUnless( _approx_eq(r2, r*r))
if __name__ == '__main__':
unittest.main()
if __name__ == '__main__':
unittest.main()
...@@ -690,6 +690,101 @@ pow = _scalar_switch(pow_elemwise, pow_scalar_r, pow_scalar_l) ...@@ -690,6 +690,101 @@ pow = _scalar_switch(pow_elemwise, pow_scalar_r, pow_scalar_l)
pow_inplace = _scalar_switch(pow_elemwise_inplace, pow_scalar_r_inplace) pow_inplace = _scalar_switch(pow_elemwise_inplace, pow_scalar_r_inplace)
#########################
# Linalg : Dot
#########################
class Dot(_Op):
nin=2
nout=1
@staticmethod
def broadcastable_rule(bx,by):
if len(bx) == 0: # x is a scalar
rval = by
else:
if len(by) >= 2: #y is a matrix or tensor
rval = bx[:-1] + by[:-2] + by[-1:]
elif len(by)==1: #y is vector
rval = bx[:-1]
else: #y is a scalar
rval = bx
return rval
def propagate_broadcastable(self, bx, by):
return [self.broadcastable_rule(bx,by)]
def impl(self, x, y):
return numpy.dot(x, y)
def grad(self, (x, y), gz):
return dot(gz, y.T), dot(x.T, gz)
if 0:
def c_support_code(self):
return blas.cblas_header_text()
def c_libs(self):
return blas.ldflags()
def c_impl(self, (_x, _y), (_z, )):
return blas.gemm_code('', '1.0', '0.0')
dot = _constructor(Dot)
class Gemm(_Op):
nin=5
nout=1
E_bcast = 'incompatible broadcastable flags'
def destroy_map(self):
return {self.out:[self.inputs[0]]}
def propagate_broadcastable(self, bz, ba, bx, by, bb):
if len(bz) != len(Dot.broadcastable_rule(bx,by)):
raise ValueError(Gemm.E_bcast, bz, bx, by)
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()
if 0:
def c_support_code(self):
return blas.cblas_header_text()
def c_libs(self):
return blas.ldflags()
def c_impl((_zin, _a, _x, _y, _b), (_z,)):
check_ab = """
{
if ((_a->descr->type_num != PyArray_DOUBLE)
&& (_a->descr->type_num != PyArray_FLOAT))
goto _dot_execute_fallback;
if ((_b->descr->type_num != PyArray_DOUBLE)
&& (_b->descr->type_num != PyArray_FLOAT))
goto _dot_execute_fallback;
}
"""
return blas.gemm_code( check_ab,
'(_a->descr->type_num == PyArray_FLOAT) ? (REAL)(((float*)_a->data)[0]) : (REAL)(((double*)_a->data)[0])',
'(_b->descr->type_num == PyArray_FLOAT) ? (REAL)(((float*)_b->data)[0]) : (REAL)(((double*)_b->data)[0])')
gemm = _constructor(Gemm)
if 0: if 0:
########################## ##########################
# Comparisons # Comparisons
......
from gof import Op, utils, Destroyer, Viewer
import gof.op
from tensor import *
###########################
#### Binary Operations ####
###########################
#########
## Dot ##
#########
class Dot(TensorOp):
@staticmethod
def _output_shape(xshape, yshape):
# This describes the logic to calculate numpy.dot(x, y).shape
# given x.shape and y.shape
if len(xshape) == 0: # x is a scalar
shape = yshape
else:
if len(yshape) >= 2: #y is a matrix or tensor
assert xshape[-1] == yshape[-2]
shape = tuple(xshape[:-1]+ yshape[:-2]+yshape[-1:])
elif len(yshape)==1: #y is vector
assert xshape[-1] == yshape[-1]
shape = tuple(xshape[:-1])
else: #y is a scalar
shape = xshape
return shape
def impl(self, x, y):
return numpy.dot(x, y)
def grad(self, (x, y), gz):
return dot(gz, transpose(y)), dot(transpose(x), gz)
def propagate_broadcastable(self, x, y):
assert len(x) == 2 and len(x) == len(y)
return [(x[0], y[1])]
def c_support_code(self):
return blas.cblas_header_text()
def c_libs(self):
return blas.ldflags()
def c_impl(self, (_x, _y), (_z, )):
return blas.gemm_code('', '1.0', '0.0')
############
## Others ##
############
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论