def run_node(cls, node, inputs, device='CPU', opset_version=_known_opset_version): super(Caffe2Backend, cls).run_node(node, inputs, device) device_option = get_device_option(Device(device)) with Workspace(), core.DeviceScope(device_option): # temporary! if isinstance(inputs, dict): for key, value in inputs.items(): workspace.FeedBlob(key, value) else: assert len(node.input) == len( inputs), "{}: expected {} but got {}".format( node.op_type, len(node.input), len(inputs)) for key, value in zip(node.input, inputs): workspace.FeedBlob(key, value) cls._inplace_rewrite([node]) init_ops, ops, _ = cls._onnx_node_to_caffe2_op( None, None, node, opset_version or cls._known_opset_version) ops = init_ops + ops for op in ops: op.device_option.CopyFrom(device_option) workspace.RunOperatorsOnce(ops) output_values = [workspace.FetchBlob(name) for name in node.output] return namedtupledict('Outputs', node.output)(*output_values)
def GetLossAndGrad(self, op, grad_ops, x, input_name, grad_name, outputs_with_grads): # First, feed in the current input. Note that we are not changing # anything else, so we don't need to feed in others. workspace.FeedBlob(input_name, x, self._device_option) # Run. workspace.RunOperatorOnce(op) loss = 0. # Get Loss and feed in the gradients, run gradient ops. for idx in outputs_with_grads: name = op.output[idx] arr = workspace.FetchBlob(name) loss += (arr**2).sum() workspace.FeedBlob(name + '_grad', arr, self._device_option) loss /= 2. # Run gradient ops workspace.RunOperatorsOnce(grad_ops) # Get gradients if isinstance(grad_name, core.GradientSlice): workspace.FeedBlob('zeros', np.zeros_like(x, dtype=np.float32)) workspace.FeedBlob('one', np.ones(1, dtype=np.float32)) sparse_to_dense_op = core.CreateOperator( 'ScatterWeightedSum', ['zeros', 'one', grad_name.indices, grad_name.values, 'one'], 'zeros') workspace.RunOperatorOnce(sparse_to_dense_op) grad = workspace.FetchBlob('zeros') else: grad = workspace.FetchBlob(grad_name) return loss, grad
def run_node(cls, node, inputs, device='CPU', opset_version=_known_opset_version, outputs_info=None): super(Caffe2Backend, cls).run_node(node, inputs, device=device, outputs_info=outputs_info) device_option = get_device_option(Device(device)) with Workspace(), core.DeviceScope(device_option): # temporary! if isinstance(inputs, dict): for key, value in inputs.items(): workspace.FeedBlob(key, value) else: assert len(node.input) == len(inputs), "{}: expected {} but got {}".format( node.op_type, len(node.input), len(inputs)) for key, value in zip(node.input, inputs): workspace.FeedBlob(key, value) ops = [] cbackend = C.Caffe2Backend() ops_str = cbackend.convert_node(node.SerializeToString(), opset_version) for s in ops_str[0] + ops_str[1]: op = caffe2_pb2.OperatorDef() op.ParseFromString(s) op.device_option.CopyFrom(device_option) ops.append(op) # For testing if "ONNX_CAFFE2_DEBUG" in os.environ: init_ops, ops2, _ = cls._onnx_node_to_caffe2_op( None, None, node, opset_version or cls._known_opset_version) ops2 = init_ops + ops2 for op in ops2: op.device_option.CopyFrom(device_option) print("\nC++:\n{}\nPython:\n{}".format(ops, ops2)) workspace.RunOperatorsOnce(ops) output_values = [workspace.FetchBlob(name) for name in node.output] return namedtupledict('Outputs', node.output)(*output_values)
def _assertGradReferenceChecks( self, op, inputs, ref_outputs, output_to_grad, grad_reference, threshold=1e-4, ): grad_blob_name = output_to_grad + '_grad' grad_ops, grad_map = core.GradientRegistry.GetBackwardPass( [op], {output_to_grad: grad_blob_name}) output_grad = workspace.FetchBlob(output_to_grad) grad_ref_outputs = grad_reference(output_grad, ref_outputs, inputs) workspace.FeedBlob(grad_blob_name, workspace.FetchBlob(output_to_grad)) workspace.RunOperatorsOnce(grad_ops) self.assertEqual(len(grad_ref_outputs), len(inputs)) for (n, ref) in zip(op.input, grad_ref_outputs): grad_names = grad_map.get(n) if not grad_names: # no grad for this input self.assertIsNone(ref) else: if isinstance(grad_names, core.BlobReference): # dense gradient ref_vals = ref ref_indices = None val_name = grad_names else: # sparse gradient ref_vals, ref_indices = ref val_name = grad_names.values vals = workspace.FetchBlob(str(val_name)) np.testing.assert_allclose( vals, ref_vals, atol=threshold, rtol=threshold, err_msg='Gradient {0} is not matching the reference'. format(val_name, ), ) if ref_indices is not None: indices = workspace.FetchBlob(str(grad_names.indices)) np.testing.assert_allclose(indices, ref_indices, atol=1e-4, rtol=1e-4)
def GetLossAndGrad( self, op, grad_ops, inputs, input_names, input_to_check, grad_name, outputs_with_grads ): for i in range(len(inputs)): workspace.FeedBlob(input_names[i], inputs[i], self._input_device_options.get( input_names[i], self._device_option)) x = inputs[input_to_check] # Run. workspace.RunOperatorOnce(op) loss = 0. # Get Loss and feed in the gradients, run gradient ops. for idx in outputs_with_grads: name = op.output[idx] arr = workspace.FetchBlob(name) loss += (arr**2).sum() workspace.FeedBlob(name + '_grad', arr, self._device_option) loss /= 2. # Run gradient ops workspace.RunOperatorsOnce(grad_ops) # Get gradients if isinstance(grad_name, core.GradientSlice): workspace.FeedBlob('zeros', np.zeros_like(x, dtype=np.float32)) workspace.FeedBlob('ones', np.ones(1, dtype=np.float32)) gv_cpu_op = core.CreateOperator( 'EnsureCPUOutput', grad_name.values, grad_name.values + '_cpu', device_option=self._device_option ) gi_cpu_op = core.CreateOperator( 'EnsureCPUOutput', grad_name.indices, grad_name.indices + '_cpu', device_option=self._device_option ) sparse_to_dense_op = core.CreateOperator( 'ScatterWeightedSum', [ 'zeros', 'ones', grad_name.indices + '_cpu', grad_name.values + '_cpu', 'ones' ], 'zeros', ) workspace.RunOperatorOnce(gv_cpu_op) workspace.RunOperatorOnce(gi_cpu_op) workspace.RunOperatorOnce(sparse_to_dense_op) grad = workspace.FetchBlob('zeros') else: grad = workspace.FetchBlob(grad_name) return loss, grad
def run_node(cls, node, inputs, device='CPU'): super(Caffe2Backend, cls).run_node(node, inputs, device) device_option = get_device_option(Device(device)) with Workspace(), core.DeviceScope(device_option): # temporary! if isinstance(inputs, dict): for key, value in inputs.items(): workspace.FeedBlob(key, value) else: assert (len(node.input) == len(inputs)) for key, value in zip(node.input, inputs): workspace.FeedBlob(key, value) cls._inplace_rewrite([node]) ops = cls._onnx_node_to_caffe2_op(node) for op in ops: op.device_option.CopyFrom(device_option) workspace.RunOperatorsOnce(ops) output_values = [workspace.FetchBlob(name) for name in node.output] return namedtupledict('Outputs', node.output)(*output_values)
def GetLossAndGrad(self, op, grad_ops, x, input_name, grad_name, outputs_with_grads): # First, feed in the current input. Note that we are not changing # anything else, so we don't need to feed in others. workspace.FeedBlob(input_name, x, self._device_option) # Run. workspace.RunOperatorOnce(op) loss = 0. # Get Loss and feed in the gradients, run gradient ops. for idx in outputs_with_grads: name = op.output[idx] arr = workspace.FetchBlob(name) loss += (arr**2).sum() workspace.FeedBlob(name + '_grad', arr, self._device_option) loss /= 2. # Run gradient ops workspace.RunOperatorsOnce(grad_ops) # Get gradients grad = workspace.FetchBlob(grad_name) return loss, grad