如何使用AutoSklearn避免根日志记录器被修改?
如何避免AutoSklearn修改根日志记录器?
问题描述
调用AutoSklearn的.fit()方法后,项目的根日志记录器格式和行为被意外修改,即使在实例化AutoML对象时配置logging_configuration参数也无法解决问题。
最小复现代码
import logging import autosklearn.regression AUTOML_CONFIG = dict(time_left_for_this_task=30, per_run_time_limit=10, memory_limit=None, n_jobs=1) x=[1, 2, 3, 4] y=[1, 2, 3, 4] logging.basicConfig(level=logging.INFO, format="%(asctime)s %(name)s %(levelname)s:%(message)s") logging.info("Initial") automl = autosklearn.regression.AutoSklearnRegressor(**AUTOML_CONFIG) logging.info("Create object") automl.fit(x,y) logging.info("Finished training") logging.warning("Finished training")
预期输出
2022-08-10 14:06:13,635 root INFO:Initial 2022-08-10 14:06:13,635 root INFO:Create object 2022-08-10 14:06:13,635 root INFO:Finished training 2022-08-10 14:06:13,635 root WARNING:Finished training
实际输出
2022-08-10 14:06:13,635 root INFO:Initial 2022-08-10 14:06:13,635 root INFO:Create object [WARNING] [2022-08-10 14:06:41,523:root] Finished training
解决方法
方法1:使用自定义项目日志器(推荐)
避免直接使用根日志器,创建专属的项目日志记录器,关闭日志传递到根日志器的功能,彻底隔离AutoSklearn的日志修改。
import logging import autosklearn.regression # 创建并配置项目专属日志器 project_logger = logging.getLogger("my_project") project_logger.setLevel(logging.INFO) # 设置日志格式 formatter = logging.Formatter("%(asctime)s %(name)s %(levelname)s:%(message)s") stream_handler = logging.StreamHandler() stream_handler.setFormatter(formatter) project_logger.addHandler(stream_handler) # 禁止日志传递到根日志器,避免被AutoSklearn修改 project_logger.propagate = False AUTOML_CONFIG = dict(time_left_for_this_task=30, per_run_time_limit=10, memory_limit=None, n_jobs=1) x=[1, 2, 3, 4] y=[1, 2, 3, 4] project_logger.info("Initial") automl = autosklearn.regression.AutoSklearnRegressor(**AUTOML_CONFIG) project_logger.info("Create object") automl.fit(x,y) project_logger.info("Finished training") project_logger.warning("Finished training")
方法2:保存并恢复根日志器配置
在调用.fit()前后,手动保存根日志器的原有配置(处理器、日志级别、格式),训练完成后恢复这些配置,抵消AutoSklearn的修改。
import logging import autosklearn.regression AUTOML_CONFIG = dict(time_left_for_this_task=30, per_run_time_limit=10, memory_limit=None, n_jobs=1) x=[1, 2, 3, 4] y=[1, 2, 3, 4] # 初始化根日志器 logging.basicConfig(level=logging.INFO, format="%(asctime)s %(name)s %(levelname)s:%(message)s") logging.info("Initial") automl = autosklearn.regression.AutoSklearnRegressor(**AUTOML_CONFIG) logging.info("Create object") # 保存根日志器的原始配置 root_logger = logging.getLogger() original_handlers = root_logger.handlers.copy() original_level = root_logger.level original_formatters = [handler.formatter for handler in original_handlers] # 执行训练 automl.fit(x, y) # 恢复根日志器的原始配置 root_logger.handlers = original_handlers root_logger.setLevel(original_level) for handler, formatter in zip(root_logger.handlers, original_formatters): handler.setFormatter(formatter) # 输出日志验证 logging.info("Finished training") logging.warning("Finished training")
方法3:配置AutoSklearn使用独立日志器
通过logging_configuration参数指定AutoSklearn使用自己的日志命名空间,避免影响根日志器。注意部分版本的AutoSklearn可能存在内部逻辑仍修改根日志器的情况,需结合前两种方法使用。
import logging import autosklearn.regression # 配置AutoSklearn的日志隔离 automl_log_config = { "version": 1, "disable_existing_loggers": False, "loggers": { "autosklearn": { "level": "INFO", "handlers": ["console"], "propagate": False } }, "handlers": { "console": { "class": "logging.StreamHandler", "formatter": "autosklearn_formatter" } }, "formatters": { "autosklearn_formatter": { "format": "[%(levelname)s] [%(asctime)s:%(name)s] %(message)s" } } } AUTOML_CONFIG = dict( time_left_for_this_task=30, per_run_time_limit=10, memory_limit=None, n_jobs=1, logging_configuration=automl_log_config ) # 初始化项目根日志器 logging.basicConfig(level=logging.INFO, format="%(asctime)s %(name)s %(levelname)s:%(message)s") x=[1, 2, 3, 4] y=[1, 2, 3, 4] logging.info("Initial") automl = autosklearn.regression.AutoSklearnRegressor(**AUTOML_CONFIG) logging.info("Create object") automl.fit(x,y) logging.info("Finished training") logging.warning("Finished training")
内容的提问来源于stack exchange,提问作者Sergei I
相关产品推荐
相关产品推荐

