def test_build_all_signature_defs_with_single_alternatives(self):
        # Force the test to run in graph mode.
        # This tests a deprecated v1 API that depends on graph-only functions such
        # as build_tensor_info.
        with ops.Graph().as_default():
            receiver_tensor = array_ops.placeholder(dtypes.string)
            receiver_tensors_alternative_1 = array_ops.placeholder(
                dtypes.int64)
            receiver_tensors_alternative_2 = array_ops.sparse_placeholder(
                dtypes.float32)
            # Note we are passing single Tensors as values of
            # receiver_tensors_alternatives, where normally that is a dict.
            # In this case a dict will be created using the default receiver tensor
            # name "input".
            receiver_tensors_alternatives = {
                "other1": receiver_tensors_alternative_1,
                "other2": receiver_tensors_alternative_2
            }
            output_1 = constant_op.constant([1.])
            output_2 = constant_op.constant(["2"])
            output_3 = constant_op.constant(["3"])
            export_outputs = {
                signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY:
                export_output.RegressionOutput(value=output_1),
                "head-2":
                export_output.ClassificationOutput(classes=output_2),
                "head-3":
                export_output.PredictOutput(
                    outputs={"some_output_3": output_3}),
            }

            signature_defs = export_utils.build_all_signature_defs(
                receiver_tensor, export_outputs, receiver_tensors_alternatives)

            expected_signature_defs = {
                "serving_default":
                signature_def_utils.regression_signature_def(
                    receiver_tensor, output_1),
                "head-2":
                signature_def_utils.classification_signature_def(
                    receiver_tensor, output_2, None),
                "head-3":
                signature_def_utils.predict_signature_def(
                    {"input": receiver_tensor}, {"some_output_3": output_3}),
                "other1:head-3":
                signature_def_utils.predict_signature_def(
                    {"input": receiver_tensors_alternative_1},
                    {"some_output_3": output_3}),
                "other2:head-3":
                signature_def_utils.predict_signature_def(
                    {"input": receiver_tensors_alternative_2},
                    {"some_output_3": output_3})

                # Note that the alternatives 'other:serving_default' and
                # 'other:head-2' are invalid, because regression and classification
                # signatures must take a single string input.  Here we verify that
                # these invalid signatures are not included in the export_utils.
            }

            self.assertDictEqual(expected_signature_defs, signature_defs)
Exemple #2
0
  def test_build_all_signature_defs_without_receiver_alternatives(self):
    receiver_tensor = array_ops.placeholder(dtypes.string)
    output_1 = constant_op.constant([1.])
    output_2 = constant_op.constant(["2"])
    output_3 = constant_op.constant(["3"])
    export_outputs = {
        signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY:
            export_output.RegressionOutput(value=output_1),
        "head-2": export_output.ClassificationOutput(classes=output_2),
        "head-3": export_output.PredictOutput(outputs={
            "some_output_3": output_3
        }),
    }

    signature_defs = export_utils.build_all_signature_defs(
        receiver_tensor, export_outputs)

    expected_signature_defs = {
        "serving_default":
            signature_def_utils.regression_signature_def(receiver_tensor,
                                                         output_1),
        "head-2":
            signature_def_utils.classification_signature_def(receiver_tensor,
                                                             output_2, None),
        "head-3":
            signature_def_utils.predict_signature_def({
                "input": receiver_tensor
            }, {"some_output_3": output_3})
    }

    self.assertDictEqual(expected_signature_defs, signature_defs)
    def test_build_all_signature_defs_without_receiver_alternatives(self):
        # Force the test to run in graph mode.
        # This tests a deprecated v1 API that depends on graph-only functions such
        # as build_tensor_info.
        with ops.Graph().as_default():
            receiver_tensor = array_ops.placeholder(dtypes.string)
            output_1 = constant_op.constant([1.])
            output_2 = constant_op.constant(["2"])
            output_3 = constant_op.constant(["3"])
            export_outputs = {
                signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY:
                export_output.RegressionOutput(value=output_1),
                "head-2":
                export_output.ClassificationOutput(classes=output_2),
                "head-3":
                export_output.PredictOutput(
                    outputs={"some_output_3": output_3}),
            }

            signature_defs = export_utils.build_all_signature_defs(
                receiver_tensor, export_outputs)

            expected_signature_defs = {
                "serving_default":
                signature_def_utils.regression_signature_def(
                    receiver_tensor, output_1),
                "head-2":
                signature_def_utils.classification_signature_def(
                    receiver_tensor, output_2, None),
                "head-3":
                signature_def_utils.predict_signature_def(
                    {"input": receiver_tensor}, {"some_output_3": output_3})
            }

            self.assertDictEqual(expected_signature_defs, signature_defs)
  def test_build_standardized_signature_def_classify_classes_only(self):
    """Tests classification with one output tensor."""
    with context.graph_mode():
      input_tensors = {
          'input-1':
              array_ops.placeholder(
                  dtypes.string, 1, name='input-tensor-1')
      }
      classes = array_ops.placeholder(dtypes.string, 1, name='output-tensor-1')

      export_output = export_output_lib.ClassificationOutput(classes=classes)
      actual_signature_def = export_output.as_signature_def(input_tensors)

      expected_signature_def = meta_graph_pb2.SignatureDef()
      shape = tensor_shape_pb2.TensorShapeProto(
          dim=[tensor_shape_pb2.TensorShapeProto.Dim(size=1)])
      dtype_string = types_pb2.DataType.Value('DT_STRING')
      expected_signature_def.inputs[
          signature_constants.CLASSIFY_INPUTS].CopyFrom(
              meta_graph_pb2.TensorInfo(name='input-tensor-1:0',
                                        dtype=dtype_string,
                                        tensor_shape=shape))
      expected_signature_def.outputs[
          signature_constants.CLASSIFY_OUTPUT_CLASSES].CopyFrom(
              meta_graph_pb2.TensorInfo(name='output-tensor-1:0',
                                        dtype=dtype_string,
                                        tensor_shape=shape))

      expected_signature_def.method_name = (
          signature_constants.CLASSIFY_METHOD_NAME)
      self.assertEqual(actual_signature_def, expected_signature_def)
