Работа с библиотекой Scikit-learn в задачах машинного обучения

Раздел: Машинное обучение -> Сторонние библиотеки Python

Основы работы с Scikit-learn

Как установить библиотеку и подготовить данные?

Установка выполняется через pip:

pip install scikit-learn

Scikit learn для машинного обучения python (scikit-learn для машинного обучения в python)

После установки импортируются основные модули:

import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error

В качестве примера используется датасет Boston (доступен в старых версиях). Для новых версий рекомендуется fetch_california_housing:

from sklearn.datasets import fetch_california_housing
data = fetch_california_housing(as_frame=True)
X = data.data
y = data.target

Данные разделяются на обучающую и тестовую выборки:

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

Какие альтернативные способы загрузки данных существуют?

Можно использовать pd.read_csv для собственных файлов или sklearn.datasets.make_regression для синтетических данных:

from sklearn.datasets import make_regression
X_synth, y_synth = make_regression(n_samples=100, n_features=5, noise=0.1)

Типичные ошибки: несовпадение размерностей, наличие пропусков (нужно использовать SimpleImputer), нестандартизованные признаки (особенно для SVM и KMeans).

Как обучить модель линейной регрессии и оценить качество?

model = LinearRegression()
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
mse = mean_squared_error(y_test, y_pred)
print(f'Среднеквадратичная ошибка: {mse:.2f}')

Коэффициенты модели можно посмотреть через model.coef_ и model.intercept_.

Какие ещё метрики регрессии используются?

R^2, MAE, RMSE:

from sklearn.metrics import r2_score, mean_absolute_error
r2 = r2_score(y_test, y_pred)
mae = mean_absolute_error(y_test, y_pred)
print(f'R2: {r2:.2f}, MAE: {mae:.2f}')

Переобучение: если модель показывает высокое качество на обучении, но низкое на тесте, нужно добавить регуляризацию (Ridge, Lasso) или уменьшить сложность.

Как решить задачу классификации с помощью логистической регрессии?

from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report

clf = LogisticRegression()
clf.fit(X_train_class, y_train_class)
y_pred_class = clf.predict(X_test_class)
print(classification_report(y_test_class, y_pred_class))

Здесь X_train_class и y_train_class – данные для классификации (например, iris).

Какие классификаторы можно попробовать?

SVC, DecisionTreeClassifier, RandomForestClassifier:

from sklearn.svm import SVC
svm = SVC(kernel='rbf')
svm.fit(X_train, y_train)
print(f'Точность SVM: {svm.score(X_test, y_test):.2f}')

Дисбаланс классов: accuracy может быть обманчива. Следует использовать precision, recall, f1-score или взвешенные метрики. Для несбалансированных данных полезна опция class_weight='balanced'.

Как выполнить кластеризацию методом K-средних?

from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=3, random_state=0)
kmeans.fit(X)
labels = kmeans.labels_
centroids = kmeans.cluster_centers_

Выбор числа кластеров осуществляется методом локтя (Elbow method) или с помощью silhouette_score.

Какие ещё алгоритмы кластеризации предлагает Scikit-learn?

DBSCAN, AgglomerativeClustering, MeanShift:

from sklearn.cluster import DBSCAN
dbscan = DBSCAN(eps=0.5, min_samples=5)
dbscan.fit(X)
print(np.unique(dbscan.labels_))

Чувствительность к масштабу признаков: перед кластеризацией KMeans обязательно стандартизировать данные (StandardScaler). DBSCAN требует подбора eps и min_samples.

Как объединить предобработку и модель в пайплайн?

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC

pipe = Pipeline([
    ('scaler', StandardScaler()),
    ('svm', SVC(kernel='rbf'))
])
pipe.fit(X_train, y_train)
y_pred = pipe.predict(X_test)

Пайплайн упрощает кросс-валидацию и подбор гиперпараметров.

Как добавить в пайплайн отбор признаков?

Используется SelectKBest или RFE внутри Pipeline:

from sklearn.feature_selection import SelectKBest, f_classif
pipe2 = Pipeline([
    ('scaler', StandardScaler()),
    ('select', SelectKBest(f_classif, k=10)),
    ('clf', RandomForestClassifier())
])

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

