Другое

Полное руководство: логирование вывода обучения SVC

Узнайте, как захватывать подробный вывод обучения sklearn.svm.SVC в файлы логов с помощью пакета wurlitzer. Полное руководство с примерами кода и лучшими практиками для надежного логирования.

Как сохранить подробный вывод (verbose output) при обучении модели sklearn.svm.SVC в файл журнала с использованием модуля logging Python

Подробный вывод при обучении sklearn.svm.SVC исходит из базовой библиотеки libsvm C, что означает, что стандартное ведение журналов Python не может его захватить напрямую. Наиболее эффективным решением является использование пакета wurlitzer для перехвата потоков stdout/stderr на уровне C и перенаправления их в файл журнала, хотя вы также можете захватить вывод через перенаправление subprocess или перенаправление stdout Python.

Содержание

Понимание проблемы

При установке verbose=True в sklearn.svm.SVC подробный вывод исходит из базовой библиотеки libsvm C, а не из кода Python. Это создает проблему, поскольку стандартные модули ведения журналов Python захватывают только вывод на уровне Python, а не потоки stdout/stderr на уровне C.

Подробный вывод обычно включает информацию такую как:

  • Количество опорных векторов (nSV)
  • Количество итераций (#iter)
  • Другие метрики оптимизации

Согласно объяснению на Cross Validated, настройка “verbose” “использует настройку времени выполнения на процесс в libsvm, которая, если включена, может работать некорректно в многопоточной среде.”


Решение с использованием пакета wurlitzer

Пакет wurlitzer специально разработан для захвата stdout/stderr на уровне C в Python путем использования os.dup2 для перенаправления потоков. Это рекомендуемый подход для захвата подробного вывода libsvm.

Установка и базовое использование

Сначала установите пакет:

bash
pip install wurlitzer

Базовая реализация

Вот как можно захватить подробный вывод SVC в файл с помощью wurlitzer:

python
import numpy as np
import sklearn
from sklearn.svm import SVC
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from wurlitzer import pipes

# Загрузка и подготовка данных
breast_data = load_breast_cancer()
X = breast_data.data
y = breast_data.target
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.33, random_state=0
)

# Создание модели SVC с подробным выводом
model = SVC(verbose=True)

# Захват вывода LibSVM в файл журнала
with open("svm_training.log", "w") as f, pipes(stdout=f, stderr=f):
    model.fit(X_train, y_train)

Как показано в ответе на Stack Overflow, этот подход “надежно захватывает как потоки C, так и Python” и является “самым чистым и надежным способом” решения этой конкретной задачи ведения журналов.


Альтернативные подходы для захвата вывода

Использование перенаправления stdout/stderr Python

Вы также можете перенаправить stdout/stderr Python для захвата подробного вывода:

python
import sys
from contextlib import redirect_stdout, redirect_stderr

model = SVC(verbose=True)

with open("svm_training.log", "w") as f:
    with redirect_stdout(f), redirect_stderr(f):
        model.fit(X_train, y_train)

Однако этот метод может не надежно захватывать весь вывод на уровне C, как отмечено в проблеме pygridtools, где говорится, что “работа с sys.stdout/sys.stdout в Python не решит” потоки на уровне C.

Подход с использованием Subprocess

Для более сложных сценариев вы можете запустить обучение в подпроцессе и захватить его вывод:

python
import subprocess
import sys
from sklearn.svm import SVC

# Запись скрипта обучения во временный файл
training_script = """
import numpy as np
from sklearn.svm import SVC
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split

# Загрузка и подготовка данных
breast_data = load_breast_cancer()
X = breast_data.data
y = breast_data.target
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.33, random_state=0
)

# Создание и обучение модели
model = SVC(verbose=True)
model.fit(X_train, y_train)
"""

# Запуск скрипта и захват вывода
with open("temp_training_script.py", "w") as f:
    f.write(training_script)

with open("svm_training.log", "w") as f:
    subprocess.run([sys.executable, "temp_training_script.py"], stdout=f, stderr=f)

Полный практический пример

Вот полный пример, демонстрирующий лучшие практики для ведения журналов обучения SVC:

python
import numpy as np
import logging
from sklearn.svm import SVC
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from wurlitzer import pipes
import os

# Настройка ведения журналов Python
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('python_app.log'),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger(__name__)

