提交 7cfd2879 authored 作者: Frédéric Bastien's avatar Frédéric Bastien 提交者: GitHub

Merge pull request #5486 from affanv14/gradchange

Change grad to L_op
...@@ -1076,6 +1076,9 @@ class ScalarOp(Op): ...@@ -1076,6 +1076,9 @@ class ScalarOp(Op):
raise utils.MethodNotDefined("grad", type(self), raise utils.MethodNotDefined("grad", type(self),
self.__class__.__name__) self.__class__.__name__)
def L_op(self, inputs, outputs, output_gradients):
return self.grad(inputs, output_gradients)
def __eq__(self, other): def __eq__(self, other):
test = (type(self) == type(other) and test = (type(self) == type(other) and
getattr(self, 'output_types_preference', None) == getattr(self, 'output_types_preference', None) ==
...@@ -1191,10 +1194,9 @@ class LogicalComparison(BinaryScalarOp): ...@@ -1191,10 +1194,9 @@ class LogicalComparison(BinaryScalarOp):
def output_types(self, *input_dtypes): def output_types(self, *input_dtypes):
return [bool] if getattr(self, 'bool', False) else [int8] return [bool] if getattr(self, 'bool', False) else [int8]
def grad(self, inputs, output_gradients): def L_op(self, inputs, outputs, output_gradients):
x, y = inputs x, y = inputs
out = self(x, y) assert outputs[0].type == bool
assert out.type == bool
return [x.zeros_like().astype(theano.config.floatX), return [x.zeros_like().astype(theano.config.floatX),
y.zeros_like().astype(theano.config.floatX)] y.zeros_like().astype(theano.config.floatX)]
...@@ -1224,10 +1226,9 @@ class FixedLogicalComparison(UnaryScalarOp): ...@@ -1224,10 +1226,9 @@ class FixedLogicalComparison(UnaryScalarOp):
def output_types(self, *input_dtypes): def output_types(self, *input_dtypes):
return [bool] if getattr(self, 'bool', False) else [int8] return [bool] if getattr(self, 'bool', False) else [int8]
def grad(self, inputs, output_gradients): def L_op(self, inputs, outputs, output_gradients):
x, = inputs x, = inputs
out = self(x) assert outputs[0].type == bool
assert out.type == bool
return [x.zeros_like().astype(theano.config.floatX)] return [x.zeros_like().astype(theano.config.floatX)]
def c_code_cache_version(self): def c_code_cache_version(self):
...@@ -1434,7 +1435,7 @@ class InRange(LogicalComparison): ...@@ -1434,7 +1435,7 @@ class InRange(LogicalComparison):
else: else:
return elem.zeros_like() return elem.zeros_like()
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x, low, hi) = inputs (x, low, hi) = inputs
(gz,) = gout (gz,) = gout
grads = [] grads = []
...@@ -1458,14 +1459,13 @@ class Switch(ScalarOp): ...@@ -1458,14 +1459,13 @@ class Switch(ScalarOp):
(z,) = outputs (z,) = outputs
return "%(z)s = %(cond)s ? %(ift)s : %(iff)s;" % locals() return "%(z)s = %(cond)s ? %(ift)s : %(iff)s;" % locals()
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(cond, ift, iff) = inputs (cond, ift, iff) = inputs
(gz,) = gout (gz,) = gout
first_part = switch(cond, gz, 0.) first_part = switch(cond, gz, 0.)
second_part = switch(cond, 0., gz) second_part = switch(cond, 0., gz)
out = self(cond, ift, iff) if (outputs[0].type.dtype in discrete_types):
if out.type.dtype in discrete_types:
first_part = 0. first_part = 0.
second_part = 0. second_part = 0.
...@@ -1604,7 +1604,7 @@ class Maximum(BinaryScalarOp): ...@@ -1604,7 +1604,7 @@ class Maximum(BinaryScalarOp):
return ('%(z)s = ((%(y)s)>(%(x)s)? (%(y)s): ' return ('%(z)s = ((%(y)s)>(%(x)s)? (%(y)s): '
'((%(x)s)>=(%(y)s)? (%(x)s): nan("")));' % locals()) '((%(x)s)>=(%(y)s)? (%(x)s): nan("")));' % locals())
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x, y) = inputs (x, y) = inputs
(gz,) = gout (gz,) = gout
if gz.type in complex_types: if gz.type in complex_types:
...@@ -1612,14 +1612,12 @@ class Maximum(BinaryScalarOp): ...@@ -1612,14 +1612,12 @@ class Maximum(BinaryScalarOp):
# but the gradient for complex is not. # but the gradient for complex is not.
raise NotImplementedError() raise NotImplementedError()
output = self(x, y) if outputs[0].type in discrete_types:
if output.type in discrete_types:
return [x.zeros_like().astype(theano.config.floatX), return [x.zeros_like().astype(theano.config.floatX),
y.zeros_like().astype(theano.config.floatX)] y.zeros_like().astype(theano.config.floatX)]
gx = eq(output, x) * gz gx = eq(outputs[0], x) * gz
gy = eq(output, y) * gz gy = eq(outputs[0], y) * gz
return (gx, gy) return (gx, gy)
maximum = Maximum(upcast_out, name='maximum') maximum = Maximum(upcast_out, name='maximum')
...@@ -1642,7 +1640,7 @@ class Minimum(BinaryScalarOp): ...@@ -1642,7 +1640,7 @@ class Minimum(BinaryScalarOp):
return ('%(z)s = ((%(y)s)<(%(x)s)? (%(y)s): ' return ('%(z)s = ((%(y)s)<(%(x)s)? (%(y)s): '
'((%(x)s)<=(%(y)s)? (%(x)s): nan("")));' % locals()) '((%(x)s)<=(%(y)s)? (%(x)s): nan("")));' % locals())
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x, y) = inputs (x, y) = inputs
(gz,) = gout (gz,) = gout
if gz.type in complex_types: if gz.type in complex_types:
...@@ -1650,12 +1648,11 @@ class Minimum(BinaryScalarOp): ...@@ -1650,12 +1648,11 @@ class Minimum(BinaryScalarOp):
# but the gradient for complex is not. # but the gradient for complex is not.
raise NotImplementedError() raise NotImplementedError()
output = minimum(x, y) if outputs[0].type in discrete_types:
if output.type in discrete_types:
return [x.zeros_like().astype(theano.config.floatX), return [x.zeros_like().astype(theano.config.floatX),
y.zeros_like().astype(theano.config.floatX)] y.zeros_like().astype(theano.config.floatX)]
gx = eq(output, x) * gz gx = eq(outputs[0], x) * gz
gy = eq(output, y) * gz gy = eq(outputs[0], y) * gz
return (gx, gy) return (gx, gy)
minimum = Minimum(upcast_out, name='minimum') minimum = Minimum(upcast_out, name='minimum')
...@@ -1679,11 +1676,11 @@ class Add(ScalarOp): ...@@ -1679,11 +1676,11 @@ class Add(ScalarOp):
else: else:
return z + " = " + op.join(inputs) + ";" return z + " = " + op.join(inputs) + ";"
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(gz,) = gout (gz,) = gout
if gz.type in complex_types: if gz.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(*inputs).type in discrete_types: if (outputs[0].type in discrete_types):
assert gz is not None assert gz is not None
retval = [] retval = []
for ii, inp in enumerate(inputs): for ii, inp in enumerate(inputs):
...@@ -1771,13 +1768,12 @@ class Sub(BinaryScalarOp): ...@@ -1771,13 +1768,12 @@ class Sub(BinaryScalarOp):
(z,) = outputs (z,) = outputs
return "%(z)s = %(x)s - %(y)s;" % locals() return "%(z)s = %(x)s - %(y)s;" % locals()
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x, y) = inputs (x, y) = inputs
(gz,) = gout (gz,) = gout
if gz.type in complex_types: if gz.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if outputs[0].type in discrete_types:
if (x - y).type in discrete_types:
return [x.zeros_like().astype(theano.config.floatX), return [x.zeros_like().astype(theano.config.floatX),
y.zeros_like().astype(theano.config.floatX)] y.zeros_like().astype(theano.config.floatX)]
...@@ -2064,11 +2060,10 @@ class Mod(BinaryScalarOp): ...@@ -2064,11 +2060,10 @@ class Mod(BinaryScalarOp):
} }
""") % locals() """) % locals()
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x, y) = inputs (x, y) = inputs
(gz,) = gout (gz,) = gout
z = self(x, y) if outputs[0].type.dtype in discrete_types:
if z.type.dtype in discrete_types:
# The gradient does not flow in if the output is discrete # The gradient does not flow in if the output is discrete
return [x.zeros_like(dtype=theano.config.floatX), return [x.zeros_like(dtype=theano.config.floatX),
y.zeros_like(dtype=theano.config.floatX)] y.zeros_like(dtype=theano.config.floatX)]
...@@ -2092,13 +2087,13 @@ class Pow(BinaryScalarOp): ...@@ -2092,13 +2087,13 @@ class Pow(BinaryScalarOp):
raise NotImplementedError('type not supported', type) raise NotImplementedError('type not supported', type)
return "%(z)s = pow(%(x)s, %(y)s);" % locals() return "%(z)s = pow(%(x)s, %(y)s);" % locals()
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x, y) = inputs (x, y) = inputs
(gz,) = gout (gz,) = gout
if gz.type in complex_types: if gz.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x, y).type in discrete_types: if outputs[0].type in discrete_types:
return [x.zeros_like().astype(theano.config.floatX), return [x.zeros_like().astype(theano.config.floatX),
y.zeros_like().astype(theano.config.floatX)] y.zeros_like().astype(theano.config.floatX)]
...@@ -2172,7 +2167,7 @@ class Clip(ScalarOp): ...@@ -2172,7 +2167,7 @@ class Clip(ScalarOp):
(z,) = outputs (z,) = outputs
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, inputs, gout): def L_op(self, inputs, outputs, gout):
(x, mn, mx) = inputs (x, mn, mx) = inputs
(gz,) = gout (gz,) = gout
assert gz.type not in complex_types assert gz.type not in complex_types
...@@ -2180,10 +2175,8 @@ class Clip(ScalarOp): ...@@ -2180,10 +2175,8 @@ class Clip(ScalarOp):
gmn = (x < mn) * gz gmn = (x < mn) * gz
gmx = (x > mx) * gz gmx = (x > mx) * gz
out = self(x, mn, mx)
def handle_int(v): def handle_int(v):
if out.type in int_types: if outputs[0].type in int_types:
return v.zeros_like().astype(config.floatX) return v.zeros_like().astype(config.floatX)
return v return v
...@@ -2366,10 +2359,10 @@ class Abs(UnaryScalarOp): ...@@ -2366,10 +2359,10 @@ class Abs(UnaryScalarOp):
def impl(self, x): def impl(self, x):
return numpy.abs(x) return numpy.abs(x)
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x,) = inputs (x,) = inputs
(gz,) = gout (gz,) = gout
if self(x).type in discrete_types: if (outputs[0].type in discrete_types):
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -2624,10 +2617,10 @@ class Neg(UnaryScalarOp): ...@@ -2624,10 +2617,10 @@ class Neg(UnaryScalarOp):
def impl(self, x): def impl(self, x):
return -x return -x
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x,) = inputs (x,) = inputs
(gz,) = gout (gz,) = gout
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -2659,12 +2652,12 @@ class Inv(UnaryScalarOp): ...@@ -2659,12 +2652,12 @@ class Inv(UnaryScalarOp):
def impl(self, x): def impl(self, x):
return numpy.float32(1.0) / x return numpy.float32(1.0) / x
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x,) = inputs (x,) = inputs
(gz,) = gout (gz,) = gout
if x.type in complex_types: if x.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -2698,12 +2691,12 @@ class Log(UnaryScalarOp): ...@@ -2698,12 +2691,12 @@ class Log(UnaryScalarOp):
return numpy.log(x, sig='f') return numpy.log(x, sig='f')
return numpy.log(x) return numpy.log(x)
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x,) = inputs (x,) = inputs
(gz,) = gout (gz,) = gout
if x.type in complex_types: if x.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -2740,12 +2733,12 @@ class Log2(UnaryScalarOp): ...@@ -2740,12 +2733,12 @@ class Log2(UnaryScalarOp):
return numpy.log2(x, sig='f') return numpy.log2(x, sig='f')
return numpy.log2(x) return numpy.log2(x)
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x,) = inputs (x,) = inputs
(gz,) = gout (gz,) = gout
if x.type in complex_types: if x.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -2779,12 +2772,12 @@ class Log10(UnaryScalarOp): ...@@ -2779,12 +2772,12 @@ class Log10(UnaryScalarOp):
return numpy.log10(x, sig='f') return numpy.log10(x, sig='f')
return numpy.log10(x) return numpy.log10(x)
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x,) = inputs (x,) = inputs
(gz,) = gout (gz,) = gout
if x.type in complex_types: if x.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -2816,12 +2809,12 @@ class Log1p(UnaryScalarOp): ...@@ -2816,12 +2809,12 @@ class Log1p(UnaryScalarOp):
return numpy.log1p(x, sig='f') return numpy.log1p(x, sig='f')
return numpy.log1p(x) return numpy.log1p(x)
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x,) = inputs (x,) = inputs
(gz,) = gout (gz,) = gout
if gz.type in complex_types: if gz.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -2851,12 +2844,12 @@ class Exp(UnaryScalarOp): ...@@ -2851,12 +2844,12 @@ class Exp(UnaryScalarOp):
return numpy.exp(x, sig='f') return numpy.exp(x, sig='f')
return numpy.exp(x) return numpy.exp(x)
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x,) = inputs (x,) = inputs
(gz,) = gout (gz,) = gout
if x.type in complex_types: if x.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -2884,12 +2877,12 @@ class Exp2(UnaryScalarOp): ...@@ -2884,12 +2877,12 @@ class Exp2(UnaryScalarOp):
return numpy.exp2(x, sig='f') return numpy.exp2(x, sig='f')
return numpy.exp2(x) return numpy.exp2(x)
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x,) = inputs (x,) = inputs
(gz,) = gout (gz,) = gout
if x.type in complex_types: if x.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -2917,12 +2910,12 @@ class Expm1(UnaryScalarOp): ...@@ -2917,12 +2910,12 @@ class Expm1(UnaryScalarOp):
return numpy.expm1(x, sig='f') return numpy.expm1(x, sig='f')
return numpy.expm1(x) return numpy.expm1(x)
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x,) = inputs (x,) = inputs
(gz,) = gout (gz,) = gout
if x.type in complex_types: if x.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -2948,12 +2941,12 @@ class Sqr(UnaryScalarOp): ...@@ -2948,12 +2941,12 @@ class Sqr(UnaryScalarOp):
def impl(self, x): def impl(self, x):
return x * x return x * x
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x,) = inputs (x,) = inputs
(gz,) = gout (gz,) = gout
if gz.type in complex_types: if gz.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -2979,12 +2972,12 @@ class Sqrt(UnaryScalarOp): ...@@ -2979,12 +2972,12 @@ class Sqrt(UnaryScalarOp):
return numpy.sqrt(x, sig='f') return numpy.sqrt(x, sig='f')
return numpy.sqrt(x) return numpy.sqrt(x)
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x,) = inputs (x,) = inputs
(gz,) = gout (gz,) = gout
if gz.type in complex_types: if gz.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -3012,12 +3005,12 @@ class Deg2Rad(UnaryScalarOp): ...@@ -3012,12 +3005,12 @@ class Deg2Rad(UnaryScalarOp):
return numpy.deg2rad(x, sig='f') return numpy.deg2rad(x, sig='f')
return numpy.deg2rad(x) return numpy.deg2rad(x)
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x,) = inputs (x,) = inputs
(gz,) = gout (gz,) = gout
if gz.type in complex_types: if gz.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -3045,12 +3038,12 @@ class Rad2Deg(UnaryScalarOp): ...@@ -3045,12 +3038,12 @@ class Rad2Deg(UnaryScalarOp):
return numpy.rad2deg(x, sig='f') return numpy.rad2deg(x, sig='f')
return numpy.rad2deg(x) return numpy.rad2deg(x)
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x,) = inputs (x,) = inputs
(gz,) = gout (gz,) = gout
if gz.type in complex_types: if gz.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -3080,12 +3073,12 @@ class Cos(UnaryScalarOp): ...@@ -3080,12 +3073,12 @@ class Cos(UnaryScalarOp):
return numpy.cos(x, sig='f') return numpy.cos(x, sig='f')
return numpy.cos(x) return numpy.cos(x)
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x,) = inputs (x,) = inputs
(gz,) = gout (gz,) = gout
if gz.type in complex_types: if gz.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -3113,12 +3106,12 @@ class ArcCos(UnaryScalarOp): ...@@ -3113,12 +3106,12 @@ class ArcCos(UnaryScalarOp):
return numpy.arccos(x, sig='f') return numpy.arccos(x, sig='f')
return numpy.arccos(x) return numpy.arccos(x)
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x,) = inputs (x,) = inputs
(gz,) = gout (gz,) = gout
if gz.type in complex_types: if gz.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -3148,12 +3141,12 @@ class Sin(UnaryScalarOp): ...@@ -3148,12 +3141,12 @@ class Sin(UnaryScalarOp):
return numpy.sin(x, sig='f') return numpy.sin(x, sig='f')
return numpy.sin(x) return numpy.sin(x)
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x,) = inputs (x,) = inputs
(gz,) = gout (gz,) = gout
if x.type in complex_types: if x.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -3181,12 +3174,12 @@ class ArcSin(UnaryScalarOp): ...@@ -3181,12 +3174,12 @@ class ArcSin(UnaryScalarOp):
return numpy.arcsin(x, sig='f') return numpy.arcsin(x, sig='f')
return numpy.arcsin(x) return numpy.arcsin(x)
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x,) = inputs (x,) = inputs
(gz,) = gout (gz,) = gout
if gz.type in complex_types: if gz.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -3214,12 +3207,12 @@ class Tan(UnaryScalarOp): ...@@ -3214,12 +3207,12 @@ class Tan(UnaryScalarOp):
return numpy.tan(x, sig='f') return numpy.tan(x, sig='f')
return numpy.tan(x) return numpy.tan(x)
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x,) = inputs (x,) = inputs
(gz,) = gout (gz,) = gout
if x.type in complex_types: if x.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -3247,12 +3240,12 @@ class ArcTan(UnaryScalarOp): ...@@ -3247,12 +3240,12 @@ class ArcTan(UnaryScalarOp):
return numpy.arctan(x, sig='f') return numpy.arctan(x, sig='f')
return numpy.arctan(x) return numpy.arctan(x)
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x,) = inputs (x,) = inputs
(gz,) = gout (gz,) = gout
if gz.type in complex_types: if gz.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -3282,13 +3275,13 @@ class ArcTan2(BinaryScalarOp): ...@@ -3282,13 +3275,13 @@ class ArcTan2(BinaryScalarOp):
return numpy.arctan2(y, x, sig='f') return numpy.arctan2(y, x, sig='f')
return numpy.arctan2(y, x) return numpy.arctan2(y, x)
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(y, x) = inputs (y, x) = inputs
(gz,) = gout (gz,) = gout
if gz.type in complex_types: if gz.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
else: else:
if self(x, y).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
gx = x.zeros_like(dtype=theano.config.floatX) gx = x.zeros_like(dtype=theano.config.floatX)
else: else:
...@@ -3329,12 +3322,12 @@ class Cosh(UnaryScalarOp): ...@@ -3329,12 +3322,12 @@ class Cosh(UnaryScalarOp):
return numpy.cosh(x, sig='f') return numpy.cosh(x, sig='f')
return numpy.cosh(x) return numpy.cosh(x)
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x,) = inputs (x,) = inputs
(gz,) = gout (gz,) = gout
if x.type in complex_types: if x.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -3362,12 +3355,12 @@ class ArcCosh(UnaryScalarOp): ...@@ -3362,12 +3355,12 @@ class ArcCosh(UnaryScalarOp):
return numpy.arccosh(x, sig='f') return numpy.arccosh(x, sig='f')
return numpy.arccosh(x) return numpy.arccosh(x)
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x,) = inputs (x,) = inputs
(gz,) = gout (gz,) = gout
if x.type in complex_types: if x.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -3399,12 +3392,12 @@ class Sinh(UnaryScalarOp): ...@@ -3399,12 +3392,12 @@ class Sinh(UnaryScalarOp):
return numpy.sinh(x, sig='f') return numpy.sinh(x, sig='f')
return numpy.sinh(x) return numpy.sinh(x)
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x,) = inputs (x,) = inputs
(gz,) = gout (gz,) = gout
if x.type in complex_types: if x.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -3432,12 +3425,12 @@ class ArcSinh(UnaryScalarOp): ...@@ -3432,12 +3425,12 @@ class ArcSinh(UnaryScalarOp):
return numpy.arcsinh(x, sig='f') return numpy.arcsinh(x, sig='f')
return numpy.arcsinh(x) return numpy.arcsinh(x)
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x,) = inputs (x,) = inputs
(gz,) = gout (gz,) = gout
if x.type in complex_types: if x.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -3470,12 +3463,12 @@ class Tanh(UnaryScalarOp): ...@@ -3470,12 +3463,12 @@ class Tanh(UnaryScalarOp):
return numpy.tanh(x, sig='f') return numpy.tanh(x, sig='f')
return numpy.tanh(x) return numpy.tanh(x)
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x,) = inputs (x,) = inputs
(gz,) = gout (gz,) = gout
if x.type in complex_types: if x.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -3503,12 +3496,12 @@ class ArcTanh(UnaryScalarOp): ...@@ -3503,12 +3496,12 @@ class ArcTanh(UnaryScalarOp):
return numpy.arctanh(x, sig='f') return numpy.arctanh(x, sig='f')
return numpy.arctanh(x) return numpy.arctanh(x)
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x,) = inputs (x,) = inputs
(gz,) = gout (gz,) = gout
if x.type in complex_types: if x.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
......
...@@ -32,12 +32,12 @@ class Erf(UnaryScalarOp): ...@@ -32,12 +32,12 @@ class Erf(UnaryScalarOp):
else: else:
super(Erf, self).impl(x) super(Erf, self).impl(x)
def grad(self, inp, grads): def L_op(self, inputs, outputs, grads):
x, = inp x, = inputs
gz, = grads gz, = grads
if x.type in complex_types: if x.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -63,12 +63,12 @@ class Erfc(UnaryScalarOp): ...@@ -63,12 +63,12 @@ class Erfc(UnaryScalarOp):
else: else:
super(Erfc, self).impl(x) super(Erfc, self).impl(x)
def grad(self, inp, grads): def L_op(self, inputs, outputs, grads):
x, = inp x, = inputs
gz, = grads gz, = grads
if x.type in complex_types: if x.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -110,12 +110,12 @@ class Erfcx(UnaryScalarOp): ...@@ -110,12 +110,12 @@ class Erfcx(UnaryScalarOp):
else: else:
super(Erfcx, self).impl(x) super(Erfcx, self).impl(x)
def grad(self, inp, grads): def L_op(self, inputs, outputs, grads):
x, = inp x, = inputs
gz, = grads gz, = grads
if x.type in complex_types: if x.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -146,12 +146,12 @@ class Erfinv(UnaryScalarOp): ...@@ -146,12 +146,12 @@ class Erfinv(UnaryScalarOp):
else: else:
super(Erfinv, self).impl(x) super(Erfinv, self).impl(x)
def grad(self, inp, grads): def L_op(self, inputs, outputs, grads):
x, = inp x, = inputs
gz, = grads gz, = grads
if x.type in complex_types: if x.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -179,12 +179,12 @@ class Erfcinv(UnaryScalarOp): ...@@ -179,12 +179,12 @@ class Erfcinv(UnaryScalarOp):
else: else:
super(Erfcinv, self).impl(x) super(Erfcinv, self).impl(x)
def grad(self, inp, grads): def L_op(self, inputs, outputs, grads):
x, = inp x, = inputs
gz, = grads gz, = grads
if x.type in complex_types: if x.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -216,12 +216,12 @@ class Gamma(UnaryScalarOp): ...@@ -216,12 +216,12 @@ class Gamma(UnaryScalarOp):
else: else:
super(Gamma, self).impl(x) super(Gamma, self).impl(x)
def grad(self, inputs, gout): def L_op(self, inputs, outputs, gout):
(x,) = inputs (x,) = inputs
(gz,) = gout (gz,) = gout
if x.type in complex_types: if x.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
...@@ -253,12 +253,12 @@ class GammaLn(UnaryScalarOp): ...@@ -253,12 +253,12 @@ class GammaLn(UnaryScalarOp):
else: else:
super(GammaLn, self).impl(x) super(GammaLn, self).impl(x)
def grad(self, inp, grads): def L_op(self, inputs, outputs, grads):
x, = inp x, = inputs
gz, = grads gz, = grads
if x.type in complex_types: if x.type in complex_types:
raise NotImplementedError() raise NotImplementedError()
if self(x).type in discrete_types: if outputs[0].type in discrete_types:
if x.type in discrete_types: if x.type in discrete_types:
return [x.zeros_like(dtype=theano.config.floatX)] return [x.zeros_like(dtype=theano.config.floatX)]
else: else:
......
...@@ -602,7 +602,7 @@ second dimension ...@@ -602,7 +602,7 @@ second dimension
ograds = [x.zeros_like() for x in outs] ograds = [x.zeros_like() for x in outs]
ograds[idx] = theano.tensor.ones_like(out) ograds[idx] = theano.tensor.ones_like(out)
bgrads = self._bgrad(inputs, ograds) bgrads = self._bgrad(inputs, outs, ograds)
rop_out = None rop_out = None
for jdx, (inp, eval_point) in enumerate(izip(inputs, for jdx, (inp, eval_point) in enumerate(izip(inputs,
...@@ -636,7 +636,7 @@ second dimension ...@@ -636,7 +636,7 @@ second dimension
def L_op(self, inputs, outs, ograds): def L_op(self, inputs, outs, ograds):
# compute grad with respect to broadcasted input # compute grad with respect to broadcasted input
rval = self._bgrad(inputs, ograds) rval = self._bgrad(inputs, outs, ograds)
# TODO: make sure that zeros are clearly identifiable # TODO: make sure that zeros are clearly identifiable
# to the gradient.grad method when the outputs have # to the gradient.grad method when the outputs have
...@@ -684,7 +684,7 @@ second dimension ...@@ -684,7 +684,7 @@ second dimension
return rval return rval
def _bgrad(self, inputs, ograds): def _bgrad(self, inputs, outputs, ograds):
# returns grad, with respect to broadcasted versions of inputs # returns grad, with respect to broadcasted versions of inputs
with change_flags(compute_test_value='off'): with change_flags(compute_test_value='off'):
...@@ -695,7 +695,10 @@ second dimension ...@@ -695,7 +695,10 @@ second dimension
scalar_inputs = list(map(as_scalar, inputs)) scalar_inputs = list(map(as_scalar, inputs))
scalar_ograds = list(map(as_scalar, ograds)) scalar_ograds = list(map(as_scalar, ograds))
scalar_igrads = self.scalar_op.grad(scalar_inputs, scalar_ograds) scalar_outputs = self.scalar_op.make_node(
*[get_scalar_type(dtype=i.type.dtype).make_variable()
for i in inputs]).outputs
scalar_igrads = self.scalar_op.L_op(scalar_inputs, scalar_outputs, scalar_ograds)
for igrad in scalar_igrads: for igrad in scalar_igrads:
assert igrad is not None, self.scalar_op assert igrad is not None, self.scalar_op
...@@ -711,6 +714,8 @@ second dimension ...@@ -711,6 +714,8 @@ second dimension
return r return r
if r in scalar_inputs: if r in scalar_inputs:
return inputs[scalar_inputs.index(r)] return inputs[scalar_inputs.index(r)]
if r in scalar_outputs:
return outputs[scalar_outputs.index(r)]
if r in scalar_ograds: if r in scalar_ograds:
return ograds[scalar_ograds.index(r)] return ograds[scalar_ograds.index(r)]
node = r.owner node = r.owner
......
...@@ -100,15 +100,14 @@ class SoftmaxWithBias(gof.Op): ...@@ -100,15 +100,14 @@ class SoftmaxWithBias(gof.Op):
# data type matches. # data type matches.
output_storage[0][0] = e_x.astype(x_dtype, copy=False) output_storage[0][0] = e_x.astype(x_dtype, copy=False)
def grad(self, inp, grads): def L_op(self, inp, outputs, grads):
x, b = inp x, b = inp
g_sm, = grads g_sm, = grads
if isinstance(g_sm.type, DisconnectedType): if isinstance(g_sm.type, DisconnectedType):
return [DisconnectedType()(), DisconnectedType()()] return [DisconnectedType()(), DisconnectedType()()]
sm = softmax_with_bias(x, b) dx = softmax_grad(g_sm, outputs[0])
dx = softmax_grad(g_sm, sm)
db = tensor.sum(dx, axis=0) db = tensor.sum(dx, axis=0)
return dx, db return dx, db
...@@ -440,18 +439,17 @@ class Softmax(gof.Op): ...@@ -440,18 +439,17 @@ class Softmax(gof.Op):
sm = e_x / e_x.sum(axis=1)[:, None] sm = e_x / e_x.sum(axis=1)[:, None]
output_storage[0][0] = sm output_storage[0][0] = sm
def grad(self, inp, grads): def L_op(self, inp, outputs, grads):
x, = inp x, = inp
g_sm, = grads g_sm, = grads
sm = softmax_op(x) return [softmax_grad(g_sm, outputs[0])]
return [softmax_grad(g_sm, sm)]
def R_op(self, inputs, eval_points): def R_op(self, inputs, eval_points):
# I think the Jacobian is symmetric so the R_op # I think the Jacobian is symmetric so the R_op
# is the same as the grad # is the same as the grad
if None in eval_points: if None in eval_points:
return [None] return [None]
return self.grad(inputs, eval_points) return self.L_op(inputs, [self(*inputs)], eval_points)
def infer_shape(self, node, shape): def infer_shape(self, node, shape):
return shape return shape
...@@ -1060,7 +1058,7 @@ class CrossentropySoftmaxArgmax1HotWithBias(gof.Op): ...@@ -1060,7 +1058,7 @@ class CrossentropySoftmaxArgmax1HotWithBias(gof.Op):
db_terms.append(db) db_terms.append(db)
if not isinstance(g_sm.type, DisconnectedType): if not isinstance(g_sm.type, DisconnectedType):
dx, db = softmax_with_bias.grad((x, b), (g_sm, )) dx, db = softmax_with_bias.L_op((x, b), [softmax_with_bias(x, b)], (g_sm, ))
dx_terms.append(dx) dx_terms.append(dx)
db_terms.append(db) db_terms.append(db)
......
...@@ -562,15 +562,14 @@ class Pool(OpenMPOp): ...@@ -562,15 +562,14 @@ class Pool(OpenMPOp):
pad, self.ndim) pad, self.ndim)
return [shp] return [shp]
def grad(self, inp, grads): def L_op(self, inputs, outputs, grads):
x, ws, stride, pad = inp x, ws, stride, pad = inputs
gz, = grads gz, = grads
disc = [DisconnectedType()() for i in inp[1:]] disc = [DisconnectedType()() for i in inputs[1:]]
if self.mode == 'max': if self.mode == 'max':
maxout = self(x, ws, stride, pad)
return [MaxPoolGrad(ndim=self.ndim, return [MaxPoolGrad(ndim=self.ndim,
ignore_border=self.ignore_border)( ignore_border=self.ignore_border)(
x, maxout, gz, ws=ws, stride=stride, pad=pad)] + disc x, outputs[0], gz, ws=ws, stride=stride, pad=pad)] + disc
else: else:
return [AveragePoolGrad(ndim=self.ndim, return [AveragePoolGrad(ndim=self.ndim,
ignore_border=self.ignore_border, ignore_border=self.ignore_border,
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论