提交 6ff2fca5 authored 作者: Razvan Pascanu's avatar Razvan Pascanu

merge

...@@ -656,49 +656,36 @@ computations. If you would like to update the value of a ...@@ -656,49 +656,36 @@ computations. If you would like to update the value of a
Elementwise Elementwise
=========== ===========
.. _libdoc_tensor_broadcastable: Casting
-------
Broadcasting in Theano vs. Numpy
--------------------------------
Broadcasting is a mechanism which allows tensors with
different numbers of dimensions to be added or multiplied
together by (virtually) replicating the smaller tensor along
the dimensions that it is lacking.
Broadcasting is the mechanism by which a scalar
may be added to a matrix, a vector to a matrix or a scalar to
a vector.
.. figure:: bcast.png .. function:: cast(x, dtype)
Broadcasting a row matrix. T and F respectively stand for Cast any tensor `x` to a Tensor of the same shape, but with a different
True and False and indicate along which dimensions we allow numerical type `dtype`.
broadcasting.
If the second argument were a vector, its shape would be This is not a reinterpret cast, but a coersion cast, similar to
``(2,)`` and its broadcastable pattern ``(F,)``. They would ``numpy.asarray(x, dtype=dtype)``.
be automatically expanded to the **left** to match the
dimensions of the matrix (adding ``1`` to the shape and ``T``
to the pattern), resulting in ``(1, 2)`` and ``(T, F)``.
It would then behave just like the example above.
.. code-block:: python
Unlike numpy which does broadcasting dynamically, Theano needs import theano.tensor as T
to know, for any operation which supports broadcasting, which x_as_float = T.matrix()
dimensions will need to be broadcasted. When applicable, this x_as_int = T.cast(x, 'int32')
information is given in the :ref:`type` of a *Variable*.
See also:
* `SciPy documentation about numpy's broadcasting <http://www.scipy.org/EricsBroadcastingDoc>`_ Attempting to casting a complex value to a real value is ambiguous and
will raise an exception. Use `real()`, `imag()`, `abs()`, or `angle()`.
* `OnLamp article about numpy's broadcasting <http://www.onlamp.com/pub/a/python/2000/09/27/numerically.html>`_ .. function:: real(x)
Return the real (not imaginary) components of Tensor x.
For non-complex `x` this function returns x.
.. function:: imag(x)
Casting Return the imaginary components of Tensor x.
------- For non-complex `x` this function returns zeros_like(x).
Comparisons Comparisons
------------ ------------
...@@ -774,6 +761,13 @@ Condition ...@@ -774,6 +761,13 @@ Condition
x,y = T.dmatrices('x','y') x,y = T.dmatrices('x','y')
z = T.switch(T.lt(a,b), x, y) z = T.switch(T.lt(a,b), x, y)
.. function:: clip(x, min, max)
Return a variable representing x, but with all elements greater than
`max` clipped to `max` and all elements less than `min` clipped to `min.
Normal broadcasting rules apply to each of `x`, `min`, and `max`.
Bit-wise Bit-wise
-------- --------
...@@ -824,6 +818,10 @@ Mathematical ...@@ -824,6 +818,10 @@ Mathematical
.. note:: Can also be accessed with ``abs(a)``. .. note:: Can also be accessed with ``abs(a)``.
.. function:: angle(a)
Returns a variable representing angular component of complex-valued Tensor `a`.
.. function:: exp(a) .. function:: exp(a)
Returns a variable representing the exponential of a, ie e^a. Returns a variable representing the exponential of a, ie e^a.
...@@ -873,6 +871,48 @@ Mathematical ...@@ -873,6 +871,48 @@ Mathematical
Returns a variable representing the hyperbolic trigonometric functions of a (hyperbolic cosine, sine and tangent). Returns a variable representing the hyperbolic trigonometric functions of a (hyperbolic cosine, sine and tangent).
.. _libdoc_tensor_broadcastable:
Broadcasting in Theano vs. Numpy
--------------------------------
Broadcasting is a mechanism which allows tensors with
different numbers of dimensions to be added or multiplied
together by (virtually) replicating the smaller tensor along
the dimensions that it is lacking.
Broadcasting is the mechanism by which a scalar
may be added to a matrix, a vector to a matrix or a scalar to
a vector.
.. figure:: bcast.png
Broadcasting a row matrix. T and F respectively stand for
True and False and indicate along which dimensions we allow
broadcasting.
If the second argument were a vector, its shape would be
``(2,)`` and its broadcastable pattern ``(F,)``. They would
be automatically expanded to the **left** to match the
dimensions of the matrix (adding ``1`` to the shape and ``T``
to the pattern), resulting in ``(1, 2)`` and ``(T, F)``.
It would then behave just like the example above.
Unlike numpy which does broadcasting dynamically, Theano needs
to know, for any operation which supports broadcasting, which
dimensions will need to be broadcasted. When applicable, this
information is given in the :ref:`type` of a *Variable*.
See also:
* `SciPy documentation about numpy's broadcasting <http://www.scipy.org/EricsBroadcastingDoc>`_
* `OnLamp article about numpy's broadcasting <http://www.onlamp.com/pub/a/python/2000/09/27/numerically.html>`_
Linear Algebra Linear Algebra
============== ==============
...@@ -939,7 +979,4 @@ Gradient / Differentiation ...@@ -939,7 +979,4 @@ Gradient / Differentiation
Full Constructor List
======================
...@@ -896,9 +896,6 @@ class Clip(ScalarOp): ...@@ -896,9 +896,6 @@ class Clip(ScalarOp):
return max return max
else: else:
return x return x
#backport
#return min if x < min else max if x > max else x
def c_code(self, node, name, (x, min, max), (z, ), sub): def c_code(self, node, name, (x, min, max), (z, ), sub):
return "%(z)s = %(x)s < %(min)s ? %(min)s : %(x)s > %(max)s ? %(max)s : %(x)s;" % locals() return "%(z)s = %(x)s < %(min)s ? %(min)s : %(x)s > %(max)s ? %(max)s : %(x)s;" % locals()
def grad(self, (x, min, max), (gz, )): def grad(self, (x, min, max), (gz, )):
...@@ -907,9 +904,7 @@ class Clip(ScalarOp): ...@@ -907,9 +904,7 @@ class Clip(ScalarOp):
return gx, None, None return gx, None, None
else: else:
return None, None, None return None, None, None
clip = Clip(upcast_out, name = 'clip')
#return gx if x.type in grad_types else None, None, None
clip = Clip(transfer_type(0), name = 'clip')
class First(BinaryScalarOp): class First(BinaryScalarOp):
def impl(self, x, y): def impl(self, x, y):
......
...@@ -1633,6 +1633,11 @@ def imag(x): ...@@ -1633,6 +1633,11 @@ def imag(x):
else: else:
return zeros_like(x) return zeros_like(x)
@constructor
def angle(x):
"""Return the angular component of complex-valued `x`"""
raise NotImplementedError()
########################## ##########################
# Misc # Misc
...@@ -1738,8 +1743,36 @@ def prod(input, axis = None): ...@@ -1738,8 +1743,36 @@ def prod(input, axis = None):
"""WRITEME""" """WRITEME"""
return elemwise.Prod(axis)(input) return elemwise.Prod(axis)(input)
class Mean(elemwise.CAReduce):
def __init__(self, axis = None):
elemwise.CAReduce.__init__(self, scal.add, axis)
def __str__(self):
if self.axis is not None:
return "Mean{%s}" % (", ".join(str(x) for x in self.axis))
else:
return "Mean"
def _output_dtype(self, idtype):
# we want to protect against overflow
return 'float64'
def perform(self, node, (input, ), (output, )):
ret = elemwise.CAReduce.perform(self,node,(input,),(output,))
output[0]=numpy.asarray(output[0]/len(input))
def c_code(self, node, name, inames, onames, sub):
ret = elemwise.CAReduce.c_code(self, node, name, inames, onames, sub)
return ret + """
*((double *)PyArray_DATA(%s)) /= PyArray_SIZE(%s);
"""%(onames[0],inames[0])
#TODO: implement the grad. When done and tested, you can make this the default version.
# def grad(self, (x,), (gout,)):
# import pdb;pdb.set_trace()
# return grad(mean(x, self.axis, op=False),[x])
@constructor @constructor
def mean(input, axis = None): def mean(input, axis = None, op = False):
"""Compute the mean value along the given axis of a tensor `input` """Compute the mean value along the given axis of a tensor `input`
:param axis: compute the mean along this axis of the tensor. None means all axes (like :param axis: compute the mean along this axis of the tensor. None means all axes (like
...@@ -1747,6 +1780,9 @@ def mean(input, axis = None): ...@@ -1747,6 +1780,9 @@ def mean(input, axis = None):
:type axis: None or int or (list of int) (see `Sum`) :type axis: None or int or (list of int) (see `Sum`)
""" """
if op:
return Mean(axis)(input)
if str(input.dtype).startswith('int'): if str(input.dtype).startswith('int'):
# we need to cast eventually anyway, and this helps # we need to cast eventually anyway, and this helps
# to prevents overflow # to prevents overflow
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论