提交 4f6c4303 authored 作者: Razvan Pascanu's avatar Razvan Pascanu

merge

...@@ -372,8 +372,8 @@ the given tolerance. ...@@ -372,8 +372,8 @@ the given tolerance.
The parameters are as follows: The parameters are as follows:
* op: something that behaves like an Op instance with a single output * op: something that behaves like an Op instance with a single output
(can be for instance a python function combining multiple ops, or calling (can be for instance a python function that combines multiple ops, or that
an op with some of the inputs being fixed to specific values). calls an op with some of the inputs being fixed to specific values).
* pt: the list of numpy.ndarrays to use as inputs to the op * pt: the list of numpy.ndarrays to use as inputs to the op
...@@ -392,15 +392,19 @@ Here is an example showing how to use verify_grad: ...@@ -392,15 +392,19 @@ Here is an example showing how to use verify_grad:
>>> # being used is Flatten(), which takes a single input). >>> # being used is Flatten(), which takes a single input).
>>> a_val = numpy.asarray([[0,1,2],[3,4,5]], dtype='float64') >>> a_val = numpy.asarray([[0,1,2],[3,4,5]], dtype='float64')
>>> tensor.verify_grad(tensor.Flatten(), [a_val]) >>> tensor.verify_grad(tensor.Flatten(), [a_val])
>>> # Testing gradient w.r.t. to a subset of an op's inputs. This is useful
>>> # in particular when the gradient w.r.t. some of the inputs cannot be Here is another example, showing how to verify the gradient w.r.t. a subset of
>>> # computed by finite difference (e.g. for discrete inputs), which would an Op's inputs. This is useful in particular when the gradient w.r.t. some of
>>> # cause verify_grad to crash. the inputs cannot be computed by finite difference (e.g. for discrete inputs),
which would cause verify_grad to crash.
>>> def test_crossentropy_softmax_grad():
>>> op = tensor.nnet.crossentropy_softmax_argmax_1hot_with_bias >>> op = tensor.nnet.crossentropy_softmax_argmax_1hot_with_bias
>>> def op_with_fixed_y_idx(x, b): >>> def op_with_fixed_y_idx(x, b):
>>> # Input `y_idx` of this Op takes integer values, so we fix them
>>> # to some constant array.
>>> # Although this op has multiple outputs, we can return only one. >>> # Although this op has multiple outputs, we can return only one.
>>> # Here, we return the first output only, and fix the value of the >>> # Here, we return the first output only.
>>> # `y_idx` input to some constant array.
>>> return op(x, b, y_idx=numpy.asarray([0, 2]))[0] >>> return op(x, b, y_idx=numpy.asarray([0, 2]))[0]
>>> x_val = numpy.asarray([[-1, 0, 1], [3, 2, 1]], dtype='float64') >>> x_val = numpy.asarray([[-1, 0, 1], [3, 2, 1]], dtype='float64')
>>> b_val = numpy.asarray([1, 2, 3], dtype='float64') >>> b_val = numpy.asarray([1, 2, 3], dtype='float64')
......
...@@ -60,8 +60,8 @@ The parameter in T.dscalar('x') in the first line is the name of this variable(i ...@@ -60,8 +60,8 @@ The parameter in T.dscalar('x') in the first line is the name of this variable(i
The function I compiled is too slow, what's up? The function I compiled is too slow, what's up?
----------------------------------------------- -----------------------------------------------
First, make sure you're running in FAST_RUN mode, by passing ``mode='FAST_RUN'`` First, make sure you're running in FAST_RUN mode, by passing ``mode='FAST_RUN'``
to ``theano.function`` or ``theano.make`` or by setting to ``PROFILE_MODE`` to ``theano.function`` or ``theano.make`` or by setting to ``FAST_RUN``
the flags :attr:`config.mode`. Some the flag :attr:`config.mode`. Some
operations have excruciatingly slow Python implementations and that operations have excruciatingly slow Python implementations and that
can negatively effect the performance of FAST_COMPILE. can negatively effect the performance of FAST_COMPILE.
......
...@@ -17,10 +17,10 @@ def _asarray(a, dtype=None, order=None): ...@@ -17,10 +17,10 @@ def _asarray(a, dtype=None, order=None):
http://projects.scipy.org/numpy/ticket/870. http://projects.scipy.org/numpy/ticket/870.
Currently, this issue has only been causing trouble when the target Currently, this issue has only been causing trouble when the target
data type is 'int32', on some computers. As a result, this is the only data type is 'int32' or 'int64', on some computers. As a result, we
situation where we may do more than a simple call to ``numpy.asarray``. If silently fix it only in this situation: if a type mismatch is detected
it turns out that a similar problem can occur for more data type, this with another data type, an exception is raised (if that happens, then this
function should be updated accordingly. function may need to be modified to also handle this other data type).
This function's name starts with a '_' to indicate that it is meant to be This function's name starts with a '_' to indicate that it is meant to be
used internally. It is imported so as to be available directly through used internally. It is imported so as to be available directly through
...@@ -28,12 +28,24 @@ def _asarray(a, dtype=None, order=None): ...@@ -28,12 +28,24 @@ def _asarray(a, dtype=None, order=None):
""" """
dtype = numpy.dtype(dtype) # Convert into dtype object. dtype = numpy.dtype(dtype) # Convert into dtype object.
rval = numpy.asarray(a, dtype=dtype, order=order) rval = numpy.asarray(a, dtype=dtype, order=order)
numpy_int32 = numpy.dtype(numpy.int32) # Note that dtype comparison must be done by comparing their `num`
if (dtype is numpy_int32 and rval.dtype is not numpy_int32): # attribute. One cannot assume that two identical data types are pointers
# Enfore the numpy.int32 dtype. # towards the same object (e.g. under Windows this appears not to be the
return rval.view(dtype=numpy_int32) # case).
if rval.dtype.num != dtype.num:
# Type mismatch between the data type we asked for, and the one
# returned by numpy.asarray.
if (dtype.num == numpy.dtype(numpy.int32).num or
dtype.num == numpy.dtype(numpy.int64).num):
# Silent fix.
return rval.view(dtype=dtype)
else:
# Unexpected mismatch: better know what is going on!
raise TypeError('numpy.array did not return the data type we '
'asked for (%s #%s), instead it returned type %s #%s: function '
'theano._asarray may need to be extended to handle this '
'data type as well.' %
(dtype, dtype.num, rval.dtype, rval.dtype.num))
else: else:
# Using ``numpy.asarray`` should work just fine.
# Debug assert if we want to detect other failure cases (untested):
# assert rval.dtype is dtype
return rval return rval
...@@ -2,9 +2,10 @@ ...@@ -2,9 +2,10 @@
""" """
import gof import gof
from copy import copy from copy import copy
import sys import sys,os
from theano import config
from gof import Op, Apply from gof import Op, Apply
from theano.gof.python25 import any
class Print(Op): class Print(Op):
"""This identity-like Op has the side effect of printing a message followed by its inputs """This identity-like Op has the side effect of printing a message followed by its inputs
...@@ -299,3 +300,58 @@ pprint.assign(lambda pstate, r: hasattr(pstate, 'target') and pstate.target is n ...@@ -299,3 +300,58 @@ pprint.assign(lambda pstate, r: hasattr(pstate, 'target') and pstate.target is n
pp = pprint pp = pprint
def pydotprint(fct, outfile=os.path.join(config.compiledir,'theano.pydotprint.png')):
"""
print to a file in png format the graph of op of a compile theano fct.
:param fct: the theano fct returned by theano.function.
:param outfile: the output file where to put the graph.
In the graph, box are an Apply Node(the execution of an op) and elipse are variable.
If variable have name they are used as the text(if multiple var have the same name, they will be merged in the graph). Otherwise, if a constant, we print the value and finaly we print the type + an uniq number to don't have multiple var merged.
We print the op of the apply in the Apply box with a number that represent the toposort order of application of those Apply.
"""
import pydot as pd
g=pd.Dot()
var_id={}
def var_name(var):
if var.name is not None:
varstr = var.name
elif isinstance(var,gof.Constant):
varstr = str(var.data)
else:
#a var id is needed as otherwise var with the same type will be merged in the graph.
i = var_id.get(var,None)
if i is None:
var_id[var]=len(var_id)
i = var_id[var]
varstr = str(var.type)+' '+str(i)
return varstr
for node_idx,node in enumerate(fct.maker.env.toposort()):
astr=str(node.op).replace(':','_')+' '+str(node_idx)
g.add_node(pd.Node(astr,shape='box'))
for var in node.inputs:
varstr=var_name(var)
if var.owner is None:
g.add_node(pd.Node(varstr,color='green'))
g.add_edge(pd.Edge(varstr,astr))
for var in node.outputs:
varstr=var_name(var)
g.add_edge(pd.Edge(astr,varstr))
if any([x[0]=='output' for x in var.env.clients(var)]):
g.add_node(pd.Node(varstr,color='blue'))
g.write_png(outfile, prog='dot')
print 'The output file is available at',outfile
#from matplotlib import pyplot
#image=pyplot.imread(outfile)
#pyplot.imshow(image)
#import pdb;pdb.set_trace()
...@@ -412,7 +412,7 @@ class Scan(theano.Op): ...@@ -412,7 +412,7 @@ class Scan(theano.Op):
warning('Can not compute gradients if inplace or updates ' \ warning('Can not compute gradients if inplace or updates ' \
'are used. Use force_gradient if you know for sure '\ 'are used. Use force_gradient if you know for sure '\
'that the gradient can be computed automatically.') 'that the gradient can be computed automatically.')
return [None for i in inputs] return [None for i in args]
else: else:
# forward pass # forward pass
y = self(*args) y = self(*args)
......
...@@ -638,7 +638,8 @@ class TensorType(Type): ...@@ -638,7 +638,8 @@ class TensorType(Type):
# Easy constructors # Easy constructors
def tensor(*args, **kwargs): def tensor(*args, **kwargs):
return TensorType(*args, **kwargs).make_variable() name = kwargs.get('name',None)
return TensorType(*args, **kwargs).make_variable(name=name)
def _multi(*fns): def _multi(*fns):
def f2(f, *names): def f2(f, *names):
...@@ -1307,8 +1308,8 @@ class MaxAndArgmax(Op): ...@@ -1307,8 +1308,8 @@ class MaxAndArgmax(Op):
axis = _as_tensor_variable(axis) axis = _as_tensor_variable(axis)
inputs = [x, axis] inputs = [x, axis]
broadcastable = [False] * (x.type.ndim - 1) #TODO: be less conservative broadcastable = [False] * (x.type.ndim - 1) #TODO: be less conservative
outputs = [tensor(x.type.dtype, broadcastable), outputs = [tensor(x.type.dtype, broadcastable,name='max'),
tensor('int32', broadcastable)] tensor('int32', broadcastable,name='argmax')]
return Apply(self, inputs, outputs) return Apply(self, inputs, outputs)
def perform(self, node, (x, axis), (max, max_idx)): def perform(self, node, (x, axis), (max, max_idx)):
max[0] = numpy.asarray(numpy.max(x, axis)) max[0] = numpy.asarray(numpy.max(x, axis))
...@@ -1336,6 +1337,8 @@ class MaxAndArgmax(Op): ...@@ -1336,6 +1337,8 @@ class MaxAndArgmax(Op):
xmax_pad = shape_padright(xmax) xmax_pad = shape_padright(xmax)
g_x = eq(xmax_pad, x) * g_max_pad g_x = eq(xmax_pad, x) * g_max_pad
return g_x, None return g_x, None
def __str__(self):
return self.__class__.__name__
_max_and_argmax = MaxAndArgmax() _max_and_argmax = MaxAndArgmax()
@_redefine_asRoutine(_max_and_argmax) @_redefine_asRoutine(_max_and_argmax)
...@@ -2897,6 +2900,9 @@ class ARange(Op): ...@@ -2897,6 +2900,9 @@ class ARange(Op):
def __hash__(self): def __hash__(self):
return hash(self.dtype) return hash(self.dtype)
def __str__(self):
return self.__class__.__name__
def make_node(self, start, stop, step): def make_node(self, start, stop, step):
start, stop, step = map(as_tensor_variable, (start, stop, step)) start, stop, step = map(as_tensor_variable, (start, stop, step))
assert start.ndim == 0 assert start.ndim == 0
......
...@@ -9,7 +9,7 @@ import numpy ...@@ -9,7 +9,7 @@ import numpy
import theano import theano
import theano.tensor as tensor import theano.tensor as tensor
from theano import gof, Op, tensor, config from theano import gof, Op, tensor, config
from theano.gof.python25 import any
import logging import logging
_logger=logging.getLogger("theano.signal.conv") _logger=logging.getLogger("theano.signal.conv")
def _debug(*msg): def _debug(*msg):
...@@ -383,10 +383,10 @@ class ConvOp(Op): ...@@ -383,10 +383,10 @@ class ConvOp(Op):
from scipy.signal.signaltools import _valfrommode, _bvalfromboundary from scipy.signal.signaltools import _valfrommode, _bvalfromboundary
from scipy.signal.sigtools import _convolve2d from scipy.signal.sigtools import _convolve2d
imshp = self.imshp imshp = self.imshp
if imshp is None: if imshp is None or any([x is None for x in imshp]):
imshp = tuple(img2d.shape[1:]) imshp = tuple(img2d.shape[1:])
kshp = self.kshp kshp = self.kshp
if kshp is None: if kshp is None or any([x is None for x in kshp]):
kshp = tuple(filtersflipped.shape[2:]) kshp = tuple(filtersflipped.shape[2:])
bsize = self.bsize bsize = self.bsize
if bsize is None: if bsize is None:
...@@ -398,16 +398,21 @@ class ConvOp(Op): ...@@ -398,16 +398,21 @@ class ConvOp(Op):
imshp_logical = self.imshp_logical imshp_logical = self.imshp_logical
if imshp_logical is None: if imshp_logical is None:
imshp_logical = imshp imshp_logical = imshp
if numpy.any([x is None for x in imshp_logical]):
imshp_logical = tuple(img2d.shape[1:])
kshp_logical = self.kshp_logical kshp_logical = self.kshp_logical
if kshp_logical is None: if kshp_logical is None:
kshp_logical = kshp kshp_logical = kshp
if numpy.any([x is None for x in kshp_logical]):
kshp = tuple(filtersflipped.shape[2:])
if self.fulloutshp is not None: if self.fulloutshp is not None:
fulloutshp = tuple(self.fulloutshp) fulloutshp = tuple(self.fulloutshp)
else: else:
fulloutshp = tuple(ConvOp.getOutputShape(imshp_logical, kshp_logical, (1,1), self.out_mode)) fulloutshp = tuple(ConvOp.getOutputShape(imshp_logical, kshp_logical, (1,1), self.out_mode))
if z[0] is None: if z[0] is None or z[0].shape!=(bsize,)+(nkern,)+fulloutshp:
z[0] = numpy.zeros((bsize,)+(nkern,)+fulloutshp, z[0] = numpy.zeros((bsize,)+(nkern,)+fulloutshp,
dtype=img2d.dtype) dtype=img2d.dtype)
zz=z[0] zz=z[0]
......
...@@ -114,6 +114,8 @@ class SoftmaxWithBias(gof.Op): ...@@ -114,6 +114,8 @@ class SoftmaxWithBias(gof.Op):
return type(self) == type(other) return type(self) == type(other)
def __hash__(self): def __hash__(self):
return tensor.hashtype(self) return tensor.hashtype(self)
def __str__(self):
return self.__class__.__name__
def make_node(self, x, b): def make_node(self, x, b):
x = tensor.as_tensor_variable(x) x = tensor.as_tensor_variable(x)
...@@ -284,6 +286,9 @@ class SoftmaxGrad(gof.Op): ...@@ -284,6 +286,9 @@ class SoftmaxGrad(gof.Op):
def __hash__(self): def __hash__(self):
return tensor.hashtype(self) return tensor.hashtype(self)
def __str__(self):
return self.__class__.__name__
def make_node(self, dy, sm, **kwargs): def make_node(self, dy, sm, **kwargs):
dy = tensor.as_tensor_variable(dy) dy = tensor.as_tensor_variable(dy)
sm = tensor.as_tensor_variable(sm) sm = tensor.as_tensor_variable(sm)
...@@ -376,6 +381,8 @@ class Softmax(gof.Op): ...@@ -376,6 +381,8 @@ class Softmax(gof.Op):
return type(self) == type(other) return type(self) == type(other)
def __hash__(self): def __hash__(self):
return hash(type(self)) return hash(type(self))
def __str__(self):
return self.__class__.__name__
def make_node(self, x): def make_node(self, x):
x = tensor.as_tensor_variable(x) x = tensor.as_tensor_variable(x)
...@@ -818,6 +825,8 @@ class CrossentropyCategorical1HotGrad(gof.Op): ...@@ -818,6 +825,8 @@ class CrossentropyCategorical1HotGrad(gof.Op):
return type(self) == type(other) return type(self) == type(other)
def __hash__(self): def __hash__(self):
return tensor.hashtype(self) return tensor.hashtype(self)
def __str__(self):
return self.__class__.__name__
def make_node(self, g_y, coding_dist, true_one_of_n): def make_node(self, g_y, coding_dist, true_one_of_n):
return gof.Apply(self, [g_y, coding_dist, true_one_of_n], [coding_dist.type()]) return gof.Apply(self, [g_y, coding_dist, true_one_of_n], [coding_dist.type()])
def perform(self, node, (g_y, coding_dist, true_one_of_n), (g_coding_strg,)): def perform(self, node, (g_y, coding_dist, true_one_of_n), (g_coding_strg,)):
...@@ -848,6 +857,8 @@ class CrossentropyCategorical1Hot(gof.Op): ...@@ -848,6 +857,8 @@ class CrossentropyCategorical1Hot(gof.Op):
return type(self) == type(other) return type(self) == type(other)
def __hash__(self): def __hash__(self):
return tensor.hashtype(self) return tensor.hashtype(self)
def __str__(self):
return self.__class__.__name__
def make_node(self, coding_dist, true_one_of_n): def make_node(self, coding_dist, true_one_of_n):
""" """
:type coding_dist: dense matrix :type coding_dist: dense matrix
...@@ -1346,6 +1357,8 @@ class Prepend_scalar_constant_to_each_row(gof.Op): ...@@ -1346,6 +1357,8 @@ class Prepend_scalar_constant_to_each_row(gof.Op):
return (type(self) == type(other)) and (self.val == other.val) return (type(self) == type(other)) and (self.val == other.val)
def __hash__(self): def __hash__(self):
return tensor.hashtype(self) ^ hash(self.val.value) return tensor.hashtype(self) ^ hash(self.val.value)
def __str__(self):
return '%s{%s}'%(self.__class__.__name__,self.val)
def make_node(self, mat): def make_node(self, mat):
#check type of input #check type of input
...@@ -1383,6 +1396,8 @@ class Prepend_scalar_to_each_row(gof.Op): ...@@ -1383,6 +1396,8 @@ class Prepend_scalar_to_each_row(gof.Op):
return (type(self) == type(other)) return (type(self) == type(other))
def __hash__(self): def __hash__(self):
return tensor.hashtype(self) return tensor.hashtype(self)
def __str__(self):
return self.__class__.__name__
def make_node(self, val, mat): def make_node(self, val, mat):
#check type of input #check type of input
......
...@@ -94,6 +94,9 @@ class TestConv2D(unittest.TestCase): ...@@ -94,6 +94,9 @@ class TestConv2D(unittest.TestCase):
self.validate((3,2,8,8), (4,2,5,5), 'full') self.validate((3,2,8,8), (4,2,5,5), 'full')
self.validate((3,2,7,5), (5,2,2,3), 'full') self.validate((3,2,7,5), (5,2,2,3), 'full')
# test filter same size as input # test filter same size as input
def test_img_kernel_same_shape(self):
self.validate((3,2,3,3), (4,2,3,3), 'full')
self.validate((3,2,3,3), (4,2,3,3), 'valid') self.validate((3,2,3,3), (4,2,3,3), 'valid')
def test_unroll_patch_false(self): def test_unroll_patch_false(self):
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论