Exemple #5
0
 def test_classify_scores_must_be_float(self):
     with context.graph_mode():
         scores = array_ops.placeholder(dtypes.string,
                                        1,
                                        name='output-tensor-1')
         with self.assertRaisesRegexp(
                 ValueError,
                 'Classification scores must be a float32 Tensor'):
             export_output_lib.ClassificationOutput(scores=scores)
Exemple #6
0
 def test_classify_classes_must_be_strings(self):
     with context.graph_mode():
         classes = array_ops.placeholder(dtypes.float32,
                                         1,
                                         name='output-tensor-1')
         with self.assertRaisesRegex(
                 ValueError,
                 'Classification classes must be a string Tensor'):
             export_output_lib.ClassificationOutput(classes=classes)
Exemple #7
0
  def test_build_all_signature_defs_with_dict_alternatives(self):
    with context.graph_mode():
      receiver_tensor = array_ops.placeholder(dtypes.string)
      receiver_tensors_alternative_1 = {
          "foo": array_ops.placeholder(dtypes.int64),
          "bar": array_ops.sparse_placeholder(dtypes.float32)}
      receiver_tensors_alternatives = {"other": receiver_tensors_alternative_1}
      output_1 = constant_op.constant([1.])
      output_2 = constant_op.constant(["2"])
      output_3 = constant_op.constant(["3"])
      export_outputs = {
          signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY:
              export_output.RegressionOutput(value=output_1),
          "head-2": export_output.ClassificationOutput(classes=output_2),
          "head-3": export_output.PredictOutput(outputs={
              "some_output_3": output_3
          }),
      }

      signature_defs = export_utils.build_all_signature_defs(
          receiver_tensor, export_outputs, receiver_tensors_alternatives)

      expected_signature_defs = {
          "serving_default":
              signature_def_utils.regression_signature_def(
                  receiver_tensor,
                  output_1),
          "head-2":
              signature_def_utils.classification_signature_def(
                  receiver_tensor,
                  output_2, None),
          "head-3":
              signature_def_utils.predict_signature_def(
                  {"input": receiver_tensor},
                  {"some_output_3": output_3}),
          "other:head-3":
              signature_def_utils.predict_signature_def(
                  receiver_tensors_alternative_1,
                  {"some_output_3": output_3})

          # Note that the alternatives 'other:serving_default' and
          # 'other:head-2' are invalid, because regession and classification
          # signatures must take a single string input.  Here we verify that
          # these invalid signatures are not included in the export_utils.
      }

      self.assertDictEqual(expected_signature_defs, signature_defs)
    def test_export_outputs_for_mode(self):
        predictions = {"predictions": constant_op.constant([1.])}
        loss = {"loss": constant_op.constant([2.])}
        metrics = {
            "metrics": (constant_op.constant([3.]), constant_op.constant([4.]))
        }
        expected_metrics = {
            "metrics/value": metrics["metrics"][0],
            "metrics/update_op": metrics["metrics"][1]
        }

        def _build_export_output(mode):
            return export_utils.export_outputs_for_mode(
                mode, None, predictions, loss, metrics)

        ret = _build_export_output(KerasModeKeys.TRAIN)
        self.assertIn(signature_constants.DEFAULT_TRAIN_SIGNATURE_DEF_KEY, ret)
        export_out = ret[signature_constants.DEFAULT_TRAIN_SIGNATURE_DEF_KEY]
        self.assertIsInstance(export_out, export_output.TrainOutput)
        self.assertEqual(export_out.predictions, predictions)
        self.assertEqual(export_out.loss, loss)
        self.assertEqual(export_out.metrics, expected_metrics)

        ret = _build_export_output(KerasModeKeys.TEST)
        self.assertIn(signature_constants.DEFAULT_EVAL_SIGNATURE_DEF_KEY, ret)
        export_out = ret[signature_constants.DEFAULT_EVAL_SIGNATURE_DEF_KEY]
        self.assertIsInstance(export_out, export_output.EvalOutput)
        self.assertEqual(export_out.predictions, predictions)
        self.assertEqual(export_out.loss, loss)
        self.assertEqual(export_out.metrics, expected_metrics)

        ret = _build_export_output(KerasModeKeys.PREDICT)
        self.assertIn(signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY,
                      ret)
        export_out = ret[signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY]
        self.assertIsInstance(export_out, export_output.PredictOutput)
        self.assertEqual(export_out.outputs, predictions)

        classes = constant_op.constant(["class5"])
        ret = export_utils.export_outputs_for_mode(
            KerasModeKeys.PREDICT,
            {"classify": export_output.ClassificationOutput(classes=classes)})
        self.assertIn("classify", ret)
        export_out = ret["classify"]
        self.assertIsInstance(export_out, export_output.ClassificationOutput)
        self.assertEqual(export_out.classes, classes)
 def test_classify_requires_classes_or_scores(self):
   with self.assertRaisesRegexp(
       ValueError, 'At least one of scores and classes must be set.'):
     export_output_lib.ClassificationOutput()
 def test_classify_requires_classes_or_scores(self):
   with self.assertRaisesRegex(
       ValueError,
       'Cannot create a ClassificationOutput with empty arguments'):
     export_output_lib.ClassificationOutput()
  def test_build_all_signature_defs_with_dict_alternatives(self):
    # Force the test to run in graph mode.
    # This tests a deprecated v1 API that depends on graph-only functions such
    # as build_tensor_info.
    with ops.Graph().as_default():
      receiver_tensor = array_ops.placeholder(dtypes.string)

      receiver_tensors_alternative_1 = {
          "foo": array_ops.placeholder(dtypes.int64),
          "bar": array_ops.sparse_placeholder(dtypes.float32)
      }

      unfed_input = array_ops.placeholder(dtypes.bool)
      receiver_tensors_alternative_2 = {"unfed": unfed_input}

      receiver_tensors_alternatives = {
          "other": receiver_tensors_alternative_1,
          "with_unfed_input": receiver_tensors_alternative_2
      }

      output_1 = constant_op.constant([1.])
      output_2 = constant_op.constant(["2"])
      output_3 = constant_op.constant(["3"])
      output_4 = unfed_input
      output_5 = math_ops.logical_not(unfed_input)
      export_outputs = {
          signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY:
              export_output.RegressionOutput(value=output_1),
          "head-2":
              export_output.ClassificationOutput(classes=output_2),
          "head-3":
              export_output.PredictOutput(outputs={"some_output_3": output_3}),
          "head-4":
              export_output.PredictOutput(outputs={"some_output_4": output_4}),
          "head-5":
              export_output.PredictOutput(outputs={"some_output_5": output_5}),
      }

      signature_defs = export_utils.build_all_signature_defs(
          receiver_tensor, export_outputs, receiver_tensors_alternatives)

      expected_signature_defs = {
          "serving_default":
              signature_def_utils.regression_signature_def(
                  receiver_tensor, output_1),
          "head-2":
              signature_def_utils.classification_signature_def(
                  receiver_tensor, output_2, None),
          "head-3":
              signature_def_utils.predict_signature_def(
                  {"input": receiver_tensor}, {"some_output_3": output_3}),
          "other:head-3":
              signature_def_utils.predict_signature_def(
                  receiver_tensors_alternative_1, {"some_output_3": output_3}),

          # Note that the alternatives 'other:serving_default' and
          # 'other:head-2' are invalid, because regression and classification
          # signatures must take a single string input.  Here we verify that
          # these invalid signatures are not included in the export_utils.

          # Similarly, we verify that 'head-4' and 'head-5', which depend on an
          # input that is not being fed as a receiver tensor, are also omitted.

          # All the three heads are present when that input is fed, however:
          "with_unfed_input:head-3":
              signature_def_utils.predict_signature_def(
                  receiver_tensors_alternative_2, {"some_output_3": output_3}),
          "with_unfed_input:head-4":
              signature_def_utils.predict_signature_def(
                  receiver_tensors_alternative_2, {"some_output_4": output_4}),
          "with_unfed_input:head-5":
              signature_def_utils.predict_signature_def(
                  receiver_tensors_alternative_2, {"some_output_5": output_5})
      }

      self.assertDictEqual(expected_signature_defs, signature_defs)