提交 2c26f2f5 authored 作者: nouiz's avatar nouiz

Merge pull request #1248 from delallea/minor

Minor stuff
......@@ -420,8 +420,8 @@ else:
" want theano to use.")
default_openmp = count > 1
# Disable it by default for now as currently only the ConvOp support
# it And this cause slow down by default as we do not disable it for
# Disable it by default for now as currently only the ConvOp supports
# it, and this causes slowdown by default as we do not disable it for
# too small convolution.
default_openmp = False
......
......@@ -472,19 +472,22 @@ class NotScalarConstantError(Exception):
not a scalar constant.
"""
class EmptyConstantError(NotScalarConstantError):
"""
Raised by get_scalar_const_value if called on something that is a
zero dimensional constant.
"""
def get_scalar_constant_value(v):
"""return the constant scalar(0-D) value underlying variable `v`
If v is the output of dimshuffles, fills, allocs, rebroadcasts, cast
this function digs through them.
If `v` is not some view of constant scalar data, then raise a NotScalarConstantError.
If `v` is not some view of constant scalar data, then raise a
NotScalarConstantError.
:note: There may be another function similar to this one in the
code, but I'm not sure where it is.
......@@ -550,17 +553,19 @@ def get_scalar_constant_value(v):
return ret[0][0]
if isinstance(v.owner.op, Subtensor) and v.ndim == 0:
# This condition depends on Subtensor always embedding constant
# indices in the Op rather than making them inputs to the Apply node
# indices in the Op rather than making them inputs to the Apply
# node.
if isinstance(v.owner.inputs[0], TensorConstant) and \
len(v.owner.inputs) == 1:
try:
return v.owner.inputs[0].data.__getitem__(
tuple(v.owner.op.idx_list))
except IndexError:
raise IndexError(str(tuple(v.owner.op.idx_list))+" is not a valid index into " + \
raise IndexError(
str(tuple(v.owner.op.idx_list)) +
" is not a valid index into " +
str(v.owner.inputs[0].data))
# The index list 'idx_list' should have length the same
# shape as the input.
# TODO: implement the case where we take a scalar in a matrix
......@@ -624,8 +629,6 @@ def get_scalar_constant_value(v):
msg += 'x=%s' % str(x)
raise ValueError(msg)
if gp_broadcastable[idx]:
return numpy.asarray(1)
......@@ -666,7 +669,7 @@ class TensorType(Type):
self.dtype_specs() # error checking is done there
self.name = name
self.numpy_dtype = numpy.dtype(self.dtype)
self.sparse_grad = sparse_grad
self.sparse_grad = sparse_grad
def filter(self, data, strict=False, allow_downcast=None):
"""Convert `data` to something which can be associated to a
......@@ -1064,7 +1067,8 @@ class TensorType(Type):
PyErr_Format(PyExc_NotImplementedError,
"expected an aligned array of type %%ld "
"(%(type_num)s), got non-aligned array of type %%ld"
" with %%ld dimensions, with 3 last dims %%ld, %%ld, %%ld"
" with %%ld dimensions, with 3 last dims "
"%%ld, %%ld, %%ld"
" and 3 last strides %%ld %%ld, %%ld.",
(long int) %(type_num)s,
(long int) type_num_%(name)s,
......@@ -1124,7 +1128,8 @@ class TensorType(Type):
PyErr_Format(PyExc_NotImplementedError,
"c_sync: expected an aligned array of type %%ld "
"(%(type_num)s), got non-aligned array of type %%ld"
" with %%ld dimensions, with 3 last dims %%ld, %%ld, %%ld"
" with %%ld dimensions, with 3 last dims "
"%%ld, %%ld, %%ld"
" and 3 last strides %%ld %%ld, %%ld.",
(long int) %(type_num)s,
(long int) type_num_%(name)s,
......@@ -1751,7 +1756,7 @@ class _tensor_py_operators:
if advanced:
if (axis is not None
and numpy.all(a == slice(None) for a in args[:axis])
and numpy.all(a == slice(None) for a in args[axis+1:])
and numpy.all(a == slice(None) for a in args[axis + 1:])
and isinstance(args[axis], (
numpy.ndarray,
list,
......@@ -2417,7 +2422,8 @@ class SpecifyShape(Op):
@note: Maybe in the future we will never do the assert!
@note: We currently don't support specifying partial shape information.
@todo: test this op with sparse and cuda ndarray. Do c code for them too.
@todo: test this op with sparse and cuda ndarray.
Do C code for them too.
"""
view_map = {0: [0]}
......@@ -3184,11 +3190,13 @@ def real(z):
"""Return real component of complex-valued tensor `z`"""
_tensor_py_operators.real = property(real)
@_scal_elemwise_with_nfunc('imag', 1, -1)
def imag(z):
"""Return imaginary component of complex-valued tensor `z`"""
_tensor_py_operators.imag = property(imag)
@_scal_elemwise_with_nfunc('angle', 1, -1)
def angle(z):
"""Return polar-coordinate angle of complex-valued tensor `z`"""
......@@ -3308,8 +3316,10 @@ class Nonzero(gof.Op):
def grad(self, inp, grads):
return [grad_undefined(self, 0, inp[0])]
_nonzero = Nonzero()
def nonzero(a, return_matrix=False):
"""
Returns one of the following:
......@@ -3354,6 +3364,7 @@ def nonzero(a, return_matrix=False):
tuple_result = tuple([matrix_result[0]])
return tuple_result
def flatnonzero(a):
"""
Return a vector of indices that are non-zero in the flattened version of a.
......@@ -3380,6 +3391,7 @@ def flatnonzero(a):
raise ValueError('Nonzero only supports non-scalar arrays.')
return nonzero(a.flatten(), return_matrix=True)[0]
def nonzero_values(a):
"""
Return a vector of non-zero elements contained in the input array.
......@@ -3416,6 +3428,7 @@ def nonzero_values(a):
"""
return a.flatten()[flatnonzero(a)]
class Tri(gof.Op):
def __init__(self, dtype=None):
if dtype is None:
......@@ -3519,7 +3532,7 @@ def triu(m, k=0):
--------
tril : lower triangle of an array
"""
return m * (1 - tri(m.shape[0], m.shape[1], k=k-1, dtype=m.dtype))
return m * (1 - tri(m.shape[0], m.shape[1], k=k - 1, dtype=m.dtype))
class Eye(gof.Op):
......@@ -3964,9 +3977,10 @@ def var(input, axis=None, keepdims=False):
left in the result as dimensions with size one. With this option,
the result will broadcast correctly against the original tensor.
:note: It use the two-pass algorithm for more stable results.
:note: It uses the two-pass algorithm for more stable results.
https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Two-pass_algorithm
It exist other implementation that are even more stable, but probably slower.
There exist other implementations that are even more stable, but
probably slower.
"""
input_ndim = input.type.ndim
......@@ -4003,9 +4017,11 @@ def std(input, axis=None, keepdims=False):
the result will broadcast correctly against the
original tensor.
:note: It call var and var use the two-pass algorithm for more stable results.
:note: It calls `var()` and `var()` uses the two-pass algorithm for more
stable results.
https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Two-pass_algorithm
It exist other implementation that are even more stable, but probably slower.
There exist other implementations that are even more stable, but
probably slower.
"""
return sqrt(var(input=input, axis=axis, keepdims=keepdims))
......@@ -4354,8 +4370,6 @@ class Subtensor(Op):
if cond is true for an entry, does not flatten it.
"""
ret = []
def helper(entry):
......@@ -4369,7 +4383,6 @@ class Subtensor(Op):
for idx in idxs:
helper(idx)
return ret
@staticmethod
......@@ -4603,16 +4616,15 @@ class Subtensor(Op):
"""
return {
"c_prefix" : "PyArray",
"c_prefix": "PyArray",
"update_flags": ("PyArray_UpdateFlags(%(view_name)s,"
" NPY_ARRAY_C_CONTIGUOUS|"
"NPY_ARRAY_F_CONTIGUOUS);"),
"set_data" : "PyArray_set_data",
"set_dim" : "PyArray_set_dim",
"set_stride" : "PyArray_set_stride",
"strides_mul" : 1,
"view_name" : "xview" }
"set_data": "PyArray_set_data",
"set_dim": "PyArray_set_dim",
"set_stride": "PyArray_set_stride",
"strides_mul": 1,
"view_name": "xview"}
@staticmethod
def helper_c_code(node, name, inputs, outputs, sub, idx_list,
......@@ -5070,7 +5082,7 @@ def inc_subtensor(x, y, inplace=False, set_instead_of_inc=False,
if (x.broadcastable[dim + dim_offset]
and not y.broadcastable[dim]):
# It is acceptable to try to increment a subtensor with a
# a broadcastable dim with a tensor that is not broadcastable
# broadcastable dim with a tensor that is not broadcastable
# on that dimension. However, its length must then be 1.
# We insert a Rebroadcast Op to make sure it is the case.
y = addbroadcast(y, dim)
......@@ -5106,6 +5118,7 @@ def inc_subtensor(x, y, inplace=False, set_instead_of_inc=False,
else:
raise TypeError('x must be result of a subtensor operation')
class IncSubtensor(Op):
"""Increment a subtensor.
......@@ -5306,7 +5319,7 @@ class IncSubtensor(Op):
alloc_zview = self.make_view_array(z, view_ndim)
# On GPU, it takes two steps to make a view
link_zview = self.link_view_array(z, fail);
link_zview = self.link_view_array(z, fail)
#Make a first view on the output, as we will write into it.
build_view = """
......@@ -5367,8 +5380,6 @@ class IncSubtensor(Op):
if not isinstance(node.inputs[0].type, TensorType):
raise NotImplementedError()
def c_code_cache_version(self):
hv = Subtensor.helper_c_code_cache_version()
if hv:
......@@ -5826,8 +5837,8 @@ class Join(Op):
# Axis can also be a constant
if not isinstance(axis, int):
try:
# Note : `get_scalar_constant_value` returns a ndarray not a
# int
# Note : `get_scalar_constant_value` returns a ndarray not
# an int
axis = int(get_scalar_constant_value(axis))
except NotScalarConstantError:
......@@ -6197,8 +6208,9 @@ class Reshape(Op):
# Try to see if we can infer that y has a constant value of 1.
# If so, that dimension should be broadcastable.
try:
bcasts[index] = (hasattr(y, 'get_scalar_constant_value') and
y.get_scalar_constant_value() == 1)
bcasts[index] = (
hasattr(y, 'get_scalar_constant_value') and
y.get_scalar_constant_value() == 1)
except NotScalarConstantError:
pass
return gof.Apply(self, [x, shp], [tensor(x.type.dtype, bcasts)])
......@@ -6317,7 +6329,9 @@ class Reshape(Op):
%(fail)s;
}
if (!PyArray_ISALIGNED(%(z)s)) {
PyErr_Format(PyExc_RuntimeError, "PyArray_Newshape returned an object that isn't aligned!");
PyErr_Format(
PyExc_RuntimeError,
"PyArray_Newshape returned an object that isn't aligned!");
%(fail)s;
}
""" % locals()
......@@ -6917,9 +6931,11 @@ class AdvancedSubtensor1(Op):
if sparse_module_ref is None:
import theano.sparse as sparse_module_ref
rval1 = [sparse_module_ref.ConstructSparseFromList()((inputs[0]), gz, inputs[1])]
rval1 = [sparse_module_ref.ConstructSparseFromList()(
(inputs[0]), gz, inputs[1])]
else:
rval1 = [advanced_inc_subtensor1(zeros_like(inputs[0]), gz, inputs[1])]
rval1 = [advanced_inc_subtensor1(
zeros_like(inputs[0]), gz, inputs[1])]
return rval1 + [DisconnectedType()()] * (len(inputs) - 1)
def R_op(self, inputs, eval_points):
......@@ -7246,6 +7262,7 @@ class AdvancedIncSubtensor(Op):
*inputs[2:]).outputs
advanced_inc_subtensor = AdvancedIncSubtensor()
def take(a, indices, axis=None, mode='raise'):
a = as_tensor_variable(a)
indices = as_tensor_variable(indices)
......@@ -7480,6 +7497,7 @@ _dot = Dot()
pprint.assign(_dot, printing.OperatorPrinter(printing.special['middle_dot'],
-1, 'left'))
def dot(a, b):
"""
Computes the dot product of two variables. For two matrices, this is
......@@ -7525,12 +7543,11 @@ def dot(a, b):
return _dot(a, b)
#########################
# Linalg : TensorDot
#########################
def tensordot(a, b, axes = 2):
def tensordot(a, b, axes=2):
"""
Given two tensors a and b,tensordot computes a generalized dot product over
the provided axes. Theano's implementation reduces all expressions to
......@@ -7652,8 +7669,8 @@ def tensordot(a, b, axes = 2):
for s1 in range(axes, b.ndim):
b_shape_1 *= b.shape[s1]
a_reshaped = a.reshape((a_shape_0, a_shape_1), ndim = 2)
b_reshaped = b.reshape((b_shape_0, b_shape_1), ndim = 2)
a_reshaped = a.reshape((a_shape_0, a_shape_1), ndim=2)
b_reshaped = b.reshape((b_shape_0, b_shape_1), ndim=2)
return _dot(a_reshaped, b_reshaped).reshape(outshape, outndim)
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论