From cd40828f4ca5a1fe10785a06ae5fd46c0af965b4 Mon Sep 17 00:00:00 2001 From: Sierra Guequierre Date: Wed, 29 Jan 2025 11:39:49 -0500 Subject: [PATCH 01/15] Update training script --- docs/data-ai/ai/train.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/data-ai/ai/train.md b/docs/data-ai/ai/train.md index a91301554d..501774bf80 100644 --- a/docs/data-ai/ai/train.md +++ b/docs/data-ai/ai/train.md @@ -72,8 +72,6 @@ setup( packages=find_packages(), include_package_data=True, install_requires=[ - "google-cloud-aiplatform", - "google-cloud-storage", # TODO: Add additional required packages ], ) @@ -124,6 +122,13 @@ def parse_args(): parser.add_argument("--dataset_file", dest="data_json", type=str) parser.add_argument("--model_output_directory", dest="model_dir", type=str) parser.add_argument("--num_epochs", dest="num_epochs", type=int) + parser.add_argument( + "--labels", + dest="labels", + type=str, + required=False, + help="Space-separated list of labels, enclosed in single quotes (e.g., 'label1 label2').", + ) args = parser.parse_args() return args.data_json, args.model_dir, args.num_epochs From 8f316e2a667c4684a80397ca28411380855d1ce3 Mon Sep 17 00:00:00 2001 From: Sierra Guequierre Date: Wed, 29 Jan 2025 11:41:21 -0500 Subject: [PATCH 02/15] more training script updates --- docs/data-ai/ai/train.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/docs/data-ai/ai/train.md b/docs/data-ai/ai/train.md index 501774bf80..129731c5ad 100644 --- a/docs/data-ai/ai/train.md +++ b/docs/data-ai/ai/train.md @@ -130,7 +130,7 @@ def parse_args(): help="Space-separated list of labels, enclosed in single quotes (e.g., 'label1 label2').", ) args = parser.parse_args() - return args.data_json, args.model_dir, args.num_epochs + return args.data_json, args.model_dir, args.num_epochs, args.labels # This is used for parsing the dataset file (produced and stored in Viam), @@ -264,14 +264,11 @@ def save_model( if __name__ == "__main__": - DATA_JSON, MODEL_DIR = parse_args() + DATA_JSON, MODEL_DIR, NUM_EPOCHS, LABELS = parse_args() IMG_SIZE = (256, 256) # Read dataset file. - # TODO: change labels to the desired model output. - LABELS = ["orange_triangle", "blue_star"] - # The model type can be changed based on whether you want the model to # output one label per image or multiple labels per image model_type = multi_label From 14a8aea04f41b906145bd6c15f7be66cdd6fab72 Mon Sep 17 00:00:00 2001 From: Sierra Guequierre Date: Wed, 29 Jan 2025 12:51:57 -0500 Subject: [PATCH 03/15] more updates --- docs/data-ai/ai/train.md | 47 ++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/docs/data-ai/ai/train.md b/docs/data-ai/ai/train.md index 129731c5ad..0585ab1cc8 100644 --- a/docs/data-ai/ai/train.md +++ b/docs/data-ai/ai/train.md @@ -63,7 +63,7 @@ my-training/ Add the following code to `setup.py` and add additional required packages on line 11: -```python {class="line-numbers linkable-line-numbers" data-line="11"} +```python {class="line-numbers linkable-line-numbers" data-line="9"} from setuptools import find_packages, setup setup( @@ -92,11 +92,13 @@ If you haven't already, create a folder called model and create an {{% expand "Click to see the template" %}} -```python {class="line-numbers linkable-line-numbers" data-line="126,170" } +```python {class="line-numbers linkable-line-numbers" data-line="139" } import argparse import json import os import typing as ty +from tensorflow.keras import Model # Add proper import +import tensorflow as tf # Add proper import single_label = "MODEL_TYPE_SINGLE_LABEL_CLASSIFICATION" multi_label = "MODEL_TYPE_MULTI_LABEL_CLASSIFICATION" @@ -106,6 +108,7 @@ unknown_label = "UNKNOWN" API_KEY = os.environ['API_KEY'] API_KEY_ID = os.environ['API_KEY_ID'] +DEFAULT_EPOCHS = 200 # This parses the required args for the training script. # The model_dir variable will contain the output directory where @@ -113,25 +116,29 @@ API_KEY_ID = os.environ['API_KEY_ID'] # The data_json variable will contain the metadata for the dataset # that you should use to train the model. def parse_args(): - """Returns dataset file, model output directory, and num_epochs if present. + """Returns dataset file, model output directory, labels, and num_epochs if present. These must be parsed as command line arguments and then used as the model input and output, respectively. The number of epochs can be used to optionally override the default. """ parser = argparse.ArgumentParser() - parser.add_argument("--dataset_file", dest="data_json", type=str) - parser.add_argument("--model_output_directory", dest="model_dir", type=str) + parser.add_argument("--dataset_file", dest="data_json", type=str, required=True) + parser.add_argument("--model_output_directory", dest="model_dir", type=str, required=True) parser.add_argument("--num_epochs", dest="num_epochs", type=int) parser.add_argument( "--labels", dest="labels", type=str, - required=False, + required=True, help="Space-separated list of labels, enclosed in single quotes (e.g., 'label1 label2').", ) args = parser.parse_args() - return args.data_json, args.model_dir, args.num_epochs, args.labels - + + if not args.labels: + raise ValueError("Labels must be provided") + + labels = [label.strip() for label in args.labels.strip("'").split()] + return args.data_json, args.model_dir, args.num_epochs, labels # This is used for parsing the dataset file (produced and stored in Viam), # parse it to get the label annotations @@ -215,8 +222,7 @@ def parse_filenames_and_bboxes_from_json( # Build the model def build_and_compile_model( - labels: ty.List[str], model_type: str, input_shape: ty.Tuple[int, int, int] -) -> Model: + labels: ty.List[str], model_type: str, input_shape: ty.Tuple[int, int, int]) -> Model: """Builds and compiles a model Args: labels: list of string lists, where each string list contains up to @@ -255,12 +261,16 @@ def save_model( model_dir: output directory for model artifacts model_name: name of saved model """ - file_type = "" - - # Save the model to the output directory. + file_type = "tflite" # Add proper file type filename = os.path.join(model_dir, f"{model_name}.{file_type}") + + # Example: Convert to TFLite + converter = tf.lite.TFLiteConverter.from_keras_model(model) + tflite_model = converter.convert() + + # Save the model with open(filename, "wb") as f: - f.write(model) + f.write(tflite_model) if __name__ == "__main__": @@ -275,14 +285,19 @@ if __name__ == "__main__": image_filenames, image_labels = parse_filenames_and_labels_from_json( DATA_JSON, LABELS, model_type) + # Validate epochs + epochs = ( + DEFAULT_EPOCHS if NUM_EPOCHS is None or NUM_EPOCHS <= 0 else int(NUM_EPOCHS) + ) + # Build and compile model on data - model = build_and_compile_model() + model = build_and_compile_model(image_labels, model_type, IMG_SIZE + (3,)) # Save labels.txt file save_labels(LABELS + [unknown_label], MODEL_DIR) # Convert the model to tflite save_model( - model, MODEL_DIR, "classification_model", IMG_SIZE + (3,) + model, MODEL_DIR, "classification_model" ) ``` From ee3016b27ac1899748965c6e4d84e943b6581dd2 Mon Sep 17 00:00:00 2001 From: Sierra Guequierre Date: Wed, 29 Jan 2025 12:54:15 -0500 Subject: [PATCH 04/15] Apply suggestions from code review --- docs/data-ai/ai/train.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/data-ai/ai/train.md b/docs/data-ai/ai/train.md index 0585ab1cc8..7cfd17e016 100644 --- a/docs/data-ai/ai/train.md +++ b/docs/data-ai/ai/train.md @@ -261,6 +261,7 @@ def save_model( model_dir: output directory for model artifacts model_name: name of saved model """ + # Save the model to the output directory file_type = "tflite" # Add proper file type filename = os.path.join(model_dir, f"{model_name}.{file_type}") From 20b19dd879e9bfb4fdeabe84a669c8142ad79ad9 Mon Sep 17 00:00:00 2001 From: Sierra Guequierre Date: Wed, 29 Jan 2025 12:54:46 -0500 Subject: [PATCH 05/15] Apply suggestions from code review --- docs/data-ai/ai/train.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/data-ai/ai/train.md b/docs/data-ai/ai/train.md index 7cfd17e016..57960aa06c 100644 --- a/docs/data-ai/ai/train.md +++ b/docs/data-ai/ai/train.md @@ -222,7 +222,8 @@ def parse_filenames_and_bboxes_from_json( # Build the model def build_and_compile_model( - labels: ty.List[str], model_type: str, input_shape: ty.Tuple[int, int, int]) -> Model: + labels: ty.List[str], model_type: str, input_shape: ty.Tuple[int, int, int] +) -> Model: """Builds and compiles a model Args: labels: list of string lists, where each string list contains up to From 2cefc0183e4ab3b81acc8b9733925964d3a2b197 Mon Sep 17 00:00:00 2001 From: Sierra Guequierre Date: Wed, 29 Jan 2025 12:56:17 -0500 Subject: [PATCH 06/15] correct line --- docs/data-ai/ai/train.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/data-ai/ai/train.md b/docs/data-ai/ai/train.md index 57960aa06c..8d1feac1d0 100644 --- a/docs/data-ai/ai/train.md +++ b/docs/data-ai/ai/train.md @@ -92,7 +92,7 @@ If you haven't already, create a folder called model and create an {{% expand "Click to see the template" %}} -```python {class="line-numbers linkable-line-numbers" data-line="139" } +```python {class="line-numbers linkable-line-numbers" data-line="140" } import argparse import json import os From 2a13f0e35e9c1ded9fdcdaf942580f99e380c832 Mon Sep 17 00:00:00 2001 From: Sierra Guequierre Date: Wed, 29 Jan 2025 13:06:10 -0500 Subject: [PATCH 07/15] fix flake8 --- docs/data-ai/ai/train.md | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/docs/data-ai/ai/train.md b/docs/data-ai/ai/train.md index 8d1feac1d0..f60a706878 100644 --- a/docs/data-ai/ai/train.md +++ b/docs/data-ai/ai/train.md @@ -92,13 +92,13 @@ If you haven't already, create a folder called model and create an {{% expand "Click to see the template" %}} -```python {class="line-numbers linkable-line-numbers" data-line="140" } +```python {class="line-numbers linkable-line-numbers" data-line="148" } import argparse import json import os import typing as ty from tensorflow.keras import Model # Add proper import -import tensorflow as tf # Add proper import +import tensorflow as tf # Add proper import single_label = "MODEL_TYPE_SINGLE_LABEL_CLASSIFICATION" multi_label = "MODEL_TYPE_MULTI_LABEL_CLASSIFICATION" @@ -115,34 +115,42 @@ DEFAULT_EPOCHS = 200 # the ML model that this script creates should be stored. # The data_json variable will contain the metadata for the dataset # that you should use to train the model. + + def parse_args(): - """Returns dataset file, model output directory, labels, and num_epochs if present. - These must be parsed as command line arguments and then used as the model - input and output, respectively. The number of epochs can be used to - optionally override the default. + """Returns dataset file, model output directory, labels, and num_epochs + if present. These must be parsed as command line arguments and then used + as the model input and output, respectively. The number of epochs can be + used to optionally override the default. """ parser = argparse.ArgumentParser() - parser.add_argument("--dataset_file", dest="data_json", type=str, required=True) - parser.add_argument("--model_output_directory", dest="model_dir", type=str, required=True) + parser.add_argument("--dataset_file", dest="data_json", + type=str, required=True) + parser.add_argument("--model_output_directory", dest="model_dir", + type=str, required=True) parser.add_argument("--num_epochs", dest="num_epochs", type=int) parser.add_argument( "--labels", dest="labels", type=str, required=True, - help="Space-separated list of labels, enclosed in single quotes (e.g., 'label1 label2').", + help="Space-separated list of labels, \ + enclosed in single quotes (e.g., 'label1 label2').", ) args = parser.parse_args() - + if not args.labels: raise ValueError("Labels must be provided") - + labels = [label.strip() for label in args.labels.strip("'").split()] return args.data_json, args.model_dir, args.num_epochs, labels + # This is used for parsing the dataset file (produced and stored in Viam), # parse it to get the label annotations # Used for training classifiction models + + def parse_filenames_and_labels_from_json( filename: str, all_labels: ty.List[str], model_type: str ) -> ty.Tuple[ty.List[str], ty.List[str]]: @@ -265,11 +273,11 @@ def save_model( # Save the model to the output directory file_type = "tflite" # Add proper file type filename = os.path.join(model_dir, f"{model_name}.{file_type}") - + # Example: Convert to TFLite converter = tf.lite.TFLiteConverter.from_keras_model(model) tflite_model = converter.convert() - + # Save the model with open(filename, "wb") as f: f.write(tflite_model) @@ -289,7 +297,8 @@ if __name__ == "__main__": # Validate epochs epochs = ( - DEFAULT_EPOCHS if NUM_EPOCHS is None or NUM_EPOCHS <= 0 else int(NUM_EPOCHS) + DEFAULT_EPOCHS if NUM_EPOCHS is None + or NUM_EPOCHS <= 0 else int(NUM_EPOCHS) ) # Build and compile model on data From d163ff83eebc4bc2fd92aa3ec1bfe1fcef2f29be Mon Sep 17 00:00:00 2001 From: Sierra Guequierre Date: Wed, 29 Jan 2025 13:13:42 -0500 Subject: [PATCH 08/15] fixup --- docs/data-ai/ai/train.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/data-ai/ai/train.md b/docs/data-ai/ai/train.md index f60a706878..b36ff50783 100644 --- a/docs/data-ai/ai/train.md +++ b/docs/data-ai/ai/train.md @@ -327,6 +327,7 @@ The script you are creating must take the following command line inputs: - `dataset_file`: a file containing the data and metadata for the training job - `model_output_directory`: the location where the produced model artifacts are saved to +- `labels`: space separated list of labels, enclosed in single quotes The `parse_args()` function in the template parses your arguments. From 47280a9c1c0f46a4255bd07ec94a52471dc16b2f Mon Sep 17 00:00:00 2001 From: Sierra Guequierre Date: Wed, 29 Jan 2025 13:56:38 -0500 Subject: [PATCH 09/15] add template without labels parsed --- docs/data-ai/ai/train.md | 223 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 221 insertions(+), 2 deletions(-) diff --git a/docs/data-ai/ai/train.md b/docs/data-ai/ai/train.md index b36ff50783..88f875d25b 100644 --- a/docs/data-ai/ai/train.md +++ b/docs/data-ai/ai/train.md @@ -88,9 +88,220 @@ If you haven't already, create a folder called model and create an

4. Add training.py code

-

Copy this template into training.py:

+

Copy one of the following templates into training.py, depending on whether or not you wish to parse labels:

-{{% expand "Click to see the template" %}} +{{% expand "Click to see the template without parsing labels (recommended for use with UI)" %}} + +```python {class="line-numbers linkable-line-numbers" data-line="132" } +import argparse +import json +import os +import typing as ty +from tensorflow.keras import Model # Add proper import +import tensorflow as tf # Add proper import + +single_label = "MODEL_TYPE_SINGLE_LABEL_CLASSIFICATION" +multi_label = "MODEL_TYPE_MULTI_LABEL_CLASSIFICATION" +labels_filename = "labels.txt" +unknown_label = "UNKNOWN" + +API_KEY = os.environ['API_KEY'] +API_KEY_ID = os.environ['API_KEY_ID'] + +DEFAULT_EPOCHS = 200 + +# This parses the required args for the training script. +# The model_dir variable will contain the output directory where +# the ML model that this script creates should be stored. +# The data_json variable will contain the metadata for the dataset +# that you should use to train the model. +def parse_args(): + """Returns dataset file, model output directory, and num_epochs + if present. These must be parsed as command line arguments and then used + as the model input and output, respectively. The number of epochs can be + used to optionally override the default. + """ + parser = argparse.ArgumentParser() + parser.add_argument("--dataset_file", dest="data_json", + type=str, required=True) + parser.add_argument("--model_output_directory", dest="model_dir", + type=str, required=True) + parser.add_argument("--num_epochs", dest="num_epochs", type=int) + args = parser.parse_args() + + return args.data_json, args.model_dir, args.num_epochs + + +# This is used for parsing the dataset file (produced and stored in Viam), +# parse it to get the label annotations +# Used for training classifiction models +def parse_filenames_and_labels_from_json( + filename: str, all_labels: ty.List[str], model_type: str +) -> ty.Tuple[ty.List[str], ty.List[str]]: + """Load and parse JSON file to return image filenames and corresponding + labels. The JSON file contains lines, where each line has the key + "image_path" and "classification_annotations". + Args: + filename: JSONLines file containing filenames and labels + all_labels: list of all N_LABELS + model_type: string single_label or multi_label + """ + image_filenames = [] + image_labels = [] + + with open(filename, "rb") as f: + for line in f: + json_line = json.loads(line) + image_filenames.append(json_line["image_path"]) + + annotations = json_line["classification_annotations"] + labels = [unknown_label] + for annotation in annotations: + if model_type == multi_label: + if annotation["annotation_label"] in all_labels: + labels.append(annotation["annotation_label"]) + # For single label model, we want at most one label. + # If multiple valid labels are present, we arbitrarily select + # the last one. + if model_type == single_label: + if annotation["annotation_label"] in all_labels: + labels = [annotation["annotation_label"]] + image_labels.append(labels) + return image_filenames, image_labels + + +# Parse the dataset file (produced and stored in Viam) to get +# bounding box annotations +# Used for training object detection models +def parse_filenames_and_bboxes_from_json( + filename: str, + all_labels: ty.List[str], +) -> ty.Tuple[ty.List[str], ty.List[str], ty.List[ty.List[float]]]: + """Load and parse JSON file to return image filenames + and corresponding labels with bboxes. + Args: + filename: JSONLines file containing filenames and bboxes + all_labels: list of all N_LABELS + """ + image_filenames = [] + bbox_labels = [] + bbox_coords = [] + + with open(filename, "rb") as f: + for line in f: + json_line = json.loads(line) + image_filenames.append(json_line["image_path"]) + annotations = json_line["bounding_box_annotations"] + labels = [] + coords = [] + for annotation in annotations: + if annotation["annotation_label"] in all_labels: + labels.append(annotation["annotation_label"]) + # Store coordinates in rel_yxyx format so that + # we can use the keras_cv function + coords.append( + [ + annotation["y_min_normalized"], + annotation["x_min_normalized"], + annotation["y_max_normalized"], + annotation["x_max_normalized"], + ] + ) + bbox_labels.append(labels) + bbox_coords.append(coords) + return image_filenames, bbox_labels, bbox_coords + + +# Build the model +def build_and_compile_model( + labels: ty.List[str], model_type: str, input_shape: ty.Tuple[int, int, int] +) -> Model: + """Builds and compiles a model + Args: + labels: list of string lists, where each string list contains up to + N_LABEL labels associated with an image + model_type: string single_label or multi_label + input_shape: 3D shape of input + """ + + # TODO: Add logic to build and compile model + + return model + + +def save_labels(labels: ty.List[str], model_dir: str) -> None: + """Saves a label.txt of output labels to the specified model directory. + Args: + labels: list of string lists, where each string list contains up to + N_LABEL labels associated with an image + model_dir: output directory for model artifacts + """ + filename = os.path.join(model_dir, labels_filename) + with open(filename, "w") as f: + for label in labels[:-1]: + f.write(label + "\n") + f.write(labels[-1]) + + +def save_model( + model: Model, + model_dir: str, + model_name: str, +) -> None: + """Save model as a TFLite model. + Args: + model: trained model + model_dir: output directory for model artifacts + model_name: name of saved model + """ + # Save the model to the output directory + file_type = "tflite" # Add proper file type + filename = os.path.join(model_dir, f"{model_name}.{file_type}") + + # Example: Convert to TFLite + converter = tf.lite.TFLiteConverter.from_keras_model(model) + tflite_model = converter.convert() + + # Save the model + with open(filename, "wb") as f: + f.write(tflite_model) + + +if __name__ == "__main__": + DATA_JSON, MODEL_DIR = parse_args() + + IMG_SIZE = (256, 256) + + # Read dataset file. + # TODO: change labels to the desired model output. + LABELS = ["orange_triangle", "blue_star"] + + # The model type can be changed based on whether you want the model to + # output one label per image or multiple labels per image + model_type = multi_label + image_filenames, image_labels = parse_filenames_and_labels_from_json( + DATA_JSON, LABELS, model_type) + + # Validate epochs + epochs = ( + DEFAULT_EPOCHS if NUM_EPOCHS is None + or NUM_EPOCHS <= 0 else int(NUM_EPOCHS) + ) + + # Build and compile model on data + model = build_and_compile_model(image_labels, model_type, IMG_SIZE + (3,)) + + # Save labels.txt file + save_labels(LABELS + [unknown_label], MODEL_DIR) + # Convert the model to tflite + save_model( + model, MODEL_DIR, "classification_model" + ) +``` + +{{% /expand %}} + +{{% expand "Click to see the template with labels parsed" %}} ```python {class="line-numbers linkable-line-numbers" data-line="148" } import argparse @@ -327,6 +538,9 @@ The script you are creating must take the following command line inputs: - `dataset_file`: a file containing the data and metadata for the training job - `model_output_directory`: the location where the produced model artifacts are saved to + +If you used the version with labels parsed, it will also take the following command line inputs: + - `labels`: space separated list of labels, enclosed in single quotes The `parse_args()` function in the template parses your arguments. @@ -576,6 +790,11 @@ In the Viam app, navigate to your list of [**DATASETS**](https://app.viam.com/da Click **Train model** and select **Train on a custom training script**, then follow the prompts. +{{% alert title="Tip" color="tip" %}} +If you used the version of training.py with labels parsed, your training job will fail with the error `ERROR training.py: error: the following arguments are required: --labels`. +Use the CLI and enter labels. +{{% /alert %}} + {{% /tab %}} {{% tab name="CLI" %}} From 4afee29fcc2198045e56570197c56c3a7a189d85 Mon Sep 17 00:00:00 2001 From: Sierra Guequierre Date: Wed, 29 Jan 2025 14:00:00 -0500 Subject: [PATCH 10/15] markdown parser fixup --- docs/data-ai/ai/train.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/data-ai/ai/train.md b/docs/data-ai/ai/train.md index 88f875d25b..af23c057bd 100644 --- a/docs/data-ai/ai/train.md +++ b/docs/data-ai/ai/train.md @@ -115,6 +115,8 @@ DEFAULT_EPOCHS = 200 # the ML model that this script creates should be stored. # The data_json variable will contain the metadata for the dataset # that you should use to train the model. + + def parse_args(): """Returns dataset file, model output directory, and num_epochs if present. These must be parsed as command line arguments and then used From fd84cd395a3743fc360b61f3615e71640a5ccf52 Mon Sep 17 00:00:00 2001 From: Sierra Guequierre Date: Wed, 29 Jan 2025 14:01:20 -0500 Subject: [PATCH 11/15] data line fixup --- docs/data-ai/ai/train.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/data-ai/ai/train.md b/docs/data-ai/ai/train.md index af23c057bd..a37f507cdf 100644 --- a/docs/data-ai/ai/train.md +++ b/docs/data-ai/ai/train.md @@ -92,7 +92,7 @@ If you haven't already, create a folder called model and create an {{% expand "Click to see the template without parsing labels (recommended for use with UI)" %}} -```python {class="line-numbers linkable-line-numbers" data-line="132" } +```python {class="line-numbers linkable-line-numbers" data-line="134" } import argparse import json import os From 9e10be857af5ecdd82b3605549d12651e6cebd47 Mon Sep 17 00:00:00 2001 From: Sierra Guequierre Date: Wed, 5 Feb 2025 11:06:58 -0500 Subject: [PATCH 12/15] Apply suggestions from code review Co-authored-by: Naomi Pentrel <5212232+npentrel@users.noreply.github.com> --- docs/data-ai/ai/train.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/data-ai/ai/train.md b/docs/data-ai/ai/train.md index a37f507cdf..6a5d6fd612 100644 --- a/docs/data-ai/ai/train.md +++ b/docs/data-ai/ai/train.md @@ -88,7 +88,7 @@ If you haven't already, create a folder called model and create an

4. Add training.py code

-

Copy one of the following templates into training.py, depending on whether or not you wish to parse labels:

+

Copy one of the following templates into training.py, depending on whether or not you wish to parse labels instead of having to hard code the labels in the training script and re-upload for each set of labels, allowing you to more easily reuse training scripts:

{{% expand "Click to see the template without parsing labels (recommended for use with UI)" %}} @@ -541,7 +541,7 @@ The script you are creating must take the following command line inputs: - `dataset_file`: a file containing the data and metadata for the training job - `model_output_directory`: the location where the produced model artifacts are saved to -If you used the version with labels parsed, it will also take the following command line inputs: +If you used the version with parsed labels, it will also take the following command line inputs: - `labels`: space separated list of labels, enclosed in single quotes @@ -793,8 +793,8 @@ In the Viam app, navigate to your list of [**DATASETS**](https://app.viam.com/da Click **Train model** and select **Train on a custom training script**, then follow the prompts. {{% alert title="Tip" color="tip" %}} -If you used the version of training.py with labels parsed, your training job will fail with the error `ERROR training.py: error: the following arguments are required: --labels`. -Use the CLI and enter labels. +If you used the version of training.py with parsed labels, your training job will fail with the error `ERROR training.py: error: the following arguments are required: --labels`. +To use labels, you must use the CLI. {{% /alert %}} {{% /tab %}} From d6193284f0d6df82af70302eed86747a0674758f Mon Sep 17 00:00:00 2001 From: Sierra Guequierre Date: Wed, 5 Feb 2025 11:07:27 -0500 Subject: [PATCH 13/15] Apply suggestions from code review --- docs/data-ai/ai/train.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/data-ai/ai/train.md b/docs/data-ai/ai/train.md index 6a5d6fd612..3368f78719 100644 --- a/docs/data-ai/ai/train.md +++ b/docs/data-ai/ai/train.md @@ -303,7 +303,7 @@ if __name__ == "__main__": {{% /expand %}} -{{% expand "Click to see the template with labels parsed" %}} +{{% expand "Click to see the template with parsed labels" %}} ```python {class="line-numbers linkable-line-numbers" data-line="148" } import argparse From dc5f4341cea38200485930c542af2a49e0eda7ad Mon Sep 17 00:00:00 2001 From: Sierra Guequierre Date: Wed, 5 Feb 2025 11:15:54 -0500 Subject: [PATCH 14/15] Apply suggestions from code review --- docs/data-ai/ai/train.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/data-ai/ai/train.md b/docs/data-ai/ai/train.md index 3368f78719..9fb040a6e2 100644 --- a/docs/data-ai/ai/train.md +++ b/docs/data-ai/ai/train.md @@ -88,7 +88,7 @@ If you haven't already, create a folder called model and create an

4. Add training.py code

-

Copy one of the following templates into training.py, depending on whether or not you wish to parse labels instead of having to hard code the labels in the training script and re-upload for each set of labels, allowing you to more easily reuse training scripts:

+

Copy one of the following templates into training.py, depending on whether or not you wish to parse labels instead of having to hard code the labels in the training script and re-upload for each set of labels, which allows you to more easily reuse training scripts:

{{% expand "Click to see the template without parsing labels (recommended for use with UI)" %}} From 4c571320fd2e1ce541297dff105abe06a3961a36 Mon Sep 17 00:00:00 2001 From: Sierra Guequierre Date: Thu, 6 Feb 2025 10:08:49 -0500 Subject: [PATCH 15/15] Apply suggestions from code review Co-authored-by: Naomi Pentrel <5212232+npentrel@users.noreply.github.com> --- docs/data-ai/ai/train.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/data-ai/ai/train.md b/docs/data-ai/ai/train.md index 9fb040a6e2..266cf6ef72 100644 --- a/docs/data-ai/ai/train.md +++ b/docs/data-ai/ai/train.md @@ -88,7 +88,8 @@ If you haven't already, create a folder called model and create an

4. Add training.py code

-

Copy one of the following templates into training.py, depending on whether or not you wish to parse labels instead of having to hard code the labels in the training script and re-upload for each set of labels, which allows you to more easily reuse training scripts:

+

You can set up your training script to use a hard coded set of labels or allow users to pass in a set of labels when using the training script. Allowing users to pass in labels when using training scripts makes your training script more flexible for reuse.

+

Copy one of the following templates into training.py, depending on how you want to handle labels:

{{% expand "Click to see the template without parsing labels (recommended for use with UI)" %}} @@ -541,7 +542,7 @@ The script you are creating must take the following command line inputs: - `dataset_file`: a file containing the data and metadata for the training job - `model_output_directory`: the location where the produced model artifacts are saved to -If you used the version with parsed labels, it will also take the following command line inputs: +If you used the training script template that allows users to pass in labels, it will also take the following command line inputs: - `labels`: space separated list of labels, enclosed in single quotes @@ -793,7 +794,7 @@ In the Viam app, navigate to your list of [**DATASETS**](https://app.viam.com/da Click **Train model** and select **Train on a custom training script**, then follow the prompts. {{% alert title="Tip" color="tip" %}} -If you used the version of training.py with parsed labels, your training job will fail with the error `ERROR training.py: error: the following arguments are required: --labels`. +If you used the version of training.py that allows users to pass in labels, your training job will fail with the error `ERROR training.py: error: the following arguments are required: --labels`. To use labels, you must use the CLI. {{% /alert %}}