Variable Naming#
Hypster provides sensible defaults for naming your variables to keep your code DRY (Don’t Repeat Yourself)
Explicit Naming#
You can explicitly name your variables using the name
parameter:
from hypster import HP, config
@config
def explicit_naming(hp: HP):
var = hp.select(["o1", "o2"], name="my_explicit_variable")
---------------------------------------------------------------------------
ModuleNotFoundError Traceback (most recent call last)
Cell In[1], line 1
----> 1 from hypster import HP, config
4 @config
5 def explicit_naming(hp: HP):
6 var = hp.select(["o1", "o2"], name="my_explicit_variable")
ModuleNotFoundError: No module named 'hypster'
Automatic Naming#
Hypster uses a name injection process to automatically name your hyperparameters. It’s important to understand how this works, especially if you have security concerns about code modification:
Source Code Modification: Hypster analyzes your configuration function’s source code and injects
name
keyword arguments into the hyperparameter calls (hp.select()
,hp.number()
, etc.).AST Transformation: This process uses Python’s Abstract Syntax Tree (AST) to modify the source code without changing its functionality.
Security Implications: While this process is designed to be safe, users with strict security requirements should be aware that it involves modifying and re-executing the source code.
Disabling Name Injection: If you prefer to avoid automatic name injection, you can disable it by using
@config(inject_names=False)
orload(..., inject_names=False)
. When disabled, you must provide explicit names for all hyperparameters.
Example of how name injection modifies your code:
from hypster import HP, config
# Original code
@config
def my_config(hp: HP):
model = hp.select(["cnn", "rnn"])
# Modified code (internal representation)
def my_config(hp: HP):
model = hp.select(["cnn", "rnn"], name="model")
Automatic Naming Rules#
Hypster automatically infers variable names by utilizing the variable names, dictionary keys, and keyword arguments:
Variable Names
Example:
a = hp.select(['option1', 'option2'])
Result: ‘a’ will be the name of this parameter
Dictionary Keys
Example:
config = {'learning_rate': hp.number(0.001)}
Result: The dictionary key ‘learning_rate’ will be the name of this parameter
Class and Function Keyword Arguments
Example:
Model(hidden_size=hp.select([64, 128, 256]))
Result: The keyword argument ‘hidden_size’ will be the name of this parameter
For nested structures, Hypster uses dot notation (key.nested_key)
to represent the hierarchy. For example:
model = Model(model_type=hp.select(['cnn', 'rnn']), # Automatically named 'model.model_type'
model_kwargs={'lr' : hp.number(0.1)} # Automatically named 'model.model_kwargs.lr'
)
Warning
Parameters are named based on the variable they’re assigned to, not the function or class name they’re associated with.
For example,
result = some_func(a = hp.select(...))
will be accessible asresult.a
, notsome_func.a
.
Example Use-Cases:#
Variable Assignment
@config
def automatic_naming(hp: HP):
# This will be automatically named 'var'
var = hp.select(["o1", "o2"])
# This will be automatically named 'model_type'
model_type = hp.select(["cnn", "rnn"])
Dictionary Keys:
@config
def dict_naming(hp: HP):
config = {
"model_type": hp.select(["cnn", "rnn"]), # Automatically named 'config.model_type'
"learning_rate": hp.number(0.001), # Automatically named 'config.learning_rate'
}
Class and function Keyword Arguments:
from hypster import HP, config
@config
def class_kwargs_naming(hp: HP):
# Note new class definitions (or imports) need to be inside the config function
class ModelConfig:
def __init__(self, model_type, learning_rate):
self.model_type = model_type
self.learning_rate = learning_rate
def func(param):
return
model = ModelConfig(
model_type=hp.select(["cnn", "rnn"]), # Automatically named 'model.model_type'
learning_rate=hp.number(0.001), # Automatically named 'model.learning_rate'
)
var = func(param=hp.select(["option1", "option2"])) # Automatically named 'var.param'
results = class_kwargs_naming(selections={"model.model_type": "cnn", "var.param": "option1"})
print(results["model"].model_type)
print(results["model"].learning_rate)
cnn
0.001
Disabling Automatic Naming#
In case you want to disable automatic naming and rely solely on explicit naming, you can do so by setting inject_names=False
:
from hypster import HP, config
@config(inject_names=False)
def class_kwargs_naming(hp: HP):
# Note new class definitions (or imports) need to be inside the config function
class ModelConfig:
def __init__(self, model_type, learning_rate):
self.model_type = model_type
self.learning_rate = learning_rate
def func(param):
return
model = ModelConfig(
model_type=hp.select(["cnn", "rnn"], name="model_type"),
learning_rate=hp.number(0.001, name="learning_rate"),
)
var = func(param=hp.select(["option1", "option2"], name="param"))
When automatic naming is disabled, you must provide explicit names for all hyperparameters. Failing to do so will result in an error:
@config(inject_names=False)
def no_injection_config(hp: HP):
a = hp.select(["a", "b"]) # This will raise an error because no name is provided
import logging
# Disable logging to prevent verbose output
logging.disable(logging.CRITICAL)
try:
no_injection_config()
print("If you see this, the error didn't occur as expected.")
except ValueError as e:
assert "`name` argument is missing" in str(e)
print("ValueError occurred as expected: `name` argument is missing")
ValueError occurred as expected: `name` argument is missing
Disabling automatic naming can be useful in scenarios where you want full control over parameter names, when the automatic naming might lead to ambiguities in your configuration, or when you have security concerns about source code modification.