| 174 | REGISTER_OP_GRADIENT("Conv2D", Conv2DGrad); |
| 175 | |
| 176 | Status MaxPoolGrad(const AttrSlice& attrs, FunctionDef* g) { |
| 177 | // clang-format off |
| 178 | *g = FDH::Define( |
| 179 | // Arg defs |
| 180 | {"input: T", "grad: T"}, |
| 181 | // Ret val defs |
| 182 | {"output: T"}, |
| 183 | // Attr defs |
| 184 | {"T: {float, half} = DT_FLOAT", |
| 185 | "ksize: list(int) >= 4", |
| 186 | "strides: list(int) >= 4", |
| 187 | GetPaddingAttrString()}, |
| 188 | // Nodes |
| 189 | { |
| 190 | // Invoke MaxPool again to recompute the outputs (removed by CSE?). |
| 191 | {{"maxpool"}, "MaxPool", {"input"}, |
| 192 | /*Attrs=*/{{"T", "$T"}, |
| 193 | {"ksize", "$ksize"}, |
| 194 | {"strides", "$strides"}, |
| 195 | {"padding", "$padding"}}}, |
| 196 | {{"output"}, "MaxPoolGrad", {"input", "maxpool", "grad"}, |
| 197 | /*Attrs=*/{{"T", "$T"}, |
| 198 | {"ksize", "$ksize"}, |
| 199 | {"strides", "$strides"}, |
| 200 | {"padding", "$padding"}}} |
| 201 | }); |
| 202 | // clang-format on |
| 203 | return Status::OK(); |
| 204 | } |
| 205 | REGISTER_OP_GRADIENT("MaxPool", MaxPoolGrad); |
| 206 | |
| 207 | Status AvgPoolGrad(const AttrSlice& attrs, FunctionDef* g) { |