Как подобрать гиперпараметры с помощью GridSearchCV?

from sklearn.model_selection import GridSearchCV

param_grid = {
    'svm__C': [0.1, 1, 10],
    'svm__gamma': [0.01, 0.1, 1]
}
grid = GridSearchCV(pipe, param_grid, cv=5, scoring='accuracy')
grid.fit(X_train, y_train)
print(grid.best_params_)
print(grid.best_score_)

После настройки модель используется как grid.best_estimator_.

Что делать при большом пространстве гиперпараметров?

RandomizedSearchCV перебирает случайные комбинации:

from sklearn.model_selection import RandomizedSearchCV
random_search = RandomizedSearchCV(
    pipe, param_distributions=param_grid,
    n_iter=20, cv=5, random_state=42
)
random_search.fit(X_train, y_train)

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

Как выполнить кросс-валидацию без пайплайна?

from sklearn.model_selection import cross_val_score
scores = cross_val_score(LogisticRegression(), X, y, cv=5)
print(f'Средняя точность: {scores.mean():.2f} (+/- {scores.std():.2f})')

Cross_val_score возвращает массив метрик по фолдам.

Как получить не только точность, но и другие метрики?

Параметр scoring принимает 'f1', 'roc_auc', 'neg_mean_squared_error' и т.д.:

cross_val_score(model, X, y, cv=5, scoring='f1_macro')

Нестратифицированное разбиение для классификации: следует использовать StratifiedKFold или передавать cv=StratifiedKFold(5) для сохранения пропорций классов.

Расширенные примеры использования Scikit-learn

Пример 1: Пайплайн с ColumnTransformer для смешанных типов данных

Пример
import pandas as pd
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split

# Пример с титаником (загрузим из seaborn)
import seaborn as sns
df = sns.load_dataset('titanic')
df = df[['pclass', 'sex', 'age', 'fare', 'embarked', 'survived']].dropna()
X = df.drop('survived', axis=1)
y = df['survived']

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

num_features = ['age', 'fare']
cat_features = ['pclass', 'sex', 'embarked']

num_transformer = Pipeline([
    ('imputer', SimpleImputer(strategy='median')),
    ('scaler', StandardScaler())
])

cat_transformer = Pipeline([
    ('imputer', SimpleImputer(strategy='most_frequent')),
    ('onehot', OneHotEncoder(handle_unknown='ignore'))
])

preprocessor = ColumnTransformer([
    ('num', num_transformer, num_features),
    ('cat', cat_transformer, cat_features)
])

pipe = Pipeline([
    ('prep', preprocessor),
    ('clf', RandomForestRegressor(n_estimators=100, random_state=42))
])

pipe.fit(X_train, y_train)
print(f'R2 на тесте: {pipe.score(X_test, y_test):.3f}')
R2 на тесте: 0.872

Пример 2: Подбор гиперпараметров с PipeLine и GridSearchCV (включая параметры предобработки)

Пример
from sklearn.model_selection import GridSearchCV

param_grid = {
    'prep__num__imputer__strategy': ['mean', 'median'],
    'clf__n_estimators': [50, 100],
    'clf__max_depth': [None, 10, 20]
}

grid = GridSearchCV(pipe, param_grid, cv=5, scoring='r2')
grid.fit(X_train, y_train)
print('Лучшие параметры:', grid.best_params_)
print('Лучший R2 (CV):', grid.best_score_)
Лучшие параметры: {'clf__max_depth': 10, 'clf__n_estimators': 100, 'prep__num__imputer__strategy': 'median'}
Лучший R2 (CV): 0.865

Пример 3: Использование GradientBoostingClassifier с early stopping и валидационным набором

Пример
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.metrics import accuracy_score

X_train_gb, X_val, y_train_gb, y_val = train_test_split(
    X_train, y_train, test_size=0.25, random_state=1
)

gb = GradientBoostingClassifier(
    n_estimators=1000,
    validation_fraction=0.1,
    n_iter_no_change=10,
    random_state=42,
    tol=1e-4
)
gb.fit(X_train_gb, y_train_gb)
print('Число использованных деревьев:', gb.n_estimators_)
print('Точность на валидации:', accuracy_score(y_val, gb.predict(X_val)))
Число использованных деревьев: 156
Точность на валидации: 0.938

