Оценка и уменьшение длительности тренировки моделей на Python
Измерение и сокращение времени обучения моделей 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 не поддерживает все модели и может давать незначительные отличия в результатах из-за численных методов.
Расширенные примеры измерения и оптимизации времени обучения
Пример 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 с нелинейными ядрами разреженная матрица может преобразовываться в плотную, что увеличит время и память.