def AddGradientOperators(self, ys, skip=0): """Add the gradient for operators in the net. Inputs: ys: a list or a dictionary specifying what blobs we want to compute derivatives of. If the input is a list, we will automatically generate their gradients with all-one values; if the input is a dictionary, for any dictionary entries that are not None, we will take the corresponding blobs as their gradients; for all those that are None, we will auto-fill them with 1. skip: skips the first n operators. This is provided mainly because a lot of nets may use the first few operators for data generation like stuff which really do not need to have gradients. Outputs: returns a map from the blob name in the input network to a blob containing gradient or a GradientSlice in case of sparse gradient Currently, this is hard-coded for float operators if there are branches (i.e. a blob is used as input to multiple operators). This is because the gradient accumulation (Sum) is float only right now. """ grad_ops, input_to_grad = GradientRegistry.GetBackwardPass( self._net.op[skip:], ys) # Check if in immediate mode: the grad_ops are actually being produced # by C++ and bypasses the CreateOperator() call, so in immediate mode # we will have to explicitly run them. if workspace.IsImmediate(): for op in grad_ops: workspace.RunOperatorImmediate(op) self._net.op.extend(grad_ops) return input_to_grad
def CreateOperator(operator_type, inputs, outputs, name='', control_input=None, device_option=None, arg=None, engine=None, **kwargs): """A function wrapper that allows one to create operators based on the operator type. The type should be a string corresponding to an operator registered with Caffe2. """ operator = caffe2_pb2.OperatorDef() operator.type = operator_type operator.name = name # Add rectified inputs and outputs inputs = _RectifyInputOutput(inputs) outputs = _RectifyInputOutput(outputs) operator.input.extend([str(i) for i in inputs]) operator.output.extend([str(o) for o in outputs]) if control_input: control_input = _RectifyInputOutput(control_input) operator.control_input.extend([str(i) for i in control_input]) # Set device option: # (1) If device_option is explicitly set, use device_option. # (2) If not, but scope.DEVICESCOPE is set, then we use scope.DEVICESCOPE. # (3) Otherwise, do not set device option. if device_option is not None: operator.device_option.CopyFrom(device_option) elif scope.DEVICESCOPE is not None: operator.device_option.CopyFrom(scope.DEVICESCOPE) if engine is not None: operator.engine = engine # random seed is defined in the device option, so we need to do special # care. if 'random_seed' in kwargs: operator.device_option.random_seed = kwargs['random_seed'] del kwargs['random_seed'] # Add given arguments that do not need parsing if arg is not None: operator.arg.extend(arg) # Add all other arguments for key, value in kwargs.items(): operator.arg.add().CopyFrom(utils.MakeArgument(key, value)) if workspace.IsImmediate(): workspace.RunOperatorImmediate(operator) return operator
def testImmediateEnterExit(self): workspace.StartImmediate(i_know=True) self.assertTrue(workspace.IsImmediate()) workspace.StopImmediate() self.assertFalse(workspace.IsImmediate())