The gradient of a Case op produced by tf.switch_case.
(op, *grads)
| 906 | |
| 907 | @ops.RegisterGradient("Case") |
| 908 | def _CaseGrad(op, *grads): # pylint: disable=invalid-name |
| 909 | """The gradient of a Case op produced by tf.switch_case.""" |
| 910 | # Get the Case operator (this logic handles the case where op is a MockOp) |
| 911 | case_op = op.outputs[0].op |
| 912 | branch_graphs = get_func_graphs(case_op) |
| 913 | assert branch_graphs |
| 914 | # Note: op.graph != ops.get_default_graph() when we are computing the gradient |
| 915 | # of a nested cond. |
| 916 | for branch_graph in branch_graphs: |
| 917 | assert branch_graph.outer_graph == case_op.graph |
| 918 | |
| 919 | # Create grad functions that compute the gradient of the branch forward |
| 920 | # graphs. These functions will capture tensors from the forward pass |
| 921 | # functions. |
| 922 | branch_grad_graphs = [] |
| 923 | for branch_graph in branch_graphs: |
| 924 | branch_grad_graphs.append( |
| 925 | _create_grad_func(branch_graph, grads, |
| 926 | util.unique_grad_fn_name(branch_graph.name))) |
| 927 | |
| 928 | if any(g.op_needs_rewrite for g in branch_grad_graphs): |
| 929 | # Modify 'op' to output the intermediates needed by the grad functions. Note |
| 930 | # that all needed intermediates are wrapped in optionals. Each optional |
| 931 | # intermediate output will have a value iff its corresponding branch is |
| 932 | # taken. |
| 933 | # NOTE(bjp): if there are any active sessions, this modification to `op` |
| 934 | # may make them unrunnable! |
| 935 | |
| 936 | if control_flow_util.GraphOrParentsInXlaContext(ops.get_default_graph()): |
| 937 | # XLA does not yet support optionals, so output intermediates directly and |
| 938 | # make them match via FakeParams, which can be converted to zeros in XLA. |
| 939 | # TODO(bjp,jpienaar): can XLA support optionals? |
| 940 | branches_intermediates = [ |
| 941 | branch_grad_graph.xla_intermediates |
| 942 | for branch_grad_graph in branch_grad_graphs |
| 943 | ] |
| 944 | extra_branch_outputs = _make_intermediates_match_xla( |
| 945 | branch_graphs, branches_intermediates) |
| 946 | else: |
| 947 | branch_intermediates = [ |
| 948 | g.wrapped_intermediates for g in branch_grad_graphs |
| 949 | ] |
| 950 | # Make outputs match by adding none optionals. |
| 951 | extra_branch_outputs = _make_intermediates_match(branch_graphs, |
| 952 | branch_intermediates) |
| 953 | |
| 954 | for branch_graph, extra_outputs in zip(branch_graphs, extra_branch_outputs): |
| 955 | branch_graph.outputs.extend(extra_outputs) |
| 956 | # TODO(bjp): indicate it's an internal bug if this fails. |
| 957 | _check_same_outputs(_CASE, branch_graphs) |
| 958 | |
| 959 | for branch_graph in branch_graphs: |
| 960 | branch_graph.name += "_rewritten" |
| 961 | |
| 962 | case_op._set_func_list_attr("branches", [ |
| 963 | util.create_new_tf_function(branch_graph) |
| 964 | for branch_graph in branch_graphs |
| 965 | ]) |
nothing calls this directly
no test coverage detected