提交 cf80a8ef authored 作者: Yann N. Dauphin's avatar Yann N. Dauphin

added sparse dot

上级 11ee6cee
差异被折叠。
...@@ -26,6 +26,15 @@ from theano import tensor ...@@ -26,6 +26,15 @@ from theano import tensor
from theano.tensor.basic import _allclose from theano.tensor.basic import _allclose
def as_sparse_format(data, format):
if format == 'csc':
return scipy.sparse.csc_matrix(data)
elif format == 'csr':
return scipy.sparse.csr_matrix(data)
else:
raise NotImplementedError()
def eval_outputs(outputs): def eval_outputs(outputs):
return compile.function([], outputs)()[0] return compile.function([], outputs)()[0]
...@@ -513,6 +522,140 @@ class test_structureddot(unittest.TestCase): ...@@ -513,6 +522,140 @@ class test_structureddot(unittest.TestCase):
if not theano.config.mode in ["DebugMode", "DEBUG_MODE"]: if not theano.config.mode in ["DebugMode", "DEBUG_MODE"]:
self.assertFalse(theano_time > overhead_rtol*scipy_time + overhead_tol) self.assertFalse(theano_time > overhead_rtol*scipy_time + overhead_tol)
class DotTests(unittest.TestCase):
def setUp(self):
x_size = (10, 1000)
y_size = (1000, 10000)
self.x_csr = scipy.sparse.csr_matrix(numpy.random.binomial(1, 0.5, x_size), dtype=theano.config.floatX)
self.x_csc = scipy.sparse.csc_matrix(numpy.random.binomial(1, 0.5, x_size), dtype=theano.config.floatX)
self.y = numpy.asarray(numpy.random.uniform(-1, 1, y_size), dtype=theano.config.floatX)
self.y_csr = scipy.sparse.csr_matrix(numpy.random.binomial(1, 0.5, y_size), dtype=theano.config.floatX)
self.y_csc = scipy.sparse.csc_matrix(numpy.random.binomial(1, 0.5, y_size), dtype=theano.config.floatX)
def test_csr_dense(self):
x = theano.sparse.csr_matrix('x')
y = theano.tensor.matrix('y')
f_a = theano.function([x, y], theano.sparse.dot(x, y))
f_b = lambda x, y: x * y
assert abs(f_a(self.x_csr, self.y) - f_b(self.x_csr, self.y)).max() < 10**-4
def test_csc_dense(self):
x = theano.sparse.csc_matrix('x')
y = theano.tensor.matrix('y')
f_a = theano.function([x, y], theano.sparse.dot(x, y))
f_b = lambda x, y: x * y
assert abs(f_a(self.x_csc, self.y) - f_b(self.x_csc, self.y)).max() < 10**-4
def test_sparse_sparse(self):
for d1, d2 in [('float32', 'float32'),
('float32', 'float64'),
('float64', 'float32'),
('float64', 'float64'),
]:
for x_f, y_f in [('csc','csc'),
('csc','csr'),
('csr','csc'),
('csr','csr'),
]:
x = theano.sparse.SparseType(format=x_f, dtype=d1)('x')
y = theano.sparse.SparseType(format=x_f, dtype=d2)('x')
f_a = theano.function([x, y], theano.sparse.dot(x, y))
f_b = lambda x, y: x * y
vx = getattr(self,'x_'+x_f).astype(d1)
vy = getattr(self,'y_'+y_f).astype(d2)
assert abs(f_a(vx, vy) - f_b(vx, vy)).max() < 10**-4
class UsmmTests(unittest.TestCase):
def setUp(self):
x_size = (10, 200)
y_size = (200, 2000)
z_size = (x_size[0], y_size[1])
self.x = numpy.asarray(numpy.random.binomial(1, 0.5, x_size), dtype=theano.config.floatX)
self.y = numpy.asarray(numpy.random.uniform(-1, 1, y_size), dtype=theano.config.floatX)
self.z = numpy.asarray(numpy.random.uniform(-1, 1, z_size), dtype=theano.config.floatX)
def test(self):
def mat(format, name, dtype):
if format == 'dense':
return theano.tensor.matrix(name, dtype=dtype)
else:
return theano.sparse.matrix(format, name, dtype=dtype)
for dtype1 in ['float32', 'float64']:
for dtype2 in ['float32', 'float64']:
for dtype3 in ['float32', 'float64']:
for dtype4 in ['float32', 'float64']:
for format1 in ['dense', 'csc','csr']:
for format2 in ['dense', 'csc','csr']:
if format1 == 'dense' and format2 == 'dense':
# Usmm won't be used!
continue
x = mat(format1, 'x', dtype1)
y = mat(format2, 'y', dtype2)
a = theano.tensor.scalar('a', dtype=dtype3)
z = theano.tensor.shared(numpy.asarray(self.z,dtype=dtype4).copy())
f_b = lambda z, a, x, y: z - a * (x * y)
x_data = numpy.asarray(self.x, dtype = dtype1)
if format1 != 'dense':
x_data = as_sparse_format(x_data, format1)
y_data = numpy.asarray(self.y, dtype = dtype2)
if format2 != 'dense':
y_data = as_sparse_format(y_data, format2)
z_data = numpy.asarray(self.z, dtype = dtype3)
f_b_out = f_b(z_data, 1, x_data, y_data)
# Can it work inplace?
inplace = dtype4 == theano.scalar.upcast(dtype1, dtype2, dtype3)
# To make it easier to check the toposort
mode = theano.compile.mode.get_default_mode().excluding('fusion')
if inplace:
f_a = theano.function([a, x, y], [],
updates={ z : z - a * theano.sparse.dot(x, y)},
mode = mode)
f_a(1, x_data, y_data)
assert abs(z.get_value(borrow=True) - f_b_out).max() < 10**-4
else:
f_a = theano.function([a, x, y], z - a * theano.sparse.dot(x, y),
mode = mode)
f_a_out = f_a(1, x_data, y_data)
assert abs(f_a_out - f_b_out).max() < 10**-4
topo = f_a.maker.env.toposort()
if (y.type.dtype == theano.scalar.upcast(dtype1, dtype2, dtype3, dtype4)
and format1=='csc' and format2=='dense'):
assert sum([isinstance(node.op, tensor.Elemwise) and isinstance(node.op.scalar_op, theano.scalar.basic.Cast) for node in topo])==len(topo)-5
topo = [node for node in topo if not(isinstance(node.op, tensor.Elemwise) and isinstance(node.op.scalar_op, theano.scalar.basic.Cast))]
assert len(topo)==5, topo
# Usmm is tested at the same time in debugmode
# Check if the optimization local_usmm and local_usmm_csx is applied
assert isinstance(topo[0].op, theano.sparse.basic.CSMProperties)
assert isinstance(topo[1].op, theano.tensor.DimShuffle)
assert isinstance(topo[2].op, theano.tensor.Subtensor)
assert topo[3].op == theano.tensor.neg
assert isinstance(topo[4].op, theano.sparse.UsmmCscDense)
if inplace:
assert topo[4].op.inplace
else:
assert len(topo)==3, topo
assert isinstance(topo[0].op, theano.tensor.DimShuffle)
assert topo[1].op == theano.tensor.neg
assert isinstance(topo[2].op, theano.sparse.Usmm)
def test_shape_i(): def test_shape_i():
sparse_dtype = 'float32' sparse_dtype = 'float32'
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论