def train_svm_with_logging():
    """Обучение SVM с захватом подробного вывода в файл журнала"""
    
    # Загрузка и подготовка данных
    logger.info("Загрузка набора данных о раке молочной железы...")
    breast_data = load_breast_cancer()
    X = breast_data.data
    y = breast_data.target
    X_train, X_test, y_train, y_test = train_test_split(
        X, y, test_size=0.33, random_state=0
    )
    
    logger.info(f"Форма обучающих данных: {X_train.shape}")
    logger.info("Начало обучения SVM с подробным выводом...")
    
    # Создание модели SVC с подробным выводом
    model = SVC(verbose=True, kernel='rbf', C=1.0, gamma='scale')
    
    # Захват вывода LibSVM в файл с помощью wurlitzer
    with open("svm_training_verbose.log", "w") as f:
        with pipes(stdout=f, stderr=f):
            model.fit(X_train, y_train)
    
    logger.info("Обучение SVM успешно завершено!")
    
    # Оценка модели
    train_score = model.score(X_train, y_train)
    test_score = model.score(X_test, y_test)
    
    logger.info(f"Точность на обучающих данных: {train_score:.4f}")
    logger.info(f"Точность на тестовых данных: {test_score:.4f}")
    
    return model

# Запуск обучения
if __name__ == "__main__":
    trained_model = train_svm_with_logging()

Этот пример объединяет как ведение журналов Python, так и подход wurlitzer для создания comprehensive журналов, включающих как информацию на уровне приложения, так и подробный процесс оптимизации libsvm.


Понимание сокращений в подробном журнале

При включении подробного вывода вы увидите различные сокращения в журнале. Согласно обсуждению на Stack Overflow о сокращениях в подробном журнале, распространенные сокращения включают:

  • nSV: Количество опорных векторов
  • #iter: Количество итераций
  • nBSV: Количество ограниченных опорных векторов
  • rho: Смещение (bias term) в функции принятия решений
  • obj: Значение целевой функции

Вот пример того, как может выглядеть подробный вывод:

optimization finished, #iter = 127
obj = -85.123456, rho = 0.789012, nSV = 142, nBSV = 56
Total nSV = 142: 142 0

Понимание этих сокращений помогает отслеживать процесс обучения и выявлять потенциальные проблемы.


Лучшие практики и рекомендации

  1. Используйте wurlitzer для вывода на уровне C: Как рекомендовано в нескольких источниках, wurlitzer - самый надежный способ захвата подробного вывода libsvm.

  2. Комбинируйте с ведением журналов Python: Используйте и wurlitzer для подробных журналов обучения, и модуль ведения журналов Python для информации на уровне приложения.

  3. Управление файлами журналов: Вращайте файлы журналов, чтобы предотвратить их чрезмерный рост, особенно для долгих процессов обучения.

  4. Обработка ошибок: Добавьте правильную обработку ошибок вокруг кода обучения, чтобы гарантировать, что журналы будут правильно закрыты даже в случае сбоя обучения.

  5. Учитывайте время: Для очень больших наборов данных подробный вывод может быть обширным. Рассмотрите возможность добавления информации о времени для отслеживания прогресса.

  6. Учет среды: Помните, что wurlitzer лучше работает в однопоточных средах, как упоминается в источнике Cross Validated.

Репозиторий wurlitzer на GitHub предоставляет дополнительные примеры и документацию для более сложных случаев использования, включая интеграцию с IPython/Jupyter notebook.


Источники

  1. Ведение журнала обучения SVC/SVM в файл - Stack Overflow
  2. Репозиторий wurlitzer на GitHub - Захват stdout/stderr на уровне C в Python
  3. Что такое “Verbose” в пакете scikit-learn Python? - Cross Validated
  4. Значение сокращений в подробном журнале SVC, scikit-learn - Stack Overflow
  5. Запись подробного журнала scikit-learn во внешний файл - Stack Overflow
  6. Проблема pygridtools/drmaa-python о захвате вывода на уровне C
  7. Пакет wurlitzer на PyPI

Заключение

Захват подробного вывода при обучении sklearn.svm.SVC требует специальной обработки, поскольку вывод исходит из базовой библиотеки libsvm C. Пакет wurlitzer предоставляет наиболее надежное решение для захвата этого вывода в файл журнала. Хотя стандартное ведение журналов Python может захватывать информацию на уровне приложения, оно не может напрямую перехватывать потоки stdout/stderr на уровне C. Для comprehensive ведения журналов объедините wurlitzer с модулем ведения журналов Python для создания как подробных журналов оптимизации, так и информации более высокого уровня на уровне приложения. Помните о правильном управлении файлами журналов и учитывайте многопоточные последствия при работе с wurlitzer в многопоточных средах.

Авторы
Проверено модерацией
Модерация