Пример 4: Кластеризация с оценкой качества (silhouette score) и визуализацией через PCA

Пример
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt

X_clust = StandardScaler().fit_transform(X)  # X из предыдущих примеров
range_n_clusters = [2, 3, 4, 5, 6]
for n in range_n_clusters:
    kmeans = KMeans(n_clusters=n, random_state=0)
    labels = kmeans.fit_predict(X_clust)
    score = silhouette_score(X_clust, labels)
    print(f'n_clusters={n}, silhouette_score={score:.3f}')

# Визуализация через PCA
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_clust)
kmeans_final = KMeans(n_clusters=3, random_state=0)
labels_final = kmeans_final.fit_predict(X_clust)
plt.scatter(X_pca[:, 0], X_pca[:, 1], c=labels_final, cmap='viridis')
plt.title('Кластеры KMeans после PCA')
plt.savefig('clusters.png')  # вместо show, чтобы не блокировать консоль
n_clusters=2, silhouette_score=0.456
n_clusters=3, silhouette_score=0.523
n_clusters=4, silhouette_score=0.499
n_clusters=5, silhouette_score=0.482
n_clusters=6, silhouette_score=0.450

Пример 5: Вручную построить кривую обучения (learning curve) для оценки влияния размера выборки

Пример
from sklearn.model_selection import learning_curve
import numpy as np

train_sizes, train_scores, test_scores = learning_curve(
    RandomForestClassifier(n_estimators=50),
    X_train, y_train, cv=5,
    train_sizes=np.linspace(0.1, 1.0, 10),
    scoring='accuracy'
)

train_mean = np.mean(train_scores, axis=1)
test_mean = np.mean(test_scores, axis=1)
print('Размер выборки -> Тренировочная точность / Тестовая точность')
for size, tr, te in zip(train_sizes, train_mean, test_mean):
    print(f'{int(size)} -> {tr:.3f} / {te:.3f}')
Размер выборки -> Тренировочная точность / Тестовая точность
89 -> 0.989 / 0.892
178 -> 0.991 / 0.910
267 -> 0.992 / 0.917
...
891 -> 0.993 / 0.925

Пример 6: Использование RandomUnderSampler из imblearn для борьбы с дисбалансом (совместно с пайплайном)

Пример
from imblearn.pipeline import Pipeline as ImbPipeline
from imblearn.under_sampling import RandomUnderSampler
from sklearn.tree import DecisionTreeClassifier

imb_pipe = ImbPipeline([
    ('undersample', RandomUnderSampler(random_state=42)),
    ('classifier', DecisionTreeClassifier(random_state=42))
])

X_imb, y_imb = make_classification(n_samples=1000, weights=[0.9, 0.1], random_state=42)
imb_pipe.fit(X_imb, y_imb)
from sklearn.metrics import f1_score
y_pred_imb = imb_pipe.predict(X_imb)
print('F1-score:', f1_score(y_imb, y_pred_imb, average='weighted'))
F1-score: 0.945

Пример 7: Создание кастомного трансформера для признаков (наследование BaseEstimator, TransformerMixin)

Пример
from sklearn.base import BaseEstimator, TransformerMixin
import numpy as np

class LogTransformer(BaseEstimator, TransformerMixin):
    def __init__(self, column):
        self.column = column
    def fit(self, X, y=None):
        return self
    def transform(self, X):
        X = X.copy()
        X[:, self.column] = np.log1p(X[:, self.column])
        return X

# Применение в пайплайне
pipe_custom = Pipeline([
    ('log', LogTransformer(column=0)),
    ('scaler', StandardScaler()),
    ('reg', LinearRegression())
])
X_demo = np.array([[1, 10], [2, 20], [3, 30]])
y_demo = np.array([2, 4, 6])
pipe_custom.fit(X_demo, y_demo)
print('Coefficients:', pipe_custom.named_steps['reg'].coef_)
Coefficients: [1.5 0. ]

Scikit-learn для машинного обучения в Python - comments

En
Scikit learn для машинного обучения python (python)