提交 2eb3a2c0 authored 作者: Rami Al-Rfou''s avatar Rami Al-Rfou'

Merge pull request #3 from viveksck/TheanoBugFix

Add a flag to decide which gradient should be returned from AdvSubtensor1
...@@ -8,9 +8,11 @@ http://www-users.cs.umn.edu/~saad/software/SPARSKIT/paper.ps ...@@ -8,9 +8,11 @@ http://www-users.cs.umn.edu/~saad/software/SPARSKIT/paper.ps
# Automatic methods for determining best sparse format? # Automatic methods for determining best sparse format?
import sys import sys
import numpy import numpy
import theano import theano
import scipy.sparse import scipy.sparse
from theano import gof, tensor, compile, scalar, config from theano import gof, tensor, compile, scalar, config
from theano.gof.python25 import all from theano.gof.python25 import all
from theano.gradient import DisconnectedType from theano.gradient import DisconnectedType
...@@ -18,6 +20,7 @@ from theano.sparse.utils import hash_from_sparse ...@@ -18,6 +20,7 @@ from theano.sparse.utils import hash_from_sparse
import theano.tests.unittest_tools as utt import theano.tests.unittest_tools as utt
from theano.gradient import grad_not_implemented from theano.gradient import grad_not_implemented
from theano.sparse.type import SparseType, _is_sparse from theano.sparse.type import SparseType, _is_sparse
from numpy.lib.stride_tricks import as_strided
sparse_formats = ['csc', 'csr'] sparse_formats = ['csc', 'csr']
...@@ -1754,8 +1757,8 @@ class AddSD(gof.op.Op): ...@@ -1754,8 +1757,8 @@ class AddSD(gof.op.Op):
%(z)s = (PyArrayObject *) PyArray_NewCopy(%(y)s, NPY_CORDER); %(z)s = (PyArrayObject *) PyArray_NewCopy(%(y)s, NPY_CORDER);
}else{ }else{
%(z)s = %(y)s; %(z)s = %(y)s;
Py_XINCREF(%(z)s);
} }
Py_XINCREF(%(z)s);
npy_intp N = PyArray_DIMS(%(_indptr)s)[0]-1; npy_intp N = PyArray_DIMS(%(_indptr)s)[0]-1;
const npy_int32 * __restrict__ indptr = (npy_int32 *)%(_indptr)s->data; const npy_int32 * __restrict__ indptr = (npy_int32 *)%(_indptr)s->data;
...@@ -3288,3 +3291,68 @@ class Usmm(gof.op.Op): ...@@ -3288,3 +3291,68 @@ class Usmm(gof.op.Op):
out[0] = rval out[0] = rval
usmm = Usmm() usmm = Usmm()
class ConstructSparseFromList(gof.Op):
"""Constructs a sparse matrix out of a list of 2-D matrix rows"""
def __hash__(self):
return hash((type(self)))
def __eq__(self, other):
return (type(self) == type(other))
def __str__(self):
return self.__class__.__name__
def make_node(self, x, y, ilist):
x_ = theano.tensor.as_tensor_variable(x)
y_ = theano.tensor.as_tensor_variable(y)
ilist_ = theano.tensor.as_tensor_variable(ilist)
if ilist_.type.dtype[:3] not in ('int', 'uin'):
raise TypeError('index must be integers')
if ilist_.type.ndim != 1:
raise TypeError('index must be vector')
if x_.type.ndim == 0:
raise TypeError('cannot index into a scalar')
if y_.type.ndim > x_.type.ndim:
raise TypeError('cannot construct sparse matrix as dimensions differ')
return gof.Apply(self, [x_, y_, ilist_], [theano.sparse.csc_matrix(dtype=x.dtype)])
def perform(self, node, inp, out_):
x, values, idx = inp
out, = out_
rows, cols = values.shape
assert rows == len(idx)
indptr = numpy.arange(cols + 1) * rows
indices = as_strided(idx,
strides=(0, idx.strides[0]),
shape = (cols, idx.shape[0])).flatten()
data = values.T.flatten()
out[0] = scipy.sparse.csc_matrix((data, indices, indptr), shape=x.shape,
dtype=x.dtype)
def infer_shape(self, node, ishapes):
x, y, ilist = ishapes
return [x]
def R_op(self, inputs, eval_points):
if None in eval_points[:2]:
return [None]
return self.make_node(eval_points[0], eval_points[1],
*inputs[2:]).outputs
def connection_pattern(self, node):
rval = [[True], [True], [False]]
return rval
def grad(self, inputs, grads):
g_output, = grads
x, y = inputs[:2]
idx_list = inputs[2:]
gx = g_output
gy = theano.tensor.advanced_subtensor1(g_output, *idx_list)
return [gx, gy] + [DisconnectedType()()] * len(idx_list)
...@@ -619,7 +619,7 @@ class TensorType(Type): ...@@ -619,7 +619,7 @@ class TensorType(Type):
Inf entries. (Used in `DebugMode`) Inf entries. (Used in `DebugMode`)
""" """
def __init__(self, dtype, broadcastable, name=None): def __init__(self, dtype, broadcastable, name=None, sparsegrad=False):
"""Initialize self.dtype and self.broadcastable. """Initialize self.dtype and self.broadcastable.
:Parameters: :Parameters:
...@@ -644,6 +644,7 @@ class TensorType(Type): ...@@ -644,6 +644,7 @@ class TensorType(Type):
self.dtype_specs() # error checking is done there self.dtype_specs() # error checking is done there
self.name = name self.name = name
self.numpy_dtype = numpy.dtype(self.dtype) self.numpy_dtype = numpy.dtype(self.dtype)
self.sparsegrad = sparsegrad
def filter(self, data, strict=False, allow_downcast=None): def filter(self, data, strict=False, allow_downcast=None):
"""Convert `data` to something which can be associated to a """Convert `data` to something which can be associated to a
...@@ -6523,7 +6524,10 @@ class AdvancedSubtensor1(Op): ...@@ -6523,7 +6524,10 @@ class AdvancedSubtensor1(Op):
gz, = grads gz, = grads
assert len(inputs) == 2 assert len(inputs) == 2
rval1 = [ConstructSparse()(inputs[0], gz, inputs[1])] if inputs[0].type.sparsegrad:
rval1 = [theano.sparse.ConstructSparseFromList()((inputs[0]), gz, inputs[1])]
else:
rval1 = [advanced_inc_subtensor1(zeros_like(inputs[0]), gz, inputs[1])]
return rval1 + [DisconnectedType()()] * (len(inputs) - 1) return rval1 + [DisconnectedType()()] * (len(inputs) - 1)
def R_op(self, inputs, eval_points): def R_op(self, inputs, eval_points):
...@@ -6535,81 +6539,6 @@ class AdvancedSubtensor1(Op): ...@@ -6535,81 +6539,6 @@ class AdvancedSubtensor1(Op):
x, ilist = ishapes x, ilist = ishapes
return [ilist + x[1:]] return [ilist + x[1:]]
class ConstructSparse(Op):
"""Constructs a sparse matrix out of a list of 2-D matrix rows"""
def __init__(self):
import scipy.sparse as ssparse
from numpy.lib.stride_tricks import as_strided
self.m_ssparse = ssparse
self.m_as_strided = as_strided
def __hash__(self):
return hash((type(self)))
def __eq__(self, other):
return (type(self) == type(other))
def __str__(self):
return self.__class__.__name__
def make_node(self, x, y, ilist):
x_ = as_tensor_variable(x)
y_ = as_tensor_variable(y)
ilist_ = as_tensor_variable(ilist)
if ilist_.type.dtype[:3] not in ('int', 'uin'):
raise TypeError('index must be integers')
if ilist_.type.ndim != 1:
raise TypeError('index must be vector')
if x_.type.ndim == 0:
raise TypeError('cannot index into a scalar')
if y_.type.ndim > x_.type.ndim:
raise TypeError('cannot construct sparse matrix as dimensions differ')
return Apply(self, [x_, y_, ilist_], [theano.sparse.csc_matrix(dtype=x.dtype)])
def perform(self, node, inp, out_):
x, values, idx = inp
out, = out_
rows, cols = values.shape
assert rows == len(idx)
indptr = numpy.arange(cols + 1) * rows
indices = self.m_as_strided(idx,
strides=(0, idx.strides[0]),
shape = (cols, idx.shape[0])).flatten()
data = values.T.flatten()
out[0] = self.m_ssparse.csc_matrix((data, indices, indptr), shape=x.shape,
dtype=x.dtype)
def infer_shape(self, node, ishapes):
x, y, ilist = ishapes
return [x]
def R_op(self, inputs, eval_points):
if None in eval_points[:2]:
return [None]
return self.make_node(eval_points[0], eval_points[1],
*inputs[2:]).outputs
def connection_pattern(self, node):
rval = [[True], [True]]
for ipt in node.inputs[2:]:
rval.append([False])
return rval
def grad(self, inputs, grads):
g_output, = grads
x, y = inputs[:2]
idx_list = inputs[2:]
gx = g_output
gy = advanced_subtensor1(g_output, *idx_list)
return [gx, gy] + [DisconnectedType()()] * len(idx_list)
advanced_subtensor1 = AdvancedSubtensor1() advanced_subtensor1 = AdvancedSubtensor1()
...@@ -6700,11 +6629,7 @@ class AdvancedIncSubtensor1(Op): ...@@ -6700,11 +6629,7 @@ class AdvancedIncSubtensor1(Op):
def connection_pattern(self, node): def connection_pattern(self, node):
rval = [[True], [True]] rval = [[True], [True], [False]]
for ipt in node.inputs[2:]:
rval.append([False])
return rval return rval
def grad(self, inputs, grads): def grad(self, inputs, grads):
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论