Оценка и уменьшение длительности тренировки моделей на Python

Раздел: Машинное обучение и ИИ -> scikit-learn

Измерение и сокращение времени обучения моделей Scikit-learn

Как получить наиболее точную оценку времени обучения модели в Scikit-learn?

Основной подход - многократный замер времени с помощью модуля timeit, который автоматически отключает сборщик мусора и минимизирует влияние внешних факторов. Для одной модели достаточно выполнить несколько повторений и вычислить среднее и стандартное отклонение.

import timeit
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import make_classification

X, y = make_classification(n_samples=1000, n_features=20, random_state=42)
model = RandomForestClassifier(n_estimators=100, random_state=42)

# Замер времени выполнения (7 повторений)
stmt = 'model.fit(X, y)'
setup = 'from __main__ import model, X, y'
times = timeit.repeat(stmt, setup, number=1, repeat=7)
print(f'Среднее: {sum(times)/len(times):.4f} сек, стд: {np.std(times):.4f}')

библиотеки для машинного обучения python (библиотеки для машинного обучения в python (scikit-learn, tensorflow, pytorch))

Среднее: 0.3245 сек, стд: 0.0123

задачи машинного обучения python (задачи машинного обучения на python)

Типичные ошибки: забыть передать number=1 (тогда замеряется время одного вызова, но повторяется много раз), или использовать time.time() без усреднения. Также следует учитывать, что первый запуск может включать компиляцию JIT-кода (если используется Numba) - его лучше исключить прогревочным запуском.

Как измерить время обучения с помощью time.time()?

Самый простой способ - засечь время до и после вызова fit(). Однако этот метод чувствителен к фоновым процессам и не позволяет усреднить результат. Пример:

import time
start = time.time()
model.fit(X, y)
elapsed = time.time() - start
print(f'Время обучения: {elapsed:.4f} сек')

Feature names python (имена признаков в python)

Время обучения: 0.3251 сек

искусственный интеллект на языке python (искусственный интеллект на python)

Проблема: однократный замер может быть неточным из-за планировщика ОС или срабатывания сборщика мусора. Решение - выполнить несколько замеров и взять минимум или среднее.

Как профилировать время обучения с помощью cProfile?

Когда нужно понять, какие этапы обучения занимают больше всего времени, удобно использовать модуль cProfile. Он поставляется со стандартной библиотекой Python и показывает время вызова каждой функции.

import cProfile, pstats
from sklearn.svm import SVC

profiler = cProfile.Profile()
profiler.enable()
svm = SVC(kernel='rbf').fit(X[:500], y[:500])
profiler.disable()

stats = pstats.Stats(profiler).sort_stats('cumtime')
stats.print_stats(15)

Python model (модели в python (машинное обучение))

         1042 function calls in 0.542 seconds
   Ordered by: cumulative time
   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.003    0.003    0.542    0.542 <string>:1(<module>)
        1    0.005    0.005    0.539    0.539 ...\svm.py:453(fit)
        1    0.102    0.102    0.102    0.102 ...\svm.py:315(_dense_fit)
       ...

статистическая библиотека python (статистическая библиотека python (scipy, statsmodels))

Ошибки: профилирование сильно замедляет выполнение (может в 10-100 раз). Для точных замеров лучше использовать timeit, а профилировщик - для поиска узких мест. Также не рекомендуется профилировать очень короткие операции.

Как ускорить обучение за счёт параллельных вычислений?

Многие модели Scikit-learn поддерживают параметр n_jobs, который задаёт число потоков для параллельной обработки. Например, RandomForest, GradientBoosting, GridSearchCV. Оптимальное значение часто равно числу ядер CPU (или -1 для всех ядер).

from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier(n_estimators=200, n_jobs=-1, random_state=42)
# Замер времени с n_jobs=-1
stmt = 'model.fit(X, y)'
time_parallel = timeit.timeit(stmt, setup, number=3) / 3
print(f'С параллелизацией: {time_parallel:.4f} сек')

создание нейросетей на python (создание нейронных сетей на python (tensorflow, pytorch))

