name: StatisticsGen description: |- Construct a StatisticsGen component. Args: examples: A Channel of `ExamplesPath` type, likely generated by the [ExampleGen component](https://www.tensorflow.org/tfx/guide/examplegen). This needs to contain two splits labeled `train` and `eval`. _required_ schema: A `Schema` channel to use for automatically configuring the value of stats options passed to TFDV. Returns: statistics: `ExampleStatistics` channel for statistics of each split provided in the input examples. inputs: - {name: examples, type: Examples} - name: stats_options type: JsonObject: {data_type: 'proto:tensorflow_data_validation.StatsOptions'} optional: true - {name: schema, type: Schema, optional: true} outputs: - {name: statistics, type: ExampleStatistics} implementation: container: image: tensorflow/tfx:0.21.4 command: - python3 - -u - -c - | def _make_parent_dirs_and_return_path(file_path: str): import os os.makedirs(os.path.dirname(file_path), exist_ok=True) return file_path def StatisticsGen( examples_path , #examples_path: 'ExamplesUri', statistics_path , #statistics_path: 'ExampleStatisticsUri', stats_options = None, schema_path = None, #schema_path: 'SchemaUri' = None, ): #) -> NamedTuple('Outputs', [ # ('statistics', 'ExampleStatisticsUri'), #]): """Construct a StatisticsGen component. Args: examples: A Channel of `ExamplesPath` type, likely generated by the [ExampleGen component](https://www.tensorflow.org/tfx/guide/examplegen). This needs to contain two splits labeled `train` and `eval`. _required_ schema: A `Schema` channel to use for automatically configuring the value of stats options passed to TFDV. Returns: statistics: `ExampleStatistics` channel for statistics of each split provided in the input examples. """ from tfx.components.statistics_gen.component import StatisticsGen as component_class #Generated code import json import os import tensorflow from google.protobuf import json_format, message from tfx.types import Artifact, channel_utils, artifact_utils arguments = locals().copy() component_class_args = {} for name, execution_parameter in component_class.SPEC_CLASS.PARAMETERS.items(): argument_value_obj = argument_value = arguments.get(name, None) if argument_value is None: continue parameter_type = execution_parameter.type if isinstance(parameter_type, type) and issubclass(parameter_type, message.Message): # Maybe FIX: execution_parameter.type can also be a tuple argument_value_obj = parameter_type() json_format.Parse(argument_value, argument_value_obj) component_class_args[name] = argument_value_obj for name, channel_parameter in component_class.SPEC_CLASS.INPUTS.items(): artifact_path = arguments[name + '_path'] if artifact_path: artifact = channel_parameter.type() artifact.uri = artifact_path + '/' # ? if channel_parameter.type.PROPERTIES and 'split_names' in channel_parameter.type.PROPERTIES: # Recovering splits subdirs = tensorflow.io.gfile.listdir(artifact_path) artifact.split_names = artifact_utils.encode_split_names(sorted(subdirs)) component_class_args[name] = channel_utils.as_channel([artifact]) component_class_instance = component_class(**component_class_args) input_dict = {name: channel.get() for name, channel in component_class_instance.inputs.get_all().items()} output_dict = {name: channel.get() for name, channel in component_class_instance.outputs.get_all().items()} exec_properties = component_class_instance.exec_properties # Generating paths for output artifacts for name, artifacts in output_dict.items(): base_artifact_path = arguments[name + '_path'] # Are there still cases where output channel has multiple artifacts? for idx, artifact in enumerate(artifacts): subdir = str(idx + 1) if idx > 0 else '' artifact.uri = os.path.join(base_artifact_path, subdir) # Ends with '/' print('component instance: ' + str(component_class_instance)) #executor = component_class.EXECUTOR_SPEC.executor_class() # Same executor = component_class_instance.executor_spec.executor_class() executor.Do( input_dict=input_dict, output_dict=output_dict, exec_properties=exec_properties, ) import argparse _parser = argparse.ArgumentParser(prog='StatisticsGen', description='Construct a StatisticsGen component.\n\n Args:\n examples: A Channel of `ExamplesPath` type, likely generated by the\n [ExampleGen component](https://www.tensorflow.org/tfx/guide/examplegen).\n This needs to contain two splits labeled `train` and `eval`. _required_\n schema: A `Schema` channel to use for automatically configuring the value\n of stats options passed to TFDV.\n\n Returns:\n statistics: `ExampleStatistics` channel for statistics of each split\n provided in the input examples.') _parser.add_argument("--examples", dest="examples_path", type=str, required=True, default=argparse.SUPPRESS) _parser.add_argument("--stats-options", dest="stats_options", type=str, required=False, default=argparse.SUPPRESS) _parser.add_argument("--schema", dest="schema_path", type=str, required=False, default=argparse.SUPPRESS) _parser.add_argument("--statistics", dest="statistics_path", type=_make_parent_dirs_and_return_path, required=True, default=argparse.SUPPRESS) _parsed_args = vars(_parser.parse_args()) _output_files = _parsed_args.pop("_output_paths", []) _outputs = StatisticsGen(**_parsed_args) _output_serializers = [ ] import os for idx, output_file in enumerate(_output_files): try: os.makedirs(os.path.dirname(output_file)) except OSError: pass with open(output_file, 'w') as f: f.write(_output_serializers[idx](_outputs[idx])) args: - --examples - {inputPath: examples} - if: cond: {isPresent: stats_options} then: - --stats-options - {inputValue: stats_options} - if: cond: {isPresent: schema} then: - --schema - {inputPath: schema} - --statistics - {outputPath: statistics}