def reshape(self, data_shapes, label_shapes=None): """Reshapes the module for new input shapes. Parameters ---------- data_shapes : list of (str, tuple) Typically is ``data_iter.provide_data``. label_shapes : list of (str, tuple) Typically is ``data_iter.provide_label``. """ assert self.binded self._data_shapes, self._label_shapes = _parse_data_desc( self.data_names, self.label_names, data_shapes, label_shapes) self._exec_group.reshape(self._data_shapes, self._label_shapes)
def reshape(self, data_shapes, label_shapes=None): """Reshape the module for new input shapes. Parameters ---------- data_shapes : list of (str, tuple) Typically is `data_iter.provide_data`. label_shapes : list of (str, tuple) Typically is `data_iter.provide_label`. """ assert self.binded # self._data_shapes, self._label_shapes = _parse_data_desc( # self.data_names, self.label_names, data_shapes, label_shapes) self._data_shapes, self._label_shapes = zip(*[_parse_data_desc(self.data_names, self.label_names, data_shape, label_shape) for data_shape, label_shape in zip(data_shapes, label_shapes)]) self._exec_group.reshape(self._data_shapes, self._label_shapes)
def bind(self, data_shapes, label_shapes=None, for_training=True, inputs_need_grad=False, force_rebind=False, shared_module=None, grad_req='write'): """Bind the symbols to construct executors. This is necessary before one can perform computation with the module. Parameters ---------- data_shapes : list of (str, tuple) Typically is `data_iter.provide_data`. label_shapes : list of (str, tuple) Typically is `data_iter.provide_label`. for_training : bool Default is `True`. Whether the executors should be bind for training. inputs_need_grad : bool Default is `False`. Whether the gradients to the input data need to be computed. Typically this is not needed. But this might be needed when implementing composition of modules. force_rebind : bool Default is `False`. This function does nothing if the executors are already binded. But with this `True`, the executors will be forced to rebind. shared_module : Module Default is `None`. This is used in bucketing. When not `None`, the shared module essentially corresponds to a different bucket -- a module with different symbol but with the same sets of parameters (e.g. unrolled RNNs with different lengths). """ # force rebinding is typically used when one want to switch from # training to prediction phase. if force_rebind: self._reset_bind() if self.binded: self.logger.warning('Already binded, ignoring bind()') return self.for_training = for_training self.inputs_need_grad = inputs_need_grad self.binded = True self._grad_req = grad_req if not for_training: assert not inputs_need_grad else: pass # this is not True, as some module might not contains a loss function # that consumes the labels # assert label_shapes is not None # self._data_shapes, self._label_shapes = _parse_data_desc( # self.data_names, self.label_names, data_shapes, label_shapes) self._data_shapes, self._label_shapes = zip(*[_parse_data_desc(self.data_names, self.label_names, data_shape, label_shape) for data_shape, label_shape in zip(data_shapes, label_shapes)]) if self._label_shapes.count(None) == len(self._label_shapes): self._label_shapes = None if shared_module is not None: assert isinstance(shared_module, Module) and \ shared_module.binded and shared_module.params_initialized shared_group = shared_module._exec_group else: shared_group = None self._exec_group = DataParallelExecutorGroup(self._symbol, self._context, self._work_load_list, self._data_shapes, self._label_shapes, self._param_names, for_training, inputs_need_grad, shared_group, logger=self.logger, fixed_param_names=self._fixed_param_names, grad_req=grad_req, state_names=self._state_names) # self._total_exec_bytes = self._exec_group._total_exec_bytes if shared_module is not None: self.params_initialized = True self._arg_params = shared_module._arg_params self._aux_params = shared_module._aux_params elif self.params_initialized: # if the parameters are already initialized, we are re-binding # so automatically copy the already initialized params self._exec_group.set_params(self._arg_params, self._aux_params) else: assert self._arg_params is None and self._aux_params is None param_arrays = [ nd.zeros(x[0].shape, dtype=x[0].dtype) for x in self._exec_group.param_arrays ] self._arg_params = {name:arr for name, arr in zip(self._param_names, param_arrays)} aux_arrays = [ nd.zeros(x[0].shape, dtype=x[0].dtype) for x in self._exec_group.aux_arrays ] self._aux_params = {name:arr for name, arr in zip(self._aux_names, aux_arrays)} if shared_module is not None and shared_module.optimizer_initialized: self.borrow_optimizer(shared_module)
def bind(modQ, data_shapes, label_shapes=None, for_training=True, inputs_need_grad=False, force_rebind=False, shared_module=None, grad_req='write'): if force_rebind: modQ._reset_bind() if modQ.binded: modQ.logger.warning('Already binded, ignoring bind()') return modQ.for_training = for_training modQ.inputs_need_grad = inputs_need_grad modQ.binded = True modQ._grad_req = grad_req if not for_training: assert not inputs_need_grad else: pass # this is not True, as some module might not contains a loss function # that consumes the labels # assert label_shapes is not None modQ._data_shapes, modQ._label_shapes = _parse_data_desc( modQ.data_names, modQ.label_names, data_shapes, label_shapes) if shared_module is not None: assert isinstance(shared_module, Module) and \ shared_module.binded and shared_module.params_initialized shared_group = shared_module._exec_group else: shared_group = None modQ._exec_group = DataParallelExecutorGroup( modQ._symbol, modQ._context, modQ._work_load_list, modQ._data_shapes, modQ._label_shapes, modQ._param_names, for_training, inputs_need_grad, shared_group, logger=modQ.logger, fixed_param_names=modQ._fixed_param_names, grad_req=grad_req, state_names=modQ._state_names) modQ._total_exec_bytes = modQ._exec_group._total_exec_bytes if shared_module is not None: modQ.params_initialized = True modQ._arg_params = shared_module._arg_params modQ._aux_params = shared_module._aux_params elif modQ.params_initialized: # if the parameters are already initialized, we are re-binding # so automatically copy the already initialized params modQ._exec_group.set_params(modQ._arg_params, modQ._aux_params) else: assert modQ._arg_params is None and modQ._aux_params is None param_arrays = [ nd.zeros(x[0].shape, dtype=x[0].dtype, ctx=x[0][0].context) for x in modQ._exec_group.param_arrays ] modQ._arg_params = { name: arr for name, arr in zip(modQ._param_names, param_arrays) } aux_arrays = [ nd.zeros(x[0].shape, dtype=x[0].dtype, ctx=x[0][0].context) for x in modQ._exec_group.aux_arrays ] modQ._aux_params = { name: arr for name, arr in zip(modQ._aux_names, aux_arrays) } if shared_module is not None and shared_module.optimizer_initialized: modQ.borrow_optimizer(shared_module)