# Parameters

Metric hyperparameters, configuration values, and experiment settings. Parameters are static key-value pairs that define your experiment.

## Basic Usage

```python

from ml_dash import Experiment

with Experiment(prefix="alice/project/my-experiment").run as exp:
    exp.params.set(
        learning_rate=0.001,
        batch_size=32,
        optimizer="adam",
        epochs=100
    )
```

## Nested Parameters

Use nested dictionaries - they're automatically flattened with dot notation:

```python

with Experiment(prefix="alice/project/my-experiment").run as exp:
    exp.params.set(
        model={
            "architecture": "resnet50",
            "pretrained": True,
            "num_classes": 1000
        },
        optimizer={
            "type": "adam",
            "lr": 0.001,
            "weight_decay": 0.0001
        }
    )

    # Stored as:
    # model.architecture = "resnet50"
    # model.pretrained = True
    # optimizer.type = "adam"
    # ...
```

## Class Objects Support

Pass configuration classes directly (perfect for `params-proto`):

```python

class TrainingConfig:
    learning_rate = 0.001
    batch_size = 32
    epochs = 100

class ModelConfig:
    architecture = "resnet50"
    hidden_size = 768

with Experiment(prefix="alice/project/my-experiment").run as exp:
    # Pass class objects directly
    exp.params.log(training=TrainingConfig, model=ModelConfig)

    # Stored as:
    # training.learning_rate = 0.001
    # training.batch_size = 32
    # training.epochs = 100
    # model.architecture = "resnet50"
    # model.hidden_size = 768
```

Private attributes (starting with `_`) are automatically skipped.

## Updating Parameters

Call `exp.params.set()` multiple times - values merge and overwrite:

```python

with Experiment(prefix="alice/project/my-experiment").run as exp:
    # Initial parameters
    exp.params.set(learning_rate=0.001, batch_size=32)

    # Add more
    exp.params.set(optimizer="adam", momentum=0.9)

    # Update existing
    exp.params.set(learning_rate=0.0001)

    # Final result:
    # learning_rate = 0.0001  (updated)
    # batch_size = 32
    # optimizer = "adam"
    # momentum = 0.9
```

## Loading from Config Files

**From JSON:**

```python

import json
from ml_dash import Experiment

with open("config.json", "r") as f:
    config = json.load(f)

with Experiment(prefix="alice/project/my-experiment").run as exp:
    exp.params.set(**config)
    exp.log("Configuration loaded")
```

**From command line arguments:**

```python

import argparse
from ml_dash import Experiment

parser = argparse.ArgumentParser()
parser.add_argument("--lr", type=float, default=0.001)
parser.add_argument("--batch-size", type=int, default=32)
args = parser.parse_args()

with Experiment(prefix="alice/project/my-experiment").run as exp:
    exp.params.set(**vars(args))
```

**From dataclass:**

```python

from dataclasses import dataclass, asdict
from ml_dash import Experiment

@dataclass
class TrainingConfig:
    learning_rate: float = 0.001
    batch_size: int = 32
    epochs: int = 100

config = TrainingConfig()

with Experiment(prefix="alice/project/my-experiment").run as exp:
    exp.params.set(**asdict(config))
```

**From params-proto (or any class):**

```python

from ml_dash import Experiment

# Works with params_proto or any Python class
class Args:
    batch_size = 64
    learning_rate = 0.001

with Experiment(prefix="alice/project/my-experiment").run as exp:
    # Pass class directly - automatically extracts attributes
    exp.params.log(Args=Args)
```

## Complete Training Configuration

```python

with Experiment(prefix="alice/cv/resnet-imagenet").run as exp:
    exp.params.set(**{
        "model": {
            "architecture": "resnet50",
            "pretrained": True,
            "num_classes": 1000
        },
        "data": {
            "dataset": "imagenet",
            "train_split": 0.8,
            "num_workers": 4
        },
        "training": {
            "epochs": 100,
            "batch_size": 256,
            "learning_rate": 0.1,
            "optimizer": "sgd",
            "momentum": 0.9
        }
    })
```

## Retrieving Parameters

Get parameters during or after an experiment:

```python

with Experiment(prefix="alice/project/my-experiment").run as exp:
    exp.params.set(learning_rate=0.001, batch_size=32)

    # Retrieve flattened parameters
    params = exp.params.get()
    print(params)
    # → {"learning_rate": 0.001, "batch_size": 32}

    # Retrieve as nested dictionary
    params_nested = exp.params.get(flatten=False)
    print(params_nested)
    # → {"learning_rate": 0.001, "batch_size": 32}
```

## API Methods

### `set()` / `log()`

Both methods do the same thing - set or merge parameters:

- **Nested dicts** are automatically flattened to dot notation
- **Class objects** are converted to dictionaries by extracting their attributes
- **Multiple calls** merge parameters (later values override earlier ones)
- Returns self for potential chaining

The `log()` method exists for semantic clarity but behaves identically to `set()`.

### `get()`

Retrieve current parameters:

- **`flatten=True` (default)**: Returns flattened dict with dot notation
- **`flatten=False`**: Returns nested dict structure

## Storage Format

**Local mode** - Stored as JSON:

```bash
cat .dash/alice/project/my-experiment/parameters.json
```

The flattened parameters sit under `"data"`:

```json
{
  "version": 1,
  "data": {
    "learning_rate": 0.001,
    "batch_size": 32,
    "optimizer": "adam",
    "model.architecture": "resnet50",
    "model.pretrained": true
  },
  "createdAt": "2025-10-29T10:30:00.000000Z",
  "updatedAt": "2025-10-29T10:30:00.000000Z"
}
```

**Remote mode** - Stored in MongoDB as a document.

---

**Next:** Learn about [Metrics](/guides/metrics.md) for time-series metrics tracking.
