Log parameters and model configuration
You can define a namespace for storing parameters, hyperparameters, configs, or other single values.
In the below examples, the parameters are stored in a namespace called parameters
. Inside that namespace, an attribute is created for each parameter.
from neptune_scale import Run
if __name__ == "__main__":
run = Run(experiment_name=...)
run.log_configs(
{
"parameters/learning_rate": 0.001,
"parameters/batch_size": 64,
},
)
You can find your logged configs in the Attributes section of the run.
Logging nested dictionaries
To log nested dictionaries to a Neptune run, use the following helper function to flatten the values:
def flatten_nested(d, parent_key="", sep="/"):
items = {}
if isinstance(d, dict):
for k, v in d.items():
new_key = f"{parent_key}{sep}{k}" if parent_key else k
if isinstance(v, (dict, list, tuple, set)):
items.update(flatten_nested(v, new_key, sep=sep))
else:
items[new_key] = v
elif isinstance(d, (list, tuple, set)):
for i, v in enumerate(d):
new_key = f"{parent_key}{sep}{i}" if parent_key else str(i)
if isinstance(v, (dict, list, tuple, set)):
items.update(flatten_nested(v, new_key, sep=sep))
else:
items[new_key] = v
else:
return d
return items
Then pass the flattened dictionary to the log_configs()
function:
nested_data = {
"config": {
"learning_rate": 0.001,
},
"metrics": {
"token_count": 76420,
"agg": {
"loss": 0.13,
"acc": 0.97,
}
},
}
if __name__ == "__main__":
run = Run(experiment_name=...)
flattened_data = flatten_nested(nested_data)
run.log_configs(data=flattened_data)
You'll get a similar nested structure in the resulting Neptune run:
run/
|-- config/
|-- learning_rate
|-- metrics/
|-- token_count
|-- agg/
|-- loss
|-- acc
Converting unsupported values
If your dictionary contains data types that Neptune doesn't support, you must convert the values to strings before logging them.
See an example function
def flatten_and_stringify_unsupported(d, parent_key="", sep="/"):
SUPPORTED_DATATYPES = [int, float, str, datetime, bool, list, set]
items = {}
if not isinstance(d, (dict, list, tuple, set)):
return d if type(d) in SUPPORTED_DATATYPES else str(d)
if isinstance(d, dict):
for k, v in d.items():
new_key = f"{parent_key}{sep}{k}" if parent_key else k
if isinstance(v, (dict, list, tuple, set)):
items |= stringify_unsupported(v, new_key, sep=sep)
else:
items[new_key] = v if type(v) in SUPPORTED_DATATYPES else str(v)
elif isinstance(d, (list, tuple, set)):
for i, v in enumerate(d):
new_key = f"{parent_key}{sep}{i}" if parent_key else str(i)
if isinstance(v, (dict, list, tuple, set)):
items.update(stringify_unsupported(v, new_key, sep=sep))
else:
items[new_key] = v if type(v) in SUPPORTED_DATATYPES else str(v)
return items
Viewing configs in the app
You can compare configs, scores, and other metadata in the experiments table, side-by-side tab, and custom dashboards.