Use blockbuilder to construct an optimizer function that executes updates of the parameters and the optimizer state. `init()` should be called before `get_function()`. Returns ------- func : Function The optimizer function.
(self)
| 302 | return self |
| 303 | |
| 304 | def get_function(self) -> Function: |
| 305 | """Use blockbuilder to construct an optimizer function that executes updates of the |
| 306 | parameters and the optimizer state. `init()` should be called before `get_function()`. |
| 307 | |
| 308 | Returns |
| 309 | ------- |
| 310 | func : Function |
| 311 | The optimizer function. |
| 312 | """ |
| 313 | self._check_init() |
| 314 | |
| 315 | plist = self.param_list |
| 316 | len_param = len(plist) |
| 317 | dtype = self.dtype |
| 318 | |
| 319 | # input variables |
| 320 | param_var = Var("params", TupleStructInfo([p.struct_info for p in plist])) |
| 321 | grad_var = Var("gradients", TupleStructInfo([p.struct_info for p in plist])) |
| 322 | state_var = Var("optim_states", TupleStructInfo([TensorStructInfo((), "int64")])) |
| 323 | |
| 324 | # constants |
| 325 | lr = const(self.lr, dtype) |
| 326 | weight_decay = const(self.weight_decay, dtype) |
| 327 | one = const(1, "int64") |
| 328 | |
| 329 | builder = BlockBuilder() |
| 330 | with builder.function(self.name, [param_var, grad_var, state_var]): |
| 331 | with builder.dataflow(): |
| 332 | param_list_new, state_list_new = [], [] |
| 333 | |
| 334 | # handle num_steps |
| 335 | num_steps = builder.emit(TupleGetItem(state_var, 0), "num_steps") |
| 336 | num_steps_new = builder.emit(add(num_steps, one), "num_steps_new") |
| 337 | state_list_new.append(num_steps_new) |
| 338 | |
| 339 | # computation logics |
| 340 | for i in range(len_param): |
| 341 | name = self.param_list[i].name_hint |
| 342 | p = builder.emit(TupleGetItem(param_var, i), name) |
| 343 | g = builder.emit(TupleGetItem(grad_var, i), name + "_grad") |
| 344 | if self.weight_decay: |
| 345 | g = builder.emit(add(multiply(weight_decay, p), g), name + "_grad_new") |
| 346 | p_new = builder.emit(subtract(p, multiply(lr, g)), name + "_new") |
| 347 | param_list_new.append(p_new) |
| 348 | |
| 349 | # handle return values |
| 350 | params_new = builder.emit_output(RxTuple(param_list_new), "params_new") |
| 351 | optim_states_new = builder.emit_output(RxTuple(state_list_new), "optim_states_new") |
| 352 | builder.emit_func_output((params_new, optim_states_new)) |
| 353 | return builder.get()[self.name] |
| 354 | |
| 355 | |
| 356 | class MomentumSGD(Optimizer): |
no test coverage detected