Returns grad * (y*x^(y-1), z*log(x)).
(op, grad)
| 1325 | |
| 1326 | @ops.RegisterGradient("Pow") |
| 1327 | def _PowGrad(op, grad): |
| 1328 | """Returns grad * (y*x^(y-1), z*log(x)).""" |
| 1329 | x = op.inputs[0] |
| 1330 | y = op.inputs[1] |
| 1331 | use_mul_no_nan = compat.forward_compatible(2019, 9, 14) |
| 1332 | skip_input_indices = None |
| 1333 | try: |
| 1334 | skip_input_indices = op.skip_input_indices |
| 1335 | # TODO(mrry): If `y` is a constant, we can combine `tf.sub()` and the |
| 1336 | # constant `1` into a single constant op. |
| 1337 | if skip_input_indices is not None and 1 in skip_input_indices and _IsScalar( |
| 1338 | y): |
| 1339 | x = math_ops.conj(x) |
| 1340 | y = math_ops.conj(y) |
| 1341 | if use_mul_no_nan: |
| 1342 | return gen_math_ops.mul_no_nan(y * math_ops.pow(x, y - 1), grad), None |
| 1343 | else: |
| 1344 | return grad * y * math_ops.pow(x, y - 1), None |
| 1345 | |
| 1346 | except AttributeError: |
| 1347 | # No gradient skipping, so do the full gradient computation |
| 1348 | pass |
| 1349 | |
| 1350 | (sx, rx, must_reduce_x), (sy, ry, must_reduce_y) = ( |
| 1351 | SmartBroadcastGradientArgs(x, y, grad)) |
| 1352 | x = math_ops.conj(x) |
| 1353 | y = math_ops.conj(y) |
| 1354 | |
| 1355 | if skip_input_indices is None or 0 not in skip_input_indices: |
| 1356 | if use_mul_no_nan: |
| 1357 | gx = gen_math_ops.mul_no_nan(y * math_ops.pow(x, y - 1), grad) |
| 1358 | else: |
| 1359 | gx = grad * y * math_ops.pow(x, y - 1) |
| 1360 | if must_reduce_x: |
| 1361 | gx = array_ops.reshape(math_ops.reduce_sum(gx, rx), sx) |
| 1362 | else: |
| 1363 | gx = None |
| 1364 | |
| 1365 | if skip_input_indices is None or 1 not in skip_input_indices: |
| 1366 | z = math_ops.conj(op.outputs[0]) |
| 1367 | |
| 1368 | # Avoid false singularity at x = 0 |
| 1369 | if x.dtype.is_complex: |
| 1370 | # real(x) < 0 is fine for the complex case |
| 1371 | mask = math_ops.not_equal(x, 0) |
| 1372 | else: |
| 1373 | # There's no sensible real value to return if x < 0, so return 0 |
| 1374 | mask = x > 0 |
| 1375 | safe_x = array_ops.where(mask, x, array_ops.ones_like(x)) |
| 1376 | log_x = array_ops.where(mask, math_ops.log(safe_x), array_ops.zeros_like(x)) |
| 1377 | if use_mul_no_nan: |
| 1378 | gy = gen_math_ops.mul_no_nan(z * log_x, grad) |
| 1379 | else: |
| 1380 | gy = grad * z * log_x |
| 1381 | if must_reduce_y: |
| 1382 | gy = array_ops.reshape(math_ops.reduce_sum(gy, ry), sy) |
| 1383 | else: |
| 1384 | gy = None |
nothing calls this directly
no test coverage detected