def testSplitTensorValueSparseVarLen(self): split_tensor_values = util.split_tensor_value( tf.compat.v1.SparseTensorValue(indices=np.array([[0, 0], [1, 0], [1, 1], [1, 2], [1, 3], [2, 0], [2, 1]]), values=np.array( [1, 2, 3, 4, 5, 6, 7]), dense_shape=np.array([3, 4]))) expected_sparse_tensor_values = [ tf.compat.v1.SparseTensorValue(indices=np.array([[0, 0]]), values=np.array([1]), dense_shape=np.array([1, 1])), tf.compat.v1.SparseTensorValue(indices=np.array([[0, 0], [0, 1], [0, 2], [0, 3]]), values=np.array([2, 3, 4, 5]), dense_shape=np.array([1, 4])), tf.compat.v1.SparseTensorValue(indices=np.array([[0, 0], [0, 1]]), values=np.array([6, 7]), dense_shape=np.array([1, 2])), ] for expected_sparse_tensor_value, got_sparse_tensor_value in zip( expected_sparse_tensor_values, split_tensor_values): self.assertSparseTensorValueEqual(expected_sparse_tensor_value, got_sparse_tensor_value)
def testSplitTensorValueSparseTypesPreserved(self): split_tensor_values = util.split_tensor_value( tf.compat.v1.SparseTensorValue( indices=np.array([[0, 0], [0, 1], [2, 0], [3, 1]]), values=np.array(['zero0', 'zero1', 'two0', 'three1'], dtype=np.object), dense_shape=np.array([4, 3]))) expected_sparse_tensor_values = [ tf.compat.v1.SparseTensorValue(indices=np.array([[0, 0], [0, 1]]), values=np.array(['zero0', 'zero1'], dtype=np.object), dense_shape=np.array([1, 2])), tf.compat.v1.SparseTensorValue(indices=np.zeros([0, 2], dtype=np.int64), values=np.zeros([0], dtype=np.object), dense_shape=np.array([1, 0])), tf.compat.v1.SparseTensorValue(indices=np.array([[0, 0]]), values=np.array(['two0'], dtype=np.object), dense_shape=np.array([1, 1])), tf.compat.v1.SparseTensorValue(indices=np.array([[0, 1]]), values=np.array(['three1'], dtype=np.object), dense_shape=np.array([1, 2])), ] for expected_sparse_tensor_value, got_sparse_tensor_value in zip( expected_sparse_tensor_values, split_tensor_values): self.assertSparseTensorValueEqual(expected_sparse_tensor_value, got_sparse_tensor_value)
def testSplitTensorValueSparse(self): split_tensor_values = util.split_tensor_value( tf.compat.v1.SparseTensorValue(indices=np.array([[0, 0], [0, 1], [1, 0], [1, 1], [3, 0], [3, 1]]), values=np.array([1, 3, 5, 7, 9, 11]), dense_shape=np.array([4, 2]))) expected_sparse_tensor_values = [ tf.compat.v1.SparseTensorValue(indices=np.array([[0, 0], [0, 1]]), values=np.array([1, 3]), dense_shape=np.array([1, 2])), tf.compat.v1.SparseTensorValue(indices=np.array([[0, 0], [0, 1]]), values=np.array([5, 7]), dense_shape=np.array([1, 2])), tf.compat.v1.SparseTensorValue(indices=np.zeros([0, 2], dtype=np.int64), values=np.zeros([0], dtype=np.int64), dense_shape=np.array([1, 0])), tf.compat.v1.SparseTensorValue(indices=np.array([[0, 0], [0, 1]]), values=np.array([9, 11]), dense_shape=np.array([1, 2])), ] for expected_sparse_tensor_value, got_sparse_tensor_value in zip( expected_sparse_tensor_values, split_tensor_values): self.assertSparseTensorValueEqual(expected_sparse_tensor_value, got_sparse_tensor_value)
def testSplitTensorValueSparseVarLenMultiDim(self): split_tensor_values = util.split_tensor_value( tf.compat.v1.SparseTensorValue( indices=np.array([[0, 0, 0], [0, 0, 1], [1, 1, 2], [1, 3, 4], [3, 0, 3], [3, 2, 1], [3, 3, 0]], dtype=np.int64), values=np.array([1, 2, 3, 4, 5, 6, 7], dtype=np.int64), dense_shape=np.array([4, 4, 5]))) expected_sparse_tensor_values = [ tf.compat.v1.SparseTensorValue(indices=np.array([[0, 0, 0], [0, 0, 1]]), values=np.array([1, 2]), dense_shape=np.array([1, 1, 2])), tf.compat.v1.SparseTensorValue(indices=np.array([[0, 1, 2], [0, 3, 4]]), values=np.array([3, 4]), dense_shape=np.array([1, 4, 5])), tf.compat.v1.SparseTensorValue(indices=np.zeros([0, 3], dtype=np.int64), values=np.zeros([0], dtype=np.int64), dense_shape=np.array([1, 0, 0])), tf.compat.v1.SparseTensorValue(indices=np.array([[0, 0, 3], [0, 2, 1], [0, 3, 0]]), values=np.array([5, 6, 7]), dense_shape=np.array([1, 4, 4])), ] for expected_sparse_tensor_value, got_sparse_tensor_value in zip( expected_sparse_tensor_values, split_tensor_values): self.assertSparseTensorValueEqual(expected_sparse_tensor_value, got_sparse_tensor_value)
def testSplitTensorValueSparseVarLen(self): split_tensor_values = util.split_tensor_value( tf.SparseTensorValue(indices=np.array([[0, 0], [1, 0], [1, 1], [1, 2], [1, 3], [2, 0], [2, 1]]), values=np.array([1, 2, 3, 4, 5, 6, 7]), dense_shape=np.array([3, 4]))) # For each of the split SparseTensorValues, the dense_shape of the original # is maintained. expected_sparse_tensor_values = [ tf.SparseTensorValue(indices=np.array([[0, 0]]), values=np.array([1]), dense_shape=np.array([1, 4])), tf.SparseTensorValue(indices=np.array([[0, 0], [0, 1], [0, 2], [0, 3]]), values=np.array([2, 3, 4, 5]), dense_shape=np.array([1, 4])), tf.SparseTensorValue(indices=np.array([[0, 0], [0, 1]]), values=np.array([6, 7]), dense_shape=np.array([1, 4])), ] for expected_sparse_tensor_value, got_sparse_tensor_value in zip( expected_sparse_tensor_values, split_tensor_values): self.assertSparseTensorValueEqual(expected_sparse_tensor_value, got_sparse_tensor_value)
def predict_list(self, input_example_bytes_list): """Like predict, but takes a list of examples.""" (features, predictions, labels) = self._session.run(fetches=(self._features_map, self._predictions_map, self._labels_map), feed_dict={ self._input_example_node: input_example_bytes_list, }) split_labels = {} for label_key in self._labels_map: split_labels[label_key] = util.split_tensor_value( labels[label_key][encoding.NODE_SUFFIX]) split_features = {} for feature_key in self._features_map: split_features[feature_key] = util.split_tensor_value( features[feature_key][encoding.NODE_SUFFIX]) split_predictions = {} for prediction_key in self._predictions_map: split_predictions[prediction_key] = util.split_tensor_value( predictions[prediction_key][encoding.NODE_SUFFIX]) result = [] for i in range(len(input_example_bytes_list)): labels = {} for label_key in self._labels_map: labels[label_key] = { encoding.NODE_SUFFIX: split_labels[label_key][i] } features = {} for feature_key in self._features_map: features[feature_key] = { encoding.NODE_SUFFIX: split_features[feature_key][i] } predictions = {} for prediction_key in self._predictions_map: predictions[prediction_key] = { encoding.NODE_SUFFIX: split_predictions[prediction_key][i] } result.append( FeaturesPredictionsLabels(features=features, predictions=predictions, labels=labels)) return result
def testSplitTensorValueDense(self): split_tensor_values = util.split_tensor_value( np.ndarray(shape=(3, 2), buffer=np.array([2, 4, 6, 8, 10, 12]))) self.assertAllEqual([ np.ndarray(shape=(1, 2), buffer=np.array([2, 4])), np.ndarray(shape=(1, 2), buffer=np.array([6, 8])), np.ndarray(shape=(1, 2), buffer=np.array([10, 12])), ], split_tensor_values)
def get_fpls_from_examples( self, input_example_bytes_list: List[bytes]) -> List[Any]: """Generates FPLs from serialized examples using a ModelAgnostic graph. Args: input_example_bytes_list: A string representing the serialized tf.example protos to be parsed by the graph. Returns: A list of FeaturesPredictionsLabels generated from the input examples. """ # Call the graph via the created session callable _get_features_fn and # get the tensor representation of the features. features = self._get_features_fn(input_example_bytes_list) split_features = {} num_examples = 0 # Split the features by the example keys. Also verify all each example # key has the same number of total examples. for key in features.keys(): split_features[key] = util.split_tensor_value(features[key]) if num_examples == 0: num_examples = len(split_features[key]) elif num_examples != len(split_features[key]): raise ValueError( 'Different keys unexpectedly had different number of ' 'examples. Key %s unexpectedly had %s elements.' % key, len(split_features[key])) # Sort out the examples into individual FPLs: one example -> one FPL. # Sort them into Features, Predictions, or Labels according to the input # config. result = [] for i in range(num_examples): labels = {} predictions = {} features = {} for key in split_features: if key in self._config.label_keys: labels[key] = { encoding.NODE_SUFFIX: split_features[key][i] } if key in self._config.prediction_keys: predictions[key] = { encoding.NODE_SUFFIX: split_features[key][i] } features[key] = {encoding.NODE_SUFFIX: split_features[key][i]} result.append( types.FeaturesPredictionsLabels(input_ref=i, features=features, predictions=predictions, labels=labels)) return result
def predict_list(self, inputs): """Like predict, but takes a list of inputs. Args: inputs: A list of input data (or a dict of keys to lists of input data). See predict for more details. Returns: A list of FeaturesPredictionsLabels. See predict for more details. Raises: ValueError: If the original input_refs tensor passed to the EvalInputReceiver does not align with the features, predictions and labels returned after feeding the inputs. """ if isinstance(inputs, dict): input_args = [] # Only add values for keys that are in the input map (in order). for key in self._input_map: if key in inputs: input_args.append(inputs[key]) else: input_args = [inputs] (features, predictions, labels, input_refs) = self._predict_list_fn(*input_args) split_labels = {} for label_key in self._labels_map: split_labels[label_key] = util.split_tensor_value( labels[label_key][encoding.NODE_SUFFIX]) split_features = {} for feature_key in self._features_map: split_features[feature_key] = util.split_tensor_value( features[feature_key][encoding.NODE_SUFFIX]) split_predictions = {} for prediction_key in self._predictions_map: split_predictions[prediction_key] = util.split_tensor_value( predictions[prediction_key][encoding.NODE_SUFFIX]) result = [] if (not isinstance(input_refs, np.ndarray) or input_refs.ndim != 1 or not np.issubdtype(input_refs.dtype, np.integer)): raise ValueError( 'input_refs should be an 1-D array of integers. input_refs was {}.' .format(input_refs)) for result_key, split_values in itertools.chain( split_labels.items(), split_features.items(), split_predictions.items()): if len(split_values) != input_refs.shape[0]: raise ValueError( 'input_refs should be batch-aligned with features, predictions' ' and labels; key {} had {} slices but input_refs had batch size' ' of {}'.format(result_key, len(split_values), input_refs.shape[0])) for i, input_ref in enumerate(input_refs): if input_ref < 0 or input_ref >= len(inputs): raise ValueError( 'An index in input_refs is out of range: {} vs {}; ' 'inputs: {}'.format(input_ref, len(inputs), inputs)) labels = {} for label_key in self._labels_map: labels[label_key] = { encoding.NODE_SUFFIX: split_labels[label_key][i] } features = {} for feature_key in self._features_map: features[feature_key] = { encoding.NODE_SUFFIX: split_features[feature_key][i] } predictions = {} for prediction_key in self._predictions_map: predictions[prediction_key] = { encoding.NODE_SUFFIX: split_predictions[prediction_key][i] } result.append( types.FeaturesPredictionsLabels(input_ref=input_ref, features=features, predictions=predictions, labels=labels)) return result
def predict_list( self, inputs: MultipleInputFeedType) -> List[FetchedTensorValues]: """Like predict, but takes a list of inputs. Args: inputs: A list of input data (or a dict of keys to lists of input data). See predict for more details. Returns: A list of FetchedTensorValues. See predict for more details. Raises: ValueError: If the original input_refs tensor passed to the EvalInputReceiver does not align with the features, predictions and labels returned after feeding the inputs. """ if isinstance(inputs, dict): input_args = [] # Only add values for keys that are in the input map (in order). for key in self._input_map: if key in inputs: input_args.append(inputs[key]) else: input_args = [inputs] (features, predictions, labels, input_refs, additional_fetches) = self._predict_list_fn(*input_args) all_fetches = additional_fetches all_fetches[constants.FEATURES_NAME] = features all_fetches[constants.LABELS_NAME] = labels all_fetches[constants.PREDICTIONS_NAME] = predictions # TODO(cyfoo): Optimise this. split_fetches = {} for group, tensors in all_fetches.items(): split_tensors = {} for key in tensors: split_tensors[key] = util.split_tensor_value(tensors[key]) split_fetches[group] = split_tensors result = [] if (not isinstance(input_refs, np.ndarray) or input_refs.ndim != 1 or not np.issubdtype(input_refs.dtype, np.integer)): raise ValueError( 'input_refs should be an 1-D array of integers. input_refs was {}.' .format(input_refs)) for group, tensors in split_fetches.items(): for result_key, split_values in tensors.items(): if len(split_values) != input_refs.shape[0]: raise ValueError( 'input_refs should be batch-aligned with fetched values; {} key ' '{} had {} slices but input_refs had batch size of {}'. format(group, result_key, len(split_values), input_refs.shape[0])) for i, input_ref in enumerate(input_refs): if input_ref < 0 or input_ref >= len(inputs): raise ValueError( 'An index in input_refs is out of range: {} vs {}; ' 'inputs: {}'.format(input_ref, len(inputs), inputs)) values = {} for group, split_tensors in split_fetches.items(): tensor_values = {} for key, split_value in split_tensors.items(): tensor_values[key] = split_value[i] values[group] = util.extract_tensor_maybe_dict( group, tensor_values) result.append( FetchedTensorValues(input_ref=input_ref, values=values)) return result
def predict_list(self, input_example_bytes_list): """Like predict, but takes a list of examples. Args: input_example_bytes_list: a list of input example bytes. Returns: A list of FeaturesPredictionsLabels (while in most cases one input_example_bytes will result in one FPL, in some cases, e.g. where examples are dynamically decoded and generated within the graph, one input_example_bytes might result in multiple examples). Raises: ValueError: if the example_ref is not a 1-D tensor integer tensor or it is not batch aligned with features, predictions and labels or it is out of range (< 0 or >= len(input_example_bytes_list)). """ (features, predictions, labels, example_refs) = self._predict_list_fn(input_example_bytes_list) split_labels = {} for label_key in self._labels_map: split_labels[label_key] = util.split_tensor_value( labels[label_key][encoding.NODE_SUFFIX]) split_features = {} for feature_key in self._features_map: split_features[feature_key] = util.split_tensor_value( features[feature_key][encoding.NODE_SUFFIX]) split_predictions = {} for prediction_key in self._predictions_map: split_predictions[prediction_key] = util.split_tensor_value( predictions[prediction_key][encoding.NODE_SUFFIX]) result = [] if (not isinstance(example_refs, np.ndarray) or example_refs.ndim != 1 or not np.issubdtype(example_refs.dtype, np.integer)): raise ValueError( 'example_ref should be an 1-D array of integers. example_ref was {}.' .format(example_refs)) for result_key, split_values in itertools.chain( split_labels.items(), split_features.items(), split_predictions.items()): if len(split_values) != example_refs.shape[0]: raise ValueError( 'example_ref should be batch-aligned with features, predictions' ' and labels; key {} had {} slices but ExampleRef had batch size' ' of {}'.format(result_key, len(split_values), example_refs.shape[0])) for i, example_ref in enumerate(example_refs): if example_ref < 0 or example_ref >= len(input_example_bytes_list): raise ValueError( 'An index in example_ref is out of range: {} vs {}; ' 'input_example_bytes: {}'.format( example_ref, len(input_example_bytes_list), input_example_bytes_list)) labels = {} for label_key in self._labels_map: labels[label_key] = { encoding.NODE_SUFFIX: split_labels[label_key][i] } features = {} for feature_key in self._features_map: features[feature_key] = { encoding.NODE_SUFFIX: split_features[feature_key][i] } predictions = {} for prediction_key in self._predictions_map: predictions[prediction_key] = { encoding.NODE_SUFFIX: split_predictions[prediction_key][i] } result.append( api_types.FeaturesPredictionsLabels(example_ref=example_ref, features=features, predictions=predictions, labels=labels)) return result