From 1a46cbdb932795a417d63706398947b6f44eb996 Mon Sep 17 00:00:00 2001 From: pollfly <75068813+pollfly@users.noreply.github.com> Date: Wed, 18 May 2022 11:49:31 +0300 Subject: [PATCH] Rewrite fundamentals sections (#252) --- docs/clearml_sdk.md | 29 - docs/clearml_sdk/clearml_sdk.md | 113 ++++ docs/clearml_sdk/model_sdk.md | 133 ++++ docs/clearml_sdk/task_sdk.md | 589 ++++++++++++++++++ docs/faq.md | 2 +- docs/fundamentals/artifacts.md | 238 ++----- docs/fundamentals/hyperparameters.md | 262 +++----- docs/fundamentals/logger.md | 2 +- docs/fundamentals/projects.md | 4 +- docs/fundamentals/task.md | 305 ++------- docs/getting_started/ds/best_practices.md | 4 +- docs/getting_started/ds/ds_first_steps.md | 4 +- docs/getting_started/ds/ds_second_steps.md | 2 +- .../mlops/mlops_first_steps.md | 4 +- docs/guides/reporting/explicit_reporting.md | 2 +- docs/guides/reporting/image_reporting.md | 2 +- docs/guides/reporting/media_reporting.md | 2 +- .../fundamentals_task_config_hyperparams.png | Bin 0 -> 39670 bytes docs/img/fundamentals_task_config_object.png | Bin 0 -> 54821 bytes .../fundamentals_task_config_properties.png | Bin 0 -> 39473 bytes docs/webapp/webapp_exp_table.md | 2 +- docs/webapp/webapp_exp_track_visual.md | 2 +- docs/webapp/webapp_profile.md | 2 +- sidebars.js | 2 +- 24 files changed, 1045 insertions(+), 660 deletions(-) delete mode 100644 docs/clearml_sdk.md create mode 100644 docs/clearml_sdk/clearml_sdk.md create mode 100644 docs/clearml_sdk/model_sdk.md create mode 100644 docs/clearml_sdk/task_sdk.md create mode 100644 docs/img/fundamentals_task_config_hyperparams.png create mode 100644 docs/img/fundamentals_task_config_object.png create mode 100644 docs/img/fundamentals_task_config_properties.png diff --git a/docs/clearml_sdk.md b/docs/clearml_sdk.md deleted file mode 100644 index 9b9d2c12..00000000 --- a/docs/clearml_sdk.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: ClearML SDK ---- - -The **ClearML Python Package** supports the [automatic logging](fundamentals/logger.md#automatic-reporting) -that documents the experiment for you, and an extensive set of powerful features and functionality you can use to improve experimentation, other workflows, and get more out of ClearML. - -The **ClearML Python Package** collects data from scripts including the Git repository (branch, commit ID, and uncommitted changes), working directory and entry point, hyperparameters, initial weights model, model snapshots (checkpoints), output model, other artifacts, metrics, logs, other reported data (from libraries and visualization toolkits), and debug samples. - -In conjunction with the **ClearML Hosted Service** (or self-hosted **ClearML Server**) and **ClearML Agent**, the **ClearML Python Package** allows you and your teammates to collaborate programmatically and using the **ClearML Web UI**. - -## Modules - -* [Task](references/sdk/task.md) - The `task` module contains the `task.Task` class which is the code template for all `Task` features and functionality, including collecting data from scripts, storing that data in a `Task` object, automatic bindings with frameworks (TensorFlow/TensorBoard, PyTorch, Keras, Fastai, scikit-learn), libraries (Pandas, Plotly, AutoKeras), and visualization tools (Matplotlib, Seaborn), and a robust set of methods for Task execution, cloning, connecting parameter dictionaries, configurations, models, working with storage, and more. - -* [Logger](references/sdk/logger.md) - The `logger` module contains the `logger.Logger` class which is the ClearML console log and metric statistics interface, and contains methods for explicit reporting, setting an upload destination in storage for debug samples, logger cache control, and TensorBoard support in addition to ClearML automatic TensorBoard logging. - -* [Model](references/sdk/model_model.md) - The `model` module contains three classes: `model.Model` which represents an existing model in ClearML that can be loaded and connected to a Task, `model.InputModel` which represents an existing model that you can load into ClearML, and `model.OutputModel` which represents the experiment output model that is always connected to the Task. - -* [Automation](references/sdk/automation_controller_pipelinecontroller.md) - The `automation` module contains classes supporting hyperparameter optimization, including Optuna, HpBandSter, grid searching, random searching, you own customized search strategies, and resource budgeting for searches; the AWS autoscaler; pipeline controllers; and Task monitoring. - -* [StorageManager](references/sdk/storage.md) - The `storage` module contains the `storage.manager.StorageManager` class which provides support for downloading and uploading from storage, including folders, S3, Google Cloud Storage, Azure Storage, and http(s). - -* [Dataset](references/sdk/dataset.md) - The `dataset` module contains classes that helps manage Dataset. Users can create, modify and delete datasets as well as retrieve them for use in their code - -## Examples - -ClearML example scripts in the [examples folder](https://github.com/allegroai/clearml/tree/master/examples) of the `clearml` GitHub repository. They are pre-loaded in the **ClearML Hosted Service**, and can be viewed, cloned, and edited in the **ClearML Web UI**, `ClearML Examples` project. The examples are each explained in this documentation's [examples section](guides/main.md). - diff --git a/docs/clearml_sdk/clearml_sdk.md b/docs/clearml_sdk/clearml_sdk.md new file mode 100644 index 00000000..b428bc10 --- /dev/null +++ b/docs/clearml_sdk/clearml_sdk.md @@ -0,0 +1,113 @@ +--- +title: Overview +--- + +The ClearML Python Package supports the [automatic logging](../fundamentals/logger.md#automatic-reporting) that documents +experiments for you, and an extensive set of powerful features and functionality you can use to improve experimentation +and other workflows. + +:::tip Installation +For installation instructions, see [Getting Started](../getting_started/ds/ds_first_steps.md#install-clearml). +::: + +The ClearML Python Package collects the scripts’ entire execution information, including: +* Git repository (branch, commit ID, and uncommitted changes) +* Working directory and entry point +* Hyperparameters +* Initial weights model, model snapshots (checkpoints), output model +* Artifacts, metrics, logs, other reported data (from libraries and visualization toolkits), and debug samples. + +In conjunction with the ClearML Hosted Service (or self-hosted [ClearML Server](../deploying_clearml/clearml_server.md)) +and [ClearML Agent](../clearml_agent.md), the ClearML Python Package allows you and your teammates to collaborate +programmatically and use the [ClearML Web UI](../webapp/webapp_overview.md). + +## Classes and Modules + +### Task +The `Task` class is the code template for all Task features and functionality including: +* Data collection and storage from scripts +* Automatic bindings with frameworks, libraries, and visualization tools +* A robust set of methods for Task execution (cloning, connecting parameter dictionaries, configurations, and models) +* and more! + +See an [overview](task_sdk.md) of `Task`'s pythonic methods or the [Task SDK reference page](task_sdk.md). + +### Model +The `model` module contains three classes that provide support for working with models in ClearML: +* `Model` - represents an existing model in ClearML that can be loaded and connected to a Task +* `InputModel` - represents an existing model that you can load into ClearML +* `OutputModel` - represents the experiment output model that is always connected to the Task + +See an [overview](../clearml_sdk/model_sdk.md) of the Model classes' pythonic methods, or the SDK reference pages for [`Model`](../references/sdk/model_model.md), +[`InputModel`](../references/sdk/model_inputmodel.md), and [`OutputModel`](../references/sdk/model_outputmodel.md). + +### Logger +The `Logger` class is the ClearML console log and metric statistics interface. The class contains methods for: +* Explicit reporting +* Setting an upload destination for debug sample storage +* Controlling ClearML's logging of TensorBoard and Matplotlib outputs + +See the [Logger SDK reference page](../references/sdk/logger.md). + + +### Hyperparameter Optimization + +ClearML's `optimization` module includes classes that support hyperparameter optimization: +* [HyperParameterOptimizer](../references/sdk/automation_controller_pipelinecontroller.md) - Hyperparameter search + controller class +* Optimization search strategy classes including [Optuna](../references/sdk/hpo_optuna_optuna_optimizeroptuna.md), [HpBandSter](../references/sdk/hpo_hpbandster_bandster_optimizerbohb.md), + [GridSearch](../references/sdk/hpo_optimization_gridsearch.md), [RandomSearch](../references/sdk/hpo_optimization_randomsearch.md), + and a base [SearchStrategy](https://github.com/allegroai/clearml/blob/master/clearml/automation/optimization.py#L310) + that can be customized + +See the [HyperParameterOptimizer SDK reference page](../references/sdk/hpo_optimization_hyperparameteroptimizer.md). + +### Pipeline + +ClearML's `automation` module includes classes that support creating pipelines: + * [PipelineController](../pipelines/pipelines_sdk_tasks.md) - A pythonic interface for + defining and configuring a pipeline controller and its steps. The controller and steps can be functions in your + python code, or existing ClearML [tasks](../fundamentals/task.md). + * [PipelineDecorator](../pipelines/pipelines_sdk_function_decorators.md) - A set + of Python decorators which transform your functions into the pipeline controller and steps. + +### Dataset +The `Dataset` class supports creating, modifying, and managing datasets, +as well as retrieving them for use in code. + +See [ClearML Data](../clearml_data/clearml_data.md) or the [Dataset SDK reference page](../references/sdk/dataset.md). + + +### StorageManager +The `StorageManager` class provides support for downloading and uploading from storage, +including local folders, S3, Google Cloud Storage, Azure Storage, and http(s). + +See the [StorageManager SDK reference page](../references/sdk/storage.md). + +### ClearmlJob +Use the ClearmlJob to create and manage jobs based on existing tasks. The class supports changing a job's parameters, +configurations, and other execution details. + +See reference page [here](../references/sdk/automation_job_clearmljob.md). + +### AutoScaler +The `AutoScaler` class facilitates implementing resource budgeting. See class methods [here](https://github.com/allegroai/clearml/blob/master/clearml/automation/auto_scaler.py). +ClearML also provides a class specifically for AWS autoscaling. See [code](https://github.com/allegroai/clearml/blob/master/clearml/automation/aws_auto_scaler.py#L22) +and [example script](https://github.com/allegroai/clearml/blob/master/examples/services/aws-autoscaler/aws_autoscaler.py). + +### TaskScheduler +The `TaskScheduler` class supports methods for scheduling periodic execution (like cron jobs). See the [code](https://github.com/allegroai/clearml/blob/master/clearml/automation/scheduler.py#L481) +and [example](https://github.com/allegroai/clearml/blob/master/examples/scheduler/cron_example.py). + +### TriggerScheduler +The `TriggerScheduler` class facilitates triggering task execution in the case that specific events occur in the system +(e.g. model publication, dataset creation, task failure). See [code](https://github.com/allegroai/clearml/blob/master/clearml/automation/trigger.py#L148) +and [usage example](https://github.com/allegroai/clearml/blob/master/examples/scheduler/trigger_example.py). + +## Examples + +The `clearml` GitHub repository includes an [examples folder](https://github.com/allegroai/clearml/tree/master/examples) +with example scripts demonstrating how to use the various functionalities of the ClearML SDK. + +These examples are pre-loaded in the [ClearML Hosted Service](https://app.clear.ml), and can be viewed, cloned, +and edited in the ClearML Web UI's `ClearML Examples` project. The examples are each explained in the [examples section](../guides/main.md). diff --git a/docs/clearml_sdk/model_sdk.md b/docs/clearml_sdk/model_sdk.md new file mode 100644 index 00000000..a80f87c4 --- /dev/null +++ b/docs/clearml_sdk/model_sdk.md @@ -0,0 +1,133 @@ +--- +title: Model +--- + +The following page provides an overview of the basic Pythonic interface to ClearML Models. + +ClearML provides the following classes to work with models: +* `Model` - represents an experiment's output model (training results). An OutputModel is always connected to a [task](../fundamentals/task.md). +* `InputModel` - represents an existing ClearML model to be used in an experiment. +* `OutputModel` - represents a ClearML model, regardless of any task connection. + +## Output Models + +### Manually Logging Models + +To manually log a model, create an instance of OutputModel class. + +```python +from clearml import OutputModel, Task + +# Instantiate a Task +task = Task.init(project_name="myProject", task_name="myTask") + +# Create an output model for the PyTorch framework +output_model = OutputModel(task=task, framework="PyTorch") +``` + +You can set the destination the model will be uploaded to and its label enumeration using the +[`OutputModel.set_upload_destination`](../references/sdk/model_outputmodel.md#set_upload_destination) and +[`OutputModel.update_labels`](../references/sdk/model_outputmodel.md#update_labels) methods respectively. + +```python +# Set the URI of the storage destination for uploaded model weight files +output_model.set_upload_destination(uri=models_upload_destination) + +# Set the label numeration +output_model.update_labels({'background': 0, 'label': 255}) +``` + +### Updating Models +ClearML doesn’t automatically log the snapshots of manually logged models. To update an experiment’s model use the +[OutputModel.update_weights](../references/sdk/model_outputmodel.md#update_weights) method. + +```python +# If validation shows this network is the best so far, update the output model +if val_log['iou'] > best_iou: + output_model.update_weights(weights_filename='models/model.pth') +``` + +* Specify either the path of a local weights file to upload (`weights_filename`), or the network location of a remote + weights file (`registered_uri`). +* Use the `upload_uri` argument to explicitly specify an upload destination for the weights file. +* Model metadata + * `update_comment` - update the model's description + * `iteration` - input the iteration number + +Alternatively, update a model through its associated task, using the [`Task.update_output_model`](../references/sdk/task.md#update_output_model) +method. + +## Input Models + +### Using Registered Models + +To use a ClearML model as an input model, create an InputModel object and [connect](../references/sdk/task.md#connect) +it to a task. + +```python +# Create an input model using the ClearML ID of a model already registered in the ClearML platform +input_model = InputModel(model_id="fd8b402e874549d6944eebd49e37eb7b") + +# Connect the input model to the task +task.connect(input_model) +``` + +### Importing Models + +To import an existing model, use the [`InputModel.import_model`](../references/sdk/model_outputmodel.md#inputmodelimport_model) +class method and specify the `weights_url` - the URL for the imported model. If the URL already exists in the ClearML +server, it is reused. Otherwise, a new model is registered. + +Then [connect](../references/sdk/task.md#connect) the model to a task. + +```python +# Instantiate a Task +task = Task.init(project_name="examples", task_name="example task") + +input_model = InputModel.import_model( + # Name for model in ClearML + name='Input Model with Network Design', + # Import the model using a URL + weights_url='https://s3/models/model.pth', + # Set label enumeration values + label_enumeration={'person' : 1, 'car' : 2, 'truck' : 3, 'bus' : 4, + 'motorcycle' : 5, 'bicycle' : 6, 'ignore': -1}, + framework='PyTorch' +) + +# Connect the input model to the task +task.connect(input_model) +``` + +## Querying Models +Retrieve a list of model objects by querying the system by model names, projects, tags, and more, using the +[`Model.query_models`](../references/sdk/model_model.md#modelquery_models) and / or +the [`InputModel.query_models`](../references/sdk/model_inputmodel.md#inputmodelquery_models) class methods. These +methods return a list of model objects that match the queries. The list is ordered according to the models’ last update +time. + +When you query models by tags, use the `-` prefix in order to filter out models with that tag. + +```python +model_list = Model.query_models( + # Only models from `examples` project + project_name='examples', + # Only models with input name + model_name=None, + # Only models with `demo` tag but without `TF` tag + tags=['demo', '-TF'], + # If `True`, only published models + only_published=False, + # If `True`, include archived models + include_archived=True, + # Maximum number of models returned + max_results=5 +) +``` + +## SDK Reference + +For information about all model methods, see the following SDK reference pages: +* [Model](../references/sdk/model_model.md) +* [InputModel](../references/sdk/model_inputmodel.md) +* [OutputModel](../references/sdk/model_outputmodel.md) \ No newline at end of file diff --git a/docs/clearml_sdk/task_sdk.md b/docs/clearml_sdk/task_sdk.md new file mode 100644 index 00000000..86f22237 --- /dev/null +++ b/docs/clearml_sdk/task_sdk.md @@ -0,0 +1,589 @@ +--- +title: Task +--- + +The following page provides an overview of the basic Pythonic interface to ClearML Tasks. + +## Task Creation + +[`Task.init`](../references/sdk/task.md) is the main method used to create tasks in ClearML. It will create a task, and +populate it with: +* A link to the running git repository (including commit ID and local uncommitted changes) +* Python packages used (i.e. directly imported Python packages, and the versions available on the machine) +* Argparse arguments (default and specific to the current execution) +* Reports to Tensorboard & Matplotlib and model checkpoints. + +:::note +ClearML object (e.g. task, project) names are required to be at least 3 characters long +::: + +```python +from clearml import Task + + +task = Task.init( + project_name='example', # project name of at least 3 characters + task_name='task template', # task name of at least 3 characters + task_type=None, + tags=None, + reuse_last_task_id=True, + continue_last_task=False, + output_uri=None, + auto_connect_arg_parser=True, + auto_connect_frameworks=True, + auto_resource_monitoring=True, + auto_connect_streams=True, +) +``` + +Once a task is created, the task object can be accessed from anywhere in the code by calling [`Task.current_task`](../references/sdk/task.md#taskcurrent_task). + +If multiple tasks need to be created in the same process (for example, for logging multiple manual runs), +make sure to close a task, before initializing a new one. To close a task simply call [`Task.close`](../references/sdk/task.md#close) +(see example [here](../guides/advanced/multiple_tasks_single_process.md)). + +When initializing a task, its project needs to be specified. If the project entered does not exist, it will be created on-the-fly. +Projects can be divided into sub-projects, just like folders are broken into sub-folders. + +For example: +```python +Task.init(project_name='main_project/sub_project', task_name='test') +``` + +Nesting projects works on multiple levels. For example: `project_name=main_project/sub_project/sub_sub_project` + +### Automatic Logging +After invoking `Task.init` in a script, ClearML starts its automagical logging, which includes the following elements: +* **Hyperparameters** - ClearML logs the following types of hyperparameters: + * Command Line Parsing - ClearML captures any command line parameters passed when invoking code that uses standard python packages, including: + * [click](https://click.palletsprojects.com) (see code example [here](https://github.com/allegroai/clearml/blob/master/examples/frameworks/click/click_multi_cmd.py)). + * argparse (see argparse logging example [here](../guides/reporting/hyper_parameters.md).) + * [Python Fire](https://github.com/google/python-fire) - see code examples [here](https://github.com/allegroai/clearml/tree/master/examples/frameworks/fire). + * [LightningCLI](https://pytorch-lightning.readthedocs.io/en/stable/common/lightning_cli.html) - see code example [here](https://github.com/allegroai/clearml/blob/master/examples/frameworks/jsonargparse/pytorch_lightning_cli.py). + * TensorFlow Definitions (`absl-py`) + * [Hydra](https://github.com/facebookresearch/hydra) - the Omegaconf which holds all the configuration files, as well as overridden values. +* **Models** - ClearML automatically logs and updates the models and all snapshot paths saved with the following frameworks: + * Tensorflow (see [code example](../guides/frameworks/tensorflow/tensorflow_mnist.md)) + * Keras (see [code example](../guides/frameworks/keras/keras_tensorboard.md)) + * Pytorch (see [code example](../guides/frameworks/pytorch/pytorch_mnist.md)) + * scikit-learn (only using joblib) (see [code example](../guides/frameworks/scikit-learn/sklearn_joblib_example.md)) + * XGBoost (only using joblib) (see [code example](../guides/frameworks/xgboost/xgboost_sample.md)) + * FastAI (see [code example](../guides/frameworks/fastai/fastai_with_tensorboard.md)) + * MegEngine (see [code example](../guides/frameworks/megengine/megengine_mnist.md)) + * CatBoost (see [code example](../guides/frameworks/catboost/catboost.md)) + +* **Metrics, scalars, plots, debug images** reported through supported frameworks, including: + * Matplotlib (see [code example](../guides/frameworks/matplotlib/matplotlib_example.md)) + * Tensorboard (see [code example](../guides/frameworks/pytorch/pytorch_tensorboardx.md)) + * TensorboardX (see [code example](../guides/frameworks/tensorboardx/tensorboardx.md)) + +* **Execution details** including: + * Git information + * Uncommitted code modifications - In cases where no git repository is detected (e.g. when a single python script is + executed outside a git repository, or when running from a Jupyter Notebook), ClearML logs the contents + of the executed script + * Python environment + * Execution [configuration](../webapp/webapp_exp_track_visual.md#configuration) + +To control a task's framework logging, use the `auto_connect_framworks` parameter of the [`Task.init`](../references/sdk/task.md#taskinit) +method. Turn off all automatic logging by setting the parameter to `False`. For finer grained control of logged frameworks, +input a dictionary, with framework-boolean pairs. + +For example: +```python +auto_connect_frameworks={ + 'matplotlib': True, 'tensorflow': False, 'tensorboard': False, 'pytorch': True, + 'xgboost': False, 'scikit': True, 'fastai': True, 'lightgbm': False, + 'hydra': True, 'detect_repository': True, 'tfdefines': True, 'joblib': True, + 'megengine': True, 'jsonargparse': True, 'catboost': True +} +``` + +### Task Reuse +Every `Task.init` call will create a new task for the current execution. +In order to mitigate the clutter that a multitude of debugging tasks might create, a task will be reused if: +* The last time it was executed (on this machine) was under 72 hours ago (configurable, see + `sdk.development.task_reuse_time_window_in_hours` in the [`sdk.development` section](../configs/clearml_conf.md#sdkdevelopment) of + the ClearML configuration reference) +* The previous task execution did not have any artifacts / models + +It's possible to always create a new task by passing `reuse_last_task_id=False`. + +See full `Task.init` reference [here](../references/sdk/task.md#taskinit). + +### Empty Task Creation + +A task can also be created without the need to execute the code itself. +Unlike the runtime detections, all the environment and configuration details need to be provided explicitly. + +For example: +```python +task = Task.create( + project_name='example', + task_name='task template', + repo='https://github.com/allegroai/clearml.git', + branch='master', + script='examples/reporting/html_reporting.py', + working_directory='.', + docker=None, +) +``` + +See full `Task.create` reference [here](../references/sdk/task.md#taskcreate). + +### Tracking Task Progress +Track a task’s progress by setting the task progress property using the [`Task.set_progress`](../references/sdk/task.md#set_progress) method. +Set a task’s progress to a numeric value between 0 - 100. Access the task’s current progress, using the +[`Task.get_progress`](../references/sdk/task.md#get_progress) method. + +```python +task = Task.init(project_name="examples", task_name="Track experiment progress") +task.set_progress(0) +# task doing stuff +task.set_progress(50) +print(task.get_progress()) +# task doing more stuff +task.set_progress(100) +``` + +While the task is running, the WebApp will show the task’s progress indication in the experiment table, next to the +task’s status. If a task failed or was aborted, you can view how much progress it had made. + +
+ +![Experiment table progress indication](../img/fundamentals_task_progress.png) + +
+ +Additionally, you can view a task’s progress in its [INFO](../webapp/webapp_exp_track_visual.md#general-information) tab +in the WebApp. + + +## Accessing Tasks +A task can be identified by its project and name, and by a unique identifier (UUID string). The name and project of +a task can be changed after an experiment has been executed, but its ID can't be changed. + +Programmatically, task objects can be retrieved by querying the system based on either the task ID or a project and name +combination using the [`Task.get_task`](../references/sdk/task.md#taskget_task) class method. If a project / name +combination is used, and multiple tasks have the exact same name, the function will return the *last modified task*. + +For example: +* Accessing a task object with a task ID: + + ```python + a_task = Task.get_task(task_id='123456deadbeef') + ``` +* Accessing a task with a project and name: + + ```python + a_task = Task.get_task(project_name='examples', task_name='artifacts') + ``` + +Once a task object is obtained, it's possible to query the state of the task, reported scalars, etc. +The task's outputs, such as artifacts and models, can also be retrieved. + +## Querying / Searching Tasks + +Searching and filtering tasks can be done via the [web UI](../webapp/webapp_overview.md) and programmatically. +Input search parameters into the [`Task.get_tasks`](../references/sdk/task.md#taskget_tasks) method, which returns a +list of task objects that match the search. + +For example: +```python +task_list = Task.get_tasks( + task_ids=None, # type Optional[Sequence[str]] + project_name=None, # Optional[str] + task_name=None, # Optional[str] + task_filter=None # Optional[Dict] +) +``` + +It's possible to also filter tasks by passing filtering rules to `task_filter`. + +For example: +```python +task_filter={ + # only tasks with tag `included_tag` and without tag `excluded_tag` + 'tags': ['included_tag', '-excluded_tag'], + # filter out archived tasks + 'system_tags': ['-archived'], + # only completed & published tasks + 'status': ['completed', 'published'], + # only training type tasks + 'type': ['training'], + # match text in task comment or task name + 'search_text': 'reg_exp_text' +} +``` + +## Cloning & Executing Tasks + +Once a task object is created, it can be copied (cloned). [`Task.clone`](../references/sdk/task.md#taskclone) returns +a copy of the original task (`source_task`). By default, the cloned task is added to the same project as the original, +and it's called "Clone Of ORIGINAL_NAME", but the name / project / comment (description) of the cloned task can be directly overridden. + +```python +task = Task.init(project_name='examples', task_name='original task',) +cloned = Task.clone( + source_task=task, # type: Optional[Union[Task, str]] + # override default name + name='newly created task', # type: Optional[str] + comment=None, # type: Optional[str] + # insert cloned task into a different project + project=None, # type: Optional[str] +) +``` + +A newly cloned task has a [draft](../fundamentals/task.md#task-states) status, so it's modifiable. + +Once a task is modified, launch it by pushing it into an execution queue with the [Task.enqueue](../references/sdk/task.md#taskenqueue) +class method. Then a [ClearML Agent](../clearml_agent.md) assigned to the queue will pull the task from the queue and execute +it. + +```python +Task.enqueue( + task=task, # type: Union[Task, str] + queue_name='default', # type: Optional[str] + queue_id=None # type: Optional[str] +) +``` + +See enqueue [example](https://github.com/allegroai/clearml/blob/master/examples/automation/programmatic_orchestration.py). + +## Advanced Flows + +### Remote Execution + +A compelling workflow is: +1. Run code on a development machine for a few iterations, or just set up the environment. +1. Move the execution to a beefier remote machine for the actual training. + +Use the [Task.execute_remotely](../references/sdk/task.md#execute_remotely) method to implement this workflow. This method +stops the current manual execution, and then re-runs it on a remote machine. + +For example: +```python +task.execute_remotely( + queue_name='default', # type: Optional[str] + clone=False, # type: bool + exit_process=True # type: bool +) +``` + +Once the method is called on the machine, it stops the local process and enqueues the current task into the `default` +queue. From there, an agent can pull and launch it. + +See the [Remote Execution](../guides/advanced/execute_remotely.md) example. + +#### Remote Function Execution +A specific function can also be launched on a remote machine with the [`Task.create_function_task`](../references/sdk/task.md#create_function_task) +method. + +For example: +```python +def run_me_remotely(some_argument): + print(some_argument) + +a_func_task = task.create_function_task( + func=run_me_remotely, # type: Callable + func_name='func_id_run_me_remotely', # type:Optional[str] + task_name='a func task', # type:Optional[str] + # everything below will be passed directly to our function as arguments + some_argument=123 +) +``` +Arguments passed to the function will be automatically logged under the `Function` section in the Hyperparameters tab. +Like any other arguments, they can be changed from the UI or programmatically. + +:::note Function Task Creation +Function tasks must be created from within a regular task, created by calling `Task.init` +::: + +### Offline Mode + +You can work with tasks in Offline Mode, in which all the data and logs that the Task captures are stored in a local +folder, which can later be uploaded to the [ClearML Server](../deploying_clearml/clearml_server.md). + +Before initializing a Task, use the [Task.set_offline](../references/sdk/task.md#taskset_offline) class method and set +the `offline_mode` argument to `True`. The method returns the Task ID and a path to the session folder. + +```python +from clearml import Task +# Use the set_offline class method before initializing a Task +Task.set_offline(offline_mode=True) +# Initialize a Task +task = Task.init(project_name="examples", task_name="my_task") + +# Rest of code is executed. All data is logged locally and not onto the server +``` + +All the information captured by the Task is saved locally. Once the task script finishes execution, it's zipped. + +Upload the execution data that the Task captured offline to the ClearML Server using one of the following: +* [`clearml-task`](../apps/clearml_task.md) CLI + ```bash + clearml-task --import-offline-session "path/to/session/.clearml/cache/offline/b786845decb14eecadf2be24affc7418.zip" + ``` + Pass the path to the zip folder containing the session with the `--import-offline-session` parameter + +* [Task.import_offline_session](../references/sdk/task.md#taskimport_offline_session) class method + ```python + from clearml import Task + Task.import_offline_session(session_folder_zip="path/to/session/.clearml/cache/offline/b786845decb14eecadf2be24affc7418.zip") + ``` + + In the `session_folder_zip` argument, insert the path to the zip folder containing the session. + +Both options will upload the Task's full execution details and outputs and return a link to the Task's results page on +the ClearML Server. + +## Artifacts +Artifacts are the output files created by a task. ClearML uploads and logs these products so they can later be easily +accessed, modified, and used. + +### Logging Artifacts +To log an artifact in a task, use the [`upload_artifact`](../references/sdk/task.md#upload_artifact) method. + +For example: +* Upload a local file containing the preprocessing results of the data: + ```python + task.upload_artifact(name='data', artifact_object='/path/to/preprocess_data.csv') + ``` + +* Upload an entire folder with all its content by passing the folder, which will be zipped and uploaded as a single + zip file: + ```python + task.upload_artifact(name='folder', artifact_object='/path/to/folder') + ``` + +* Serialize and upload a Python object. ClearML automatically chooses the file format based on the object’s type, or you + can explicitly specify the format as follows: + * dict - `.json` (default), `.yaml` + * pandas.DataFrame - `.csv.gz` (default), `.parquet`, `.feather`, `.pickle` + * numpy.ndarray - `.npz` (default), `.csv.gz` + * PIL.Image - Any PIL-supported extensions (default `.png`) + + For example: + ```python + person_dict = {'name': 'Erik', 'age': 30} + + # upload as JSON artifact + task.upload_artifact(name='person dictionary json', artifact_object=person_dict) + + # upload as YAML artifact + task.upload_artifact( + name='person dictionary yaml', + artifact_object=person_dict, + extension_name="yaml" + ) + ``` + +See more details in the [Artifacts Reporting example](../guides/reporting/artifacts.md) and in the [SDK reference](../references/sdk/task.md#upload_artifact). + +### Using Artifacts +A task's artifacts are accessed through the task’s *artifact* property which lists the artifacts’ locations. + +The artifacts can subsequently be retrieved from their respective locations by using: +* `get_local_copy()`- Downloads the artifact and caches it for later use, returning the path to the cached copy. +* `get()` - Returns a Python object constructed from the downloaded artifact file. + +The code below demonstrates how to access a file artifact using the previously generated preprocessed data: +```python +# get instance of task that created artifact, using task ID +preprocess_task = Task.get_task(task_id='the_preprocessing_task_id') +# access artifact +local_csv = preprocess_task.artifacts['data'].get_local_copy() +``` + +See more details in the [Using Artifacts example](https://github.com/allegroai/clearml/blob/master/examples/reporting/using_artifacts_example.py). + +## Models +The following is an overview of working with models through a `Task` object. It is also possible to work directly with model +objects (see [Models (SDK)](model_sdk.md)). + +### Logging Models Manually + +To manually log a model in a task, create an instance of the [OutputModel](../references/sdk/model_outputmodel.md) class. +An OutputModel object is always registered as an output model of the task it is constructed from. + +For example: + +```python +from clearml import OutputModel, Task + +# Instantiate a Task +task = Task.init(project_name="myProject", task_name="myTask") + +# Instantiate an OutputModel with a task object argument +output_model = OutputModel(task=task, framework="PyTorch") +``` + +### Updating Models Manually + +The snapshots of manually uploaded models aren't automatically captured. To update a task's model, use the +[Task.update_output_model](../references/sdk/task.md#update_output_model) method: + +```python +task.update_output_model(model_path='path/to/model') +``` + +It's possible to modify the following parameters: +* Model location +* Model name +* Model description +* Iteration number +* Model tags + +Models can also be manually updated independently, without any task. See [OutputModel.update_weights](../references/sdk/model_outputmodel.md#update_weights). + +### Using Models + +Accessing a task’s previously trained model is quite similar to accessing task artifacts. A task's models are accessed +through the task’s models property which lists the input models and output model snapshots’ locations. + +The models can subsequently be retrieved from their respective locations by using `get_local_copy()` which downloads the +model and caches it for later use, returning the path to the cached copy (if using Tensorflow, the snapshots are stored +in a folder, so the `local_weights_path` will point to a folder containing the requested snapshot). + +```python +prev_task = Task.get_task(task_id='the_training_task') +last_snapshot = prev_task.models['output'][-1] +local_weights_path = last_snapshot.get_local_copy() +``` + +Notice that if one of the frameworks loads an existing weights file, the running task will automatically update its +"Input Model", pointing directly to the original training task's model. This makes it easy to get the full lineage of +every trained and used model in our system! + +Models loaded by the ML framework appear under the "Input Models" section, under the Artifacts tab in the ClearML UI. + +### Setting Upload Destination + +ClearML automatically captures the storage location of Models created by frameworks such as TF, Pytorch, and scikit-learn. +By default, it stores the local path they are saved at. + +To automatically store all created models by a specific experiment, modify the `Task.init` function as such: + +```python +task = Task.init(project_name='examples', task_name='storing model', output_uri='s3://my_models/') +``` + +To automatically store all models created by any experiment at a specific location, edit the `clearml.conf` (see + [ClearML Configuration Reference](../configs/clearml_conf.md#sdkdevelopment)) and set `sdk.developmenmt.default_output_uri` +to the desired storage (see [Storage](../integrations/storage.md)). This is especially helpful when +using [clearml-agent](../clearml_agent.md) to execute code. + +## Configuration + +### Manual Hyperparameter Logging + +#### Setting Parameters + +To define parameters manually use the [`Task.set_parameters`](../references/sdk/task.md#set_parameters) method to specify +name-value pairs in a parameter dictionary. + +Parameters can be designated into sections: specify a parameter’s section by prefixing its name, delimited with a slash +(i.e. `section_name/parameter_name’:value`). `General` is the default section. + +Call the [`set_parameter`](../references/sdk/task.md#set_parameter) method to set a single parameter. + +```python +task = Task.init(project_name='examples', task_name='parameters') + +# override parameters with provided dictionary +task.set_parameters({'Args/epochs':7, 'lr': 0.5}) + +# setting a single parameter +task.set_parameter(name='decay',value=0.001) +``` + +:::warning Overwriting Parameters +The `set_parameters` method replaces any existing hyperparameters in the task. +::: + +#### Adding Parameters +To update the parameters in a task, use the [`Task.set_parameters_as_dict`](../references/sdk/task.md#set_parameters_as_dict) +method. Arguments and values are input as a dictionary. Like in `set_parameters` above, the parameter's section can +be specified. + +```python +task = Task.task_get(task_id='123456789') + +# add parameters +task.set_parameters_as_dict({'my_args/lr':0.3, 'epochs':10}) +``` + +### Accessing Parameters + +To access all task parameters, use the [`Task.get_parameters`](../references/sdk/task.md#get_parameters) method. This +method returns a flattened dictionary of the `'section/parameter': 'value'` pairs. + +```python +task = Task.get_task(project_name='examples', task_name='parameters') + +# will print a flattened dictionary of the 'section/parameter': 'value' pairs +print(task.get_parameters()) +``` + +Access a specific parameter with the [`Task.get_parameter`](../references/sdk/task.md#get_parameter) method specifying +the parameter name. + +### Tracking Python Objects + +ClearML can track Python objects (such as dictionaries and custom classes) as they evolve in your code, and log them to +your task’s configuration using the [`Task.connect`](../references/sdk/task.md#connect) method. Once objects are connected +to a task, ClearML automatically logs all object elements (e.g. class members, dictionary key-values pairs). + +```python +class person: + def __init__(self, name, age): + self.name = name + self.age = age + +me = person('Erik', 5) + +params_dictionary = {'epochs': 3, 'lr': 0.4} + +task = Task.init(project_name='examples',task_name='argparser') + +task.connect(me) +task.connect(params_dictionary) +``` + +![Task parameters](../img/fundamentals_task_config_hyperparams.png) + +### Configuration Objects + +Configuration objects more elaborate than a key-value dictionary (such as nested dictionaries or configuration files), +can be logged to a task using the [`Task.connect_configuration`](../references/sdk/task.md#connect_configuration) method. +This method saves configuration objects as blobs (i.e. ClearML is not aware of their internal structure). + +```python +# connect a configuration dictionary +model_config_dict = { + 'value': 13.37, 'dict': {'sub_value': 'string'}, 'list_of_ints': [1, 2, 3, 4], +} +model_config_dict = task.connect_configuration(name='dictionary', configuration=model_config_dict) + +# connect a configuration file +config_file_yaml = task.connect_configuration(name="yaml file", configuration='path/to/configuration/file.yaml', ) +``` + +![Task configuration objects](../img/fundamentals_task_config_object.png) + +### User Properties +A task’s user properties do not impact task execution so you can add / modify the properties at any stage. Add user +properties to a task with the [Task.set_user_properties](../references/sdk/task.md#set_user_properties) method. + +```python +task.set_user_properties( + {"name": "backbone", "description": "network type", "value": "great"} +) +``` + +The above example sets the "backbone" property in a task. + +![Task user properties](../img/fundamentals_task_config_properties.png) + +## SDK Reference +For detailed information, see the complete [Task SDK reference page](../references/sdk/task.md) \ No newline at end of file diff --git a/docs/faq.md b/docs/faq.md index ae3b48fd..7194fbd2 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -302,7 +302,7 @@ parameters_dict = Task.current_task().connect(parameters_dict) **I noticed that all of my experiments appear as "Training" Are there other options?** -Yes! When creating experiments and calling [Task.init](fundamentals/task.md#usage), +Yes! When creating experiments and calling [Task.init](references/sdk/task.md#taskinit), you can provide an experiment type. ClearML supports [multiple experiment types](fundamentals/task.md#task-types). For example: ```python diff --git a/docs/fundamentals/artifacts.md b/docs/fundamentals/artifacts.md index 1f0fe3e8..c0a651f8 100644 --- a/docs/fundamentals/artifacts.md +++ b/docs/fundamentals/artifacts.md @@ -1,193 +1,77 @@ --- -title: Artifacts & Models +title: Models --- -ClearML allows easy storage of experiments' output products as **artifacts** that can later be accessed easily -and used, through the web UI or programmatically. +ClearML supports tracking, updating, and visualizing models. -A few examples of artifacts are: -* Model snapshot / weights file -* Data preprocessing -* Feature representation of data -* and more! +Models are stored in ClearML as experiment artifacts, but unlike other artifacts that are dependent on their creating +task, models are independent entities with their own unique ID. Models can be accessed directly with a model object or +indirectly via their creating task. This property makes Models a standalone entry that can be used as an artifactory +interface. -## Artifacts -### Logging Artifacts -To log any type of artifact to a Task, use the [`upload_artifact`](../references/sdk/task.md#upload_artifact) method. -For example: +## Automatically Logging Models -* Upload a local file containing the preprocessing results of the data. -```python -task.upload_artifact(name='data', artifact_object='/path/to/preprocess_data.csv') -``` -* Upload an entire folder with all its content by passing the folder, which will be zipped and uploaded as a single - zip file: -```python -task.upload_artifact(name='folder', artifact_object='/path/to/folder/') -``` -* Serialize and upload a Python object. ClearML automatically chooses the file format based on the object’s type, or you - can explicitly specify the format as follows: - * dict - `.json` (default), `.yaml` - * pandas.DataFrame - `.csv.gz` (default), `.parquet`, `.feather`, `.pickle` - * numpy.ndarray - `.npz` (default), `.csv.gz` - * PIL.Image - Any PIL-supported extensions (default `.png`) +Once integrated into code, ClearML automatically logs and tracks models and any snapshots created by the following +frameworks: +- Tensorflow (see [code example](../guides/frameworks/tensorflow/tensorflow_mnist.md)) +- Keras (see [code example](../guides/frameworks/keras/keras_tensorboard.md)) +- Pytorch (see [code example](../guides/frameworks/pytorch/pytorch_mnist.md)) +- scikit-learn (only using joblib) (see [code example](../guides/frameworks/scikit-learn/sklearn_joblib_example.md)) +- XGBoost (only using joblib) (see [code example](../guides/frameworks/xgboost/xgboost_sample.md)) +- FastAI (see [code example](../guides/frameworks/fastai/fastai_with_tensorboard.md)) +- MegEngine (see [code example](../guides/frameworks/megengine/megengine_mnist.md)) +- CatBoost (see [code example](../guides/frameworks/catboost/catboost.md)) + +When a supported framework loads a weights file, the running task will be automatically updated, with its input model +pointing directly to the original training task's model. + +## Manually Logging Models + +### Output Models + +ClearML stores training results as output models. The `OutputModel` object is instantiated with a task object as an +argument (see [`task`](../references/sdk/model_outputmodel.md) parameter), so it's automatically registered as the Task’s +output model. Since OutputModel objects are connected to tasks, the models are traceable in experiments. + +Output models are read-write so weights can be updated throughout training. Additionally, users can specify a model's +network design and label enumeration. Once an output model is registered, it can be used as the input model for another +experiment. + +The snapshots of manually uploaded models aren't automatically captured, but ClearML provides methods to update them +through a `Task` or `OutputModel` object. + +### Input Models + +ClearML provides flexibility for explicitly connecting input models and experimentation, including: + +* Importing pre-trained models from external sources such as Amazon AWS, GIT repositories, PyTorch, and TensorFlow. +* Using standalone models already registered in ClearML by previously run experiments. +* Defining your own input models in scripts - For example: - ```python - person_dict = {'name': 'Erik', 'age': 30} - - # upload as JSON artifact - task.upload_artifact(name='person dictionary json', artifact_object=person_dict) - - # upload as YAML artifact - task.upload_artifact( - name='person dictionary yaml', - artifact_object=person_dict, - extension_name="yaml" - ) - ``` +## Setting Upload Destination -See more details in the artifacts [example](../guides/reporting/artifacts.md). +* ClearML automatically captures the storage path of Models created by supported frameworks. By default, it stores the + local path they are saved to. +* Upload destinations can be specified explicitly on a per OutputModel or per experiment basis. Alternatively, the upload + destination of all OutputModels can be specified in the ClearML [configuration file](../configs/clearml_conf.md). -### Using Artifacts -To access a Task's artifact in order to use it: -1. Get the Task that created the artifact (see more details on [querying](task.md#querying--searching-tasks) -Tasks). +## WebApp Interface -1. Retrieve all the Task's artifacts with the *artifact* property, which is essentially a dictionary, -where the key is the artifact name, and the value is the artifact itself. -1. Access a specific artifact using one of the following methods: - - Access files by calling `get_local_copy()`, which caches the files for later use and returns a path to the cached - file - - Access object artifacts by using the `get()` method that returns the Python object. - -The code below demonstrates how to access a file artifact using the previously generated preprocessed data: -```python -# get instance of Task that created artifact, using Task ID -preprocess_task = Task.get_task(task_id='the_preprocessing_task_id') -# access artifact -local_csv = preprocess_task.artifacts['data'].get_local_copy() -``` +In the ClearML's web UI, model information can be located through a project's Model Table or through the model's creating +task. -See more details in the using artifacts [example](../guides/reporting/using_artifacts.md). +Models associated with a task appear in the task's **ARTIFACTS** tab. To see further model details, including design, +label enumeration, and general information, click the model name, which is a hyperlink to the +[model's detail page](../webapp/webapp_model_viewing.md). -### List of Supported Artifacts +Models can also be accessed through their associated project's [Model Table](../webapp/webapp_model_table.md), where all +the models associated with a project are listed. -- Numpy array (as npz file) -- Pandas dataframe -- PIL (converted to jpg) -- Files and folders -- Python objects (pickled) +![WebApp Model](../img/examples_model_update_model.png) -## Models -Models are a special kind of artifact and, unlike regular artifacts, which can only be accessed with the creating Task's ID, -Models are entities with their own unique ID that can be accessed directly or via the creating task. +## SDK Interface -This property makes Models a standalone entry that can be used as an artifactory interface. +See [the Models SDK interface](../clearml_sdk/model_sdk.md) for an overview for using the most basic Pythonic methods of the model +classes. See a detailed list of all available methods in the [Model](../references/sdk/model_model.md), [OutputModel](../references/sdk/model_outputmodel.md), and [InputModel](../references/sdk/model_inputmodel.md) +reference pages. -### Automatic Model Logging - -When models are saved using certain frameworks (for instance, by calling the `torch.save()` method), ClearML automatically -logs the models and all snapshot paths. - -![image](../img/examples_model_update_model.png) - -See automatic model logging examples: -* [TF](../guides/frameworks/tensorflow/tensorflow_mnist.md) -* [PyTorch](../guides/frameworks/pytorch/pytorch_mnist.md) -* [Keras](../guides/frameworks/keras/keras_tensorboard.md) -* [Scikit-Learn](../guides/frameworks/scikit-learn/sklearn_joblib_example.md) -* [XGBoost](../guides/frameworks/xgboost/xgboost_sample.md) -* [FastAI](../guides/frameworks/fastai/fastai_with_tensorboard.md) - - -### Manual Model Logging - -To manually log a model, create an instance of OutputModel class: -```python -from clearml import OutputModel, Task - -# Instantiate a Task -task = Task.init(project_name="myProject", task_name="myTask") - -# Instantiate an OutputModel, with a Task object argument -output_model = OutputModel(task=task, framework="PyTorch") -``` - -The OutputModel object is always connected to a Task object as it's instantiated with a Task object as an argument. -It is, therefore, automatically registered as the Task’s output model. - -The snapshots of manually uploaded models aren't automatically captured, but there are two methods -to update an output model. - -#### Updating Via Task Object -Using the [Task.update_output_model](../references/sdk/task.md#update_output_model) method: - -```python -task.update_output_model(model_path='path/to/model') -``` -It's possible to modify the following parameters: -* Weights file / folder - Uploads the files specified with the `model_path`. - If a remote storage is provided (S3 / GS / Https etc...), it saves the URL. -* Model Metadata - Model name, description, iteration number of model, and tags. - -#### Updating Via Model Object -Using the [OutputModel.update_weights](../references/sdk/model_outputmodel.md#update_weights) method: - -```python -output_model.update_weights() -``` -* Specify either the name of a locally stored weights file to upload (`weights_filename`), or the URI of a storage destination -for model weight upload (`registered_uri`). -* Model Metadata - Model description and iteration number. - -See [Model Configuration](../guides/reporting/model_config.md) example. - -### Using Models - -Loading a previously trained model is quite similar to loading artifacts. - -```python -prev_task = Task.get_task(task_id='the_training_task') -last_snapshot = prev_task.models['output'][-1] -local_weights_path = last_snapshot.get_local_copy() -``` -1. Get the instance of the Task that created the original weights files -2. Query the Task on its output models (a list of snapshots) -3. Get the latest snapshot (if using Tensorflow, the snapshots are stored in a folder, so the `local_weights_path` will point to a folder containing the requested snapshot). - -Notice that if one of the frameworks will load the weights file, the running Task will automatically update, with -"Input Model" pointing directly to the original training Task's model. With this feature, it's easy to get a full genealogy -of every trained and used model in our system! - -Loading framework models appear under the "Input Models" section, under the Artifacts tab in the ClearML UI. - -### Setting Upload Destination - -ClearML automatically captures the storage path of Models created by frameworks such as TF, Pytorch, and scikit-learn. By default, -it stores the local loading path they are saved to. - -To automatically store all created models by a specific experiment, modify the `Task.init()` function as such: -```python -task = Task.init(project_name='examples', task_name='storing model', output_uri='s3://my_models/') -``` - -To automatically store all created models from all experiments in a certain storage medium, edit the `clearml.conf` (see - [ClearML Configuration Reference](../configs/clearml_conf.md#sdkdevelopment)) and set `sdk.developmenmt.default_output_uri` to the desired -storage (see [Storage](../integrations/storage.md)). -This is especially helpful when using [clearml-agent](../clearml_agent.md) to execute code. - -### List of Supported Frameworks - -- TensorFlow -- Keras -- PyTorch -- PyTorch Ignite -- PyTorch Lightning -- scikit-learn (only using joblib) -- XGBoost (only using joblib) -- AutoKeras -- FastAI -- LightGBM -- MegEngine -- CatBoost \ No newline at end of file diff --git a/docs/fundamentals/hyperparameters.md b/docs/fundamentals/hyperparameters.md index 801b3892..a3fefbd6 100644 --- a/docs/fundamentals/hyperparameters.md +++ b/docs/fundamentals/hyperparameters.md @@ -2,217 +2,117 @@ title: Hyperparameters --- -Hyperparameters are the configuration options given for a script. -ClearML logs hyperparameters used in experiments from multiple different sources. +Hyperparameters are a script's configuration options. Since hyperparameters can have substantial impact on +model performance, it is crucial to efficiently track and manage them. -In ClearML, parameters are split into 3 sections: -- User Properties - Modifiable section that can be edited post execution. -- Hyperparameters - Individual parameters for configuration. -- Configuration Objects - Usually configuration files (Json / YAML) or python objects. - -These sections are further broken down into sub-sections (General / Args / TF_Define) for convenience. +ClearML supports tracking and managing hyperparameters in each experiment and provides a dedicated [hyperparameter +optimization module](hpo.md). With ClearML's logging and tracking capabilities, experiments can be reproduced, and their +hyperparameters and results can be saved and compared, which is key to understanding model behavior. -![image](../img/hyperparameters_sections.png) +ClearML lets you easily try out different hyperparameter values without changing your original code. ClearML’s [execution +agent](../clearml_agent.md) will override the original values with any new ones you specify through the web UI (see +[Configuration](../webapp/webapp_exp_tuning.md#configuration) in the Tuning Experiments page). It's also possible to +programmatically set experiment parameters. -## Command Line Parsing -ClearML captures any command line parameters passed when invoking code that uses standard python packages such as -argparse, [click](https://click.palletsprojects.com), or [Python Fire](https://github.com/google/python-fire). This happens automatically with no additional code required beyond -initializing ClearML. +## Tracking Hyperparameters +Hyperparameters can be added from anywhere in your code, and ClearML provides multiple ways to obtain them! ClearML logs +and tracks hyperparameters of various types, supporting automatic logging and explicit reporting. -### Argparse Example +### Automatic Logging +Once a ClearML Task has been [initialized](../references/sdk/task.md#taskinit) in a script, ClearML automatically captures and tracks +the following types of parameters: +* Command line parsing - command line parameters passed when invoking code that uses standard python packages, including: + * [click](https://click.palletsprojects.com) - see code example [here](https://github.com/allegroai/clearml/blob/master/examples/frameworks/click/click_multi_cmd.py). + * [argparse](https://docs.python.org/3/library/argparse.html) - see code example [here](../guides/frameworks/pytorch/pytorch_tensorboardx.md). + * [Python Fire](https://github.com/google/python-fire) - see code examples [here](https://github.com/allegroai/clearml/tree/master/examples/frameworks/fire). + * [LightningCLI](https://pytorch-lightning.readthedocs.io/en/stable/common/lightning_cli.html) - see code example [here](https://github.com/allegroai/clearml/blob/master/examples/frameworks/jsonargparse/pytorch_lightning_cli.py). +* TensorFlow Definitions (`absl-py`). See examples of ClearML's automatic logging of TF Defines: + * [TensorFlow MNIST](../guides/frameworks/tensorflow/tensorflow_mnist.md) + * [TensorBoard PR Curve](../guides/frameworks/tensorflow/tensorboard_pr_curve.md) +* [Hydra](https://github.com/facebookresearch/hydra) - ClearML logs the `Omegaconf` which holds all the configuration files, + as well as values overridden during runtime. See code example [here](https://github.com/allegroai/clearml/blob/master/examples/frameworks/hydra/hydra_example.py). + +:::tip Disabling Automatic Logging +Automatic logging can be disabled. See this [FAQ](../faq.md#controlling_logging). +::: -```python -from clearml import Task -import argparse +### Environment Variables -parser = argparse.ArgumentParser(description="Script Argparser") -parser.add_argument("-lr", default=0.001, help="Initial learning rate") -parser.add_argument("-epochs", default= 10, help="Total number of epochs") -args = parser.parse_args() - - -task = Task.init(project_name="examples",task_name="argparser logging") -``` - -See another argparse logging example [here](../guides/reporting/hyper_parameters.md). - -### Click Example - -```python -from clearml import Task -import click - -task = Task.init(project_name='examples', task_name='click single command') - -@click.command() -@click.option('--count', default=1, help='Number of greetings.') -@click.option('--name', prompt='Your name', - help='The person to greet.') -def hello(count, name): - for x in range(count): - click.echo("Hello {}!".format(name)) - -hello() -``` - -See another code example [here](https://github.com/allegroai/clearml/blob/master/examples/frameworks/click/click_multi_cmd.py). - -## Connecting Objects - -Users can directly connect objects, such as dictionaries or even custom classes, to Tasks. -All class members will be automatically fetched and logged by ClearML. - -* Connecting a class: -```python -class person: - def __init__(self, name, age): - self.name = name - self.age = age - - -me = person('Erik',5) - -task = Task.init(project_name='examples',task_name='argparser') - -task.connect(me) -``` -See connecting configuration objects example [here](../guides/reporting/hyper_parameters.md). - - -* Connecting a dictionary: -```python -task = Task.init(project_name='examples', task_name='dictionary logging') - -params_dictionary = {'epochs': 3, 'lr': 0.4} - -task.connect(params_dictionary) -``` - -## User Properties - -User properties are an editable key / value store, which enables adding information to an experiment, -making it easier to search / filter. User properties are like parameters that can also be added after a Task's execution, which -can also be added to an [experiment table](../webapp/webapp_exp_table.md) (i.e. customize columns). - -For example: -```python -task.set_user_properties({"name": "backbone", - "description": "network type", - "value": "great"}) -``` - -The above example will connect to the Task a user property named "backbone", with the description "network type", and -the value of "great". - -## Environment Variables - -:::important +:::important Experiment Reproducibility Relying on environment variables makes an experiment not fully reproducible, since ClearML Agent can't reproduce them at runtime. ::: -Environment variables can be logged by modifying the [clearml.conf](../configs/clearml_conf.md) file. Modify the *log_os_environments* +Environment variables can be logged by modifying the [clearml.conf](../configs/clearml_conf.md) file. Modify the `log_os_environments` parameter specifying parameters to log. -`log_os_environments: ["AWS_*", "CUDA_VERSION"]` +```editorconfig +log_os_environments: ["AWS_*", "CUDA_VERSION"]` +``` -It's also possible to specify environment variables using the CLEARML_LOG_ENVIRONMENT variable. +It's also possible to specify environment variables using the `CLEARML_LOG_ENVIRONMENT` variable. -:::note -The CLEARML_LOG_ENVIRONMENT always overrides the clearml.conf file. +:::note Overriding clearml.conf +The `CLEARML_LOG_ENVIRONMENT` always overrides the `clearml.conf` file. ::: -## TF Defines +When a script that has integrated ClearML is executed, the environment variables listed in `clearml.conf` or specified by +the `CLEARML_LOG_ENVIRONMENT` variable are logged by ClearML. -ClearML automatically captures TensorFlow definitions, which are used as configuration files for Tensorflow. +### Explicit Logging -See examples of ClearML's automatic logging of TF Defines: -* [TensorFlow MNIST](../guides/frameworks/tensorflow/tensorflow_mnist.md) -* [TensorBoard PR Curve](../guides/frameworks/tensorflow/tensorboard_pr_curve.md) +To augment its automatic logging, ClearML supports explicitly logging parameters. ClearML provides methods to directly +connect Python objects and configuration objects, as well as manually set and update task parameters. -## Hydra +#### Connecting Python Objects +Users can directly connect Python objects, such as dictionaries and custom classes, to tasks, using the +[Task.connect](../references/sdk/task.md#connect) method. Once objects are connected to a task, all object elements +(e.g. class members, dictionary key-values pairs) are automatically logged by ClearML. Additionally, ClearML tracks these +values as they change through your code. -[Hydra](https://github.com/facebookresearch/hydra) is a module developed by FaceBook AI Research to manage experiments' -parameters. Hydra offers the best of both worlds, managing configurations with files while making parameters overridable at runtime. +When connecting objects to ClearML, users can directly access and modify an object's elements (e.g. a specific key-value +pair in a parameter dictionary). -ClearML logs the Omegaconf which holds all the configuration files, as well as overridden values. +#### Connecting Configuration Objects +Configuration objects are dictionaries or configuration files connected to the task using the +[Task.connect_configuration](../references/sdk/task.md#connect_configuration) method. With this method, configuration +objects are saved as blobs i.e. ClearML is not aware of their internal structure. -Check out the [example code](https://github.com/allegroai/clearml/blob/master/examples/frameworks/hydra/hydra_example.py), -which demonstrates the creation of a configuration object to which configuration values can be added and overridden using the -command line. +#### Setting and Updating Parameters +ClearML provides methods to set and update task parameters manually. Use the [Task.set_parameters](../references/sdk/task.md#set_parameters) +method to define parameters manually. To update the parameters in an experiment, use the [Task.set_parameters_as_dict](../references/sdk/task.md#set_parameters_as_dict) +method. The `set_parameters_as_dict` method updates parameters while the `set_parameters` method overrides the parameters. -## Configuration Objects +ClearML does not automatically track changes to explicitly set parameters. -Configuration objects are dictionaries or configuration files connected to the Task. Unlike Hyperparameters, these are saved as a whole and not -divided into individual parameters. +### User Properties +User properties do not impact tasks execution and so can be modified at any stage. They offer the convenience of setting +helpful values which then be displayed in the [experiment table](../webapp/webapp_exp_table.md) (i.e. customize columns), +making it easier to search / filter experiments. Add user properties to an experiment with the +[Task.set_user_properties](../references/sdk/task.md#set_user_properties) method. -To connect a configuration dictionary: -```python -model_config_dict = { - 'value': 13.37, - 'dict': {'sub_value': 'string', 'sub_integer': 11}, - 'list_of_ints': [1, 2, 3, 4], -} -model_config_dict = task.connect_configuration(name='dictionary', configuration=model_config_dict) -``` +### Accessing Parameters +ClearML provides methods to directly access a task’s logged parameters. -To connect a configuration file: -```python -config_file_yaml = task.connect_configuration(name="yaml file", configuration='path/to/configuration/file.yaml', ) -``` +To get all of a task's parameters and properties (hyperparameters, configuration objects, and user properties), use the +[Task.get_parameters](../references/sdk/task.md#get_parameters) method, which will return a dictionary with the parameters, +including their sub-sections (see [WebApp sections](#webapp-access) below). -Configuration objects can be split into categories in the Configuration section. -The "name" argument, is the name of the section that the object will go into. If a section name is not specified, the default section is *General*. +## WebApp Interface -![Configuration objects](../img/fundamentals_hyperparameters_config_objects.png) +Configurations can be viewed in web UI experiment pages, in the **CONFIGURATIONS** panel. -## Manual Parameter Access +The configuration panel is split into three sections according to type: +- **User Properties** - Modifiable section that can be edited post-execution. +- **Hyperparameters** - Individual parameters for configuration +- **Configuration Objects** - Usually configuration files (Json / YAML) or Python objects. + +These sections are further broken down into sub-sections based on how the parameters were logged (General / Args / TF_Define / Environment). -### Manual Parameter Input +![Task hyperparameters sections](../img/hyperparameters_sections.png) -In addition to connecting a dictionary or a class to log hyperparameters, users can also use the `set_parameters` method - to define parameters manually. Parameters are inputted as dictionaries. +## SDK Interface -Additionally, parameters can be categorized, and each category appears in its own section in the hyperparameter tab of the web UI. -Specify a section by putting its name before the parameter, for example `'Args/epochs': 'value'` - 'epochs' will go into the -'Args' section. If a section isn't specified, the parameter will go into the *General* section by default. - -Calling the `set_parameter` method will set a single parameter. - -```python -task = Task.init(project_name='examples', task_name='parameters') - -# override parameters with provided dictionary -task.set_parameters({'Args/epochs':7, 'lr': 0.5}) - -# setting a single parameter -task.set_parameter(name='decay',value=0.001) -``` -:::warning -The *set_parameters* method will override any parameters already logged. -::: - -### Adding Parameters -To update the parameters in an experiment, use the `set_parameters_as_dict` method . Arguments and values are inputted as a dictionary. -Like in the `set_parameters` method, the dictionary can be nested, so the parameter's section can be specified. - -```python -task = Task.task_get(task_id='123456789') - -# add parameters -task.set_parameters_as_dict({'my_args/lr':0.3, 'epochs':10}) -``` - - -### Accessing Parameters - -To get all Task's parameters, use the `get_parameters()` method, which will return a dictionary with the parameters, including -their section. - -```python -task = Task.get_task(project_name='examples', task_name='parameters') - -# will print a flattened dictionary of the 'section/parameter': 'value' pairs. {'Args/epochs': '7', 'General/lr': '0.5'} -print(task.get_parameters()) -``` +See the [Configuration section](../clearml_sdk/task_sdk.md#configuration) of the Task SDK page for an overview of basic Pythonic +methods for working with hyperparameters. \ No newline at end of file diff --git a/docs/fundamentals/logger.md b/docs/fundamentals/logger.md index 6ce2282b..cc5fe8c0 100644 --- a/docs/fundamentals/logger.md +++ b/docs/fundamentals/logger.md @@ -71,7 +71,7 @@ logger = task.get_logger() ### Media Reporting ClearML also supports reporting media (such as audio, video and images) for every iteration. -This section is mostly used for debugging. It's recommended to use [artifacts](artifacts.md#artifacts) for storing script +This section is mostly used for debugging. It's recommended to use [artifacts](task.md#artifacts) for storing script outputs that would be used later on. Only the last X results of each title / series are saved to prevent overloading the server. diff --git a/docs/fundamentals/projects.md b/docs/fundamentals/projects.md index 6d337f56..4732cb73 100644 --- a/docs/fundamentals/projects.md +++ b/docs/fundamentals/projects.md @@ -2,7 +2,7 @@ title: Projects --- -Projects are contextual containers for [tasks](task.md) and [models](artifacts.md#models) (as well as [dataviews](../hyperdatasets/dataviews.md) +Projects are contextual containers for [tasks](task.md) and [models](artifacts.md) (as well as [dataviews](../hyperdatasets/dataviews.md) when Hyper-Datasets are enabled), providing a logical structure similar to file system folders. An often useful method is to categorize components into projects according to models or objectives. Grouping into projects helps in identifying tasks, models, and dataviews when queried. @@ -27,7 +27,7 @@ models, and dataviews, can be viewed in the project's [experiments table](../web ### Creating Subprojects -When [initializing a task](task.md#task-creation), its project needs to be specified. If the project entered does not exist, it will be created. +When [initializing a task](../clearml_sdk/task_sdk.md#task-creation), its project needs to be specified. If the project entered does not exist, it will be created. Projects can contain subprojects, just like folders can contain sub-folders. Input into the `project_name` parameter a target project path. The project path should follow the project tree hierarchy, in which the project and subprojects are slash (`/`) delimited. diff --git a/docs/fundamentals/task.md b/docs/fundamentals/task.md index 11003862..2fb5358a 100644 --- a/docs/fundamentals/task.md +++ b/docs/fundamentals/task.md @@ -1,5 +1,5 @@ --- -title: Task / Experiment +title: Tasks --- **ClearML Task** lies at the heart of ClearML's experiment manager. @@ -20,7 +20,7 @@ you can work with tasks in Offline Mode, in which all information is saved in a In the UI and code, tasks are grouped into [projects](projects.md), which are logical entities similar to folders. Users can decide how to group tasks, though different models or objectives are usually grouped into different projects. -Tasks that are in the system can be accessed and utilized with code. To [access a task](#accessing-tasks), it can be identified either by a +Tasks that are in the system can be accessed and utilized with code. To [access a task](../clearml_sdk/task_sdk.md#accessing-tasks), it can be identified either by a project name & task name combination or by a unique ID. It's possible to copy ([clone](../webapp/webapp_exp_reproducing.md)) a task multiple times and to modify it for re-execution. @@ -33,7 +33,7 @@ The sections of **ClearML Task** are made up of the information that a task capt execution details and execution outputs. This information is used for tracking and visualizing results, reproducing, tuning, and comparing experiments, and executing workflows. -The captured [code execution information](../webapp/webapp_exp_track_visual.md#execution-details) includes: +The captured [code execution information](../webapp/webapp_exp_track_visual.md#execution) includes: * Git information * Uncommitted code modifications * Python environment @@ -42,17 +42,53 @@ The captured [code execution information](../webapp/webapp_exp_track_visual.md#e The captured [execution output](../webapp/webapp_exp_track_visual.md#experiment-results) includes: * [Console output](../webapp/webapp_exp_track_visual.md#console) * [Scalars](../webapp/webapp_exp_track_visual.md#scalars) -* [Plots](../webapp/webapp_exp_track_visual.md#other-plots) +* [Plots](../webapp/webapp_exp_track_visual.md#plots) * [Debug samples](../webapp/webapp_exp_track_visual.md#debug-samples) -* [Models](artifacts.md#models) +* [Models](artifacts.md) To view a more in depth description of each task section, see [Tracking Experiments and Visualizing Results](../webapp/webapp_exp_track_visual.md). -## Task Types +### Artifacts +ClearML allows easy storage of experiments' output products as artifacts that can later be accessed easily and used, +through the [web UI](../webapp/webapp_overview.md) or programmatically. + +ClearML provides methods to easily track files generated throughout your experiments’ execution such as: + +- Numpy objects +- Pandas DataFrames +- PIL +- Files and folders +- Python objects +- and more! + +Most importantly, ClearML also logs experiments’ input and output models as well as interim model snapshots (see +[Models](artifacts.md)). + +#### Logging Artifacts +ClearML provides an explicit logging interface that supports manually reporting a variety of artifacts. Any type of +artifact can be logged to a task using the [`Task.upload_artifact`](../references/sdk/task.md#upload_artifacts) method. +See more details in the [Artifacts Reporting example](../guides/reporting/artifacts.md). + +ClearML can be configured to upload artifacts to any of the supported types of storage, which include local and shared +folders, AWS S3 buckets, Google Cloud Storage, and Azure Storage. For more information, see [Storage](../integrations/storage.md). + +:::note Debug Sample Storage +Debug samples are handled differently, see [`Logger.set_default_upload_destination`](../references/sdk/logger.md#set_default_upload_destination) +::: + +#### Accessing Artifacts +Artifacts that have been logged can be accessed by other tasks [through the task](../clearml_sdk/task_sdk.md#accessing-tasks) +they are attached to, and then retrieving the artifact with one of its following methods: +* `get_local_copy()` - caches the files for later use and returns a path to the cached file. +* `get()` - use for Python objects. The method that returns the Python object. + +See more details in the [Using Artifacts example](https://github.com/allegroai/clearml/blob/master/examples/reporting/using_artifacts_example.py). + +## Task Types Tasks have a *type* attribute, which denotes their purpose (Training / Testing / Data processing). This helps to further -organize projects and ensure tasks are easy to [search and find](#querying--searching-tasks). The default task type is *training*. -Available task types are: +organize projects and ensure tasks are easy to [search and find](../clearml_sdk/task_sdk.md#querying--searching-tasks). +The default task type is *training*. Available task types are: - Experimentation - *training*, *testing*, *inference* @@ -67,7 +103,7 @@ Available task types are: ## Task Lifecycle ClearML Tasks are created in one of the following methods: -* Manually running code that is instrumented with the ClearML SDK and invokes `Task.init()`. +* Manually running code that is instrumented with the ClearML SDK and invokes [`Task.init`](../references/sdk/task.md#taskinit). * Cloning an existing task. * Creating a task via CLI using [clearml-task](../apps/clearml_task.md). @@ -104,11 +140,11 @@ The above diagram demonstrates how a previously run task can be used as a baseli ## Task States -The state of a Task represents its stage in the Task lifecycle. It indicates whether the Task is read-write (editable) or +The state of a task represents its stage in the task lifecycle. It indicates whether the task is read-write (editable) or read-only. For each state, a state transition indicates which actions can be performed on an experiment, and the new state after performing an action. -The following table describes the Task states and state transitions. +The following table describes the task states and state transitions. | State | Description / Usage | State Transition | |---|---|---| @@ -120,249 +156,8 @@ The following table describes the Task states and state transitions. | *Aborted* | The experiment ran, and was manually or programmatically terminated. | The same as *Completed*. | | *Published* | The experiment is read-only. Publish an experiment to prevent changes to its inputs and outputs. | A *Published* experiment cannot be reset. If it is cloned, the state of the newly cloned experiment becomes *Draft*. | +## SDK Interface -## Usage - -### Task Creation - -`Task.init()` is the main method used to create Tasks in ClearML. It will create a Task, and populate it with: -* A link to the running git repository (including commit ID and local uncommitted changes) -* Python packages used (i.e. directly imported Python packages, and the versions available on the machine) -* Argparse arguments (default and specific to the current execution) -* Reports to Tensorboard & Matplotlib and model checkpoints. - -:::note -ClearML object (e.g. task, project) names are required to be at least 3 characters long -::: - -```python -from clearml import Task - - -task = Task.init( - project_name='example', # project name of at least 3 characters - task_name='task template', # task name of at least 3 characters - task_type=None, - tags=None, - reuse_last_task_id=True, - continue_last_task=False, - output_uri=None, - auto_connect_arg_parser=True, - auto_connect_frameworks=True, - auto_resource_monitoring=True, - auto_connect_streams=True, -) -``` - -When a Task is initialized, it automatically captures parameters and outputs from supported frameworks. To control what ClearML -automatically logs, see this [FAQ](../faq.md#controlling_logging). - -Once a Task is created, the Task object can be accessed from anywhere in the code by calling [`Task.current_task`](../references/sdk/task.md#taskcurrent_task). - -If multiple Tasks need to be created in the same process (for example, for logging multiple manual runs), -make sure to close a Task, before initializing a new one. To close a task simply call `task.close` -(see example [here](../guides/advanced/multiple_tasks_single_process.md)). - -When initializing a Task, its project needs to be specified. If the project entered does not exist, it will be created. -Projects can be divided into subprojects, just like folders are broken into sub-folders. -For example: -```python -Task.init(project_name='main_project/sub_project', task_name='test') -``` - -Nesting projects works on multiple levels. For example: `project_name=main_project/sub_project/sub_sub_project` - - -#### Task Reuse -Every `Task.init` call will create a new Task for the current execution. -In order to mitigate the clutter that a multitude of debugging Tasks might create, a Task will be reused if: -* The last time it was executed (on this machine) was under 72 hours ago (configurable, see - `sdk.development.task_reuse_time_window_in_hours` in the [`sdk.development` section](../configs/clearml_conf.md#sdkdevelopment) of - the ClearML configuration reference) -* The previous Task execution did not have any artifacts / models - -It's possible to always create a new Task by passing `reuse_last_task_id=False`. - -See full `Task.init` documentation [here](../references/sdk/task.md#taskinit). - -### Empty Task Creation - -A Task can also be created without the need to execute the code itself. -Unlike the runtime detections, all the environment and configuration details needs to be provided explicitly. - -For example: -```python -task = Task.create( - project_name='example', - task_name='task template', - repo='https://github.com/allegroai/clearml.git', - branch='master', - script='examples/reporting/html_reporting.py', - working_directory='.', - docker=None, -) -``` - -See [`Task.create`](../references/sdk/task.md#taskcreate) in the Python SDK reference. - -### Tracking Task Progress -Track a task’s progress by setting the task progress property using the [`Task.set_progress`](../references/sdk/task.md#set_progress) method. -Set a task’s progress to a numeric value between 0 - 100. Access the task’s current progress, using the -[`Task.get_progress`](../references/sdk/task.md#get_progress) method. - -```python -task = Task.init(project_name="examples", task_name="Track experiment progress") -task.set_progress(0) -# task doing stuff -task.set_progress(50) -print(task.get_progress()) -# task doing more stuff -task.set_progress(100) -``` - -While the task is running, the WebApp will show the task’s progress indication in the experiment table, next to the -task’s status. If a task failed or was aborted, you can view how much progress it had made. - -
- -![Experiment table progress indication](../img/fundamentals_task_progress.png) - -
- -Additionally, you can view a task’s progress in its [INFO](../webapp/webapp_exp_track_visual.md#general-information) tab -in the WebApp. - -### Accessing Tasks -A Task can be identified by its project and name, and by a unique identifier (UUID string). The name and project of -a Task can be changed after an experiment has been executed, but its ID can't be changed. - -:::tip Locating Task IDs -To locate a task ID, go to the task's info panel in the [WebApp](../webapp/webapp_overview.md). In the top of the panel, -to the right of the task name, click `ID` and the task ID appears -::: - -Programmatically, Task objects can be retrieved by querying the system based on either the Task ID or a project and name -combination. If a project / name combination is used, and multiple Tasks have the exact same name, the function will return -the *last modified Task*. - -For example: -* Accessing a Task object with a Task ID: -```python -a_task = Task.get_task(task_id='123456deadbeef') -``` -* Accessing a Task with a project / name: -```python -a_task = Task.get_task(project_name='examples', task_name='artifacts') -``` - -Once a Task object is obtained, it's possible to query the state of the Task, reported scalars, etc. -The Task's outputs, such as artifacts and models, can also be retrieved. - -### Querying / Searching Tasks - -Searching and filtering Tasks can be done via the [web UI](../webapp/webapp_overview.md), but also programmatically. -Input search parameters into the `Task.get_tasks` method, which returns a list of Task objects that match the search. - -For example: -```python -task_list = Task.get_tasks( - task_ids=None, # type Optional[Sequence[str]] - project_name=None, # Optional[str] - task_name=None, # Optional[str] - task_filter=None # Optional[Dict] -) -``` - -It's possible to also filter Tasks by passing filtering rules to `task_filter`. - For example: -```python -task_filter={ - # only Tasks with tag `included_tag` and without tag `excluded_tag` - 'tags': ['included_tag', '-excluded_tag'], - # filter out archived Tasks - 'system_tags': ['-archived'], - # only completed & published Tasks - 'status': ['completed', 'published'], - # only training type Tasks - 'type': ['training'], - # match text in Task comment or task name - 'search_text': 'reg_exp_text' -} -``` - -### Cloning & Executing Tasks - -Once a Task object is created, it can be a copied (cloned). `Task.clone` returns a copy of the original Task (`source_task`). -By default, the cloned Task is added to the same project as the original, and it's called "Clone Of ORIGINAL_NAME", but -the name / project / comment of the cloned Task can be directly overridden. - -```python -cloned = Task.clone( - source_task=task, # type: Optional[Union[Task, str]] - # override default name - name='newly created task', # type: Optional[str] - comment=None, # type: Optional[str] - # insert cloned Task into a different project - project=None, # type: Optional[str] -) -``` - -A cloned Task starts in [draft](#task-states) mode, so its Task configurations can be edited (see -[Task.set_parameters](../references/sdk/task.md#set_parameters)). -Once a Task is modified, launch it by pushing it into an execution queue, then a [ClearML Agent](../clearml_agent.md) will pull -it from the queue and execute the Task. - -```python -Task.enqueue( - task=task, # type: Union[Task, str] - queue_name='default', # type: Optional[str] - queue_id=None # type: Optional[str] -) -``` - -See enqueue [example](https://github.com/allegroai/clearml/blob/master/examples/automation/programmatic_orchestration.py). - -### Advanced Remote Execution - -A compelling workflow is: -1. Running code on the development machine for a few iterations, or just setting up the environment. -1. Moving the execution to a beefier remote machine for the actual training. - -For example, to stop the current manual execution, and then re-run it on a remote machine, simply add the following -function call to the code: -```python -task.execute_remotely( - queue_name='default', # type: Optional[str] - clone=False, # type: bool - exit_process=True # type: bool -) -``` - -Once the function is called on the machine, it will stop the local process and enqueue the current Task into the *default* -queue. From there, an agent will be able to pick it up and launch it. - -See the [Remote Execution](https://github.com/allegroai/clearml/blob/master/examples/advanced/execute_remotely_example.py) example. - -#### Remote Function Execution -A specific function can also be launched on a remote machine with `create_function_task`. - -For example: -```python -def run_me_remotely(some_argument): - print(some_argument) - -a_func_task = task.create_function_task( - func=run_me_remotely, # type: Callable - func_name='func_id_run_me_remotely', # type:Optional[str] - task_name='a func task', # type:Optional[str] - # everything below will be passed directly to our function as arguments - some_argument=123 -) -``` -Arguments passed to the function will be automatically logged under the `Function` section in the Hyperparameters tab. -Like any other arguments, they can be changed from the UI or programmatically. - -:::note -Function Tasks must be created from within a regular Task, created by calling `Task.init()` -::: +See [the task SDK interface](../clearml_sdk/task_sdk.md) for an overview for using the most basic Pythonic methods of the `Task`class. +See the [Task reference page](../references/sdk/task.md) for a complete list of available list. diff --git a/docs/getting_started/ds/best_practices.md b/docs/getting_started/ds/best_practices.md index 772a718a..3fcd0961 100644 --- a/docs/getting_started/ds/best_practices.md +++ b/docs/getting_started/ds/best_practices.md @@ -24,7 +24,7 @@ During early stages of model development, while code is still being modified hea The abovementioned setups might be folded into each other and that's great! If you have a GPU machine for each researcher, that's awesome! The goal of this phase is to get a code, dataset and environment setup, so we can start digging to find the best model! -- [ClearML SDK](../../clearml_sdk.md) should be integrated into your code (check out our [getting started](ds_first_steps.md)). +- [ClearML SDK](../../clearml_sdk/clearml_sdk.md) should be integrated into your code (check out our [getting started](ds_first_steps.md)). This helps visualizing the results and tracking progress. - [ClearML Agent](../../clearml_agent.md) helps moving your work to other machines without the hassle of rebuilding the environment every time, while also creating an easy queue interface that easily allows you to just drop your experiments to be executed one by one @@ -43,7 +43,7 @@ yields the best performing model for our task! Visualization and comparisons dashboards keep your sanity at bay! In this stage we usually have a docker container with all the binaries that we need. -- [ClearML SDK](../../clearml_sdk.md) ensures that all the metrics, parameters and Models are automatically logged and can later be +- [ClearML SDK](../../clearml_sdk/clearml_sdk.md) ensures that all the metrics, parameters and Models are automatically logged and can later be accessed, [compared](../../webapp/webapp_exp_comparing.md) and [tracked](../../webapp/webapp_exp_track_visual.md). - [ClearML Agent](../../clearml_agent.md) does the heavy lifting. It reproduces the execution environment, clones your code, applies code patches, manages parameters (Including overriding them on the fly), executes the code and queues multiple tasks diff --git a/docs/getting_started/ds/ds_first_steps.md b/docs/getting_started/ds/ds_first_steps.md index f35dafab..5414f240 100644 --- a/docs/getting_started/ds/ds_first_steps.md +++ b/docs/getting_started/ds/ds_first_steps.md @@ -81,7 +81,7 @@ Now you can integrate ClearML into your code! In ClearML, experiments are organized as [Tasks](../../fundamentals/task.md). ClearML will automatically log your experiment and code, including outputs and parameters from popular ML frameworks, -once you integrate the ClearML [SDK](../../clearml_sdk.md) with your code. To control what ClearML automatically logs, see this [FAQ](../../faq.md#controlling_logging). +once you integrate the ClearML [SDK](../../clearml_sdk/clearml_sdk.md) with your code. To control what ClearML automatically logs, see this [FAQ](../../faq.md#controlling_logging). At the beginning of your code, import the `clearml` package: @@ -113,7 +113,7 @@ ClearML results page: https://app.clear.ml/projects/4043a1657f374e9298649c6ba72a **That’s it!** You are done integrating ClearML with your code :) -Now, [command-line arguments](../../fundamentals/hyperparameters.md#command-line-parsing), [console output](../../fundamentals/logger.md#types-of-logged-results) as well as Tensorboard and Matplotlib will automatically be logged in the UI under the created Task. +Now, [command-line arguments](../../fundamentals/hyperparameters.md#tracking-hyperparameters), [console output](../../fundamentals/logger.md#types-of-logged-results) as well as Tensorboard and Matplotlib will automatically be logged in the UI under the created Task.
Sit back, relax, and watch your models converge :) or continue to see what else can be done with ClearML [here](ds_second_steps.md). diff --git a/docs/getting_started/ds/ds_second_steps.md b/docs/getting_started/ds/ds_second_steps.md index 8f917f84..2b209947 100644 --- a/docs/getting_started/ds/ds_second_steps.md +++ b/docs/getting_started/ds/ds_second_steps.md @@ -68,7 +68,7 @@ If the object type is unknown ClearML pickles it and uploads the pickle file. task.upload_artifacts(my_numpy_matrix, name='features') ``` -Check out all [artifact logging](../../fundamentals/artifacts.md) options. +Check out all [artifact logging](../../clearml_sdk/task_sdk.md#artifacts) options. ### Using Artifacts diff --git a/docs/getting_started/mlops/mlops_first_steps.md b/docs/getting_started/mlops/mlops_first_steps.md index 58c6cdee..a5b0146f 100644 --- a/docs/getting_started/mlops/mlops_first_steps.md +++ b/docs/getting_started/mlops/mlops_first_steps.md @@ -131,7 +131,7 @@ cloned_task.set_parameter(name='internal/magic', value=42) ``` #### Report Artifacts -Artifacts are files created by your task. Users can upload [multiple types of data](../../fundamentals/artifacts.md#logging-artifacts), +Artifacts are files created by your task. Users can upload [multiple types of data](../../clearml_sdk/task_sdk.md#logging-artifacts), objects and files to a task anywhere from code. ```python @@ -141,7 +141,7 @@ Task.current_task().upload_artifact(name='a_file', artifact_object='local_file.b Task.current_task().upload_artifact(name='numpy', artifact_object=np.ones(4,4)) ``` -Artifacts serve as a great way to pass and reuse data between tasks. Artifacts can be [retrieved](../../fundamentals/artifacts.md#using-artifacts) +Artifacts serve as a great way to pass and reuse data between tasks. Artifacts can be [retrieved](../../clearml_sdk/task_sdk.md#using-artifacts) by accessing the Task that created them. These artifacts can be modified and uploaded to other tasks. ```python diff --git a/docs/guides/reporting/explicit_reporting.md b/docs/guides/reporting/explicit_reporting.md index cdaeb262..d85bd3a4 100644 --- a/docs/guides/reporting/explicit_reporting.md +++ b/docs/guides/reporting/explicit_reporting.md @@ -298,5 +298,5 @@ python pytorch_mnist_tutorial.py ## Next Steps * See the [User Interface](../../webapp/webapp_overview.md) section to learn about its features. -* See the [ClearML Python Package Reference](../../clearml_sdk.md) to learn about +* See the [ClearML Python Package Reference](../../clearml_sdk/clearml_sdk.md) to learn about all the available classes and methods. \ No newline at end of file diff --git a/docs/guides/reporting/image_reporting.md b/docs/guides/reporting/image_reporting.md index 61b45e22..2f0b327e 100644 --- a/docs/guides/reporting/image_reporting.md +++ b/docs/guides/reporting/image_reporting.md @@ -12,7 +12,7 @@ demonstrates reporting (uploading) images in several formats, including: ClearML uploads images to the bucket specified in the ClearML [configuration file](../../configs/clearml_conf.md), or ClearML can be configured for image storage, see [Logger.set_default_upload_destination](../../references/sdk/logger.md#set_default_upload_destination) -(storage for [artifacts](../../fundamentals/artifacts.md#setting-upload-destination) is different). Set credentials for +(storage for [artifacts](../../clearml_sdk/task_sdk.md#setting-upload-destination) is different). Set credentials for storage in the ClearML configuration file. When the script runs, it creates an experiment named `image reporting`, which is associated with the `examples` project. diff --git a/docs/guides/reporting/media_reporting.md b/docs/guides/reporting/media_reporting.md index 4c5a14e6..0c680563 100644 --- a/docs/guides/reporting/media_reporting.md +++ b/docs/guides/reporting/media_reporting.md @@ -10,7 +10,7 @@ method to upload from: * URL of media already uploaded to some storage ClearML uploads media to the bucket specified in the ClearML configuration file or ClearML can be configured for image storage, see [Logger.set_default_upload_destination](../../references/sdk/logger.md#set_default_upload_destination) -(storage for [artifacts](../../fundamentals/artifacts.md#setting-upload-destination) is different). Set credentials for storage in the ClearML +(storage for [artifacts](../../clearml_sdk/task_sdk.md#setting-upload-destination) is different). Set credentials for storage in the ClearML [configuration file](../../configs/clearml_conf.md). ClearML reports media in the **ClearML Web UI** **>** experiment details **>** **RESULTS** tab **>** **DEBUG SAMPLES** diff --git a/docs/img/fundamentals_task_config_hyperparams.png b/docs/img/fundamentals_task_config_hyperparams.png new file mode 100644 index 0000000000000000000000000000000000000000..cf0cc43678219fe0260e2534efe6459274a59042 GIT binary patch literal 39670 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 literal 0 HcmV?d00001 diff --git a/docs/img/fundamentals_task_config_object.png b/docs/img/fundamentals_task_config_object.png new file mode 100644 index 0000000000000000000000000000000000000000..bd76e6bece3770329cef7ee2b1082ce5b7a47e1a GIT binary patch literal 54821 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 literal 0 HcmV?d00001 diff --git a/docs/img/fundamentals_task_config_properties.png b/docs/img/fundamentals_task_config_properties.png new file mode 100644 index 0000000000000000000000000000000000000000..843bab601409c28e85a666486c03c0de461ae8cd GIT binary patch literal 39473 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 literal 0 HcmV?d00001 diff --git a/docs/webapp/webapp_exp_table.md b/docs/webapp/webapp_exp_table.md index cef7bbaa..9dd6996f 100644 --- a/docs/webapp/webapp_exp_table.md +++ b/docs/webapp/webapp_exp_table.md @@ -28,7 +28,7 @@ The experiments table default and customizable columns are described in the foll | **TYPE** | Type of experiment. ClearML supports multiple [task types](../fundamentals/task.md#task-types) for experimentation, and a variety of workflows and use cases. | Default | | **NAME** | Experiment name. | Default | | **TAGS** | Descriptive, user-defined, color-coded tags assigned to experiments. Use tags to classify experiments, and filter the list. See [tagging experiments](webapp_exp_track_visual.md#tagging-experiments). | Default | -| **STATUS** | Experiment state (status). See a list of the [task states and state transitions](../fundamentals/task.md#task-states). If you programmatically set task progress values, you will also see a progress indicator for Running, Failed, and Aborted tasks. See [here](../fundamentals/task.md#tracking-task-progress). | Default | +| **STATUS** | Experiment state (status). See a list of the [task states and state transitions](../fundamentals/task.md#task-states). If you programmatically set task progress values, you will also see a progress indicator for Running, Failed, and Aborted tasks. See [here](../clearml_sdk/task_sdk.md#tracking-task-progress). | Default | | **PROJECT** | Name of experiment's project. | Default | | **USER** | User who created or cloned the experiment. | Default (hidden) | | **STARTED** | Elapsed time since the experiment started. To view the date and time of start, hover over the elapsed time. | Default | diff --git a/docs/webapp/webapp_exp_track_visual.md b/docs/webapp/webapp_exp_track_visual.md index 36421bec..011ef5c3 100644 --- a/docs/webapp/webapp_exp_track_visual.md +++ b/docs/webapp/webapp_exp_track_visual.md @@ -5,7 +5,7 @@ title: Tracking Experiments and Visualizing Results While an experiment is running, and any time after it finishes, track it and visualize the results in the ClearML Web UI, including: -* [Execution details](#execution-details) - Code, the base Docker image used for [ClearML Agent](../clearml_agent.md), output destination for artifacts, and the logging level. +* [Execution details](#execution) - Code, the base Docker image used for [ClearML Agent](../clearml_agent.md), output destination for artifacts, and the logging level. * [Configuration](#configuration) - Hyperparameters, user properties, and configuration objects. * [Artifacts](#artifacts) - Input model, output model, model snapshot locations, other artifacts. * [General information](#general-information) - Information about the experiment, for example: the experiment start, create, and last update times and dates, user creating the experiment, and its description. diff --git a/docs/webapp/webapp_profile.md b/docs/webapp/webapp_profile.md index be4bb7fc..b0e5be4b 100644 --- a/docs/webapp/webapp_profile.md +++ b/docs/webapp/webapp_profile.md @@ -236,7 +236,7 @@ and / or user groups have access permissions to the following workspace resource * [Projects](../fundamentals/projects.md) * [Tasks](../fundamentals/task.md) -* [Models](../fundamentals/artifacts.md#models) +* [Models](../fundamentals/artifacts.md) * [Dataviews](../hyperdatasets/dataviews.md) * [Datasets](../hyperdatasets/dataset.md) * [Queues](../fundamentals/agents_and_queues.md#what-is-a-queue) diff --git a/sidebars.js b/sidebars.js index 0d600ed6..73a8bf04 100644 --- a/sidebars.js +++ b/sidebars.js @@ -15,7 +15,7 @@ module.exports = { }, 'getting_started/architecture']}, {'ClearML Fundamentals': ['fundamentals/projects', 'fundamentals/task', 'fundamentals/hyperparameters', 'fundamentals/artifacts', 'fundamentals/logger', 'fundamentals/agents_and_queues', 'fundamentals/hpo']}, - 'clearml_sdk', + {'ClearML SDK': ['clearml_sdk/clearml_sdk', 'clearml_sdk/task_sdk', 'clearml_sdk/model_sdk']}, 'clearml_agent', {'ClearML Pipelines':['pipelines/pipelines', {"Building Pipelines":