Вопрос или проблема
Как передать несколько значений каждому параметру в команде mlflow run?
Цель состоит в том, чтобы передать словарь в GridSearchCV в качестве param_grid для выполнения перекрестной проверки.
В моем основном коде я получаю параметры командной строки с помощью argparse. Добавляя nargs=”+” в add_argument(), я могу записывать значения с пробелами для каждого гиперпараметра, а затем применить vars() для создания словаря. См. код ниже:
import argparse
# Создайте параметры для командной строки
param_names = list(RandomForestClassifier().get_params().keys())
# Типы параметров в том же порядке, в котором они появлются в param_names, используя get_params()
param_types = [bool, float, dict, str, int, float, int, float, float, float,
float, float, float, int, int, bool, int, int, bool]
# Разрешить только необязательные аргументы командной строки
parser = argparse.ArgumentParser()
grid_group = parser.add_argument_group('param_grid_group')
for i, p in enumerate(param_names):
grid_group.add_argument(f'--{p}', type=param_types[i], nargs="+")
# Создайте param_grid для передачи в GridSearchCV
param_grid_unprocessed = vars(parser.parse_args())
Это хорошо работает с классической командой python :
python my_code.py --max_depth 2 3 4 --n_estimators 400 600 1000
Как я сказал, здесь я могу просто написать значения через пробел для каждого гиперпараметра, и код выше делает магию, группируя значения внутри списка и возвращая словарь ниже, который затем я могу передать в GridSearchCV :
{'max_depth':[2, 3, 4], 'n_estimators':[400, 600, 1000]}
Однако с командой mlflow run я пока не могу это сделать, так как она принимает только одно значение для каждого параметра. Вот мой файл MLproject :
name: mlflow_project
conda_env: conda.yml
entry_points:
main:
parameters:
max_depth: int
n_estimators: int
command: "python my_code.py --max_depth {max_depth} --n_estimators {n_estimators}"
Так что это работает :
mlflow run . -P max_depth=2 -P n_estimators=400
Но не это :
mlflow run . -P max_depth=[2, 3, 4] -P n_estimators=[400, 600, 1000]
В документации кажется, что это невозможно сделать. Есть ли какой-либо способ обойти эту проблему?
Один из вариантов – перейти с argparse
на fire
. Fire – это сторонний пакет Python для создания интерфейсов командной строки (CLI). Fire имеет лучшую поддержку для группировки команд.
Ответ или решение
Чтобы передать несколько значений для одного параметра при использовании команды mlflow run
, необходимо учитывать ограничения, связанные с тем, как mlflow обрабатывает параметры. В вашей ситуации вы хотите передать массив значений для гиперпараметров, используемых в GridSearchCV
. В данном ответе мы рассмотрим, как это можно обойти с использованием альтернативных подходов к сбору параметров и выполнению запуска.
Проблема
Команда mlflow run
не поддерживает передачу массивов через параметры, так как принимает только одно значение для каждого параметра. Ваш код с использованием argparse
работает хорошо для классического запуска, но не может адаптироваться под ограничения mlflow
.
Решение
-
Использование JSON для передачи списков
Один из способов обойти это ограничение – передать параметры в формате JSON. В вашем MLproject файле вам нужно будет изменить способ передачи параметров, чтобы он принимал строку и разбирал её в коде:name: mlflow_project conda_env: conda.yml entry_points: main: parameters: max_depth: str n_estimators: str command: "python my_code.py --max_depth {max_depth} --n_estimators {n_estimators}"
Затем в вашем коде, используя
argparse
, вы можете разбирать эти строки в списки:import argparse import json parser = argparse.ArgumentParser() grid_group = parser.add_argument_group('param_grid_group') grid_group.add_argument('--max_depth', type=str) grid_group.add_argument('--n_estimators', type=str) params = vars(parser.parse_args()) max_depth = json.loads(params['max_depth']) n_estimators = json.loads(params['n_estimators']) param_grid = { 'max_depth': max_depth, 'n_estimators': n_estimators }
Теперь вы можете вызывать команду
mlflow run
, передавая значения в формате JSON:mlflow run . -P max_depth='[2, 3, 4]' -P n_estimators='[400, 600, 1000]'
-
Использование несколько запусков mlflow
В зависимости от ваших требований, возможно, имеет смысл запускать командуmlflow run
несколько раз (например, используя скрипт), чтобы перебрать комбинации параметров. Например:from itertools import product depths = [2, 3, 4] estimators = [400, 600, 1000] for depth, estimator in product(depths, estimators): command = f"mlflow run . -P max_depth={depth} -P n_estimators={estimator}" os.system(command)
-
Использование сторонних библиотек
Как вы уже упомянули, вы можете рассмотреть возможность использования библиотеки, такой какFire
, для упрощения работы с CLI.Fire
позволяет автоматически создавать командные интерфейсы из объектов Python и лучше обрабатывает такие структуры данных, как списки.
Заключение
Передача нескольких значений для одного параметра в mlflow run
требует определенных обходных путей. Используя формат JSON, перебор комбинаций параметров или сторонние библиотеки, вы можете эффективно использовать гибкость, необходимую для вашего проекта машинного обучения. Важно протестировать выбранный метод, чтобы убедиться в его работоспособности и производительности в рамках вашей задачи.