提交 2e2b0901 authored 作者: james@mackie's avatar james@mackie

added ones_like, zeros_like, misc unittests

上级 216fab0b
import os # for building the location of the .omega/omega_compiled cache directory import os # for building the location of the .omega/omega_compiled cache directory
import sys # for adding the inline code cache to the include path import sys # for adding the inline code cache to the include path
import platform # import platform #
import unittest
import os import weakref
import sys import inspect
import md5
import copy
import gof import gof
from gof import current_mode, set_mode, build_mode, eval_mode, build_eval_mode, pop_mode, UNCOMPUTED, UNDEFINED, PythonR from gof import current_mode, set_mode, build_mode, eval_mode, build_eval_mode, pop_mode, UNCOMPUTED, UNDEFINED, PythonR
...@@ -12,13 +14,8 @@ import type_spec ...@@ -12,13 +14,8 @@ import type_spec
import cutils import cutils
import numpy import numpy
import weakref
import inspect
import md5
from scipy import weave from scipy import weave
from copy import copy as pycopy
# __all__ = ['set_mode', 'get_mode', 'NumpyR', 'NumpyOp'] # __all__ = ['set_mode', 'get_mode', 'NumpyR', 'NumpyOp']
...@@ -40,7 +37,8 @@ def print_graph(*rs): ...@@ -40,7 +37,8 @@ def print_graph(*rs):
literals_db = {} literals_db = {}
literals_id_db = weakref.WeakValueDictionary() #literals_id_db = weakref.WeakValueDictionary()
literals_id_db = {}
#input floating point scalars will be cast to arrays of this type #input floating point scalars will be cast to arrays of this type
# see TRAC(#31) # see TRAC(#31)
...@@ -170,6 +168,7 @@ def _literal_unhashable(x): ...@@ -170,6 +168,7 @@ def _literal_unhashable(x):
return r return r
def literal(x): def literal(x):
"""Return a PythonR instance wrapping a literal."""
if _hashable(x): if _hashable(x):
return _literal_hashable(x) return _literal_hashable(x)
else: else:
...@@ -624,7 +623,7 @@ class elemwise(omega_op): ...@@ -624,7 +623,7 @@ class elemwise(omega_op):
else: else:
res = cls._impl(self) res = cls._impl(self)
if isinstance(res, (list, tuple)): if isinstance(res, (list, tuple)):
res = pycopy(res) res = copy.copy(res)
else: else:
res = [res] res = [res]
for output, input in dmap.items(): for output, input in dmap.items():
...@@ -645,7 +644,6 @@ class elemwise(omega_op): ...@@ -645,7 +644,6 @@ class elemwise(omega_op):
C.__name__ = cls.__name__ + "_inplace%s" % dmap C.__name__ = cls.__name__ + "_inplace%s" % dmap
return C return C
def scalar_switch(normal_f, scalar_f, scalar_f_reverse = None): def scalar_switch(normal_f, scalar_f, scalar_f_reverse = None):
def f(x, y): def f(x, y):
x, y = wrap(x), wrap(y) x, y = wrap(x), wrap(y)
...@@ -659,7 +657,6 @@ def scalar_switch(normal_f, scalar_f, scalar_f_reverse = None): ...@@ -659,7 +657,6 @@ def scalar_switch(normal_f, scalar_f, scalar_f_reverse = None):
return normal_f(x, y) return normal_f(x, y)
return f return f
class NumpyR(gof.PythonR): class NumpyR(gof.PythonR):
"""The class for storing ndarray return values from omega ops. """The class for storing ndarray return values from omega ops.
The class provides additional functionality compared to the normal PythonR: The class provides additional functionality compared to the normal PythonR:
...@@ -723,8 +720,8 @@ class NumpyR(gof.PythonR): ...@@ -723,8 +720,8 @@ class NumpyR(gof.PythonR):
def __copy__(self): return array_copy(self) def __copy__(self): return array_copy(self)
#def __getitem__(self, item): return get_slice(self, item) def __getitem__(self, item): return get_slice(self, item)
#def __getslice__(self, item): return get_slice(self, item) def __getslice__(self, *args): return get_slice(self, slice(*args))
def wrap_producer(f): def wrap_producer(f):
...@@ -803,7 +800,7 @@ class twice(elemwise): ...@@ -803,7 +800,7 @@ class twice(elemwise):
def c_foreach((x_i, ), (z_i, )): def c_foreach((x_i, ), (z_i, )):
"z_i = x_i + x_i;" "z_i = x_i + x_i;"
itwice = twice.inplace_version() twice_inplace = twice.inplace_version()
## Subtraction ## ## Subtraction ##
...@@ -841,49 +838,6 @@ mul_elemwise_inplace = mul_elemwise.inplace_version() ...@@ -841,49 +838,6 @@ mul_elemwise_inplace = mul_elemwise.inplace_version()
mul_elemwise_inplace.set_impl(assert_same_shapes(numpy.ndarray.__imul__)) mul_elemwise_inplace.set_impl(assert_same_shapes(numpy.ndarray.__imul__))
class scale(tensor_scalar_op):
impl = tensor_scalar_impl(numpy.ndarray.__mul__)
def grad(x, a, gz):
return scale(a, gz), sum(mul_elemwise(x, gz))
c_expr = "x_i * a"
scale_inplace = scale.inplace_version()
scale_inplace.set_impl(tensor_scalar_impl(numpy.ndarray.__imul__))
class sqr(elemwise):
def impl(x):
return x * x
def grad(x, gz):
return scale(mul_elemwise(x, gz), 2.0)
def c_foreach((x_i, ), (z_i, )):
return "z_i = x_i * x_i;"
isqr = sqr.inplace_version()
isqr.set_impl(lambda x: x.__imul__(x))
class sqrt(elemwise):
impl = numpy.sqrt
def grad(x, gz):
return scale(div(gz, sqrt(x)), 0.5)
def c_foreach((x_i, ), (z_i, )):
return "z_i = pow(x_i, 0.5);"
isqrt = sqrt.inplace_version()
isqrt.set_impl(lambda x: x.__ipow__(0.5))
## Exponentiation ##
class exp(elemwise):
impl = numpy.exp
def c_foreach((x_i, ), (z_i, )):
return "z_i = exp(x_i);"
## Element-wise division ## ## Element-wise division ##
class div_elemwise(elemwise): class div_elemwise(elemwise):
...@@ -909,6 +863,16 @@ def div_scalar_r_inplace(x, a): ...@@ -909,6 +863,16 @@ def div_scalar_r_inplace(x, a):
## Scaling ## ## Scaling ##
class scale(tensor_scalar_op):
impl = tensor_scalar_impl(numpy.ndarray.__mul__)
def grad(x, a, gz):
return scale(a, gz), sum(mul_elemwise(x, gz))
c_expr = "x_i * a"
scale_inplace = scale.inplace_version()
scale_inplace.set_impl(tensor_scalar_impl(numpy.ndarray.__imul__))
class neg(elemwise): class neg(elemwise):
impl = numpy.ndarray.__neg__ impl = numpy.ndarray.__neg__
def grad(x, gz): def grad(x, gz):
...@@ -916,8 +880,8 @@ class neg(elemwise): ...@@ -916,8 +880,8 @@ class neg(elemwise):
def c_foreach((x_i, ), (z_i, )): def c_foreach((x_i, ), (z_i, )):
return "z_i = -x_i;" return "z_i = -x_i;"
ineg = neg.inplace_version() neg_inplace = neg.inplace_version()
ineg.set_impl(lambda x: x.__imul__(-1)) neg_inplace.set_impl(lambda x: x.__imul__(-1))
class inv_elemwise(elemwise): class inv_elemwise(elemwise):
...@@ -927,7 +891,7 @@ class inv_elemwise(elemwise): ...@@ -927,7 +891,7 @@ class inv_elemwise(elemwise):
def c_foreach((x_i, ), (z_i, )): def c_foreach((x_i, ), (z_i, )):
return "z_i = 1 / x_i;" return "z_i = 1 / x_i;"
iinv_elemwise = inv_elemwise.inplace_version() inv_elemwise_inplace = inv_elemwise.inplace_version()
## Dot product ## ## Dot product ##
...@@ -1167,6 +1131,7 @@ class gemm(omega_op, inplace): ...@@ -1167,6 +1131,7 @@ class gemm(omega_op, inplace):
'(_a->descr->type_num == PyArray_FLOAT) ? (REAL)(((float*)_a->data)[0]) : (REAL)(((double*)_a->data)[0])', '(_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])') '(_b->descr->type_num == PyArray_FLOAT) ? (REAL)(((float*)_b->data)[0]) : (REAL)(((double*)_b->data)[0])')
## Transposition ## ## Transposition ##
class transpose(omega_op, view): class transpose(omega_op, view):
...@@ -1260,6 +1225,48 @@ class transpose(omega_op, view): ...@@ -1260,6 +1225,48 @@ class transpose(omega_op, view):
def transpose_copy(x): def transpose_copy(x):
return array_copy(transpose(x)) return array_copy(transpose(x))
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)
## Copy ## ## Copy ##
...@@ -1272,13 +1279,38 @@ class array_copy(elemwise): ...@@ -1272,13 +1279,38 @@ class array_copy(elemwise):
## Power ## ## Power ##
class sqr(elemwise):
def impl(x):
return x * x
def grad(x, gz):
return scale(mul_elemwise(x, gz), 2.0)
def c_foreach((x_i, ), (z_i, )):
return "z_i = x_i * x_i;"
sqr_inplace = sqr.inplace_version()
sqr_inplace.set_impl(lambda x: x.__imul__(x))
class sqrt(elemwise):
impl = numpy.sqrt
def grad(x, gz):
return scale(div(gz, sqrt(x)), 0.5)
def c_foreach((x_i, ), (z_i, )):
return "z_i = pow(x_i, 0.5);"
sqrt_inplace = sqrt.inplace_version()
sqrt_inplace.set_impl(lambda x: x.__ipow__(0.5))
class exp(elemwise): class exp(elemwise):
def impl(x): return numpy.exp(x) def impl(x): return numpy.exp(x)
def grad(x, gz): return gz * exp(x) def grad(x, gz): return gz * exp(x)
def c_foreach((x_i, ), (z_i, )): return "z_i = exp(x_i);"
class log(elemwise): class log(elemwise):
def impl(x): return numpy.log(x) def impl(x): return numpy.log(x)
def grad(x, gz): return gz / x def grad(x, gz): return gz / x
def c_foreach((x_i, ), (z_i, )): return "z_i = log(x_i);"
class pow_elemwise(elemwise): class pow_elemwise(elemwise):
impl = assert_same_shapes(numpy.ndarray.__pow__) impl = assert_same_shapes(numpy.ndarray.__pow__)
...@@ -1309,6 +1341,21 @@ class pow_scalar_r(tensor_scalar_op): ...@@ -1309,6 +1341,21 @@ class pow_scalar_r(tensor_scalar_op):
pow_scalar_r_inplace = pow_scalar_r.inplace_version() pow_scalar_r_inplace = pow_scalar_r.inplace_version()
pow_scalar_r_inplace.set_impl(tensor_scalar_impl(numpy.ndarray.__ipow__)) pow_scalar_r_inplace.set_impl(tensor_scalar_impl(numpy.ndarray.__ipow__))
class _testCase_power(unittest.TestCase):
def setUp(self):
build_eval_mode()
numpy.random.seed(44)
def tearDown(self):
pop_mode()
def test_0(self):
r = numpy.random.rand(50)
er = exp(r)
ler = log(er)
a,b = numpy.max(ler-r), numpy.min(ler-r)
self.failUnless(a < 1.0e-13 and b > -1.0e-13, 'exp and log are not inverses')
## Others ## ## Others ##
...@@ -1346,7 +1393,7 @@ class fill(elemwise): ...@@ -1346,7 +1393,7 @@ class fill(elemwise):
def c_foreach((model_i, value), (z_i, )): def c_foreach((model_i, value), (z_i, )):
return "z_i = value0;" return "z_i = value0;"
ifill = fill.inplace_version() fill_inplace = fill.inplace_version()
class sum(elemwise): class sum(elemwise):
impl = numpy.sum impl = numpy.sum
...@@ -1359,6 +1406,103 @@ class sum(elemwise): ...@@ -1359,6 +1406,103 @@ class sum(elemwise):
def c_foreach((x_i, ), (sum, )): def c_foreach((x_i, ), (sum, )):
return "sump[0] += x_i;" return "sump[0] += x_i;"
class ones_like(elemwise):
impl = numpy.ones_like
def grad(x, gz): return UNDEFINED
class zeros_like(elemwise):
impl = numpy.zeros_like
def grad(x, gz): return UNDEFINED
## Array slicing ##
class get_slice(omega_op, view):
def impl(x, item): return x.__getitem__(item)
def grad(x, gz): raise NotImplemented
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(e.message == \
'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]
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(e.message == "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(e.message == "'NumpyR' object does not support item assignment")
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.data.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]
wa1.data.shape
self.failUnless(numpy.all(a[1:3] == wa1.data))
a[1] *= -1.0
self.failUnless(numpy.all(a[1:3] == wa1.data))
add = scalar_switch(add_elemwise, add_scalar, add_scalar) add = scalar_switch(add_elemwise, add_scalar, add_scalar)
add_inplace = scalar_switch(add_elemwise_inplace, add_scalar_inplace) add_inplace = scalar_switch(add_elemwise_inplace, add_scalar_inplace)
...@@ -1376,3 +1520,6 @@ pow = scalar_switch(pow_elemwise, pow_scalar_r, pow_scalar_l) ...@@ -1376,3 +1520,6 @@ 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)
if __name__ == '__main__':
unittest.main()
...@@ -205,11 +205,15 @@ class PythonOp(Op): ...@@ -205,11 +205,15 @@ class PythonOp(Op):
for input in self.inputs: for input in self.inputs:
if input not in exc: if input not in exc:
self.check_input(input) self.check_input(input)
if 0:
#J- why is this try catch here? Leftover debug?
try: try:
results = self._impl() results = self._impl()
except Exception, e: except Exception, e:
print "Error in %s: %s" % (self, e) print "Error in %s: %s" % (self, e)
raise raise
else:
results = self._impl()
if self.nout == 1: if self.nout == 1:
self.out.set_value(results) self.out.set_value(results)
else: else:
......
...@@ -331,4 +331,3 @@ class _testCase (unittest.TestCase): ...@@ -331,4 +331,3 @@ class _testCase (unittest.TestCase):
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论