Как с помощью линейной модели отобрать важные признаки?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Отбор важных признаков с помощью линейной модели
Линейные модели обладают одним из самых интерпретируемых механизмов отбора признаков через коэффициенты регрессии. Этот метод простой, быстрый и часто очень эффективный для уменьшения размерности данных и улучшения обобщающей способности модели.
Основной принцип
В линейной модели каждому признаку соответствует коэффициент (вес). Абсолютное значение коэффициента показывает, насколько важен этот признак для предсказания:
y = w0 + w1*x1 + w2*x2 + ... + wn*xn
Где w_i коэффициент признака x_i. Большие |w_i| означают, что признак x_i сильно влияет на предсказание.
Способ 1: Логистическая регрессия для классификации
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
import numpy as np
import pandas as pd
# Стандартизируем признаки (важно для справедливого сравнения коэффициентов!)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X_train)
# Обучаем логистическую регрессию
model = LogisticRegression(
penalty=l2,
C=1.0, # Параметр регуляризации
max_iter=1000,
random_state=42
)
model.fit(X_scaled, y_train)
# Получаем коэффициенты
coefficients = model.coef_[0] # Для бинарной классификации
# Создаём DataFrame для визуализации
feature_importance = pd.DataFrame({
feature: X.columns,
coefficient: np.abs(coefficients), # Берём абсолютные значения
direction: np.sign(coefficients) # +1 если увеличивает вероятность, -1 если уменьшает
}).sort_values(by=coefficient, ascending=False)
print(feature_importance.head(10))
Способ 2: Ridge и Lasso регрессия
Ridge регрессия (L2) сжимает коэффициенты, но не обнуляет:
from sklearn.linear_model import Ridge, RidgeCV
# Кросс-валидированная выборка параметра регуляризации
ridge_cv = RidgeCV(alphas=np.logspace(-3, 3, 100), cv=5)
ridge_cv.fit(X_scaled, y_train)
print(f"Best alpha: {ridge_cv.alpha_:.4f}")
print(f"R2 score: {ridge_cv.score(X_test_scaled, y_test):.4f}")
# Коэффициенты Ridge
ridge_coefs = ridge_cv.coef_
feature_importance = pd.DataFrame({
feature: X.columns,
coefficient: np.abs(ridge_coefs)
}).sort_values(by=coefficient, ascending=False)
Lasso регрессия (L1) обнуляет неважные признаки — идеально для отбора:
from sklearn.linear_model import Lasso, LassoCV
# LassoCV автоматически выбирает оптимальный параметр alpha
lasso_cv = LassoCV(
alphas=np.logspace(-4, 0, 100),
cv=5,
random_state=42
)
lasso_cv.fit(X_scaled, y_train)
print(f"Best alpha: {lasso_cv.alpha_:.4f}")
print(f"Non-zero coefficients: {np.sum(lasso_cv.coef_ != 0)}")
print(f"R2 score: {lasso_cv.score(X_test_scaled, y_test):.4f}")
# Lasso обнуляет неважные признаки
important_features = X.columns[lasso_cv.coef_ != 0]
print(f"Important features: {list(important_features)}")
# Визуализируем
feature_importance = pd.DataFrame({
feature: X.columns,
coefficient: np.abs(lasso_cv.coef_)
})[lambda df: df[coefficient] > 0].sort_values(
by=coefficient,
ascending=False
)
print(feature_importance)
Способ 3: ElasticNet (комбинация Ridge и Lasso)
Comбинирует преимущества обоих подходов:
from sklearn.linear_model import ElasticNetCV
elastic_cv = ElasticNetCV(
l1_ratio=np.linspace(0, 1, 11), # 0 = Ridge, 1 = Lasso
alphas=np.logspace(-3, 1, 50),
cv=5,
random_state=42
)
elastic_cv.fit(X_scaled, y_train)
print(f"Best alpha: {elastic_cv.alpha_:.4f}")
print(f"Best l1_ratio: {elastic_cv.l1_ratio_:.2f}")
print(f"Non-zero coefficients: {np.sum(elastic_cv.coef_ != 0)}")
Способ 4: Пошаговый отбор с помощью RFE
Recursive Feature Elimination с линейной моделью:
from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegression
# Рекурсивно исключаем признаки с наименьшими коэффициентами
rfe = RFE(
estimator=LogisticRegression(max_iter=1000, random_state=42),
n_features_to_select=10, # Выбираем топ 10 признаков
step=1 # Исключаем по одному признаку за итерацию
)
rfe.fit(X_scaled, y_train)
# Какие признаки выбраны
selected_features = X.columns[rfe.support_]
print(f"Selected features: {list(selected_features)}")
# Рейтинг признаков (1 = выбран, 2 = исключён второй и т.д.)
feature_ranking = pd.DataFrame({
feature: X.columns,
ranking: rfe.ranking_
}).sort_values(by=ranking)
print(feature_ranking)
Способ 5: SelectFromModel
Автоматический отбор признаков на основе порога коэффициентов:
from sklearn.feature_selection import SelectFromModel
# Обучаем модель
lasso = Lasso(alpha=0.01, random_state=42)
lasso.fit(X_scaled, y_train)
# Выбираем признаки с коэффициентами, превышающими порог
selector = SelectFromModel(
lasso,
prefit=True,
threshold=0.01 # Или можно использовать mean, median и т.д.
)
selected_features = X.columns[selector.get_support()]
X_selected = selector.transform(X_scaled)
print(f"Selected {X_selected.shape[1]} features out of {X_scaled.shape[1]}")
print(f"Features: {list(selected_features)}")
Практический пример: предсказание цены дома
import pandas as pd
from sklearn.linear_model import LassoCV
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
# Загружаем данные
df = pd.read_csv(houses.csv)
X = df.drop(columns=[price])
y = df[price]
# Разбиваем на train/test
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)
X_test_scaled = scaler.transform(X_test)
# Применяем Lasso с кросс-валидацией
lasso_cv = LassoCV(
alphas=np.logspace(-3, 1, 100),
cv=5,
random_state=42
)
lasso_cv.fit(X_train_scaled, y_train)
# Результаты
print(f"Best alpha: {lasso_cv.alpha_:.4f}")
print(f"R2 on train: {lasso_cv.score(X_train_scaled, y_train):.4f}")
print(f"R2 on test: {lasso_cv.score(X_test_scaled, y_test):.4f}")
# Важные признаки
feature_importance = pd.DataFrame({
feature: X.columns,
coefficient: np.abs(lasso_cv.coef_),
original_coefficient: lasso_cv.coef_
}).sort_values(by=coefficient, ascending=False)
print("\nTop 10 important features:")
print(feature_importance.head(10))
# Визуализация
import matplotlib.pyplot as plt
top_n = 15
top_features = feature_importance.head(top_n)
plt.figure(figsize=(10, 6))
plt.barh(range(len(top_features)), top_features[coefficient])
plt.yticks(range(len(top_features)), top_features[feature])
plt.xlabel(Absolute Coefficient)
plt.title(Top Feature Importance (Lasso))
plt.tight_layout()
plt.show()
Сравнение методов отбора
| Метод | Тип отбора | Скорость | Интерпретируемость | Когда использовать |
|---|---|---|---|---|
| Логистическая регрессия | Все коэффициенты | Быстро | Отличная | Базовый анализ |
| Ridge | Все коэффициенты | Быстро | Хорошая | Мультиколлинеарность |
| Lasso | Обнуляет признаки | Быстро | Отличная | Нужен компактный набор |
| ElasticNet | Гибридный | Быстро | Хорошая | Когда L1 и L2 вместе |
| RFE | Пошаговый | Медленно | Хорошая | Точный отбор |
| SelectFromModel | Пороговый | Быстро | Отличная | Автоматический отбор |
Лучшие практики
1. ВСЕГДА стандартизируй признаки:
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
2. Используй кросс-валидацию для выбора параметра регуляризации:
lasso_cv = LassoCV(cv=5)
lasso_cv.fit(X_scaled, y)
3. Проверяй результаты на тестовом наборе:
test_score = model.score(X_test_scaled, y_test)
4. Если признаков больше 100, начни с Lasso:
lasso = Lasso(alpha=0.01)
lasso.fit(X_scaled, y)
selected = X.columns[np.abs(lasso.coef_) > 0.001]
В большинстве случаев Lasso с кросс-валидацией обеспечивает отличный баланс между простотой, скоростью и качеством отбора признаков.