С параллелизацией: 0.1567 сек

Ai script python (скрипты для искусственного интеллекта на python)

Проблемы: некоторые модели (SVM, линейные) не распараллеливаются, а для деревьев слишком большой n_jobs может вызвать перегрузку памяти и замедление из-за накладных расходов на синхронизацию. Лучше начинать с n_jobs=2 и увеличивать постепенно.

Как уменьшить время обучения за счёт уменьшения объёма данных?

Для больших датасетов имеет смысл использовать стратифицированную выборку или кластеризацию для построения прототипа модели. Пример со стратифицированной выборкой:

from sklearn.model_selection import train_test_split
# Стратифицированная выборка 20% данных
X_sub, _, y_sub, _ = train_test_split(X, y, train_size=0.2, stratify=y, random_state=42)
model.fit(X_sub, y_sub)

Random forest python (random forest в python)

Время обучения: 0.0654 сек

Python время обучения (время обучения модели в python)

Риск: снижение качества модели. Способ коррекции - обучить полную модель только на лучших гиперпараметрах, найденных на подвыборке.

Как использовать инкрементное обучение (partial_fit)?

Метод partial_fit позволяет обучать модель порциями, что снижает пиковое потребление памяти и иногда ускоряет сходимость. Поддерживается в SGDClassifier, SGDRegressor, PassiveAggressiveClassifier, а также в некоторых моделях из sklearn.neural_network.

from sklearn.linear_model import SGDClassifier
model = SGDClassifier(loss='log', random_state=42)
chunk_size = 200
for i in range(0, len(X), chunk_size):
    model.partial_fit(X[i:i+chunk_size], y[i:i+chunk_size], classes=[0,1])

машинное обучение на данных python (машинное обучение на данных с помощью python)

Проблемы: не все модели поддерживают partial_fit, и для стохастических методов нужно правильно выбирать learning rate. Также инкрементное обучение может оказаться медленнее, если порции слишком малы.

Как ускорить обучение с помощью GPU (cuML)?

Библиотека cuML (от RAPIDS) реализует алгоритмы Scikit-learn на CUDA. Для работы требуется совместимый GPU и установленные драйверы. Пример с RandomForest:

# установка: pip install cuml-cu11
from cuml.ensemble import RandomForestClassifier as cumlRF
cuml_model = cumlRF(n_estimators=100)
cuml_model.fit(X, y)

нейросеть python (нейросеть на python)

Время обучения: 0.0234 сек (на GPU)

Ошибки: несовместимость версий (cuDF, cudf), отсутствие GPU или недостаток памяти. Также cuML не поддерживает все модели и может давать незначительные отличия в результатах из-за численных методов.

- рекомендательная система python (разработка рекомендательной системы на python)
- библиотека scikit python (библиотека scikit-learn для python)

Расширенные примеры измерения и оптимизации времени обучения

Пример 1. Замер времени обучения с автоматическим отбрасыванием выбросов

Используем timeit.repeat и отбрасываем самый быстрый и самый медленный замеры для повышения робастности.

Пример
import timeit, numpy as np
from sklearn.linear_model import LogisticRegression

X_big, y_big = make_classification(n_samples=5000, n_features=50)
model = LogisticRegression(max_iter=1000, solver='lbfgs')

def time_model(model, X, y, repeat=10):
    stmt = 'model.fit(X, y)'
    setup = 'from __main__ import model, X, y'
    times = timeit.repeat(stmt, setup, number=1, repeat=repeat)
    times = sorted(times)[1:-1]  # отбрасываем min и max
    return np.mean(times), np.std(times)

mean_time, std_time = time_model(model, X_big, y_big, repeat=10)
print(f'Усреднённое время: {mean_time:.4f} ± {std_time:.4f} сек')
Усреднённое время: 0.5123 ± 0.0142 сек

Пример 2. Профилирование обучения с визуализацией через snakeviz

Сначала сохраняем профиль в файл, затем открываем его в браузере с помощью snakeviz.

