Base class for configurations, all configuration must inherit from this class. For a in depth tutorial about configs, head over Configurations
Important
Models are not coupled with Config
, therefore they are unaware of the configuration system. Each Config
is linked to a specific model, not viceversa.
Note
A Config
holds what is needed to create a model. Therefore, they are perfect to share custom version of a specific architecture. A Config
is data container. Thus, it must not have any side effect, any logic that requires the Config
values to be somehow processed must be implemented in the Config.build
function.
A custom configuration can be written as follows:
from glasses.config import Config
# Assume we have a model
class MyModel(nn.Module):
def __init__(in_channels: int, out_channels: int):
super().__init__()
self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=1)
def forward(self, x):
return self.conv(x)
# Let's create it's configuration
@dataclass
class MyConfig(Config):
in_channels: int
out_channels: int
def build(self) -> nn.Module:
# create a `MyModel` instance using `MyConfig`
return MyModel(**self.__dict__)
model: MyModel = MyConfig(2, 2).build()
Each Config is linked to a specific model, not viceversa. Models had no idea about the configuration system and can be created normally as you expect with their constructor.
Nested Configurations
Source code in glasses/config/__init__.py
| @dataclass
class Config:
"""
Base class for configurations, all configuration **must** inherit from this class. For a in depth tutorial about configs, head over [Configurations](/)
!!! important
Models are not coupled with `Config`, therefore they are unaware of the configuration system. Each `Config` is linked to a specific model, not viceversa.
!!! note
A `Config` holds what is needed to create a model. Therefore, they are perfect to share custom version of a specific architecture. A `Config` is **data container**. Thus, it **must not have any side effect**, any logic that requires the `Config` values to be somehow processed must be implemented in the [`Config.build`](#glasses.config.Config.build) function.
A custom configuration can be written as follows:
```python
from glasses.config import Config
# Assume we have a model
class MyModel(nn.Module):
def __init__(in_channels: int, out_channels: int):
super().__init__()
self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=1)
def forward(self, x):
return self.conv(x)
# Let's create it's configuration
@dataclass
class MyConfig(Config):
in_channels: int
out_channels: int
def build(self) -> nn.Module:
# create a `MyModel` instance using `MyConfig`
return MyModel(**self.__dict__)
model: MyModel = MyConfig(2, 2).build()
```
Each Config is linked to a specific model, not viceversa. Models had no idea about the configuration system and can be created normally as you expect with their constructor.
## Nested Configurations
"""
def build(self) -> nn.Module:
raise NotImplementedError
def panel(self) -> Panel:
table = Table(
title=self.__class__.__name__,
box=box.SIMPLE,
show_header=False,
highlight=True,
)
for key, val in self.__dict__.items():
# if one field is a Config instance
if isinstance(val, Config):
table.add_row("", "")
table.add_row(f"[bold]{key}", val.panel())
else:
table.add_row(key, str(val))
return Panel(table)
def summary(self):
console = Console()
console.print(self.panel(), justify="left")
|