Computes the gradient of the wrapped function.
(*args, **kwds)
| 198 | # accept lists and np.ndarrays. |
| 199 | |
| 200 | def grad_fn(*args, **kwds): |
| 201 | """Computes the gradient of the wrapped function.""" |
| 202 | this_tape = tape.push_new_tape() |
| 203 | try: |
| 204 | end_node = f(*args, **kwds) |
| 205 | if end_node is None: |
| 206 | raise ValueError("Cannot differentiate a function that returns None; " |
| 207 | "did you forget to return a value from {}?".format( |
| 208 | f.__name__)) |
| 209 | finally: |
| 210 | tape.pop_tape(this_tape) |
| 211 | # Note: variables are returned in construction order. This ensures unique |
| 212 | # order across executions. |
| 213 | variables = this_tape.watched_variables() |
| 214 | if not variables: |
| 215 | raise ValueError("No trainable variables were accessed while the " |
| 216 | "function was being computed.") |
| 217 | |
| 218 | sources = [v.handle for v in variables] |
| 219 | grad = imperative_grad.imperative_grad(this_tape, nest.flatten(end_node), |
| 220 | sources) |
| 221 | return end_node, list(zip(grad, variables)) |
| 222 | |
| 223 | return grad_fn |
| 224 |