You are viewing a plain text version of this content. The canonical link for it is here.
Posted to github@beam.apache.org by GitBox <gi...@apache.org> on 2022/10/01 01:23:22 UTC
[GitHub] [beam] AnandInguva opened a new pull request, #23456: TFX image classification example
AnandInguva opened a new pull request, #23456:
URL: https://github.com/apache/beam/pull/23456
**Please** add a meaningful description for your change here
------------------------
Thank you for your contribution! Follow this checklist to help us incorporate your contribution quickly and easily:
- [ ] [**Choose reviewer(s)**](https://beam.apache.org/contribute/#make-your-change) and mention them in a comment (`R: @username`).
- [ ] Mention the appropriate issue in your description (for example: `addresses #123`), if applicable. This will automatically add a link to the pull request in the issue. If you would like the issue to automatically close on merging the pull request, comment `fixes #<ISSUE NUMBER>` instead.
- [ ] Update `CHANGES.md` with noteworthy changes.
- [ ] If this contribution is large, please file an Apache [Individual Contributor License Agreement](https://www.apache.org/licenses/icla.pdf).
See the [Contributor Guide](https://beam.apache.org/contribute) for more tips on [how to make review process smoother](https://beam.apache.org/contribute/get-started-contributing/#make-the-reviewers-job-easier).
To check the build health, please visit [https://github.com/apache/beam/blob/master/.test-infra/BUILD_STATUS.md](https://github.com/apache/beam/blob/master/.test-infra/BUILD_STATUS.md)
GitHub Actions Tests Status (on master branch)
------------------------------------------------------------------------------------------------
[](https://github.com/apache/beam/actions?query=workflow%3A%22Build+python+source+distribution+and+wheels%22+branch%3Amaster+event%3Aschedule)
[](https://github.com/apache/beam/actions?query=workflow%3A%22Python+Tests%22+branch%3Amaster+event%3Aschedule)
[](https://github.com/apache/beam/actions?query=workflow%3A%22Java+Tests%22+branch%3Amaster+event%3Aschedule)
[](https://github.com/apache/beam/actions?query=workflow%3A%22Go+tests%22+branch%3Amaster+event%3Aschedule)
See [CI.md](https://github.com/apache/beam/blob/master/CI.md) for more information about GitHub Actions CI.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on a diff in pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on code in PR #23456:
URL: https://github.com/apache/beam/pull/23456#discussion_r1001102928
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/build_tensorflow_model.py:
##########
@@ -0,0 +1,71 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import tensorflow as tf
+
+
+class TFModelWrapperWithSignature(tf.keras.Model):
+ def __init__(
+ self,
+ model,
+ preprocess_input=None,
+ input_dtype=tf.float32,
+ feature_description=None):
+ super().__init__()
+ self.model = model
+ self.preprocess_input = preprocess_input
+ self.input_dtype = input_dtype
+ self.feature_description = feature_description
+ if not feature_description:
+ self.feature_description = {'image': tf.io.FixedLenFeature((), tf.string)}
+
+ @tf.function(input_signature=[tf.TensorSpec(shape=[None], dtype=tf.string)])
+ def call(self, serialized_examples):
+ features = tf.io.parse_example(
+ serialized_examples, features=self.feature_description)
+
+ # using TensorArray as suggested at
+ # https://github.com/tensorflow/tensorflow/issues/39323#issuecomment-627586602
+ batch = len(features['image'])
+ deserialized_vectors = tf.TensorArray(
+ self.input_dtype, size=batch, dynamic_size=True)
+ # issue arise with the indexing at features['image']
+ # Vectorized version of tf.io.parse_tensor is not available
+ # https://github.com/tensorflow/tensorflow/issues/43706
+ for i in range(batch):
+ deserialized_value = tf.io.parse_tensor(
+ features['image'][i], out_type=self.input_dtype)
+
+ # http://github.com/tensorflow/tensorflow/issues/30409#issuecomment-508962873
+ # In Graph mode, return value must get assigned in order to
+ # update the array
+ deserialized_vectors = deserialized_vectors.write(i, deserialized_value)
+
+ # deserialized_value = tf.expand_dims(deserialized_vectors, axis=0)
+ deserialized_tensor = deserialized_vectors.stack()
+ if self.preprocess_input:
+ deserialized_tensor = self.preprocess_input(deserialized_tensor)
+ return self.model(deserialized_tensor, training=False)
Review Comment:
Added **kwargs
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] damccorm merged pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
damccorm merged PR #23456:
URL: https://github.com/apache/beam/pull/23456
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] github-actions[bot] commented on pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
github-actions[bot] commented on PR #23456:
URL: https://github.com/apache/beam/pull/23456#issuecomment-1270192569
Stopping reviewer notifications for this pull request: requested by reviewer
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on PR #23456:
URL: https://github.com/apache/beam/pull/23456#issuecomment-1271737090
cc: @yeandy
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on PR #23456:
URL: https://github.com/apache/beam/pull/23456#issuecomment-1295069140
Run Python 3.10 PostCommit
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] damccorm commented on pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
damccorm commented on PR #23456:
URL: https://github.com/apache/beam/pull/23456#issuecomment-1287051759
Looks like tests are failing because tensorflow isn't installed; we probably need to add that as a test dependency in setup.py
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on a diff in pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on code in PR #23456:
URL: https://github.com/apache/beam/pull/23456#discussion_r1008342396
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/requirements.txt:
##########
@@ -0,0 +1,19 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.s
+#
+
+tfx_bsl
Review Comment:
```suggestion
tfx-bsl
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] ryanthompson591 commented on a diff in pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
ryanthompson591 commented on code in PR #23456:
URL: https://github.com/apache/beam/pull/23456#discussion_r992348524
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/tensorflow_image_classification.py:
##########
@@ -16,12 +16,12 @@
#
"""
-A pipeline tha uses TFX RunInference API to perform Image classification.
+A pipeline that uses TFX RunInference API to perform image classification.
Please look at https://github.com/tensorflow/tfx-bsl/tree/master/tfx_bsl/beam.
-Note: For the Tensorflow Model, it needs to be updated with a @tf.function
- Signature to accept bytes as inputs and should have logic to decode
- bytes to data which should be acceptable by the tensorflow model.
+Note: A Tensorflow Model needs to be updated with a @tf.function
+ Signature in order to accept bytes as inputs, and should have logic to decode
Review Comment:
s/Signature/signature
So this example hopes to have some sort of pretrained model and we just update it with a signature? This seems messy, is this the only way to use TF models?
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/build_tensorflow_model.py:
##########
@@ -0,0 +1,71 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import tensorflow as tf
+
+
+class TFModelWrapperWithSignature(tf.keras.Model):
+ def __init__(
+ self,
+ model,
+ preprocess_input=None,
+ input_dtype=tf.float32,
+ feature_description=None):
+ super().__init__()
+ self.model = model
+ self.preprocess_input = preprocess_input
+ self.input_dtype = input_dtype
+ self.feature_description = feature_description
+ if not feature_description:
+ self.feature_description = {'image': tf.io.FixedLenFeature((), tf.string)}
+
+ @tf.function(input_signature=[tf.TensorSpec(shape=[None], dtype=tf.string)])
+ def call(self, serialized_examples):
+ features = tf.io.parse_example(
+ serialized_examples, features=self.feature_description)
+
+ # using TensorArray as suggested at
+ # https://github.com/tensorflow/tensorflow/issues/39323#issuecomment-627586602
+ batch = len(features['image'])
+ deserialized_vectors = tf.TensorArray(
+ self.input_dtype, size=batch, dynamic_size=True)
+ # issue arise with the indexing at features['image']
+ # Vectorized version of tf.io.parse_tensor is not available
+ # https://github.com/tensorflow/tensorflow/issues/43706
+ for i in range(batch):
+ deserialized_value = tf.io.parse_tensor(
+ features['image'][i], out_type=self.input_dtype)
+
+ # http://github.com/tensorflow/tensorflow/issues/30409#issuecomment-508962873
+ # In Graph mode, return value must get assigned in order to
+ # update the array
+ deserialized_vectors = deserialized_vectors.write(i, deserialized_value)
+
+ # deserialized_value = tf.expand_dims(deserialized_vectors, axis=0)
Review Comment:
do we want to keep this commented code in?
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/build_tensorflow_model.py:
##########
@@ -0,0 +1,71 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import tensorflow as tf
+
+
+class TFModelWrapperWithSignature(tf.keras.Model):
+ def __init__(
+ self,
+ model,
+ preprocess_input=None,
+ input_dtype=tf.float32,
+ feature_description=None):
+ super().__init__()
+ self.model = model
+ self.preprocess_input = preprocess_input
+ self.input_dtype = input_dtype
+ self.feature_description = feature_description
+ if not feature_description:
+ self.feature_description = {'image': tf.io.FixedLenFeature((), tf.string)}
+
+ @tf.function(input_signature=[tf.TensorSpec(shape=[None], dtype=tf.string)])
+ def call(self, serialized_examples):
+ features = tf.io.parse_example(
+ serialized_examples, features=self.feature_description)
+
+ # using TensorArray as suggested at
+ # https://github.com/tensorflow/tensorflow/issues/39323#issuecomment-627586602
+ batch = len(features['image'])
+ deserialized_vectors = tf.TensorArray(
+ self.input_dtype, size=batch, dynamic_size=True)
+ # issue arise with the indexing at features['image']
Review Comment:
This comment was strange. I think all your trying to say is:
```
# Use a for loop to vectorize the tensor.
# https://github.com/tensorflow/tensorflow/issues/43706
```
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/build_tensorflow_model.py:
##########
@@ -0,0 +1,71 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import tensorflow as tf
+
+
+class TFModelWrapperWithSignature(tf.keras.Model):
+ def __init__(
+ self,
+ model,
+ preprocess_input=None,
+ input_dtype=tf.float32,
+ feature_description=None):
+ super().__init__()
+ self.model = model
+ self.preprocess_input = preprocess_input
+ self.input_dtype = input_dtype
+ self.feature_description = feature_description
+ if not feature_description:
+ self.feature_description = {'image': tf.io.FixedLenFeature((), tf.string)}
+
+ @tf.function(input_signature=[tf.TensorSpec(shape=[None], dtype=tf.string)])
+ def call(self, serialized_examples):
+ features = tf.io.parse_example(
+ serialized_examples, features=self.feature_description)
+
+ # using TensorArray as suggested at
+ # https://github.com/tensorflow/tensorflow/issues/39323#issuecomment-627586602
+ batch = len(features['image'])
+ deserialized_vectors = tf.TensorArray(
+ self.input_dtype, size=batch, dynamic_size=True)
+ # issue arise with the indexing at features['image']
+ # Vectorized version of tf.io.parse_tensor is not available
+ # https://github.com/tensorflow/tensorflow/issues/43706
+ for i in range(batch):
+ deserialized_value = tf.io.parse_tensor(
+ features['image'][i], out_type=self.input_dtype)
+
+ # http://github.com/tensorflow/tensorflow/issues/30409#issuecomment-508962873
+ # In Graph mode, return value must get assigned in order to
+ # update the array
+ deserialized_vectors = deserialized_vectors.write(i, deserialized_value)
+
+ # deserialized_value = tf.expand_dims(deserialized_vectors, axis=0)
+ deserialized_tensor = deserialized_vectors.stack()
+ if self.preprocess_input:
+ deserialized_tensor = self.preprocess_input(deserialized_tensor)
+ return self.model(deserialized_tensor, training=False)
+
+
+def save_tf_model(path, model=None, preprocess_input=None):
+ if not model:
+ model = tf.keras.applications.MobileNetV2(weights='imagenet')
+ preprocess_input = tf.keras.applications.mobilenet_v2.preprocess_input
+ signature_model = TFModelWrapperWithSignature(
+ model=model, preprocess_input=preprocess_input)
+ tf.saved_model.save(signature_model, path)
Review Comment:
I would add a run method at the bottom of this file that allows you to run this sample code.
It's unclear how to use this otherwise.
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/tensorflow_image_classification.py:
##########
@@ -0,0 +1,195 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+"""
+A pipeline that uses TFX RunInference API to perform image classification.
+Please look at https://github.com/tensorflow/tfx-bsl/tree/master/tfx_bsl/beam.
+
+Note: A Tensorflow Model needs to be updated with a @tf.function
+ Signature in order to accept bytes as inputs, and should have logic to decode
+ bytes to data that is acceptable by the TensorFlow model.
+ Please take a look at build_tensorflow_model.py on how to modify
+ TF Model's signature.
+"""
+
+import argparse
+import io
+import logging
+import os
+from typing import Iterable
+from typing import Iterator
+from typing import Optional
+from typing import Tuple
+
+import apache_beam as beam
+import tensorflow as tf
+from apache_beam.io.filesystems import FileSystems
+from apache_beam.ml.inference.base import KeyedModelHandler
+from apache_beam.ml.inference.base import RunInference
+from apache_beam.options.pipeline_options import PipelineOptions
+from apache_beam.options.pipeline_options import SetupOptions
+from apache_beam.runners.runner import PipelineResult
+from PIL import Image
+from tfx_bsl.public.beam.run_inference import CreateModelHandler
+from tfx_bsl.public.beam.run_inference import prediction_log_pb2
+from tfx_bsl.public.proto import model_spec_pb2
+
+_IMG_SIZE = (224, 224)
+
+
+def filter_empty_lines(text: str) -> Iterator[str]:
+ if len(text.strip()) > 0:
+ yield text
+
+
+def read_and_process_image(
+ image_file_name: str,
+ path_to_dir: Optional[str] = None) -> Tuple[str, tf.Tensor]:
+ if path_to_dir is not None:
+ image_file_name = os.path.join(path_to_dir, image_file_name)
+ with FileSystems().open(image_file_name, 'r') as file:
+ data = Image.open(io.BytesIO(file.read())).convert('RGB')
+ # Note: Converts the image dtype from uint8 to float32
+ # https://www.tensorflow.org/api_docs/python/tf/image/resize
+ image = tf.keras.preprocessing.image.img_to_array(data)
+ image = tf.image.resize(image, _IMG_SIZE)
+ return image_file_name, image
+
+
+def convert_image_to_example_proto(tensor):
+ """
+ This method performs the following:
+ 1. Accepts the tensor as input
+ 2. Serializes the tensor into bytes and pass it through
+ tf.train.Feature
+ 3. Pass the serialized tensor feature using tf.train.Example
+ Proto to the RunInference transform.
+
+ Args:
+ tensor: A TF tensor.
+ Returns:
+ example_proto: A tf.train.Example containing serialized tensor.
+ """
+ serialized_non_scalar = tf.io.serialize_tensor(tensor)
+ feature_of_bytes = tf.train.Feature(
+ bytes_list=tf.train.BytesList(value=[serialized_non_scalar.numpy()]))
+ features_for_example = {'image': feature_of_bytes}
+ example_proto = tf.train.Example(
+ features=tf.train.Features(feature=features_for_example))
+ return example_proto
+
+
+class ProcessInferenceToString(beam.DoFn):
+ def process(
+ self, element: Tuple[str,
+ prediction_log_pb2.PredictionLog]) -> Iterable[str]:
+ """
+ Args:
+ element: Tuple of str, and PredictionLog. Inference can be parsed
+ from prediction_log
+ returns:
+ str of filename and inference.
+ """
+ filename, predict_log = element[0], element[1].predict_log
+ output_value = predict_log.response.outputs
+ output_tensor = (
+ tf.io.decode_raw(
+ output_value['output_0'].tensor_content, out_type=tf.float32))
+ max_index_output_tensor = tf.math.argmax(output_tensor, axis=0)
+ yield filename + ',' + str(tf.get_static_value(max_index_output_tensor))
+
+
+def parse_known_args(argv):
+ """Parses args for the workflow."""
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ '--input',
+ dest='input',
+ required=True,
+ help='Path to the text file containing image names.')
+ parser.add_argument(
+ '--output',
+ dest='output',
+ required=True,
+ help='Path where to save output predictions.'
+ ' text file.')
Review Comment:
Fix help text.
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/tfx_bsl_inference_it_test.py:
##########
@@ -0,0 +1,89 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import logging
+import unittest
+import uuid
+
+import pytest
+
+from apache_beam.io.filesystems import FileSystems
+from apache_beam.testing.test_pipeline import TestPipeline
+
+# pylint: disable=ungrouped-imports
+try:
+ import tfx_bsl
+ from apache_beam.examples.inference.tfx_bsl import tensorflow_image_classification
+except ImportError as e:
+ tfx_bsl = None
+# pylint: disable=line-too-long
+_EXPECTED_OUTPUTS = {
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005001.JPEG': '681',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005002.JPEG': '333',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005003.JPEG': '711',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005004.JPEG': '286',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005005.JPEG': '445',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005006.JPEG': '288',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005007.JPEG': '880',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005008.JPEG': '534',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005009.JPEG': '888',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005010.JPEG': '996',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005011.JPEG': '327',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005012.JPEG': '573'
+}
+
+
+def process_outputs(filepath):
Review Comment:
This might not be part of this PR but are we doing this similar thing elsewhere? It might be worth thinking about making a utility method or inherited class at some point.
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/build_tensorflow_model.py:
##########
@@ -0,0 +1,71 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import tensorflow as tf
+
+
+class TFModelWrapperWithSignature(tf.keras.Model):
Review Comment:
Can you comment that into the code somehow, since it wouldn't be apparent to me if I was just looking at this code what it's purpose is. I mean this whole module is not used anywhere else as far as I can tell.
If I understand correctly it would be something like:
```
# This demonstrates how to build and save the model used in tensorflow_image_classification.py.
# To prepare a model you will need:
# 1. Instruction 1
#. 2. Instruction 2 ....
# A saved model should be placed in GCS and then can be referenced in ...
```
TFModelWrapperWithSignature( ...
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/tensorflow_image_classification.py:
##########
@@ -0,0 +1,195 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+"""
+A pipeline that uses TFX RunInference API to perform image classification.
+Please look at https://github.com/tensorflow/tfx-bsl/tree/master/tfx_bsl/beam.
+
+Note: A Tensorflow Model needs to be updated with a @tf.function
+ Signature in order to accept bytes as inputs, and should have logic to decode
+ bytes to data that is acceptable by the TensorFlow model.
+ Please take a look at build_tensorflow_model.py on how to modify
+ TF Model's signature.
+"""
+
+import argparse
+import io
+import logging
+import os
+from typing import Iterable
+from typing import Iterator
+from typing import Optional
+from typing import Tuple
+
+import apache_beam as beam
+import tensorflow as tf
+from apache_beam.io.filesystems import FileSystems
+from apache_beam.ml.inference.base import KeyedModelHandler
+from apache_beam.ml.inference.base import RunInference
+from apache_beam.options.pipeline_options import PipelineOptions
+from apache_beam.options.pipeline_options import SetupOptions
+from apache_beam.runners.runner import PipelineResult
+from PIL import Image
+from tfx_bsl.public.beam.run_inference import CreateModelHandler
+from tfx_bsl.public.beam.run_inference import prediction_log_pb2
+from tfx_bsl.public.proto import model_spec_pb2
+
+_IMG_SIZE = (224, 224)
+
+
+def filter_empty_lines(text: str) -> Iterator[str]:
+ if len(text.strip()) > 0:
+ yield text
+
+
+def read_and_process_image(
+ image_file_name: str,
+ path_to_dir: Optional[str] = None) -> Tuple[str, tf.Tensor]:
+ if path_to_dir is not None:
+ image_file_name = os.path.join(path_to_dir, image_file_name)
+ with FileSystems().open(image_file_name, 'r') as file:
+ data = Image.open(io.BytesIO(file.read())).convert('RGB')
+ # Note: Converts the image dtype from uint8 to float32
+ # https://www.tensorflow.org/api_docs/python/tf/image/resize
+ image = tf.keras.preprocessing.image.img_to_array(data)
+ image = tf.image.resize(image, _IMG_SIZE)
+ return image_file_name, image
+
+
+def convert_image_to_example_proto(tensor):
+ """
+ This method performs the following:
+ 1. Accepts the tensor as input
+ 2. Serializes the tensor into bytes and pass it through
+ tf.train.Feature
+ 3. Pass the serialized tensor feature using tf.train.Example
+ Proto to the RunInference transform.
+
+ Args:
+ tensor: A TF tensor.
+ Returns:
+ example_proto: A tf.train.Example containing serialized tensor.
+ """
+ serialized_non_scalar = tf.io.serialize_tensor(tensor)
+ feature_of_bytes = tf.train.Feature(
+ bytes_list=tf.train.BytesList(value=[serialized_non_scalar.numpy()]))
+ features_for_example = {'image': feature_of_bytes}
+ example_proto = tf.train.Example(
+ features=tf.train.Features(feature=features_for_example))
+ return example_proto
+
+
+class ProcessInferenceToString(beam.DoFn):
+ def process(
+ self, element: Tuple[str,
+ prediction_log_pb2.PredictionLog]) -> Iterable[str]:
+ """
+ Args:
+ element: Tuple of str, and PredictionLog. Inference can be parsed
+ from prediction_log
+ returns:
+ str of filename and inference.
+ """
+ filename, predict_log = element[0], element[1].predict_log
+ output_value = predict_log.response.outputs
+ output_tensor = (
+ tf.io.decode_raw(
+ output_value['output_0'].tensor_content, out_type=tf.float32))
+ max_index_output_tensor = tf.math.argmax(output_tensor, axis=0)
+ yield filename + ',' + str(tf.get_static_value(max_index_output_tensor))
+
+
+def parse_known_args(argv):
+ """Parses args for the workflow."""
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ '--input',
+ dest='input',
+ required=True,
+ help='Path to the text file containing image names.')
+ parser.add_argument(
+ '--output',
+ dest='output',
+ required=True,
+ help='Path where to save output predictions.'
+ ' text file.')
+ parser.add_argument(
+ '--model_path',
+ dest='model_path',
+ required=True,
+ help="Path to the model.")
+ parser.add_argument(
+ '--images_dir',
+ default=None,
+ help='Path to the directory where images are stored.'
+ 'Not required if image names in the input file have absolute path.')
+ return parser.parse_known_args(argv)
+
+
+def run(
+ argv=None, save_main_session=True, test_pipeline=None) -> PipelineResult:
+ """
+ Args:
+ argv: Command line arguments defined for this example.
+ save_main_session: Used for internal testing.
+ test_pipeline: Used for internal testing.
+ """
+ known_args, pipeline_args = parse_known_args(argv)
+ pipeline_options = PipelineOptions(pipeline_args)
+ pipeline_options.view_as(SetupOptions).save_main_session = save_main_session
+
+ saved_model_spec = model_spec_pb2.SavedModelSpec(
+ model_path=known_args.model_path)
+ inferece_spec_type = model_spec_pb2.InferenceSpecType(
+ saved_model_spec=saved_model_spec)
+ model_handler = CreateModelHandler(inferece_spec_type)
+ # create a KeyedModelHandler to accommodate image names as keys.
+ keyed_model_handler = KeyedModelHandler(model_handler)
+
+ pipeline = test_pipeline
+ if not test_pipeline:
+ pipeline = beam.Pipeline(options=pipeline_options)
+
+ filename_value_pair = (
+ pipeline
+ | 'ReadImageNames' >> beam.io.ReadFromText(known_args.input)
+ | 'FilterEmptyLines' >> beam.ParDo(filter_empty_lines)
Review Comment:
is it possible to have cleaned input as our example input, instead of needing to clean it in our sample code.
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/build_tensorflow_model.py:
##########
@@ -0,0 +1,71 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import tensorflow as tf
+
+
+class TFModelWrapperWithSignature(tf.keras.Model):
+ def __init__(
+ self,
+ model,
+ preprocess_input=None,
+ input_dtype=tf.float32,
+ feature_description=None):
+ super().__init__()
+ self.model = model
+ self.preprocess_input = preprocess_input
+ self.input_dtype = input_dtype
+ self.feature_description = feature_description
+ if not feature_description:
+ self.feature_description = {'image': tf.io.FixedLenFeature((), tf.string)}
+
+ @tf.function(input_signature=[tf.TensorSpec(shape=[None], dtype=tf.string)])
+ def call(self, serialized_examples):
+ features = tf.io.parse_example(
+ serialized_examples, features=self.feature_description)
+
+ # using TensorArray as suggested at
+ # https://github.com/tensorflow/tensorflow/issues/39323#issuecomment-627586602
+ batch = len(features['image'])
+ deserialized_vectors = tf.TensorArray(
+ self.input_dtype, size=batch, dynamic_size=True)
+ # issue arise with the indexing at features['image']
+ # Vectorized version of tf.io.parse_tensor is not available
+ # https://github.com/tensorflow/tensorflow/issues/43706
+ for i in range(batch):
+ deserialized_value = tf.io.parse_tensor(
+ features['image'][i], out_type=self.input_dtype)
+
+ # http://github.com/tensorflow/tensorflow/issues/30409#issuecomment-508962873
+ # In Graph mode, return value must get assigned in order to
+ # update the array
+ deserialized_vectors = deserialized_vectors.write(i, deserialized_value)
+
+ # deserialized_value = tf.expand_dims(deserialized_vectors, axis=0)
+ deserialized_tensor = deserialized_vectors.stack()
+ if self.preprocess_input:
+ deserialized_tensor = self.preprocess_input(deserialized_tensor)
+ return self.model(deserialized_tensor, training=False)
+
+
+def save_tf_model(path, model=None, preprocess_input=None):
+ if not model:
Review Comment:
Is the purpose of passing in a model to continue training on a partially trained model?
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/build_tensorflow_model.py:
##########
@@ -0,0 +1,71 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import tensorflow as tf
+
+
+class TFModelWrapperWithSignature(tf.keras.Model):
+ def __init__(
+ self,
+ model,
+ preprocess_input=None,
+ input_dtype=tf.float32,
+ feature_description=None):
+ super().__init__()
+ self.model = model
+ self.preprocess_input = preprocess_input
+ self.input_dtype = input_dtype
+ self.feature_description = feature_description
+ if not feature_description:
+ self.feature_description = {'image': tf.io.FixedLenFeature((), tf.string)}
+
+ @tf.function(input_signature=[tf.TensorSpec(shape=[None], dtype=tf.string)])
+ def call(self, serialized_examples):
+ features = tf.io.parse_example(
+ serialized_examples, features=self.feature_description)
+
+ # using TensorArray as suggested at
Review Comment:
this comment just seems out of place. Maybe make it more specific.
For example (and I don't know if this is right or not):
```
# A tensor Array is a set of all our input data. It is structured in this fashion:
#. a width x height x color matrix of float32 values representing the color value for each pixel.
# See https://github.com/tensorflow/tensorflow/issues/39323#issuecomment-627586602
# for more discussion on this setup.
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on a diff in pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on code in PR #23456:
URL: https://github.com/apache/beam/pull/23456#discussion_r1001022538
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/build_tensorflow_model.py:
##########
@@ -0,0 +1,71 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import tensorflow as tf
+
+
+class TFModelWrapperWithSignature(tf.keras.Model):
+ def __init__(
+ self,
+ model,
+ preprocess_input=None,
+ input_dtype=tf.float32,
+ feature_description=None):
+ super().__init__()
+ self.model = model
+ self.preprocess_input = preprocess_input
+ self.input_dtype = input_dtype
+ self.feature_description = feature_description
+ if not feature_description:
+ self.feature_description = {'image': tf.io.FixedLenFeature((), tf.string)}
+
+ @tf.function(input_signature=[tf.TensorSpec(shape=[None], dtype=tf.string)])
+ def call(self, serialized_examples):
+ features = tf.io.parse_example(
+ serialized_examples, features=self.feature_description)
+
+ # using TensorArray as suggested at
+ # https://github.com/tensorflow/tensorflow/issues/39323#issuecomment-627586602
+ batch = len(features['image'])
+ deserialized_vectors = tf.TensorArray(
+ self.input_dtype, size=batch, dynamic_size=True)
+ # issue arise with the indexing at features['image']
+ # Vectorized version of tf.io.parse_tensor is not available
+ # https://github.com/tensorflow/tensorflow/issues/43706
+ for i in range(batch):
+ deserialized_value = tf.io.parse_tensor(
+ features['image'][i], out_type=self.input_dtype)
+
+ # http://github.com/tensorflow/tensorflow/issues/30409#issuecomment-508962873
+ # In Graph mode, return value must get assigned in order to
+ # update the array
+ deserialized_vectors = deserialized_vectors.write(i, deserialized_value)
+
+ # deserialized_value = tf.expand_dims(deserialized_vectors, axis=0)
+ deserialized_tensor = deserialized_vectors.stack()
+ if self.preprocess_input:
+ deserialized_tensor = self.preprocess_input(deserialized_tensor)
+ return self.model(deserialized_tensor, training=False)
+
+
+def save_tf_model(path, model=None, preprocess_input=None):
+ if not model:
Review Comment:
We can pass in any TF model and we would get a model with modified signature at output so that it would be compatible with the TFX_BSL run inference.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] yeandy commented on a diff in pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
yeandy commented on code in PR #23456:
URL: https://github.com/apache/beam/pull/23456#discussion_r1001022994
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/build_tensorflow_model.py:
##########
@@ -0,0 +1,71 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import tensorflow as tf
+
+
+class TFModelWrapperWithSignature(tf.keras.Model):
+ def __init__(
+ self,
+ model,
+ preprocess_input=None,
+ input_dtype=tf.float32,
+ feature_description=None):
+ super().__init__()
+ self.model = model
+ self.preprocess_input = preprocess_input
+ self.input_dtype = input_dtype
+ self.feature_description = feature_description
+ if not feature_description:
+ self.feature_description = {'image': tf.io.FixedLenFeature((), tf.string)}
+
+ @tf.function(input_signature=[tf.TensorSpec(shape=[None], dtype=tf.string)])
+ def call(self, serialized_examples):
+ features = tf.io.parse_example(
+ serialized_examples, features=self.feature_description)
+
+ # using TensorArray as suggested at
+ # https://github.com/tensorflow/tensorflow/issues/39323#issuecomment-627586602
+ batch = len(features['image'])
+ deserialized_vectors = tf.TensorArray(
+ self.input_dtype, size=batch, dynamic_size=True)
+ # issue arise with the indexing at features['image']
+ # Vectorized version of tf.io.parse_tensor is not available
+ # https://github.com/tensorflow/tensorflow/issues/43706
+ for i in range(batch):
+ deserialized_value = tf.io.parse_tensor(
+ features['image'][i], out_type=self.input_dtype)
+
+ # http://github.com/tensorflow/tensorflow/issues/30409#issuecomment-508962873
+ # In Graph mode, return value must get assigned in order to
+ # update the array
+ deserialized_vectors = deserialized_vectors.write(i, deserialized_value)
+
+ # deserialized_value = tf.expand_dims(deserialized_vectors, axis=0)
+ deserialized_tensor = deserialized_vectors.stack()
+ if self.preprocess_input:
+ deserialized_tensor = self.preprocess_input(deserialized_tensor)
+ return self.model(deserialized_tensor, training=False)
+
+
+def save_tf_model(path, model=None, preprocess_input=None):
Review Comment:
👍
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] codecov[bot] commented on pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
codecov[bot] commented on PR #23456:
URL: https://github.com/apache/beam/pull/23456#issuecomment-1264192144
# [Codecov](https://codecov.io/gh/apache/beam/pull/23456?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation) Report
> Merging [#23456](https://codecov.io/gh/apache/beam/pull/23456?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation) (1f371f5) into [master](https://codecov.io/gh/apache/beam/commit/f2d426d2d2c088a573ab5a96e6e6bfc1bbf45b21?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation) (f2d426d) will **decrease** coverage by `0.05%`.
> The diff coverage is `0.00%`.
```diff
@@ Coverage Diff @@
## master #23456 +/- ##
==========================================
- Coverage 73.44% 73.38% -0.06%
==========================================
Files 718 720 +2
Lines 95680 95849 +169
==========================================
+ Hits 70271 70338 +67
- Misses 24098 24200 +102
Partials 1311 1311
```
| Flag | Coverage Δ | |
|---|---|---|
| python | `83.10% <0.00%> (-0.12%)` | :arrow_down: |
Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#carryforward-flags-in-the-pull-request-comment) to find out more.
| [Impacted Files](https://codecov.io/gh/apache/beam/pull/23456?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation) | Coverage Δ | |
|---|---|---|
| [...\_beam/examples/inference/build\_tensorflow\_model.py](https://codecov.io/gh/apache/beam/pull/23456/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-c2Rrcy9weXRob24vYXBhY2hlX2JlYW0vZXhhbXBsZXMvaW5mZXJlbmNlL2J1aWxkX3RlbnNvcmZsb3dfbW9kZWwucHk=) | `0.00% <0.00%> (ø)` | |
| [...mples/inference/tensorflow\_image\_classification.py](https://codecov.io/gh/apache/beam/pull/23456/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-c2Rrcy9weXRob24vYXBhY2hlX2JlYW0vZXhhbXBsZXMvaW5mZXJlbmNlL3RlbnNvcmZsb3dfaW1hZ2VfY2xhc3NpZmljYXRpb24ucHk=) | `0.00% <0.00%> (ø)` | |
| [.../python/apache\_beam/testing/test\_stream\_service.py](https://codecov.io/gh/apache/beam/pull/23456/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-c2Rrcy9weXRob24vYXBhY2hlX2JlYW0vdGVzdGluZy90ZXN0X3N0cmVhbV9zZXJ2aWNlLnB5) | `88.09% <0.00%> (-4.77%)` | :arrow_down: |
| [sdks/python/apache\_beam/utils/interactive\_utils.py](https://codecov.io/gh/apache/beam/pull/23456/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-c2Rrcy9weXRob24vYXBhY2hlX2JlYW0vdXRpbHMvaW50ZXJhY3RpdmVfdXRpbHMucHk=) | `95.12% <0.00%> (-2.44%)` | :arrow_down: |
| [...che\_beam/runners/interactive/interactive\_runner.py](https://codecov.io/gh/apache/beam/pull/23456/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-c2Rrcy9weXRob24vYXBhY2hlX2JlYW0vcnVubmVycy9pbnRlcmFjdGl2ZS9pbnRlcmFjdGl2ZV9ydW5uZXIucHk=) | `90.50% <0.00%> (-1.27%)` | :arrow_down: |
| [...eam/runners/portability/fn\_api\_runner/execution.py](https://codecov.io/gh/apache/beam/pull/23456/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-c2Rrcy9weXRob24vYXBhY2hlX2JlYW0vcnVubmVycy9wb3J0YWJpbGl0eS9mbl9hcGlfcnVubmVyL2V4ZWN1dGlvbi5weQ==) | `92.44% <0.00%> (-0.65%)` | :arrow_down: |
| [...eam/runners/interactive/interactive\_environment.py](https://codecov.io/gh/apache/beam/pull/23456/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-c2Rrcy9weXRob24vYXBhY2hlX2JlYW0vcnVubmVycy9pbnRlcmFjdGl2ZS9pbnRlcmFjdGl2ZV9lbnZpcm9ubWVudC5weQ==) | `91.71% <0.00%> (-0.31%)` | :arrow_down: |
| [...hon/apache\_beam/runners/worker/bundle\_processor.py](https://codecov.io/gh/apache/beam/pull/23456/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-c2Rrcy9weXRob24vYXBhY2hlX2JlYW0vcnVubmVycy93b3JrZXIvYnVuZGxlX3Byb2Nlc3Nvci5weQ==) | `93.42% <0.00%> (-0.13%)` | :arrow_down: |
| [sdks/python/apache\_beam/coders/coder\_impl.py](https://codecov.io/gh/apache/beam/pull/23456/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-c2Rrcy9weXRob24vYXBhY2hlX2JlYW0vY29kZXJzL2NvZGVyX2ltcGwucHk=) | `93.80% <0.00%> (-0.11%)` | :arrow_down: |
| [setup.py](https://codecov.io/gh/apache/beam/pull/23456/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-c2V0dXAucHk=) | `0.00% <0.00%> (ø)` | |
| ... and [8 more](https://codecov.io/gh/apache/beam/pull/23456/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation) | |
:mega: We’re building smart automated test selection to slash your CI/CD build times. [Learn more](https://about.codecov.io/iterative-testing/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on a diff in pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on code in PR #23456:
URL: https://github.com/apache/beam/pull/23456#discussion_r989147853
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/build_tensorflow_model.py:
##########
@@ -0,0 +1,71 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import tensorflow as tf
+
Review Comment:
Yep. I will add it.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on PR #23456:
URL: https://github.com/apache/beam/pull/23456#issuecomment-1302514360
Run Python 3.9 PostCommit
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on a diff in pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on code in PR #23456:
URL: https://github.com/apache/beam/pull/23456#discussion_r1001955562
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/build_tensorflow_model.py:
##########
@@ -0,0 +1,71 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import tensorflow as tf
+
+
+class TFModelWrapperWithSignature(tf.keras.Model):
Review Comment:
I will add it once the postcommit passes
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] damccorm commented on pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
damccorm commented on PR #23456:
URL: https://github.com/apache/beam/pull/23456#issuecomment-1287099263
Run Python 3.7 PostCommit
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] damccorm commented on a diff in pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
damccorm commented on code in PR #23456:
URL: https://github.com/apache/beam/pull/23456#discussion_r1001882384
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/build_tensorflow_model.py:
##########
@@ -0,0 +1,71 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import tensorflow as tf
+
+
+class TFModelWrapperWithSignature(tf.keras.Model):
Review Comment:
+1 on adding a class header function here, I think making this step clear could be one of the biggest value adds of this example
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/tensorflow_image_classification.py:
##########
@@ -0,0 +1,195 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+"""
+A pipeline that uses TFX RunInference API to perform image classification.
+Please look at https://github.com/tensorflow/tfx-bsl/tree/master/tfx_bsl/beam.
+
+Note: A Tensorflow Model needs to be updated with a @tf.function
+ Signature in order to accept bytes as inputs, and should have logic to decode
+ bytes to data that is acceptable by the TensorFlow model.
+ Please take a look at build_tensorflow_model.py on how to modify
+ TF Model's signature.
+"""
+
+import argparse
+import io
+import logging
+import os
+from typing import Iterable
+from typing import Iterator
+from typing import Optional
+from typing import Tuple
+
+import apache_beam as beam
+import tensorflow as tf
+from apache_beam.io.filesystems import FileSystems
+from apache_beam.ml.inference.base import KeyedModelHandler
+from apache_beam.ml.inference.base import RunInference
+from apache_beam.options.pipeline_options import PipelineOptions
+from apache_beam.options.pipeline_options import SetupOptions
+from apache_beam.runners.runner import PipelineResult
+from PIL import Image
+from tfx_bsl.public.beam.run_inference import CreateModelHandler
+from tfx_bsl.public.beam.run_inference import prediction_log_pb2
+from tfx_bsl.public.proto import model_spec_pb2
+
+_IMG_SIZE = (224, 224)
+
+
+def filter_empty_lines(text: str) -> Iterator[str]:
+ if len(text.strip()) > 0:
+ yield text
+
+
+def read_and_process_image(
+ image_file_name: str,
+ path_to_dir: Optional[str] = None) -> Tuple[str, tf.Tensor]:
+ if path_to_dir is not None:
+ image_file_name = os.path.join(path_to_dir, image_file_name)
+ with FileSystems().open(image_file_name, 'r') as file:
+ data = Image.open(io.BytesIO(file.read())).convert('RGB')
+ # Note: Converts the image dtype from uint8 to float32
+ # https://www.tensorflow.org/api_docs/python/tf/image/resize
+ image = tf.keras.preprocessing.image.img_to_array(data)
+ image = tf.image.resize(image, _IMG_SIZE)
+ return image_file_name, image
+
+
+def convert_image_to_example_proto(tensor):
+ """
+ This method performs the following:
+ 1. Accepts the tensor as input
+ 2. Serializes the tensor into bytes and pass it through
+ tf.train.Feature
+ 3. Pass the serialized tensor feature using tf.train.Example
+ Proto to the RunInference transform.
+
+ Args:
+ tensor: A TF tensor.
+ Returns:
+ example_proto: A tf.train.Example containing serialized tensor.
+ """
+ serialized_non_scalar = tf.io.serialize_tensor(tensor)
+ feature_of_bytes = tf.train.Feature(
+ bytes_list=tf.train.BytesList(value=[serialized_non_scalar.numpy()]))
+ features_for_example = {'image': feature_of_bytes}
+ example_proto = tf.train.Example(
+ features=tf.train.Features(feature=features_for_example))
+ return example_proto
+
+
+class ProcessInferenceToString(beam.DoFn):
+ def process(
+ self, element: Tuple[str,
+ prediction_log_pb2.PredictionLog]) -> Iterable[str]:
+ """
+ Args:
+ element: Tuple of str, and PredictionLog. Inference can be parsed
+ from prediction_log
+ returns:
+ str of filename and inference.
+ """
+ filename, predict_log = element[0], element[1].predict_log
+ output_value = predict_log.response.outputs
+ output_tensor = (
+ tf.io.decode_raw(
+ output_value['output_0'].tensor_content, out_type=tf.float32))
+ max_index_output_tensor = tf.math.argmax(output_tensor, axis=0)
+ yield filename + ',' + str(tf.get_static_value(max_index_output_tensor))
+
+
+def parse_known_args(argv):
+ """Parses args for the workflow."""
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ '--input',
+ dest='input',
+ required=True,
+ help='Path to the text file containing image names.')
+ parser.add_argument(
+ '--output',
+ dest='output',
+ required=True,
+ help='Path where to save output predictions.'
+ ' text file.')
+ parser.add_argument(
+ '--model_path',
+ dest='model_path',
+ required=True,
+ help="Path to the model.")
+ parser.add_argument(
+ '--images_dir',
+ default=None,
+ help='Path to the directory where images are stored.'
+ 'Not required if image names in the input file have absolute path.')
+ return parser.parse_known_args(argv)
+
+
+def run(
+ argv=None, save_main_session=True, test_pipeline=None) -> PipelineResult:
+ """
+ Args:
+ argv: Command line arguments defined for this example.
+ save_main_session: Used for internal testing.
+ test_pipeline: Used for internal testing.
+ """
+ known_args, pipeline_args = parse_known_args(argv)
+ pipeline_options = PipelineOptions(pipeline_args)
+ pipeline_options.view_as(SetupOptions).save_main_session = save_main_session
+
+ saved_model_spec = model_spec_pb2.SavedModelSpec(
+ model_path=known_args.model_path)
+ inferece_spec_type = model_spec_pb2.InferenceSpecType(
+ saved_model_spec=saved_model_spec)
+ model_handler = CreateModelHandler(inferece_spec_type)
+ # create a KeyedModelHandler to accommodate image names as keys.
+ keyed_model_handler = KeyedModelHandler(model_handler)
+
+ pipeline = test_pipeline
+ if not test_pipeline:
+ pipeline = beam.Pipeline(options=pipeline_options)
+
+ filename_value_pair = (
+ pipeline
+ | 'ReadImageNames' >> beam.io.ReadFromText(known_args.input)
+ | 'FilterEmptyLines' >> beam.ParDo(filter_empty_lines)
Review Comment:
I don't mind doing this, but maybe we can simplify to
`| 'FilterEmptyLines' >> beam.Filter(lambda txt: len(text.strip()) > 0)`
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on PR #23456:
URL: https://github.com/apache/beam/pull/23456#issuecomment-1271735077
Run Portable_Python PreCommit
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on a diff in pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on code in PR #23456:
URL: https://github.com/apache/beam/pull/23456#discussion_r1001107826
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/tensorflow_image_classification.py:
##########
@@ -16,12 +16,12 @@
#
"""
-A pipeline tha uses TFX RunInference API to perform Image classification.
+A pipeline that uses TFX RunInference API to perform image classification.
Please look at https://github.com/tensorflow/tfx-bsl/tree/master/tfx_bsl/beam.
-Note: For the Tensorflow Model, it needs to be updated with a @tf.function
- Signature to accept bytes as inputs and should have logic to decode
- bytes to data which should be acceptable by the tensorflow model.
+Note: A Tensorflow Model needs to be updated with a @tf.function
+ Signature in order to accept bytes as inputs, and should have logic to decode
Review Comment:
We can use any TF Model. this is one example where we load the TF model with modified signature to use the RUnInference transform on the images.
We don't update the signature as part of this example. it is done prior to running this pipeline and saved in a path accessible by the pipeline
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on PR #23456:
URL: https://github.com/apache/beam/pull/23456#issuecomment-1295020749
> @AnandInguva looks like the postcommit is still failing
I am not sure what is the root cause of the failure. Some dependency issues or I see some TensorRT errors, may be because machine type is different on Jenkins. I will update the test
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on PR #23456:
URL: https://github.com/apache/beam/pull/23456#issuecomment-1302814331
Run Portable_Python PreCommit
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on PR #23456:
URL: https://github.com/apache/beam/pull/23456#issuecomment-1302525069
Python 3.10 wheels for TFX BSL is not released yet. So I moved the inference test suite to Python 3.9. I tried to run only InferencePostCommit tests as part of Python 3.9 PostCommits and it passed.

Ignore the UI of the run. It doesn't show all the results. There is a bug already filed for that.
https://ci-beam.apache.org/job/beam_PostCommit_Python39_PR/96/console#gradle-task-26
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on a diff in pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on code in PR #23456:
URL: https://github.com/apache/beam/pull/23456#discussion_r1001040192
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/tensorflow_image_classification.py:
##########
@@ -0,0 +1,195 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+"""
+A pipeline that uses TFX RunInference API to perform image classification.
+Please look at https://github.com/tensorflow/tfx-bsl/tree/master/tfx_bsl/beam.
+
+Note: A Tensorflow Model needs to be updated with a @tf.function
+ Signature in order to accept bytes as inputs, and should have logic to decode
+ bytes to data that is acceptable by the TensorFlow model.
+ Please take a look at build_tensorflow_model.py on how to modify
+ TF Model's signature.
+"""
+
+import argparse
+import io
+import logging
+import os
+from typing import Iterable
+from typing import Iterator
+from typing import Optional
+from typing import Tuple
+
+import apache_beam as beam
+import tensorflow as tf
+from apache_beam.io.filesystems import FileSystems
+from apache_beam.ml.inference.base import KeyedModelHandler
+from apache_beam.ml.inference.base import RunInference
+from apache_beam.options.pipeline_options import PipelineOptions
+from apache_beam.options.pipeline_options import SetupOptions
+from apache_beam.runners.runner import PipelineResult
+from PIL import Image
+from tfx_bsl.public.beam.run_inference import CreateModelHandler
+from tfx_bsl.public.beam.run_inference import prediction_log_pb2
+from tfx_bsl.public.proto import model_spec_pb2
+
+_IMG_SIZE = (224, 224)
+
+
+def filter_empty_lines(text: str) -> Iterator[str]:
+ if len(text.strip()) > 0:
+ yield text
+
+
+def read_and_process_image(
+ image_file_name: str,
+ path_to_dir: Optional[str] = None) -> Tuple[str, tf.Tensor]:
+ if path_to_dir is not None:
+ image_file_name = os.path.join(path_to_dir, image_file_name)
+ with FileSystems().open(image_file_name, 'r') as file:
+ data = Image.open(io.BytesIO(file.read())).convert('RGB')
+ # Note: Converts the image dtype from uint8 to float32
+ # https://www.tensorflow.org/api_docs/python/tf/image/resize
+ image = tf.keras.preprocessing.image.img_to_array(data)
+ image = tf.image.resize(image, _IMG_SIZE)
+ return image_file_name, image
+
+
+def convert_image_to_example_proto(tensor):
+ """
+ This method performs the following:
+ 1. Accepts the tensor as input
+ 2. Serializes the tensor into bytes and pass it through
+ tf.train.Feature
+ 3. Pass the serialized tensor feature using tf.train.Example
+ Proto to the RunInference transform.
+
+ Args:
+ tensor: A TF tensor.
+ Returns:
+ example_proto: A tf.train.Example containing serialized tensor.
+ """
+ serialized_non_scalar = tf.io.serialize_tensor(tensor)
+ feature_of_bytes = tf.train.Feature(
+ bytes_list=tf.train.BytesList(value=[serialized_non_scalar.numpy()]))
+ features_for_example = {'image': feature_of_bytes}
+ example_proto = tf.train.Example(
+ features=tf.train.Features(feature=features_for_example))
+ return example_proto
+
+
+class ProcessInferenceToString(beam.DoFn):
+ def process(
+ self, element: Tuple[str,
+ prediction_log_pb2.PredictionLog]) -> Iterable[str]:
+ """
+ Args:
+ element: Tuple of str, and PredictionLog. Inference can be parsed
+ from prediction_log
+ returns:
+ str of filename and inference.
+ """
+ filename, predict_log = element[0], element[1].predict_log
+ output_value = predict_log.response.outputs
+ output_tensor = (
+ tf.io.decode_raw(
+ output_value['output_0'].tensor_content, out_type=tf.float32))
+ max_index_output_tensor = tf.math.argmax(output_tensor, axis=0)
+ yield filename + ',' + str(tf.get_static_value(max_index_output_tensor))
+
+
+def parse_known_args(argv):
+ """Parses args for the workflow."""
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ '--input',
+ dest='input',
+ required=True,
+ help='Path to the text file containing image names.')
+ parser.add_argument(
+ '--output',
+ dest='output',
+ required=True,
+ help='Path where to save output predictions.'
+ ' text file.')
+ parser.add_argument(
+ '--model_path',
+ dest='model_path',
+ required=True,
+ help="Path to the model.")
+ parser.add_argument(
+ '--images_dir',
+ default=None,
+ help='Path to the directory where images are stored.'
+ 'Not required if image names in the input file have absolute path.')
+ return parser.parse_known_args(argv)
+
+
+def run(
+ argv=None, save_main_session=True, test_pipeline=None) -> PipelineResult:
+ """
+ Args:
+ argv: Command line arguments defined for this example.
+ save_main_session: Used for internal testing.
+ test_pipeline: Used for internal testing.
+ """
+ known_args, pipeline_args = parse_known_args(argv)
+ pipeline_options = PipelineOptions(pipeline_args)
+ pipeline_options.view_as(SetupOptions).save_main_session = save_main_session
+
+ saved_model_spec = model_spec_pb2.SavedModelSpec(
+ model_path=known_args.model_path)
+ inferece_spec_type = model_spec_pb2.InferenceSpecType(
+ saved_model_spec=saved_model_spec)
+ model_handler = CreateModelHandler(inferece_spec_type)
+ # create a KeyedModelHandler to accommodate image names as keys.
+ keyed_model_handler = KeyedModelHandler(model_handler)
+
+ pipeline = test_pipeline
+ if not test_pipeline:
+ pipeline = beam.Pipeline(options=pipeline_options)
+
+ filename_value_pair = (
+ pipeline
+ | 'ReadImageNames' >> beam.io.ReadFromText(known_args.input)
+ | 'FilterEmptyLines' >> beam.ParDo(filter_empty_lines)
Review Comment:
I am sorry. I didn't understand this.
Did you mean to have `beam.Create([examples])`?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on a diff in pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on code in PR #23456:
URL: https://github.com/apache/beam/pull/23456#discussion_r1001040192
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/tensorflow_image_classification.py:
##########
@@ -0,0 +1,195 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+"""
+A pipeline that uses TFX RunInference API to perform image classification.
+Please look at https://github.com/tensorflow/tfx-bsl/tree/master/tfx_bsl/beam.
+
+Note: A Tensorflow Model needs to be updated with a @tf.function
+ Signature in order to accept bytes as inputs, and should have logic to decode
+ bytes to data that is acceptable by the TensorFlow model.
+ Please take a look at build_tensorflow_model.py on how to modify
+ TF Model's signature.
+"""
+
+import argparse
+import io
+import logging
+import os
+from typing import Iterable
+from typing import Iterator
+from typing import Optional
+from typing import Tuple
+
+import apache_beam as beam
+import tensorflow as tf
+from apache_beam.io.filesystems import FileSystems
+from apache_beam.ml.inference.base import KeyedModelHandler
+from apache_beam.ml.inference.base import RunInference
+from apache_beam.options.pipeline_options import PipelineOptions
+from apache_beam.options.pipeline_options import SetupOptions
+from apache_beam.runners.runner import PipelineResult
+from PIL import Image
+from tfx_bsl.public.beam.run_inference import CreateModelHandler
+from tfx_bsl.public.beam.run_inference import prediction_log_pb2
+from tfx_bsl.public.proto import model_spec_pb2
+
+_IMG_SIZE = (224, 224)
+
+
+def filter_empty_lines(text: str) -> Iterator[str]:
+ if len(text.strip()) > 0:
+ yield text
+
+
+def read_and_process_image(
+ image_file_name: str,
+ path_to_dir: Optional[str] = None) -> Tuple[str, tf.Tensor]:
+ if path_to_dir is not None:
+ image_file_name = os.path.join(path_to_dir, image_file_name)
+ with FileSystems().open(image_file_name, 'r') as file:
+ data = Image.open(io.BytesIO(file.read())).convert('RGB')
+ # Note: Converts the image dtype from uint8 to float32
+ # https://www.tensorflow.org/api_docs/python/tf/image/resize
+ image = tf.keras.preprocessing.image.img_to_array(data)
+ image = tf.image.resize(image, _IMG_SIZE)
+ return image_file_name, image
+
+
+def convert_image_to_example_proto(tensor):
+ """
+ This method performs the following:
+ 1. Accepts the tensor as input
+ 2. Serializes the tensor into bytes and pass it through
+ tf.train.Feature
+ 3. Pass the serialized tensor feature using tf.train.Example
+ Proto to the RunInference transform.
+
+ Args:
+ tensor: A TF tensor.
+ Returns:
+ example_proto: A tf.train.Example containing serialized tensor.
+ """
+ serialized_non_scalar = tf.io.serialize_tensor(tensor)
+ feature_of_bytes = tf.train.Feature(
+ bytes_list=tf.train.BytesList(value=[serialized_non_scalar.numpy()]))
+ features_for_example = {'image': feature_of_bytes}
+ example_proto = tf.train.Example(
+ features=tf.train.Features(feature=features_for_example))
+ return example_proto
+
+
+class ProcessInferenceToString(beam.DoFn):
+ def process(
+ self, element: Tuple[str,
+ prediction_log_pb2.PredictionLog]) -> Iterable[str]:
+ """
+ Args:
+ element: Tuple of str, and PredictionLog. Inference can be parsed
+ from prediction_log
+ returns:
+ str of filename and inference.
+ """
+ filename, predict_log = element[0], element[1].predict_log
+ output_value = predict_log.response.outputs
+ output_tensor = (
+ tf.io.decode_raw(
+ output_value['output_0'].tensor_content, out_type=tf.float32))
+ max_index_output_tensor = tf.math.argmax(output_tensor, axis=0)
+ yield filename + ',' + str(tf.get_static_value(max_index_output_tensor))
+
+
+def parse_known_args(argv):
+ """Parses args for the workflow."""
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ '--input',
+ dest='input',
+ required=True,
+ help='Path to the text file containing image names.')
+ parser.add_argument(
+ '--output',
+ dest='output',
+ required=True,
+ help='Path where to save output predictions.'
+ ' text file.')
+ parser.add_argument(
+ '--model_path',
+ dest='model_path',
+ required=True,
+ help="Path to the model.")
+ parser.add_argument(
+ '--images_dir',
+ default=None,
+ help='Path to the directory where images are stored.'
+ 'Not required if image names in the input file have absolute path.')
+ return parser.parse_known_args(argv)
+
+
+def run(
+ argv=None, save_main_session=True, test_pipeline=None) -> PipelineResult:
+ """
+ Args:
+ argv: Command line arguments defined for this example.
+ save_main_session: Used for internal testing.
+ test_pipeline: Used for internal testing.
+ """
+ known_args, pipeline_args = parse_known_args(argv)
+ pipeline_options = PipelineOptions(pipeline_args)
+ pipeline_options.view_as(SetupOptions).save_main_session = save_main_session
+
+ saved_model_spec = model_spec_pb2.SavedModelSpec(
+ model_path=known_args.model_path)
+ inferece_spec_type = model_spec_pb2.InferenceSpecType(
+ saved_model_spec=saved_model_spec)
+ model_handler = CreateModelHandler(inferece_spec_type)
+ # create a KeyedModelHandler to accommodate image names as keys.
+ keyed_model_handler = KeyedModelHandler(model_handler)
+
+ pipeline = test_pipeline
+ if not test_pipeline:
+ pipeline = beam.Pipeline(options=pipeline_options)
+
+ filename_value_pair = (
+ pipeline
+ | 'ReadImageNames' >> beam.io.ReadFromText(known_args.input)
+ | 'FilterEmptyLines' >> beam.ParDo(filter_empty_lines)
Review Comment:
I am sorry. I didn't understand this.
Did you mean to have `beam.Create([examples])`?
NVM, understood what you mean
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] ryanthompson591 commented on a diff in pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
ryanthompson591 commented on code in PR #23456:
URL: https://github.com/apache/beam/pull/23456#discussion_r1004721652
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/build_tensorflow_model.py:
##########
@@ -0,0 +1,99 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Intended only for internal testing.
+
+from typing import Dict
+from typing import Optional
+
+import tensorflow as tf
+
+
+class TFModelWrapperWithSignature(tf.keras.Model):
+ def __init__(
+ self,
+ model,
+ preprocess_input=None,
+ input_dtype=None,
+ feature_description=None,
+ **kwargs):
Review Comment:
If we can be specific about kwargs should be, that would be ideal. If not it's fine.
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/build_tensorflow_model.py:
##########
@@ -0,0 +1,99 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Intended only for internal testing.
+
+from typing import Dict
+from typing import Optional
+
+import tensorflow as tf
+
+
+class TFModelWrapperWithSignature(tf.keras.Model):
+ def __init__(
+ self,
+ model,
+ preprocess_input=None,
+ input_dtype=None,
+ feature_description=None,
+ **kwargs):
+ super().__init__()
+ self.model = model
+ self.preprocess_input = preprocess_input
+ self.input_dtype = input_dtype
+ self.feature_description = feature_description
+ if not feature_description:
+ self.feature_description = {'image': tf.io.FixedLenFeature((), tf.string)}
+ self._kwargs = kwargs
+
+ @tf.function(input_signature=[tf.TensorSpec(shape=[None], dtype=tf.string)])
+ def call(self, serialized_examples):
+ features = tf.io.parse_example(
+ serialized_examples, features=self.feature_description)
+
+ # Initialize a TensorArray to store the deserialized values.
+ # For more details, please look at
+ # https://github.com/tensorflow/tensorflow/issues/39323#issuecomment-627586602
+ batch = len(features['image'])
Review Comment:
rename to batch_len ?
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/build_tensorflow_model.py:
##########
@@ -0,0 +1,99 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Intended only for internal testing.
+
+from typing import Dict
+from typing import Optional
+
+import tensorflow as tf
+
+
+class TFModelWrapperWithSignature(tf.keras.Model):
+ def __init__(
+ self,
+ model,
+ preprocess_input=None,
+ input_dtype=None,
+ feature_description=None,
+ **kwargs):
+ super().__init__()
+ self.model = model
+ self.preprocess_input = preprocess_input
+ self.input_dtype = input_dtype
+ self.feature_description = feature_description
+ if not feature_description:
+ self.feature_description = {'image': tf.io.FixedLenFeature((), tf.string)}
+ self._kwargs = kwargs
+
+ @tf.function(input_signature=[tf.TensorSpec(shape=[None], dtype=tf.string)])
+ def call(self, serialized_examples):
+ features = tf.io.parse_example(
+ serialized_examples, features=self.feature_description)
+
+ # Initialize a TensorArray to store the deserialized values.
+ # For more details, please look at
+ # https://github.com/tensorflow/tensorflow/issues/39323#issuecomment-627586602
+ batch = len(features['image'])
+ deserialized_vectors = tf.TensorArray(
+ self.input_dtype, size=batch, dynamic_size=True)
+ # Vectorized version of tf.io.parse_tensor is not available.
+ # Use for loop to vectorize the tensor. For more details, refer
+ # https://github.com/tensorflow/tensorflow/issues/43706
+ for i in range(batch):
+ deserialized_value = tf.io.parse_tensor(
+ features['image'][i], out_type=self.input_dtype)
+ # http://github.com/tensorflow/tensorflow/issues/30409#issuecomment-508962873
+ # In Graph mode, return value must get assigned in order to
+ # update the array
+ deserialized_vectors = deserialized_vectors.write(i, deserialized_value)
+
+ deserialized_tensor = deserialized_vectors.stack()
+ if self.preprocess_input:
+ deserialized_tensor = self.preprocess_input(deserialized_tensor)
+ return self.model(deserialized_tensor, **self._kwargs)
+
+
+def save_tf_model_with_signature(
+ path_to_save_model,
+ model=None,
+ preprocess_input=None,
+ input_dtype=tf.float32,
+ feature_description: Optional[Dict] = None,
+ **kwargs,
+):
+ """
+ Helper function used to save the Tensorflow Model with a serving signature.
+ This is intended only for internal testing.
+ Args:
+ path_to_save_model: Path to save the model with modified signature.
+ model: Base tensorflow model used for TFX-BSL RunInference transform.
+ preprocess_input: Preprocess method to be included as part of the
+ Model's serving signature.
+ input_dtype: dtype of the inputs to the model.
Review Comment:
call out if this is a list or what the expected input is?
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/tensorflow_image_classification.py:
##########
@@ -0,0 +1,192 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+"""
+A pipeline that uses TFX RunInference API to perform image classification.
+Please look at https://github.com/tensorflow/tfx-bsl/tree/master/tfx_bsl/beam.
Review Comment:
How about here for documentation?
https://www.tensorflow.org/tfx/tfx_bsl/api_docs/python/tfx_bsl/public/beam/run_inference/CreateModelHandler
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/build_tensorflow_model.py:
##########
@@ -0,0 +1,71 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import tensorflow as tf
+
+
+class TFModelWrapperWithSignature(tf.keras.Model):
Review Comment:
Not done. Adding comments shouldn't effect the postcommit.
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/tfx_bsl_inference_it_test.py:
##########
@@ -0,0 +1,99 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import logging
+import unittest
+import uuid
+
+import pytest
+
+from apache_beam.io.filesystems import FileSystems
+from apache_beam.testing.test_pipeline import TestPipeline
+
+# pylint: disable=ungrouped-imports
+try:
+ import tfx_bsl
+ import tensorflow as tf
+ from apache_beam.examples.inference.tfx_bsl import tensorflow_image_classification
+ from apache_beam.examples.inference.tfx_bsl.build_tensorflow_model import save_tf_model_with_signature
+except ImportError as e:
+ tfx_bsl = None
+# pylint: disable=line-too-long
+_EXPECTED_OUTPUTS = {
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005001.JPEG': '681',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005002.JPEG': '333',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005003.JPEG': '711',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005004.JPEG': '286',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005005.JPEG': '445',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005006.JPEG': '288',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005007.JPEG': '880',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005008.JPEG': '534',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005009.JPEG': '888',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005010.JPEG': '996',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005011.JPEG': '327',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005012.JPEG': '573'
+}
+
+
+def process_outputs(filepath):
+ with FileSystems().open(filepath) as f:
+ lines = f.readlines()
+ lines = [l.decode('utf-8').strip('\n') for l in lines]
+ return lines
+
+
+@unittest.skipIf(
+ tfx_bsl is None, 'Missing dependencies. '
+ 'Test depends on tfx_bsl')
+class TFXRunInferenceTests(unittest.TestCase):
+ @pytest.mark.uses_tensorflow
+ @pytest.mark.it_postcommit
+ def test_tfx_run_inference_mobilenetv2(self):
Review Comment:
why are we using mobilenetv2? Wouldn't a GPU model be better?
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/build_tensorflow_model.py:
##########
@@ -0,0 +1,99 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Intended only for internal testing.
+
+from typing import Dict
+from typing import Optional
+
+import tensorflow as tf
+
+
+class TFModelWrapperWithSignature(tf.keras.Model):
+ def __init__(
+ self,
+ model,
+ preprocess_input=None,
+ input_dtype=None,
+ feature_description=None,
+ **kwargs):
+ super().__init__()
+ self.model = model
+ self.preprocess_input = preprocess_input
+ self.input_dtype = input_dtype
+ self.feature_description = feature_description
+ if not feature_description:
+ self.feature_description = {'image': tf.io.FixedLenFeature((), tf.string)}
+ self._kwargs = kwargs
+
+ @tf.function(input_signature=[tf.TensorSpec(shape=[None], dtype=tf.string)])
+ def call(self, serialized_examples):
+ features = tf.io.parse_example(
+ serialized_examples, features=self.feature_description)
+
+ # Initialize a TensorArray to store the deserialized values.
+ # For more details, please look at
+ # https://github.com/tensorflow/tensorflow/issues/39323#issuecomment-627586602
+ batch = len(features['image'])
+ deserialized_vectors = tf.TensorArray(
+ self.input_dtype, size=batch, dynamic_size=True)
+ # Vectorized version of tf.io.parse_tensor is not available.
+ # Use for loop to vectorize the tensor. For more details, refer
+ # https://github.com/tensorflow/tensorflow/issues/43706
+ for i in range(batch):
+ deserialized_value = tf.io.parse_tensor(
+ features['image'][i], out_type=self.input_dtype)
+ # http://github.com/tensorflow/tensorflow/issues/30409#issuecomment-508962873
Review Comment:
I like the comment format:
```
# Some description of why this exists.
# See http://mylink...
```
Here you have it flipped.
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/tensorflow_image_classification.py:
##########
@@ -0,0 +1,192 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+"""
+A pipeline that uses TFX RunInference API to perform image classification.
Review Comment:
A sample pipeline illustrating how to use Apache Beams run_inference api with tfx-bsl's CreateModelHandler API.
---- some more suggested text you might add---
The images for this example are taken from <insert something>.
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/build_tensorflow_model.py:
##########
@@ -0,0 +1,99 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Intended only for internal testing.
+
+from typing import Dict
+from typing import Optional
+
+import tensorflow as tf
+
+
+class TFModelWrapperWithSignature(tf.keras.Model):
+ def __init__(
+ self,
+ model,
+ preprocess_input=None,
+ input_dtype=None,
+ feature_description=None,
+ **kwargs):
+ super().__init__()
+ self.model = model
+ self.preprocess_input = preprocess_input
+ self.input_dtype = input_dtype
+ self.feature_description = feature_description
+ if not feature_description:
+ self.feature_description = {'image': tf.io.FixedLenFeature((), tf.string)}
+ self._kwargs = kwargs
+
+ @tf.function(input_signature=[tf.TensorSpec(shape=[None], dtype=tf.string)])
+ def call(self, serialized_examples):
+ features = tf.io.parse_example(
+ serialized_examples, features=self.feature_description)
+
+ # Initialize a TensorArray to store the deserialized values.
+ # For more details, please look at
+ # https://github.com/tensorflow/tensorflow/issues/39323#issuecomment-627586602
+ batch = len(features['image'])
+ deserialized_vectors = tf.TensorArray(
+ self.input_dtype, size=batch, dynamic_size=True)
+ # Vectorized version of tf.io.parse_tensor is not available.
+ # Use for loop to vectorize the tensor. For more details, refer
+ # https://github.com/tensorflow/tensorflow/issues/43706
+ for i in range(batch):
+ deserialized_value = tf.io.parse_tensor(
+ features['image'][i], out_type=self.input_dtype)
+ # http://github.com/tensorflow/tensorflow/issues/30409#issuecomment-508962873
+ # In Graph mode, return value must get assigned in order to
+ # update the array
+ deserialized_vectors = deserialized_vectors.write(i, deserialized_value)
+
+ deserialized_tensor = deserialized_vectors.stack()
+ if self.preprocess_input:
+ deserialized_tensor = self.preprocess_input(deserialized_tensor)
+ return self.model(deserialized_tensor, **self._kwargs)
Review Comment:
What are you expecting in kwargs? Is it possible to make it known though comment or explicitly?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on a diff in pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on code in PR #23456:
URL: https://github.com/apache/beam/pull/23456#discussion_r1005137787
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/tensorflow_image_classification.py:
##########
@@ -0,0 +1,192 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+"""
+A pipeline that uses TFX RunInference API to perform image classification.
Review Comment:
SG
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on PR #23456:
URL: https://github.com/apache/beam/pull/23456#issuecomment-1287057576
> Looks like tests are failing because tensorflow isn't installed; we probably need to add that as a test dependency in setup.py
This test was meant to run only on PostCommit. I reorder imports so that unittests would skip this file but postcommits would be able to run it.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on a diff in pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on code in PR #23456:
URL: https://github.com/apache/beam/pull/23456#discussion_r1001034865
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/build_tensorflow_model.py:
##########
@@ -0,0 +1,71 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import tensorflow as tf
+
+
+class TFModelWrapperWithSignature(tf.keras.Model):
+ def __init__(
+ self,
+ model,
+ preprocess_input=None,
+ input_dtype=tf.float32,
+ feature_description=None):
+ super().__init__()
+ self.model = model
+ self.preprocess_input = preprocess_input
+ self.input_dtype = input_dtype
+ self.feature_description = feature_description
+ if not feature_description:
+ self.feature_description = {'image': tf.io.FixedLenFeature((), tf.string)}
+
+ @tf.function(input_signature=[tf.TensorSpec(shape=[None], dtype=tf.string)])
+ def call(self, serialized_examples):
+ features = tf.io.parse_example(
+ serialized_examples, features=self.feature_description)
+
+ # using TensorArray as suggested at
+ # https://github.com/tensorflow/tensorflow/issues/39323#issuecomment-627586602
+ batch = len(features['image'])
+ deserialized_vectors = tf.TensorArray(
+ self.input_dtype, size=batch, dynamic_size=True)
+ # issue arise with the indexing at features['image']
+ # Vectorized version of tf.io.parse_tensor is not available
+ # https://github.com/tensorflow/tensorflow/issues/43706
+ for i in range(batch):
+ deserialized_value = tf.io.parse_tensor(
+ features['image'][i], out_type=self.input_dtype)
+
+ # http://github.com/tensorflow/tensorflow/issues/30409#issuecomment-508962873
+ # In Graph mode, return value must get assigned in order to
+ # update the array
+ deserialized_vectors = deserialized_vectors.write(i, deserialized_value)
+
+ # deserialized_value = tf.expand_dims(deserialized_vectors, axis=0)
+ deserialized_tensor = deserialized_vectors.stack()
+ if self.preprocess_input:
+ deserialized_tensor = self.preprocess_input(deserialized_tensor)
+ return self.model(deserialized_tensor, training=False)
Review Comment:
Hm.. I thought every subclass of tf.keras.Model has support for training optional parameter. Can you share me the link to the model you are using? I will change this accordingly.
https://screenshot.googleplex.com/4dydDnHDUcTuURD
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] github-actions[bot] commented on pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
github-actions[bot] commented on PR #23456:
URL: https://github.com/apache/beam/pull/23456#issuecomment-1270187136
Assigning reviewers. If you would like to opt out of this review, comment `assign to next reviewer`:
R: @tvalentyn for label python.
Available commands:
- `stop reviewer notifications` - opt out of the automated review tooling
- `remind me after tests pass` - tag the comment author after tests pass
- `waiting on author` - shift the attention set back to the author (any comment or push by the author will return the attention set to the reviewers)
The PR bot will only process comments in the main thread (not review comments).
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on a diff in pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on code in PR #23456:
URL: https://github.com/apache/beam/pull/23456#discussion_r1001017034
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/build_tensorflow_model.py:
##########
@@ -0,0 +1,71 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import tensorflow as tf
+
+
+class TFModelWrapperWithSignature(tf.keras.Model):
+ def __init__(
+ self,
+ model,
+ preprocess_input=None,
+ input_dtype=tf.float32,
+ feature_description=None):
+ super().__init__()
+ self.model = model
+ self.preprocess_input = preprocess_input
+ self.input_dtype = input_dtype
+ self.feature_description = feature_description
+ if not feature_description:
+ self.feature_description = {'image': tf.io.FixedLenFeature((), tf.string)}
+
+ @tf.function(input_signature=[tf.TensorSpec(shape=[None], dtype=tf.string)])
+ def call(self, serialized_examples):
+ features = tf.io.parse_example(
+ serialized_examples, features=self.feature_description)
+
+ # using TensorArray as suggested at
+ # https://github.com/tensorflow/tensorflow/issues/39323#issuecomment-627586602
+ batch = len(features['image'])
+ deserialized_vectors = tf.TensorArray(
+ self.input_dtype, size=batch, dynamic_size=True)
+ # issue arise with the indexing at features['image']
+ # Vectorized version of tf.io.parse_tensor is not available
+ # https://github.com/tensorflow/tensorflow/issues/43706
+ for i in range(batch):
+ deserialized_value = tf.io.parse_tensor(
+ features['image'][i], out_type=self.input_dtype)
+
+ # http://github.com/tensorflow/tensorflow/issues/30409#issuecomment-508962873
+ # In Graph mode, return value must get assigned in order to
+ # update the array
+ deserialized_vectors = deserialized_vectors.write(i, deserialized_value)
+
+ # deserialized_value = tf.expand_dims(deserialized_vectors, axis=0)
+ deserialized_tensor = deserialized_vectors.stack()
+ if self.preprocess_input:
+ deserialized_tensor = self.preprocess_input(deserialized_tensor)
+ return self.model(deserialized_tensor, training=False)
+
+
+def save_tf_model(path, model=None, preprocess_input=None):
Review Comment:
as of now, we don't run it anywhere but I can make use of this method for the Performance tests. I will add instructions on how to use it
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] damccorm commented on pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
damccorm commented on PR #23456:
URL: https://github.com/apache/beam/pull/23456#issuecomment-1293987467
Run Python 3.7 PostCommit
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on PR #23456:
URL: https://github.com/apache/beam/pull/23456#issuecomment-1302814535
Run Python PreCommit
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on PR #23456:
URL: https://github.com/apache/beam/pull/23456#issuecomment-1270916738
Run Python 3.9 PostCommit
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on a diff in pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on code in PR #23456:
URL: https://github.com/apache/beam/pull/23456#discussion_r1001104076
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/tfx_bsl_inference_it_test.py:
##########
@@ -0,0 +1,89 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import logging
+import unittest
+import uuid
+
+import pytest
+
+from apache_beam.io.filesystems import FileSystems
+from apache_beam.testing.test_pipeline import TestPipeline
+
+# pylint: disable=ungrouped-imports
+try:
+ import tfx_bsl
+ from apache_beam.examples.inference.tfx_bsl import tensorflow_image_classification
+except ImportError as e:
+ tfx_bsl = None
+# pylint: disable=line-too-long
+_EXPECTED_OUTPUTS = {
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005001.JPEG': '681',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005002.JPEG': '333',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005003.JPEG': '711',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005004.JPEG': '286',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005005.JPEG': '445',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005006.JPEG': '288',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005007.JPEG': '880',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005008.JPEG': '534',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005009.JPEG': '888',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005010.JPEG': '996',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005011.JPEG': '327',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005012.JPEG': '573'
+}
+
+
+def process_outputs(filepath):
Review Comment:
Yes. I will make a note of this and open a different PR soon
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on PR #23456:
URL: https://github.com/apache/beam/pull/23456#issuecomment-1286145346
R: @damccorm
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on PR #23456:
URL: https://github.com/apache/beam/pull/23456#issuecomment-1270189513
stop reviewer notifications
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] yeandy commented on a diff in pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
yeandy commented on code in PR #23456:
URL: https://github.com/apache/beam/pull/23456#discussion_r1001024019
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/build_tensorflow_model.py:
##########
@@ -0,0 +1,71 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import tensorflow as tf
+
+
+class TFModelWrapperWithSignature(tf.keras.Model):
+ def __init__(
+ self,
+ model,
+ preprocess_input=None,
+ input_dtype=tf.float32,
+ feature_description=None):
+ super().__init__()
+ self.model = model
+ self.preprocess_input = preprocess_input
+ self.input_dtype = input_dtype
+ self.feature_description = feature_description
+ if not feature_description:
+ self.feature_description = {'image': tf.io.FixedLenFeature((), tf.string)}
+
+ @tf.function(input_signature=[tf.TensorSpec(shape=[None], dtype=tf.string)])
+ def call(self, serialized_examples):
+ features = tf.io.parse_example(
+ serialized_examples, features=self.feature_description)
+
+ # using TensorArray as suggested at
+ # https://github.com/tensorflow/tensorflow/issues/39323#issuecomment-627586602
+ batch = len(features['image'])
+ deserialized_vectors = tf.TensorArray(
+ self.input_dtype, size=batch, dynamic_size=True)
+ # issue arise with the indexing at features['image']
+ # Vectorized version of tf.io.parse_tensor is not available
+ # https://github.com/tensorflow/tensorflow/issues/43706
+ for i in range(batch):
+ deserialized_value = tf.io.parse_tensor(
+ features['image'][i], out_type=self.input_dtype)
+
+ # http://github.com/tensorflow/tensorflow/issues/30409#issuecomment-508962873
+ # In Graph mode, return value must get assigned in order to
+ # update the array
+ deserialized_vectors = deserialized_vectors.write(i, deserialized_value)
+
+ # deserialized_value = tf.expand_dims(deserialized_vectors, axis=0)
+ deserialized_tensor = deserialized_vectors.stack()
+ if self.preprocess_input:
+ deserialized_tensor = self.preprocess_input(deserialized_tensor)
+ return self.model(deserialized_tensor, training=False)
Review Comment:
I was testing with a different model, and got this issue
```
TypeError: in user code:
File "/Users/yeandy/projects/beam/sdks/python/apache_beam/examples/inference/tfx_bsl/build_tensorflow_model.py", line 62, in call *
return self.model(deserialized_tensor, training=False)
TypeError: f(input_tensor) got unexpected keyword argument `training`.
```
May need to change to kwargs here?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on a diff in pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on code in PR #23456:
URL: https://github.com/apache/beam/pull/23456#discussion_r1001034865
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/build_tensorflow_model.py:
##########
@@ -0,0 +1,71 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import tensorflow as tf
+
+
+class TFModelWrapperWithSignature(tf.keras.Model):
+ def __init__(
+ self,
+ model,
+ preprocess_input=None,
+ input_dtype=tf.float32,
+ feature_description=None):
+ super().__init__()
+ self.model = model
+ self.preprocess_input = preprocess_input
+ self.input_dtype = input_dtype
+ self.feature_description = feature_description
+ if not feature_description:
+ self.feature_description = {'image': tf.io.FixedLenFeature((), tf.string)}
+
+ @tf.function(input_signature=[tf.TensorSpec(shape=[None], dtype=tf.string)])
+ def call(self, serialized_examples):
+ features = tf.io.parse_example(
+ serialized_examples, features=self.feature_description)
+
+ # using TensorArray as suggested at
+ # https://github.com/tensorflow/tensorflow/issues/39323#issuecomment-627586602
+ batch = len(features['image'])
+ deserialized_vectors = tf.TensorArray(
+ self.input_dtype, size=batch, dynamic_size=True)
+ # issue arise with the indexing at features['image']
+ # Vectorized version of tf.io.parse_tensor is not available
+ # https://github.com/tensorflow/tensorflow/issues/43706
+ for i in range(batch):
+ deserialized_value = tf.io.parse_tensor(
+ features['image'][i], out_type=self.input_dtype)
+
+ # http://github.com/tensorflow/tensorflow/issues/30409#issuecomment-508962873
+ # In Graph mode, return value must get assigned in order to
+ # update the array
+ deserialized_vectors = deserialized_vectors.write(i, deserialized_value)
+
+ # deserialized_value = tf.expand_dims(deserialized_vectors, axis=0)
+ deserialized_tensor = deserialized_vectors.stack()
+ if self.preprocess_input:
+ deserialized_tensor = self.preprocess_input(deserialized_tensor)
+ return self.model(deserialized_tensor, training=False)
Review Comment:
Hm.. I thought every subclass of tf.keras.Model has support for training optional parameter. Can you share me the link to the model you are using? I will change this accordingly.

--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on PR #23456:
URL: https://github.com/apache/beam/pull/23456#issuecomment-1302814692
Failing tests seems irrelevant but running them one more time
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on PR #23456:
URL: https://github.com/apache/beam/pull/23456#issuecomment-1270188494
stop reviewer notification
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] yeandy commented on a diff in pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
yeandy commented on code in PR #23456:
URL: https://github.com/apache/beam/pull/23456#discussion_r990242890
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/tensorflow_image_classification.py:
##########
@@ -0,0 +1,195 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+"""
+A pipeline tha uses TFX RunInference API to perform Image classification.
+Please look at https://github.com/tensorflow/tfx-bsl/tree/master/tfx_bsl/beam.
+
+Note: For the Tensorflow Model, it needs to be updated with a @tf.function
+ Signature to accept bytes as inputs and should have logic to decode
+ bytes to data which should be acceptable by the tensorflow model.
+ Please take a look at build_tensorflow_model.py on how to modify
+ TF Model's signature.
+"""
+
+import argparse
+import io
+import logging
+import os
+from typing import Iterable
+from typing import Iterator
+from typing import Optional
+from typing import Tuple
+
+import apache_beam as beam
+import tensorflow as tf
+from apache_beam.io.filesystems import FileSystems
+from apache_beam.ml.inference.base import KeyedModelHandler
+from apache_beam.ml.inference.base import RunInference
+from apache_beam.options.pipeline_options import PipelineOptions
+from apache_beam.options.pipeline_options import SetupOptions
+from apache_beam.runners.runner import PipelineResult
+from PIL import Image
+from tfx_bsl.public.beam.run_inference import CreateModelHandler
+from tfx_bsl.public.beam.run_inference import prediction_log_pb2
+from tfx_bsl.public.proto import model_spec_pb2
+
+_IMG_SIZE = (224, 224)
+
+
+def filter_empty_lines(text: str) -> Iterator[str]:
+ if len(text.strip()) > 0:
+ yield text
+
+
+def read_and_process_image(
+ image_file_name: str,
+ path_to_dir: Optional[str] = None) -> Tuple[str, tf.Tensor]:
+ if path_to_dir is not None:
+ image_file_name = os.path.join(path_to_dir, image_file_name)
+ with FileSystems().open(image_file_name, 'r') as file:
+ data = Image.open(io.BytesIO(file.read())).convert('RGB')
+ # Note: Converts the image dtype from uint8 to float32
+ # https://www.tensorflow.org/api_docs/python/tf/image/resize
+ image = tf.keras.preprocessing.image.img_to_array(data)
+ image = tf.image.resize(image, _IMG_SIZE)
+ return image_file_name, image
+
+
+def convert_image_to_example_proto(tensor):
+ """
+ This method performs the following:
+ 1. Accepts the tensor as input
+ 2. Serializes the tensor into bytes and pass it through
+ tf.train.Feature
+ 3. Pass the serialized tensor feature using tf.train.Example
+ Proto to the RunInference transform.
+
+ Args:
+ tensor: A TF tensor.
+ Returns:
+ example_proto: A tf.train.Example containing serialized tensor.
+ """
+ serialized_non_scalar = tf.io.serialize_tensor(tensor)
+ feature_of_bytes = tf.train.Feature(
+ bytes_list=tf.train.BytesList(value=[serialized_non_scalar.numpy()]))
+ features_for_example = {'image': feature_of_bytes}
+ example_proto = tf.train.Example(
+ features=tf.train.Features(feature=features_for_example))
+ return example_proto
+
+
+class ProcessInferenceToString(beam.DoFn):
+ def process(
+ self, element: Tuple[str,
+ prediction_log_pb2.PredictionLog]) -> Iterable[str]:
+ """
+ Args:
+ element: Tuple of str, and PredictionLog. Inference can be parsed
+ from prediction_log
+ returns:
+ str of filename and inference.
+ """
+ filename, predict_log = element[0], element[1].predict_log
+ output_value = predict_log.response.outputs
+ output_tensor = (
+ tf.io.decode_raw(
+ output_value['output_0'].tensor_content, out_type=tf.float32))
+ max_index_output_tensor = tf.math.argmax(output_tensor, axis=0)
+ yield filename + ',' + str(tf.get_static_value(max_index_output_tensor))
+
+
+def parse_known_args(argv):
+ """Parses args for the workflow."""
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ '--input',
+ dest='input',
+ required=True,
+ help='Path to the text file containing image names.')
+ parser.add_argument(
+ '--output',
+ dest='output',
+ required=True,
+ help='Path where to save output predictions.'
+ ' text file.')
+ parser.add_argument(
+ '--model_path',
+ dest='model_path',
+ required=True,
+ help="Path to the model.")
+ parser.add_argument(
+ '--images_dir',
+ default=None,
+ help='Path to the directory where images are stored.'
+ 'Not required if image names in the input file have absolute path.')
+ return parser.parse_known_args(argv)
+
+
+def run(
+ argv=None, save_main_session=True, test_pipeline=None) -> PipelineResult:
+ """
+ Args:
+ argv: Command line arguments defined for this example.
+ save_main_session: Used for internal testing.
+ test_pipeline: Used for internal testing.
+ """
+ known_args, pipeline_args = parse_known_args(argv)
+ pipeline_options = PipelineOptions(pipeline_args)
+ pipeline_options.view_as(SetupOptions).save_main_session = save_main_session
+
+ saved_model_spec = model_spec_pb2.SavedModelSpec(
+ model_path=known_args.model_path)
+ inferece_spec_type = model_spec_pb2.InferenceSpecType(
+ saved_model_spec=saved_model_spec)
+ model_handler = CreateModelHandler(inferece_spec_type)
+ # create a keyedModelHandler to accommodate image names as keys.
+ keyed_model_handler = KeyedModelHandler(model_handler)
+
+ pipeline = test_pipeline
+ if not test_pipeline:
+ pipeline = beam.Pipeline(options=pipeline_options)
Review Comment:
Can't we just rename the input param from `test_pipeline` to `pipeline` (line 144) so we don't have to set `pipeline = test_pipeline`?
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/build_tensorflow_model.py:
##########
@@ -0,0 +1,71 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import tensorflow as tf
+
+
+class TFModelWrapperWithSignature(tf.keras.Model):
+ def __init__(
+ self,
+ model,
+ preprocess_input=None,
+ input_dtype=tf.float32,
+ feature_description=None):
+ super().__init__()
+ self.model = model
+ self.preprocess_input = preprocess_input
+ self.input_dtype = input_dtype
+ self.feature_description = feature_description
+ if not feature_description:
+ self.feature_description = {'image': tf.io.FixedLenFeature((), tf.string)}
+
+ @tf.function(input_signature=[tf.TensorSpec(shape=[None], dtype=tf.string)])
+ def call(self, serialized_examples):
+ features = tf.io.parse_example(
+ serialized_examples, features=self.feature_description)
+
+ # using TensorArray as suggested at
+ # https://github.com/tensorflow/tensorflow/issues/39323#issuecomment-627586602
+ batch = len(features['image'])
+ deserialized_vectors = tf.TensorArray(
+ self.input_dtype, size=batch, dynamic_size=True)
+ # issue arise with the indexing at features['image']
+ # Vectorized version of tf.io.parse_tensor is not available
+ # https://github.com/tensorflow/tensorflow/issues/43706
+ for i in range(batch):
+ deserialized_value = tf.io.parse_tensor(
+ features['image'][i], out_type=self.input_dtype)
+
+ # http://github.com/tensorflow/tensorflow/issues/30409#issuecomment-508962873
+ # In Graph mode, return value must get assigned in order to
+ # update the array
+ deserialized_vectors = deserialized_vectors.write(i, deserialized_value)
+
+ # deserialized_value = tf.expand_dims(deserialized_vectors, axis=0)
+ deserialized_tensor = deserialized_vectors.stack()
+ if self.preprocess_input:
+ deserialized_tensor = self.preprocess_input(deserialized_tensor)
+ return self.model(deserialized_tensor, training=False)
+
+
+def save_tf_model(path, model=None, preprocess_input=None):
Review Comment:
This doesn't actually get run anywhere, right? It's looks to be just reference for a user. Are there any instructions on how to use `save_tf_model`?
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/tensorflow_image_classification.py:
##########
@@ -0,0 +1,195 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+"""
+A pipeline tha uses TFX RunInference API to perform Image classification.
+Please look at https://github.com/tensorflow/tfx-bsl/tree/master/tfx_bsl/beam.
+
+Note: For the Tensorflow Model, it needs to be updated with a @tf.function
+ Signature to accept bytes as inputs and should have logic to decode
+ bytes to data which should be acceptable by the tensorflow model.
+ Please take a look at build_tensorflow_model.py on how to modify
+ TF Model's signature.
+"""
+
+import argparse
+import io
+import logging
+import os
+from typing import Iterable
+from typing import Iterator
+from typing import Optional
+from typing import Tuple
+
+import apache_beam as beam
+import tensorflow as tf
+from apache_beam.io.filesystems import FileSystems
+from apache_beam.ml.inference.base import KeyedModelHandler
+from apache_beam.ml.inference.base import RunInference
+from apache_beam.options.pipeline_options import PipelineOptions
+from apache_beam.options.pipeline_options import SetupOptions
+from apache_beam.runners.runner import PipelineResult
+from PIL import Image
+from tfx_bsl.public.beam.run_inference import CreateModelHandler
+from tfx_bsl.public.beam.run_inference import prediction_log_pb2
+from tfx_bsl.public.proto import model_spec_pb2
+
+_IMG_SIZE = (224, 224)
+
+
+def filter_empty_lines(text: str) -> Iterator[str]:
+ if len(text.strip()) > 0:
+ yield text
+
+
+def read_and_process_image(
+ image_file_name: str,
+ path_to_dir: Optional[str] = None) -> Tuple[str, tf.Tensor]:
+ if path_to_dir is not None:
+ image_file_name = os.path.join(path_to_dir, image_file_name)
+ with FileSystems().open(image_file_name, 'r') as file:
+ data = Image.open(io.BytesIO(file.read())).convert('RGB')
+ # Note: Converts the image dtype from uint8 to float32
+ # https://www.tensorflow.org/api_docs/python/tf/image/resize
+ image = tf.keras.preprocessing.image.img_to_array(data)
+ image = tf.image.resize(image, _IMG_SIZE)
+ return image_file_name, image
+
+
+def convert_image_to_example_proto(tensor):
+ """
+ This method performs the following:
+ 1. Accepts the tensor as input
+ 2. Serializes the tensor into bytes and pass it through
+ tf.train.Feature
+ 3. Pass the serialized tensor feature using tf.train.Example
+ Proto to the RunInference transform.
+
+ Args:
+ tensor: A TF tensor.
+ Returns:
+ example_proto: A tf.train.Example containing serialized tensor.
+ """
+ serialized_non_scalar = tf.io.serialize_tensor(tensor)
+ feature_of_bytes = tf.train.Feature(
+ bytes_list=tf.train.BytesList(value=[serialized_non_scalar.numpy()]))
+ features_for_example = {'image': feature_of_bytes}
+ example_proto = tf.train.Example(
+ features=tf.train.Features(feature=features_for_example))
+ return example_proto
+
+
+class ProcessInferenceToString(beam.DoFn):
+ def process(
+ self, element: Tuple[str,
+ prediction_log_pb2.PredictionLog]) -> Iterable[str]:
+ """
+ Args:
+ element: Tuple of str, and PredictionLog. Inference can be parsed
+ from prediction_log
+ returns:
+ str of filename and inference.
+ """
+ filename, predict_log = element[0], element[1].predict_log
+ output_value = predict_log.response.outputs
+ output_tensor = (
+ tf.io.decode_raw(
+ output_value['output_0'].tensor_content, out_type=tf.float32))
+ max_index_output_tensor = tf.math.argmax(output_tensor, axis=0)
+ yield filename + ',' + str(tf.get_static_value(max_index_output_tensor))
+
+
+def parse_known_args(argv):
+ """Parses args for the workflow."""
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ '--input',
+ dest='input',
+ required=True,
+ help='Path to the text file containing image names.')
+ parser.add_argument(
+ '--output',
+ dest='output',
+ required=True,
+ help='Path where to save output predictions.'
+ ' text file.')
+ parser.add_argument(
+ '--model_path',
+ dest='model_path',
+ required=True,
+ help="Path to the model.")
+ parser.add_argument(
+ '--images_dir',
+ default=None,
+ help='Path to the directory where images are stored.'
+ 'Not required if image names in the input file have absolute path.')
+ return parser.parse_known_args(argv)
+
+
+def run(
+ argv=None, save_main_session=True, test_pipeline=None) -> PipelineResult:
+ """
+ Args:
+ argv: Command line arguments defined for this example.
+ save_main_session: Used for internal testing.
+ test_pipeline: Used for internal testing.
+ """
+ known_args, pipeline_args = parse_known_args(argv)
+ pipeline_options = PipelineOptions(pipeline_args)
+ pipeline_options.view_as(SetupOptions).save_main_session = save_main_session
+
+ saved_model_spec = model_spec_pb2.SavedModelSpec(
+ model_path=known_args.model_path)
+ inferece_spec_type = model_spec_pb2.InferenceSpecType(
+ saved_model_spec=saved_model_spec)
+ model_handler = CreateModelHandler(inferece_spec_type)
+ # create a keyedModelHandler to accommodate image names as keys.
Review Comment:
nit
```suggestion
# create a KeyedModelHandler to accommodate image names as keys.
```
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/tensorflow_image_classification.py:
##########
@@ -0,0 +1,195 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+"""
+A pipeline tha uses TFX RunInference API to perform Image classification.
+Please look at https://github.com/tensorflow/tfx-bsl/tree/master/tfx_bsl/beam.
Review Comment:
```suggestion
A pipeline that uses TFX RunInference API to perform image classification.
Please look at https://github.com/tensorflow/tfx-bsl/tree/master/tfx_bsl/beam.
```
##########
sdks/python/test-suites/direct/common.gradle:
##########
@@ -233,10 +234,38 @@ task sklearnInferenceTest {
}
}
+// Scikit-learn RunInference IT tests
Review Comment:
```suggestion
// TensorFlow Extended (TFX) RunInference IT tests
```
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/tensorflow_image_classification.py:
##########
@@ -0,0 +1,195 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+"""
+A pipeline tha uses TFX RunInference API to perform Image classification.
+Please look at https://github.com/tensorflow/tfx-bsl/tree/master/tfx_bsl/beam.
+
+Note: For the Tensorflow Model, it needs to be updated with a @tf.function
+ Signature to accept bytes as inputs and should have logic to decode
+ bytes to data which should be acceptable by the tensorflow model.
+ Please take a look at build_tensorflow_model.py on how to modify
+ TF Model's signature.
+"""
+
+import argparse
+import io
+import logging
+import os
+from typing import Iterable
+from typing import Iterator
+from typing import Optional
+from typing import Tuple
+
+import apache_beam as beam
+import tensorflow as tf
+from apache_beam.io.filesystems import FileSystems
+from apache_beam.ml.inference.base import KeyedModelHandler
+from apache_beam.ml.inference.base import RunInference
+from apache_beam.options.pipeline_options import PipelineOptions
+from apache_beam.options.pipeline_options import SetupOptions
+from apache_beam.runners.runner import PipelineResult
+from PIL import Image
+from tfx_bsl.public.beam.run_inference import CreateModelHandler
+from tfx_bsl.public.beam.run_inference import prediction_log_pb2
+from tfx_bsl.public.proto import model_spec_pb2
+
+_IMG_SIZE = (224, 224)
+
+
+def filter_empty_lines(text: str) -> Iterator[str]:
+ if len(text.strip()) > 0:
+ yield text
+
+
+def read_and_process_image(
+ image_file_name: str,
+ path_to_dir: Optional[str] = None) -> Tuple[str, tf.Tensor]:
+ if path_to_dir is not None:
+ image_file_name = os.path.join(path_to_dir, image_file_name)
+ with FileSystems().open(image_file_name, 'r') as file:
+ data = Image.open(io.BytesIO(file.read())).convert('RGB')
+ # Note: Converts the image dtype from uint8 to float32
+ # https://www.tensorflow.org/api_docs/python/tf/image/resize
+ image = tf.keras.preprocessing.image.img_to_array(data)
+ image = tf.image.resize(image, _IMG_SIZE)
+ return image_file_name, image
+
+
+def convert_image_to_example_proto(tensor):
Review Comment:
Are we able to add input and return types here?
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/tensorflow_image_classification.py:
##########
@@ -0,0 +1,195 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+"""
+A pipeline tha uses TFX RunInference API to perform Image classification.
+Please look at https://github.com/tensorflow/tfx-bsl/tree/master/tfx_bsl/beam.
+
+Note: For the Tensorflow Model, it needs to be updated with a @tf.function
+ Signature to accept bytes as inputs and should have logic to decode
+ bytes to data which should be acceptable by the tensorflow model.
+ Please take a look at build_tensorflow_model.py on how to modify
+ TF Model's signature.
Review Comment:
```suggestion
Note: A Tensorflow Model needs to be updated with a @tf.function
Signature in order to accept bytes as inputs, and should have logic to decode
bytes to data that is acceptable by the TensorFlow model.
Please take a look at build_tensorflow_model.py on how to modify
TF Model's signature.
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] yeandy commented on a diff in pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
yeandy commented on code in PR #23456:
URL: https://github.com/apache/beam/pull/23456#discussion_r1001022781
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/build_tensorflow_model.py:
##########
@@ -0,0 +1,71 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import tensorflow as tf
+
+
+class TFModelWrapperWithSignature(tf.keras.Model):
+ def __init__(
+ self,
+ model,
+ preprocess_input=None,
+ input_dtype=tf.float32,
+ feature_description=None):
+ super().__init__()
+ self.model = model
+ self.preprocess_input = preprocess_input
+ self.input_dtype = input_dtype
+ self.feature_description = feature_description
+ if not feature_description:
+ self.feature_description = {'image': tf.io.FixedLenFeature((), tf.string)}
+
+ @tf.function(input_signature=[tf.TensorSpec(shape=[None], dtype=tf.string)])
+ def call(self, serialized_examples):
+ features = tf.io.parse_example(
+ serialized_examples, features=self.feature_description)
+
+ # using TensorArray as suggested at
+ # https://github.com/tensorflow/tensorflow/issues/39323#issuecomment-627586602
+ batch = len(features['image'])
+ deserialized_vectors = tf.TensorArray(
+ self.input_dtype, size=batch, dynamic_size=True)
+ # issue arise with the indexing at features['image']
+ # Vectorized version of tf.io.parse_tensor is not available
+ # https://github.com/tensorflow/tensorflow/issues/43706
+ for i in range(batch):
+ deserialized_value = tf.io.parse_tensor(
+ features['image'][i], out_type=self.input_dtype)
+
+ # http://github.com/tensorflow/tensorflow/issues/30409#issuecomment-508962873
+ # In Graph mode, return value must get assigned in order to
+ # update the array
+ deserialized_vectors = deserialized_vectors.write(i, deserialized_value)
+
+ # deserialized_value = tf.expand_dims(deserialized_vectors, axis=0)
+ deserialized_tensor = deserialized_vectors.stack()
+ if self.preprocess_input:
+ deserialized_tensor = self.preprocess_input(deserialized_tensor)
+ return self.model(deserialized_tensor, training=False)
+
+
+def save_tf_model(path, model=None, preprocess_input=None):
Review Comment:
Can we add args for `input_dtype=tf.float32` and `feature_description` too?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on PR #23456:
URL: https://github.com/apache/beam/pull/23456#issuecomment-1286144909
> Looks pretty good. I like it.
>
> Is there a place where you got the original classification model from?
Yes, from the pretrained tensorflow models. TensorHub?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on PR #23456:
URL: https://github.com/apache/beam/pull/23456#issuecomment-1295327399
Run Python 3.10 PostCommit
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on PR #23456:
URL: https://github.com/apache/beam/pull/23456#issuecomment-1292360996
PTAL @ryanthompson591 @damccorm
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] damccorm commented on pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
damccorm commented on PR #23456:
URL: https://github.com/apache/beam/pull/23456#issuecomment-1303452229
> Failing tests seems irrelevant but running them one more time
Yeah, I think these are due to https://github.com/apache/beam/pull/23971
I think this is good to merge
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on a diff in pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on code in PR #23456:
URL: https://github.com/apache/beam/pull/23456#discussion_r990207415
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/build_tensorflow_model.py:
##########
@@ -0,0 +1,71 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import tensorflow as tf
+
Review Comment:
I added a brief summary. I think we shouldn't add where we host the model as per the discussions on licensing we had few weeks ago.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on PR #23456:
URL: https://github.com/apache/beam/pull/23456#issuecomment-1271736961
PTAL @ryanthompson591
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on a diff in pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on code in PR #23456:
URL: https://github.com/apache/beam/pull/23456#discussion_r989147556
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/build_tensorflow_model.py:
##########
@@ -0,0 +1,71 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import tensorflow as tf
+
+
+class TFModelWrapperWithSignature(tf.keras.Model):
Review Comment:
The idea here is to provide users a simple wrapper in which the signature is predefined for images and deserializing the `Example` Proto is also done along with deserializing `tensor` as well.
This can be used as an example for the users on how to build a tensorflow model with modified signature.
Also, the parameters in the constructor can be used for testing only purpose.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on a diff in pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on code in PR #23456:
URL: https://github.com/apache/beam/pull/23456#discussion_r1001106061
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/build_tensorflow_model.py:
##########
@@ -0,0 +1,71 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import tensorflow as tf
+
+
+class TFModelWrapperWithSignature(tf.keras.Model):
+ def __init__(
+ self,
+ model,
+ preprocess_input=None,
+ input_dtype=tf.float32,
+ feature_description=None):
+ super().__init__()
+ self.model = model
+ self.preprocess_input = preprocess_input
+ self.input_dtype = input_dtype
+ self.feature_description = feature_description
+ if not feature_description:
+ self.feature_description = {'image': tf.io.FixedLenFeature((), tf.string)}
+
+ @tf.function(input_signature=[tf.TensorSpec(shape=[None], dtype=tf.string)])
+ def call(self, serialized_examples):
+ features = tf.io.parse_example(
+ serialized_examples, features=self.feature_description)
+
+ # using TensorArray as suggested at
+ # https://github.com/tensorflow/tensorflow/issues/39323#issuecomment-627586602
+ batch = len(features['image'])
+ deserialized_vectors = tf.TensorArray(
+ self.input_dtype, size=batch, dynamic_size=True)
+ # issue arise with the indexing at features['image']
+ # Vectorized version of tf.io.parse_tensor is not available
+ # https://github.com/tensorflow/tensorflow/issues/43706
+ for i in range(batch):
+ deserialized_value = tf.io.parse_tensor(
+ features['image'][i], out_type=self.input_dtype)
+
+ # http://github.com/tensorflow/tensorflow/issues/30409#issuecomment-508962873
+ # In Graph mode, return value must get assigned in order to
+ # update the array
+ deserialized_vectors = deserialized_vectors.write(i, deserialized_value)
+
+ # deserialized_value = tf.expand_dims(deserialized_vectors, axis=0)
+ deserialized_tensor = deserialized_vectors.stack()
+ if self.preprocess_input:
+ deserialized_tensor = self.preprocess_input(deserialized_tensor)
+ return self.model(deserialized_tensor, training=False)
+
+
+def save_tf_model(path, model=None, preprocess_input=None):
+ if not model:
+ model = tf.keras.applications.MobileNetV2(weights='imagenet')
+ preprocess_input = tf.keras.applications.mobilenet_v2.preprocess_input
+ signature_model = TFModelWrapperWithSignature(
+ model=model, preprocess_input=preprocess_input)
+ tf.saved_model.save(signature_model, path)
Review Comment:
I am using this in the integration test where we load the model and save the model using this method and then use that model in the run inference transform
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on a diff in pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on code in PR #23456:
URL: https://github.com/apache/beam/pull/23456#discussion_r1001018365
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/tensorflow_image_classification.py:
##########
@@ -0,0 +1,195 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+"""
+A pipeline tha uses TFX RunInference API to perform Image classification.
+Please look at https://github.com/tensorflow/tfx-bsl/tree/master/tfx_bsl/beam.
+
+Note: For the Tensorflow Model, it needs to be updated with a @tf.function
+ Signature to accept bytes as inputs and should have logic to decode
+ bytes to data which should be acceptable by the tensorflow model.
+ Please take a look at build_tensorflow_model.py on how to modify
+ TF Model's signature.
+"""
+
+import argparse
+import io
+import logging
+import os
+from typing import Iterable
+from typing import Iterator
+from typing import Optional
+from typing import Tuple
+
+import apache_beam as beam
+import tensorflow as tf
+from apache_beam.io.filesystems import FileSystems
+from apache_beam.ml.inference.base import KeyedModelHandler
+from apache_beam.ml.inference.base import RunInference
+from apache_beam.options.pipeline_options import PipelineOptions
+from apache_beam.options.pipeline_options import SetupOptions
+from apache_beam.runners.runner import PipelineResult
+from PIL import Image
+from tfx_bsl.public.beam.run_inference import CreateModelHandler
+from tfx_bsl.public.beam.run_inference import prediction_log_pb2
+from tfx_bsl.public.proto import model_spec_pb2
+
+_IMG_SIZE = (224, 224)
+
+
+def filter_empty_lines(text: str) -> Iterator[str]:
+ if len(text.strip()) > 0:
+ yield text
+
+
+def read_and_process_image(
+ image_file_name: str,
+ path_to_dir: Optional[str] = None) -> Tuple[str, tf.Tensor]:
+ if path_to_dir is not None:
+ image_file_name = os.path.join(path_to_dir, image_file_name)
+ with FileSystems().open(image_file_name, 'r') as file:
+ data = Image.open(io.BytesIO(file.read())).convert('RGB')
+ # Note: Converts the image dtype from uint8 to float32
+ # https://www.tensorflow.org/api_docs/python/tf/image/resize
+ image = tf.keras.preprocessing.image.img_to_array(data)
+ image = tf.image.resize(image, _IMG_SIZE)
+ return image_file_name, image
+
+
+def convert_image_to_example_proto(tensor):
Review Comment:
Done
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on a diff in pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on code in PR #23456:
URL: https://github.com/apache/beam/pull/23456#discussion_r1005136732
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/build_tensorflow_model.py:
##########
@@ -0,0 +1,99 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Intended only for internal testing.
+
+from typing import Dict
+from typing import Optional
+
+import tensorflow as tf
+
+
+class TFModelWrapperWithSignature(tf.keras.Model):
+ def __init__(
+ self,
+ model,
+ preprocess_input=None,
+ input_dtype=None,
+ feature_description=None,
+ **kwargs):
+ super().__init__()
+ self.model = model
+ self.preprocess_input = preprocess_input
+ self.input_dtype = input_dtype
+ self.feature_description = feature_description
+ if not feature_description:
+ self.feature_description = {'image': tf.io.FixedLenFeature((), tf.string)}
+ self._kwargs = kwargs
+
+ @tf.function(input_signature=[tf.TensorSpec(shape=[None], dtype=tf.string)])
+ def call(self, serialized_examples):
+ features = tf.io.parse_example(
+ serialized_examples, features=self.feature_description)
+
+ # Initialize a TensorArray to store the deserialized values.
+ # For more details, please look at
+ # https://github.com/tensorflow/tensorflow/issues/39323#issuecomment-627586602
+ batch = len(features['image'])
+ deserialized_vectors = tf.TensorArray(
+ self.input_dtype, size=batch, dynamic_size=True)
+ # Vectorized version of tf.io.parse_tensor is not available.
+ # Use for loop to vectorize the tensor. For more details, refer
+ # https://github.com/tensorflow/tensorflow/issues/43706
+ for i in range(batch):
+ deserialized_value = tf.io.parse_tensor(
+ features['image'][i], out_type=self.input_dtype)
+ # http://github.com/tensorflow/tensorflow/issues/30409#issuecomment-508962873
+ # In Graph mode, return value must get assigned in order to
+ # update the array
+ deserialized_vectors = deserialized_vectors.write(i, deserialized_value)
+
+ deserialized_tensor = deserialized_vectors.stack()
+ if self.preprocess_input:
+ deserialized_tensor = self.preprocess_input(deserialized_tensor)
+ return self.model(deserialized_tensor, **self._kwargs)
Review Comment:
Its something similar in line with `inference_args`. Some models need additional args during inference. These can be passed through kwargs since its easy for now
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] damccorm commented on pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
damccorm commented on PR #23456:
URL: https://github.com/apache/beam/pull/23456#issuecomment-1294342358
@AnandInguva looks like the postcommit is still failing
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on a diff in pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on code in PR #23456:
URL: https://github.com/apache/beam/pull/23456#discussion_r1005127324
##########
sdks/python/apache_beam/examples/inference/tfx_bsl/tfx_bsl_inference_it_test.py:
##########
@@ -0,0 +1,99 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import logging
+import unittest
+import uuid
+
+import pytest
+
+from apache_beam.io.filesystems import FileSystems
+from apache_beam.testing.test_pipeline import TestPipeline
+
+# pylint: disable=ungrouped-imports
+try:
+ import tfx_bsl
+ import tensorflow as tf
+ from apache_beam.examples.inference.tfx_bsl import tensorflow_image_classification
+ from apache_beam.examples.inference.tfx_bsl.build_tensorflow_model import save_tf_model_with_signature
+except ImportError as e:
+ tfx_bsl = None
+# pylint: disable=line-too-long
+_EXPECTED_OUTPUTS = {
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005001.JPEG': '681',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005002.JPEG': '333',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005003.JPEG': '711',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005004.JPEG': '286',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005005.JPEG': '445',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005006.JPEG': '288',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005007.JPEG': '880',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005008.JPEG': '534',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005009.JPEG': '888',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005010.JPEG': '996',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005011.JPEG': '327',
+ 'gs://apache-beam-ml/datasets/imagenet/raw-data/validation/ILSVRC2012_val_00005012.JPEG': '573'
+}
+
+
+def process_outputs(filepath):
+ with FileSystems().open(filepath) as f:
+ lines = f.readlines()
+ lines = [l.decode('utf-8').strip('\n') for l in lines]
+ return lines
+
+
+@unittest.skipIf(
+ tfx_bsl is None, 'Missing dependencies. '
+ 'Test depends on tfx_bsl')
+class TFXRunInferenceTests(unittest.TestCase):
+ @pytest.mark.uses_tensorflow
+ @pytest.mark.it_postcommit
+ def test_tfx_run_inference_mobilenetv2(self):
Review Comment:
Its a smaller model used for Integration test on direct runner. For benchmarks we use larger models run on Dataflow
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [beam] AnandInguva commented on pull request #23456: TFX image classification example
Posted by GitBox <gi...@apache.org>.
AnandInguva commented on PR #23456:
URL: https://github.com/apache/beam/pull/23456#issuecomment-1302526044
Run Python 3.9 PostCommit
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@beam.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org