scikit-learnMiddleCoding
Как работают VotingClassifier и StackingClassifier в scikit-learn?
VotingClassifier объединяет предсказания через голосование (hard — большинство меток, soft — усреднение вероятностей); StackingClassifier обучает мета-модель на out-of-fold предсказаниях базовых моделей через cross-validation, что даёт лучшее качество ценой большего времени обучения.
VotingClassifier и StackingClassifier в scikit-learn
Оба класса реализуют ансамблевые методы, но используют разные стратегии объединения предсказаний базовых моделей.
VotingClassifier
Объединяет предсказания нескольких моделей через голосование. Два режима: hard (мажоритарное голосование по меткам классов) и soft (усреднение вероятностей).
from sklearn.ensemble import VotingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
X, y = make_classification(n_samples=1000, n_features=20, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Hard voting: мажоритарное голосование по предсказанным классам
voting_hard = VotingClassifier(
estimators=[
('lr', LogisticRegression(random_state=42)),
('dt', DecisionTreeClassifier(max_depth=5, random_state=42)),
('svm', SVC(kernel='rbf', random_state=42)), # SVC без probability=True
],
voting='hard',
)
voting_hard.fit(X_train, y_train)
print(f'Hard voting accuracy: {accuracy_score(y_test, voting_hard.predict(X_test)):.3f}')
# Soft voting: усреднение вероятностей (обычно лучше hard)
voting_soft = VotingClassifier(
estimators=[
('lr', LogisticRegression(random_state=42)),
('dt', DecisionTreeClassifier(max_depth=5, random_state=42)),
# SVC нужен probability=True для soft voting
('svm', SVC(kernel='rbf', probability=True, random_state=42)),
],
voting='soft',
weights=[2, 1, 1], # логистическая регрессия имеет вес 2
)
voting_soft.fit(X_train, y_train)
print(f'Soft voting accuracy: {accuracy_score(y_test, voting_soft.predict(X_test)):.3f}')
# Доступ к отдельным estimators
print(voting_soft.named_estimators_['lr'].coef_.shape)
StackingClassifier
Обучает мета-модель (final_estimator) на предсказаниях базовых моделей (first level). Базовые модели обучаются через cross-validation, чтобы мета-модель обучалась на out-of-fold предсказаниях.
from sklearn.ensemble import StackingClassifier, RandomForestClassifier, GradientBoostingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
import numpy as np
# Базовые модели (first level)
base_estimators = [
('rf', RandomForestClassifier(n_estimators=100, random_state=42)),
('gb', GradientBoostingClassifier(n_estimators=100, random_state=42)),
('lr', LogisticRegression(max_iter=1000, random_state=42)),
]
# Мета-модель (second level) обучается на предсказаниях base estimators
stacking = StackingClassifier(
estimators=base_estimators,
final_estimator=LogisticRegression(), # мета-классификатор
cv=5, # кросс-валидация для out-of-fold предсказаний
stack_method='predict_proba', # передаём вероятности, не метки
passthrough=False, # True: добавить исходные X к мета-признакам
n_jobs=-1,
)
stacking.fit(X_train, y_train)
print(f'Stacking accuracy: {accuracy_score(y_test, stacking.predict(X_test)):.3f}')
# CV оценка
scores = cross_val_score(stacking, X_train, y_train, cv=5, scoring='accuracy')
print(f'CV accuracy: {scores.mean():.3f} ± {scores.std():.3f}')
# Получить предсказания первого уровня
transform_output = stacking.transform(X_test) # мета-признаки
print(f'Meta-features shape: {transform_output.shape}') # (n_samples, n_classes * n_estimators)
Когда что использовать
- VotingClassifier: быстрый ансамбль разнородных моделей, когда модели примерно одинаковы по качеству. Простота и интерпретируемость.
- StackingClassifier: когда хотите извлечь максимальное качество; мета-модель учится, когда доверять каждой базовой модели. Медленнее из-за CV при fit.
- Stacking обычно превосходит Voting на Kaggle, но требует большего датасета и времени обучения.
Подводные камни
- Использовать soft voting с моделью без
predict_proba(SVC безprobability=True) — ValueError при fit. - Не обеспечить разнообразие базовых моделей в VotingClassifier — 3 одинаковых LogisticRegression не лучше одного.
- В StackingClassifier использовать
cv=None(prefit estimators) — мета-модель обучается на train predictions, что вызывает overfitting мета-уровня. - Игнорировать
passthrough=Trueв Stacking: иногда добавление исходных признаков к мета-признакам значительно улучшает результат. - Обучать Stacking без достаточного размера датасета — мета-модель переобучается при < 1000 примеров.
- Не использовать
n_jobs=-1в StackingClassifier — обучение 5 fold × N моделей последовательно занимает в разы дольше. - Не проверять, что базовые модели обучены на одинаковых признаках — проблема при использовании разных preprocessing для разных моделей вне единого Pipeline.
- Смешивать Stacking с GridSearchCV без осторожности: кросс-валидация внутри Stacking nested в outer CV — экспоненциальный рост времени.
Common mistakes
- Объяснять
voting and stackingтолько синтаксисом без shape, dtype, состояния или режима выполнения. - Игнорировать leakage, воспроизводимость, пустые входы и скрытые копии данных.
- Не проверять production-симптомы: latency, память, ретраи, дрейф качества и несовпадение версий.
What the interviewer is testing
- Может ли связать
voting and stackingс реальным контрактом входов и выходов. - Упоминает ли тесты, метрики, reproducibility и диагностику ошибок.
- Видит ли различие между demo-кодом в ноутбуке и production-пайплайном.