def perform(self, node, inp, out):
input, = inp
output, = out
axis = self.axis
if axis is None:
axis = list(range(input.ndim))
variable = input
to_reduce = reversed(sorted(axis))
if hasattr(self, 'acc_dtype') and self.acc_dtype is not None:
acc_dtype = self.acc_dtype
else:
acc_dtype = node.outputs[0].type.dtype
if to_reduce:
for dimension in to_reduce:
# If it's a zero-size array, use scalar_op.identity
# if available
if variable.shape[dimension] == 0:
if hasattr(self.scalar_op, 'identity'):
# Compute the shape of the output
v_shape = list(variable.shape)
del v_shape[dimension]
variable = numpy.empty(tuple(v_shape),
dtype=acc_dtype)
variable.fill(self.scalar_op.identity)
else:
raise ValueError((
"Input (%s) has zero-size on axis %s, but "
"self.scalar_op (%s) has no attribute 'identity'"
% (variable, dimension, self.scalar_op)))
else:
# Numpy 1.6 has a bug where you sometimes have to specify
# "dtype='object'" in reduce for it to work, if the ufunc
# was built with "frompyfunc". We need to find out if we
# are in one of these cases (only "object" is supported in
# the output).
if ((self.ufunc.ntypes == 1) and
(self.ufunc.types[0][-1] == 'O')):
variable = self.ufunc.reduce(variable, dimension,
dtype='object')
else:
variable = self.ufunc.reduce(variable, dimension,
dtype=acc_dtype)
variable = numpy.asarray(variable)
if numpy.may_share_memory(variable, input):
# perhaps numpy is clever for reductions of size 1?
# We don't want this.
variable = variable.copy()
output[0] = theano._asarray(variable,
dtype=node.outputs[0].type.dtype)
else:
# Force a copy
output[0] = numpy.array(variable, copy=True,
dtype=node.outputs[0].type.dtype)
评论列表
文章目录