Пример
import cProfile
import pstats
import sklearn

prof = cProfile.Profile()
prof.enable()
knn = sklearn.neighbors.KNeighborsClassifier(n_neighbors=5).fit(X_big, y_big)
prof.disable()

# Сохраняем результат
prof.dump_stats('knn_profile.prof')
# В командной строке: snakeviz knn_profile.prof
Откроется интерактивный график вызовов.

Пример 3. Параллельный GridSearchCV с таймингом каждой комбинации

Чтобы оценить время полного перебора гиперпараметров, можно использовать RandomizedSearchCV с параллелизацией и логированием.

Пример
from sklearn.model_selection import RandomizedSearchCV
from sklearn.ensemble import GradientBoostingClassifier
import time

gbm = GradientBoostingClassifier(random_state=42)
param_dist = {'max_depth': [3,5,7], 'n_estimators': [50,100,200]}

random_search = RandomizedSearchCV(gbm, param_dist, n_iter=5, cv=3, n_jobs=-1, verbose=1, random_state=42)

t0 = time.time()
random_search.fit(X_big, y_big)
t_total = time.time() - t0
print(f'Общее время поиска: {t_total:.2f} сек')
print(f'Лучшие параметры: {random_search.best_params_}')
Fitting 3 folds for each of 5 candidates, totalling 15 fits
Общее время поиска: 14.82 сек
Лучшие параметры: {'n_estimators': 200, 'max_depth': 7}

Пример 4. Сравнение времен обучения разных моделей на одном датасете

Построим таблицу со средним временем и точностью.

Пример
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
from sklearn.neighbors import KNeighborsClassifier
import pandas as pd

models = [
    ('DecisionTree', DecisionTreeClassifier()),
    ('SVM (rbf)', SVC()),
    ('kNN', KNeighborsClassifier(n_neighbors=5)),
    ('RF', RandomForestClassifier(n_estimators=100))
]

results = []
for name, model in models:
    start = time.time()
    model.fit(X_big, y_big)
    elapsed = time.time() - start
    results.append({'model': name, 'time': round(elapsed, 3)})

df = pd.DataFrame(results)
print(df)
         model   time
0  DecisionTree  0.032
1     SVM (rbf)  3.045
2           kNN  0.891
3            RF  0.512

Пример 5. Использование joblib для кеширования обученной модели (уменьшение времени повторного обучения)

При частом перезапуске ноутбука полезно сохранять модель на диск.

Пример
import joblib

# Обучение и сохранение
model = RandomForestClassifier(n_estimators=100).fit(X, y)
joblib.dump(model, 'model.pkl')

# При следующем запуске загружаем вместо обучения
loaded_model = joblib.load('model.pkl')
# Замер времени загрузки
import timeit
load_time = timeit.timeit('joblib.load("model.pkl")', setup='import joblib', number=1)
print(f'Время загрузки: {load_time:.4f} сек (вместо обучения за ~0.3 сек)')
Время загрузки: 0.0021 сек (вместо обучения за ~0.3 сек)

Пример 6. Ускорение обучения с помощью преобразования данных в разреженный формат (для SVM, текстовых данных)

Пример
from scipy.sparse import csr_matrix
from sklearn.datasets import fetch_20newsgroups
from sklearn.feature_extraction.text import TfidfVectorizer

news = fetch_20newsgroups(subset='train')
vectorizer = TfidfVectorizer(max_features=5000)
X_sparse = vectorizer.fit_transform(news.data)
y_sparse = news.target

# Сравнение плотного и разреженного обучения SVM
svm_sparse = SVC(kernel='linear').fit(X_sparse, y_sparse)
# Замер времени

Разреженная матрица: (11314, 5000) ~ 0.6% заполненности. Время обучения: 3.2 сек

Предостережения: не все модели эффективно работают с разреженными данными (например, деревья решений их не поддерживают). Для SVM с нелинейными ядрами разреженная матрица может преобразовываться в плотную, что увеличит время и память.

Время обучения модели в Python - comments

En
Python время обучения (python)