Шпаргалка: sklearn¶
~4 минуты чтения
Предварительно: Выбор модели | Метрики
Sklearn -- главная библиотека для классического ML в Python. Единый API: fit() / predict() / transform() для всех алгоритмов. Pipeline автоматически предотвращает data leakage. Эта шпаргалка -- рабочий reference с копируемым кодом для каждого этапа: preprocessing -> model selection -> evaluation.
Быстрый старт¶
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score
# Базовый пайплайн
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train) # (1)!
X_test_scaled = scaler.transform(X_test) # (2)!
model.fit(X_train_scaled, y_train)
y_pred = model.predict(X_test_scaled)
print(f"Accuracy: {accuracy_score(y_test, y_pred):.4f}")
fit_transform=fit+transformза один вызов. Scaler запоминает mean/std с train данных.- Только
transformна тесте!fit_transformна тесте = data leakage (scaler увидит тестовые статистики).
Classification¶
| Алгоритм | Когда использовать | Ключевые параметры | Код |
|---|---|---|---|
| LogisticRegression | Линейно разделимые классы, baseline | C, penalty, solver |
LogisticRegression(C=1.0) |
| RandomForestClassifier | Универсальный, feature importance | n_estimators, max_depth, min_samples_split |
RandomForestClassifier(n_estimators=100) |
| GradientBoostingClassifier | Высокое качество, медленный | n_estimators, learning_rate, max_depth |
GradientBoostingClassifier(n_estimators=100) |
| SVC | Нелинейные границы, малые данные | C, kernel, gamma |
SVC(kernel='rbf', C=1.0) |
| KNeighborsClassifier | Простой baseline, малые данные | n_neighbors, weights, metric |
KNeighborsClassifier(n_neighbors=5) |
| DecisionTreeClassifier | Интерпретируемость | max_depth, min_samples_split |
DecisionTreeClassifier(max_depth=5) |
| GaussianNB | Текст, быстрый baseline | var_smoothing |
GaussianNB() |
| MLPClassifier | Нелинейные зависимости | hidden_layer_sizes, alpha, learning_rate |
MLPClassifier(hidden_layer_sizes=(100,)) |
Примеры использования¶
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.svm import SVC
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.neural_network import MLPClassifier
# Logistic Regression с регуляризацией
lr = LogisticRegression(
C=0.1, # Сила регуляризации (меньше = сильнее)
penalty='l2', # l1, l2, elasticnet, None
solver='lbfgs', # lbfgs, liblinear, saga
max_iter=1000,
class_weight='balanced' # Для дисбаланса классов
)
# Random Forest
rf = RandomForestClassifier(
n_estimators=100, # Количество деревьев
max_depth=10, # Глубина деревьев
min_samples_split=5, # Мин. примеров для разбиения
min_samples_leaf=2, # Мин. примеров в листе
max_features='sqrt', # Признаков на разбиение
n_jobs=-1, # Все ядра CPU
random_state=42
)
# SVM с RBF kernel
svm = SVC(
C=1.0, # Штраф за ошибки
kernel='rbf', # linear, poly, rbf, sigmoid
gamma='scale', # Ширина ядра
probability=True # Для predict_proba
)
Regression¶
| Алгоритм | Когда использовать | Ключевые параметры | Код |
|---|---|---|---|
| LinearRegression | Baseline, интерпретируемость | - | LinearRegression() |
| Ridge | Много признаков, мультиколлинеарность | alpha |
Ridge(alpha=1.0) |
| Lasso | Feature selection, sparse | alpha |
Lasso(alpha=1.0) |
| ElasticNet | Комбинация Ridge + Lasso | alpha, l1_ratio |
ElasticNet(alpha=1.0, l1_ratio=0.5) |
| RandomForestRegressor | Нелинейные зависимости | n_estimators, max_depth |
RandomForestRegressor(n_estimators=100) |
| GradientBoostingRegressor | Высокое качество | n_estimators, learning_rate |
GradientBoostingRegressor() |
| SVR | Нелинейные, малые данные | C, kernel, epsilon |
SVR(kernel='rbf') |
from sklearn.linear_model import LinearRegression, Ridge, Lasso, ElasticNet
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor
# Ridge Regression
ridge = Ridge(
alpha=1.0, # Сила L2 регуляризации
fit_intercept=True
)
# Lasso (создаёт sparse модель)
lasso = Lasso(
alpha=0.1, # Сила L1 регуляризации
max_iter=10000
)
# ElasticNet
elastic = ElasticNet(
alpha=1.0, # Общая сила регуляризации
l1_ratio=0.5 # Баланс L1/L2 (0=Ridge, 1=Lasso)
)
Clustering¶
| Алгоритм | Когда использовать | Ключевые параметры | Код |
|---|---|---|---|
| KMeans | Сферические кластеры | n_clusters, init, n_init |
KMeans(n_clusters=3) |
| DBSCAN | Произвольная форма, выбросы | eps, min_samples |
DBSCAN(eps=0.5, min_samples=5) |
| AgglomerativeClustering | Иерархия кластеров | n_clusters, linkage |
AgglomerativeClustering(n_clusters=3) |
| GaussianMixture | Мягкая кластеризация | n_components, covariance_type |
GaussianMixture(n_components=3) |
from sklearn.cluster import KMeans, DBSCAN, AgglomerativeClustering
from sklearn.mixture import GaussianMixture
# K-Means
kmeans = KMeans(
n_clusters=3,
init='k-means++', # Умная инициализация
n_init=10, # Количество запусков
max_iter=300,
random_state=42
)
labels = kmeans.fit_predict(X)
centers = kmeans.cluster_centers_
# DBSCAN (не нужно задавать k)
dbscan = DBSCAN(
eps=0.5, # Радиус окрестности
min_samples=5, # Мин. точек для core point
metric='euclidean'
)
labels = dbscan.fit_predict(X) # -1 = выброс
Preprocessing¶
Scaling¶
from sklearn.preprocessing import (
StandardScaler, # z-score: (x - mean) / std
MinMaxScaler, # [0, 1]: (x - min) / (max - min)
RobustScaler, # Устойчив к выбросам: (x - median) / IQR
MaxAbsScaler, # [-1, 1] для sparse данных
Normalizer # L2 норма для каждого примера
)
# Стандартизация (для большинства алгоритмов)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train) # fit + transform на train
X_test_scaled = scaler.transform(X_test) # ТОЛЬКО transform на test!
# Нормализация [0, 1]
minmax = MinMaxScaler(feature_range=(0, 1))
# Для выбросов
robust = RobustScaler(quantile_range=(25, 75))
fit_transform на тестовых данных = data leakage
scaler.fit_transform(X_test) -- грубая ошибка. fit считает mean/std по данным. Если сделать fit на тесте -- scaler узнает распределение тестовых данных, и метрики будут завышены. Правильно: fit_transform ТОЛЬКО на train, потом transform на test/val/prod. Pipeline автоматически делает это правильно -- используйте Pipeline для любого preprocessing.
Encoding¶
from sklearn.preprocessing import (
LabelEncoder, # Категории -> числа
OneHotEncoder, # Категории -> бинарные столбцы
OrdinalEncoder # Порядковые категории -> числа
)
# Label Encoding (для target)
le = LabelEncoder()
y_encoded = le.fit_transform(y)
y_decoded = le.inverse_transform(y_encoded)
# One-Hot Encoding
ohe = OneHotEncoder(
sparse_output=False, # Dense matrix
drop='first', # Избежать dummy trap
handle_unknown='ignore' # Для новых категорий
)
X_encoded = ohe.fit_transform(X[['category_column']])
Imputation¶
from sklearn.impute import SimpleImputer, KNNImputer
# Простая импутация
imputer = SimpleImputer(
strategy='mean' # mean, median, most_frequent, constant
)
X_imputed = imputer.fit_transform(X)
# KNN импутация (лучше качество)
knn_imputer = KNNImputer(n_neighbors=5)
X_imputed = knn_imputer.fit_transform(X)
Feature Selection¶
from sklearn.feature_selection import (
SelectKBest,
SelectFromModel,
RFE,
f_classif, f_regression, chi2, mutual_info_classif
)
# По статистическому тесту
selector = SelectKBest(score_func=f_classif, k=10)
X_selected = selector.fit_transform(X, y)
selected_features = X.columns[selector.get_support()]
# По важности модели
from sklearn.ensemble import RandomForestClassifier
selector = SelectFromModel(
RandomForestClassifier(n_estimators=100),
threshold='median'
)
X_selected = selector.fit_transform(X, y)
# Recursive Feature Elimination
rfe = RFE(
estimator=RandomForestClassifier(),
n_features_to_select=10,
step=1
)
X_selected = rfe.fit_transform(X, y)
rankings = rfe.ranking_ # 1 = selected
Model Selection¶
Train-Test Split¶
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
X, y,
test_size=0.2, # 20% на тест
random_state=42, # Воспроизводимость
stratify=y # Сохранить пропорции классов
)
Cross-Validation¶
from sklearn.model_selection import (
cross_val_score,
cross_validate,
KFold,
StratifiedKFold,
TimeSeriesSplit
)
# Простая кросс-валидация
scores = cross_val_score(model, X, y, cv=5, scoring='accuracy')
print(f"Mean: {scores.mean():.4f} (+/- {scores.std()*2:.4f})")
# Несколько метрик
results = cross_validate(
model, X, y, cv=5,
scoring=['accuracy', 'f1', 'roc_auc'],
return_train_score=True
)
# Стратифицированная (для классификации)
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
for train_idx, val_idx in skf.split(X, y):
X_train, X_val = X[train_idx], X[val_idx]
y_train, y_val = y[train_idx], y[val_idx]
# Для временных рядов
tscv = TimeSeriesSplit(n_splits=5)
for train_idx, val_idx in tscv.split(X):
# Обучение только на прошлых данных
pass
Hyperparameter Tuning¶
from sklearn.model_selection import GridSearchCV, RandomizedSearchCV
# Grid Search (перебор всех комбинаций)
param_grid = {
'n_estimators': [100, 200, 300],
'max_depth': [5, 10, 15, None],
'min_samples_split': [2, 5, 10]
}
grid_search = GridSearchCV(
RandomForestClassifier(),
param_grid,
cv=5,
scoring='f1',
n_jobs=-1,
verbose=1
)
grid_search.fit(X_train, y_train)
print(f"Best params: {grid_search.best_params_}")
print(f"Best score: {grid_search.best_score_:.4f}")
best_model = grid_search.best_estimator_
# Random Search (быстрее для большого пространства)
from scipy.stats import randint, uniform
param_dist = {
'n_estimators': randint(100, 500),
'max_depth': randint(5, 50),
'min_samples_split': randint(2, 20)
}
random_search = RandomizedSearchCV(
RandomForestClassifier(),
param_dist,
n_iter=50, # Количество комбинаций
cv=5,
scoring='f1',
n_jobs=-1,
random_state=42
)
Pipelines¶
from sklearn.pipeline import Pipeline, make_pipeline
from sklearn.compose import ColumnTransformer
# Простой pipeline
pipe = Pipeline([
('scaler', StandardScaler()),
('classifier', LogisticRegression())
])
pipe.fit(X_train, y_train) # (1)!
y_pred = pipe.predict(X_test) # (2)!
# make_pipeline (автоименование)
pipe = make_pipeline(StandardScaler(), LogisticRegression())
# Разная обработка для разных типов признаков
numeric_features = ['age', 'income']
categorical_features = ['gender', 'city']
preprocessor = ColumnTransformer(
transformers=[
('num', StandardScaler(), numeric_features),
('cat', OneHotEncoder(drop='first'), categorical_features) # (3)!
],
remainder='passthrough'
)
full_pipe = Pipeline([
('preprocessor', preprocessor),
('classifier', RandomForestClassifier())
])
fit()вызываетscaler.fit_transform(X_train)->classifier.fit(X_scaled, y). Scaler учит статистики ТОЛЬКО на train.predict()вызываетscaler.transform(X_test)->classifier.predict(X_scaled). Статистики scaler из train -- нет leakage.drop='first'убирает одну dummy-колонку для предотвращения мультиколлинеарности (dummy variable trap). Критично для LogReg, не важно для деревьев.
Metrics¶
Classification¶
from sklearn.metrics import (
accuracy_score,
precision_score, recall_score, f1_score,
roc_auc_score, average_precision_score,
confusion_matrix, classification_report,
precision_recall_curve, roc_curve
)
# Базовые метрики
print(f"Accuracy: {accuracy_score(y_test, y_pred):.4f}")
print(f"Precision: {precision_score(y_test, y_pred):.4f}")
print(f"Recall: {recall_score(y_test, y_pred):.4f}")
print(f"F1: {f1_score(y_test, y_pred):.4f}")
# Для вероятностей
y_prob = model.predict_proba(X_test)[:, 1]
print(f"ROC-AUC: {roc_auc_score(y_test, y_prob):.4f}")
print(f"PR-AUC: {average_precision_score(y_test, y_prob):.4f}")
# Детальный отчёт
print(classification_report(y_test, y_pred))
# Confusion matrix
cm = confusion_matrix(y_test, y_pred)
# [[TN, FP],
# [FN, TP]]
# Multiclass
f1_score(y_test, y_pred, average='macro') # Среднее по классам
f1_score(y_test, y_pred, average='weighted') # Взвешенное по размеру
f1_score(y_test, y_pred, average='micro') # Глобальное
Regression¶
from sklearn.metrics import (
mean_squared_error,
mean_absolute_error,
r2_score,
mean_absolute_percentage_error
)
print(f"MSE: {mean_squared_error(y_test, y_pred):.4f}")
print(f"RMSE: {mean_squared_error(y_test, y_pred, squared=False):.4f}")
print(f"MAE: {mean_absolute_error(y_test, y_pred):.4f}")
print(f"R2: {r2_score(y_test, y_pred):.4f}")
print(f"MAPE: {mean_absolute_percentage_error(y_test, y_pred):.4f}")
Clustering¶
from sklearn.metrics import (
silhouette_score,
calinski_harabasz_score,
davies_bouldin_score,
adjusted_rand_score, # Если есть истинные метки
normalized_mutual_info_score
)
print(f"Silhouette: {silhouette_score(X, labels):.4f}") # [-1, 1], больше лучше
print(f"Calinski-Harabasz: {calinski_harabasz_score(X, labels):.4f}") # больше лучше
print(f"Davies-Bouldin: {davies_bouldin_score(X, labels):.4f}") # меньше лучше
Быстрый выбор модели¶
graph TD
START{"Тип задачи?"} --> CLS["Классификация"]
START --> REG["Регрессия"]
CLS --> INTERP{"Интерпретируемость?"}
INTERP -->|"Да"| INTERP_Y["LogisticRegression<br/>DecisionTree"]
INTERP -->|"Нет"| DATA_SIZE{"Данных мало<br/>< 1000?"}
DATA_SIZE -->|"Да"| SMALL["SVC(rbf), KNN"]
DATA_SIZE -->|"Нет"| SPEED{"Важна скорость?"}
SPEED -->|"Да"| FAST["RandomForest<br/>LogisticRegression"]
SPEED -->|"Нет"| BEST["GradientBoosting<br/>XGBoost, LightGBM"]
REG --> LINEAR{"Линейная<br/>зависимость?"}
LINEAR -->|"Да"| MULTI{"Мультиколлинеарность?"}
MULTI -->|"Да"| REGULARIZED["Ridge, Lasso<br/>ElasticNet"]
MULTI -->|"Нет"| LINREG["LinearRegression"]
LINEAR -->|"Нет"| NONLIN["RandomForest<br/>GradientBoosting<br/>XGBoost"]
style START fill:#e8eaf6,stroke:#3f51b5
style CLS fill:#e8f5e9,stroke:#4caf50
style REG fill:#fff3e0,stroke:#ef6c00
style BEST fill:#e8f5e9,stroke:#4caf50
style NONLIN fill:#fff3e0,stroke:#ef6c00
Полезные паттерны¶
Feature Importance¶
# Для деревьев
importances = model.feature_importances_
feature_imp = pd.DataFrame({
'feature': X.columns,
'importance': importances
}).sort_values('importance', ascending=False)
# Permutation importance (универсальный)
from sklearn.inspection import permutation_importance
result = permutation_importance(model, X_test, y_test, n_repeats=10)
Learning Curves¶
from sklearn.model_selection import learning_curve
import matplotlib.pyplot as plt
train_sizes, train_scores, val_scores = learning_curve(
model, X, y, cv=5,
train_sizes=np.linspace(0.1, 1.0, 10),
scoring='accuracy'
)
plt.plot(train_sizes, train_scores.mean(axis=1), label='Train')
plt.plot(train_sizes, val_scores.mean(axis=1), label='Validation')
plt.xlabel('Training Size')
plt.ylabel('Score')
plt.legend()
Class Weights для дисбаланса¶
from sklearn.utils.class_weight import compute_class_weight
# Автоматический расчёт
weights = compute_class_weight('balanced', classes=np.unique(y), y=y)
class_weights = dict(zip(np.unique(y), weights))
model = RandomForestClassifier(class_weight='balanced')
# или
model = LogisticRegression(class_weight={0: 1, 1: 10})
Сохранение модели¶
import joblib
# Сохранить
joblib.dump(model, 'model.joblib')
joblib.dump(pipe, 'pipeline.joblib')
# Загрузить
model = joblib.load('model.joblib')
Самопроверка
-
Pipeline: Напишите Pipeline для задачи классификации с: (a) StandardScaler для числовых, OneHotEncoder для категориальных (ColumnTransformer), (b) RandomForestClassifier, © GridSearchCV по 3 гиперпараметрам. Почему Pipeline предотвращает data leakage, а ручной preprocessing -- нет?
-
Cross-validation: У вас временные ряды (цены акций за 5 лет). Почему нельзя использовать StratifiedKFold? Какой splitter правильный и почему? Напишите код.
-
Дисбаланс: Датасет с 3% fraud. Напишите код: (a)
class_weight='balanced'для LogReg, (b) сравните ROC-AUC и PR-AUC черезcross_validate. Какая метрика более информативна и почему?
Источники¶
- scikit-learn -- User Guide -- официальная документация
- scikit-learn -- Pipeline -- ColumnTransformer и Pipeline
- scikit-learn -- Cross-validation -- стратегии валидации
- scikit-learn -- Model selection -- flowchart выбора модели
See Also¶
- Model Selection Cheatsheet — какой алгоритм выбрать
- Metrics Cheatsheet — scoring параметры для GridSearchCV
- Hyperparameters Cheatsheet — что тюнить в каждой модели
- Classical ML Interview Q&A — Pipeline и cross-validation вопросы