Базовая структура
├── src
├── conf
├── config.yaml
└── data
└── model
├── distillbert.yaml
├── roberta.yaml
└── preprocessing
├── distillbert.yaml
├── roberta.yaml
└── secrets
├── example.yaml
├── .gitignore
└── training
├── distillbert.yaml
├── roberta.yaml
├── SA_example.py
Для начала нужно создать папку, содержащую файлы конфигураций. Название и локация этой папки внутри проекта могут быть произвольными, в нашем случае это будет src/conf
. Внутри неё каждая подпапка будет соответствовать отдельному направлению, или группе конфигураций, связанных с тем или иным аспектом проекта. Например, добавим папки data
, model
, preprocessing
, secrets
и training
для групп параметров, связанных с источниками данных, определением модели, предобработкой данных, параметрами авторизации и обучением модели соответственно. Папка secrets
будет хранить реквизиты для различных облачных сервисов, хранилищ данных и прочего. Поскольку для компоновки конфига при помощи Hydra нет необходимости явно перечислять множество параметров, достаточно добавать secrets
в локальный .gitignore
, чтобы получить удобный способ работать с конфиденциальными данными и не публиковать их в удаленном репозитории. Внутри каждой группы (папки) можно поместить произвольное число .yaml
-файлов, соответствующих различным вариантам настроек. Добавим набор параметров для простой предобработки текстовых данных (preprocessing/distillbert.yaml
, preprocessing/roberta.yaml
), параметры для инициализации моделей (model/distillbert.yaml
, model/roberta.yaml
), а также параметры обучения модели (training/distillbert.yaml
, training/roberta.yaml
), так что итоговое дерево файлов будет выглядеть следующим образом:
Приоритет параметров
conf/preprocessing/roberta.yaml
padding : max_length
tokenizer_name : siebert/sentiment-roberta-large-english
test_size : 5000
train_size : 20000
max_length : 256
defaults :
- preprocessing : distillbert
- training : distillbert
- model : distillbert
- secrets : example
- _self_
preprocessing :
test_size : 10000
train_size : 50000
max_length : 512
[2024-03-21 23:52:30,126][ __main__ ][ INFO ] - preprocessing:
padding: max_length
max_length: 512
tokenizer_name: siebert/sentiment-roberta-large-english
test_size: 10000
train_size: 50000
conf/preprocessing/roberta.yaml
padding : max_length
tokenizer_name : siebert/sentiment-roberta-large-english
test_size : 5000
train_size : 20000
max_length : 256
defaults :
- _self_
- preprocessing : distillbert
- training : distillbert
- model : distillbert
- secrets : example
preprocessing :
test_size : 10000
train_size : 50000
max_length : 512
[2024-03-21 23:52:30,126][ __main__ ][ INFO ] - preprocessing:
test_size: 5000
train_size: 20000
max_length: 256
padding: max_length
tokenizer_name: siebert/sentiment-roberta-large-english
В главном конфиге можно указывать не только дефолтные группы, но и отдельные параметры ровно так же, как и в дочерних конфигах. В случае, когда имя параметра в главном конфиге совпадает с именем параметра в дочернем, результирующее значение параметра определяется по местонахождению поля _self_
:
если оно указано в конце списка defaults
, то будет использовано значение из src/conf
если оно указано в начале списка defaults
, то будет использовано значение из src/conf/*/*.yaml
Модель RoBERTa обладает бОльшим числом параметров, поэтому (в учебных целях) разумно уменьшить для неё максимальную длину входных последовательностей (в токенах), а также размеры тестовой и обучающей выборок, ускорив таким образом время обучения и инференса. Заметим, что в conf/preprocessing/roberta.yaml
указаны отличные от главного конфига значения параметров max_length
, test_size
, train_size
.
В примере слева параметр max_length
определен как в главном конфиге (512), так и в conf/preprocessing/roberta.yaml
(256), а поскольку _self_
указано в конце списка дефолтных параметров, будет использовано значение 512.
В примере справа итоговым значением будет выбрано 256.
То же относительно остальных двух параметров.
hydra_main(), запуск .py-модулей из терминала
@hydra.main (version_base= None , config_path= "src/conf" , config_name= "config" )
def main(cfg: DictConfig):
param = cfg["group_name" ]["param" ]
# some logic with param...
Интеграция Hydra в python-модуль осуществляется при помощи декоратора hydra_main()
, который принимает в качестве параметров путь до папки с конфигурациями (относительно вызываемого модуля) и название главного файла конфигурации без указания расширения -.yaml
(то есть, в нашем случае, config
). Декоратор скомпонует параметры дефолтных групп главного конфига и свои собственные, считает их, и вернет в виде объекта DictConfig
билиотеки OmegaConf
.
Инициализация объектов
from hydra.utils import instantiate
model = instantiate(confifg['model' ])
_target_ : transformers.AutoModelForSequenceClassification.from_pretrained
_convert_ : object
pretrained_model_name_or_path : lxyuan/distilbert-base-multilingual-cased-sentiments-student
problem_type : single_label_classification
num_labels : 2
ignore_mismatched_sizes : True
При создании файла конфигурации можно воспользоваться полем _target_
, указав его значением экземпляр класса или вызываемый объект (callable). При этом остальные поля, указанные на том же уровне, будут использованы как параметры при инициализации класса. Отдельно импортировать этот класс в самом python-модуле не нужно, достаточно воспользоваться методом instantiate()
. В некоторых случаях может понадобиться также дополнительное поле _convert_
, определяющее, как instantiate
будет обращаться с параметрами класса, не указанными в конфиге, а передаваемыми в runtime: конвертировать их в OmegaConf
-контейнер полностью (None), частично (partial), или же вообще не конвертировать (object).
Итог
Прежде всего, Hydra — удобный инструмент для организации множества файлов с параметрами в единую конфигурацию, который упрощает процесс разработки и исследований.
Механизмы, перечисленные выше, хотя и предоставляют дополнительные возможности (логирование, multirun, параллельный запуск и оптимизация), являются опциональными и лишь дополняют основное предназначение.