AIM-PIbd-31-Malafeev-L-S/lab_4/lab4.ipynb

22 KiB
Raw Permalink Blame History

Lab 4 Malafeev PIbd-31

1.Для начала выберем бизнес-цели для задач регрессии и классификации.

Классификация. Цель: определить, откликнется ли клиент на маркетинговую кампанию. Столбец целевой переменной - Response, 1 - откликнулся, 0 - нет. Признаки - Возраст, Уровень дохода. (Age, Income)

Регрессия. Цель: прогноз расходов клиента. Столбец целевой переменной: Total_Spending - общие расходы, будут считаться по всем расходам. Признаки такие же.

2.Достижимый уровень качества: Классификация: Оценка метрики accuracy: ориентир 70-80% (с учетом ограниченных признаков). Регрессия: MSE (среднеквадратичная ошибка): минимизация, ориентир в зависимости от разброса целевой переменной. R^2 > 0.6

3.Ориентир. Классификация: DummyClassifier, предсказывающий самый частый класс, даст accuracy ~50-60%. Регрессия: Прогноз среднего значения целевой переменной.

In [29]:
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

data = pd.read_csv(".//datasetlab1//marketing_campaign.csv", sep="\t")
data2 = pd.read_csv(".//datasetlab1//marketing_campaign2.csv", sep="\t")

# Преобразуем данные для классификации (дата для отклика на кампанию)
data['Age'] = 2024 - data['Year_Birth'] 
data = data[['Age', 'Income', 'Response']] 

X_class = data[['Age', 'Income']]
y_class = data['Response']

# Преобразуем данные для регрессии (прогноз расходов)
data2['Age'] = 2024 - data2['Year_Birth']  
data2['Total_Spending'] = (data2['MntWines'] + data2['MntFruits'] + data2['MntMeatProducts'] +
                           data2['MntFishProducts'] + data2['MntSweetProducts'] + data2['MntGoldProds'])
data2 = data2[['Age', 'Income', 'Total_Spending']]  

# Разделение на признаки и целевую переменную для регрессии
X_reg = data2[['Age', 'Income']]
y_reg = data2['Total_Spending']

# Масштабирование данных
scaler = StandardScaler()
X_class_scaled = scaler.fit_transform(X_class)
X_reg_scaled = scaler.fit_transform(X_reg)

# Разделение на тренировочные и тестовые выборки
X_train_class, X_test_class, y_train_class, y_test_class = train_test_split(X_class_scaled, y_class, test_size=0.3, random_state=42)
X_train_reg, X_test_reg, y_train_reg, y_test_reg = train_test_split(X_reg_scaled, y_reg, test_size=0.3, random_state=42)

# Проверим, что все выглядит правильно
print(f"X_class_train: {X_train_class.shape}, y_class_train: {y_train_class.shape}")
print(f"X_reg_train: {X_train_reg.shape}, y_reg_train: {y_train_reg.shape}")
X_class_train: (1568, 2), y_class_train: (1568,)
X_reg_train: (1568, 2), y_reg_train: (1568,)

5-6.Выбор трёх моделей и построение конвейера

In [ ]:
import numpy as np
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.impute import SimpleImputer
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
from sklearn.pipeline import Pipeline

# Удаляем строки с пропущенными значениями
X_class_scaled = X_class.dropna()
y_class = y_class[X_class_scaled.index]

models = [
    ('Logistic Regression', LogisticRegression(max_iter=1000)),
    ('Random Forest', RandomForestClassifier(n_estimators=100)),
    ('SVM', SVC())
]

# Создаем конвейер
imputer = SimpleImputer(strategy='mean') 
scaler = StandardScaler()

for name, model in models:
    pipe = Pipeline([
        ('imputer', imputer),
        ('scaler', scaler),
        ('classifier', model)
    ])
    
    scores = cross_val_score(pipe, X_class_scaled, y_class, cv=5, scoring='accuracy')
    print(f"{name} - Средняя точность модели: {scores.mean():.4f} ± {scores.std():.4f}")
Logistic Regression - Средняя точность модели: 0.8475 ± 0.0027
Random Forest - Средняя точность модели: 0.8258 ± 0.0099
SVM - Средняя точность модели: 0.8529 ± 0.0027

Вот такие модели и конвейр я выбрал: Imputer: Заполняет пропущенные значения средним (если они есть). Scaler: Масштабирует данные с помощью StandardScaler. Classifier: Используются три модели: LogisticRegression: Логистическая регрессия. RandomForestClassifier: Случайный лес. SVC: Метод опорных векторов (SVM).

7.Теперь сделаем настройку гиперпараметров.

In [32]:
from sklearn.model_selection import GridSearchCV
models = [
    ('Logistic Regression', LogisticRegression(max_iter=1000), {'classifier__C': [0.1, 1, 10], 'classifier__solver': ['lbfgs', 'liblinear']}),
    ('Random Forest', RandomForestClassifier(n_estimators=100), {'classifier__n_estimators': [50, 100, 200], 'classifier__max_depth': [10, 20, None]}),
    ('SVM', SVC(), {'classifier__C': [0.1, 1, 10], 'classifier__kernel': ['linear', 'rbf']})
]

for name, model, param_grid in models:
    pipe = Pipeline([
        ('imputer', imputer),
        ('scaler', scaler),
        ('classifier', model)
    ])
    
    grid_search = GridSearchCV(pipe, param_grid, cv=5, scoring='accuracy', n_jobs=-1, verbose=1)
    grid_search.fit(X_class_scaled, y_class)

    print(f"{name} - Лучшие гиперпараметры: {grid_search.best_params_}")
    print(f"{name} - Лучшая точность: {grid_search.best_score_:.4f}")
    print("-" * 50)
Fitting 5 folds for each of 6 candidates, totalling 30 fits
Logistic Regression - Лучшие гиперпараметры: {'classifier__C': 0.1, 'classifier__solver': 'lbfgs'}
Logistic Regression - Лучшая точность: 0.8484
--------------------------------------------------
Fitting 5 folds for each of 9 candidates, totalling 45 fits
Random Forest - Лучшие гиперпараметры: {'classifier__max_depth': 10, 'classifier__n_estimators': 100}
Random Forest - Лучшая точность: 0.8520
--------------------------------------------------
Fitting 5 folds for each of 6 candidates, totalling 30 fits
SVM - Лучшие гиперпараметры: {'classifier__C': 1, 'classifier__kernel': 'rbf'}
SVM - Лучшая точность: 0.8529
--------------------------------------------------

Тут мы проходим по моделям и настраиваем гиперпараметры с помощью GridSearchCV с помощью кросс-валидации. Параметры: cv=5: 5 фолдов для кросс-валидации. scoring='accuracy': Мы используем точность как метрику. n_jobs=-1: Используем все доступные процессоры для ускорения вычислений. verbose=1: Подробный вывод процесса.

8.Обучим модели

In [34]:
best_models = {} 
for name, model, param_grid in models: 
    grid_search.fit(X_class_scaled, y_class)
    best_models[name] = grid_search.best_estimator_
Fitting 5 folds for each of 6 candidates, totalling 30 fits
Fitting 5 folds for each of 6 candidates, totalling 30 fits
Fitting 5 folds for each of 6 candidates, totalling 30 fits

9.Оценим модели.

In [41]:
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score

# Оценка качества классификации
for name, model in best_models.items():
    y_pred_class = model.predict(X_class_scaled)  # Предсказание для классификации

# Оценка качества регрессии
for name, model in best_models.items():
    y_pred_reg = model.predict(X_reg_scaled)  # Предсказание для регрессии

Т.к. вывод слишком длинный, приложу его тут(вылазит Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...):
Оценка качества для модели Logistic Regression:
Accuracy: 0.8528880866425993
Precision: 0.8181818181818182
Recall: 0.02702702702702703
F1-Score: 0.05232558139534884
ROC AUC: Не поддерживается для этой модели


Оценка качества для модели Random Forest:
Accuracy: 0.8528880866425993
Precision: 0.8181818181818182
Recall: 0.02702702702702703
F1-Score: 0.05232558139534884
ROC AUC: Не поддерживается для этой модели


Оценка качества для модели SVM:
Accuracy: 0.8528880866425993
Precision: 0.8181818181818182
Recall: 0.02702702702702703
F1-Score: 0.05232558139534884
ROC AUC: Не поддерживается для этой модели


Задача регрессии:
Оценка качества для модели Logistic Regression:
MAE: 605.7982142857143
MSE: 729533.7598214286
RMSE: 854.1274845252485
R²: -1.0122722045012051


Оценка качества для модели Random Forest:
MAE: 605.7982142857143
MSE: 729533.7598214286
RMSE: 854.1274845252485
R²: -1.0122722045012051


Оценка качества для модели SVM:
MAE: 605.7982142857143
MSE: 729533.7598214286
RMSE: 854.1274845252485
R²: -1.0122722045012051

Почему выбрал эти метирки:
Классификация (Отклик на предложение)
Целевая переменная — бинарная (0 и 1), где 1 — откликнулся, а 0 — не откликнулся. Для классификации подходящими метриками являются:

Accuracy (Точность): Это доля правильно классифицированных объектов среди всех. Подходит для оценки общей эффективности модели. Однако важно учитывать, что если классы несбалансированы, точность может быть обманчивой.
Precision (Точность):

Это доля истинных положительных случаев среди всех предсказанных положительных случаев. Важна для задач, где важно минимизировать количество ложных срабатываний, например, когда модель ошибочно классифицирует клиента как откликнувшегося (True Positive).
Recall (Полнота):

Это доля истинных положительных случаев среди всех истинных положительных случаев. Важно для задач, где важно не пропустить откликнувшихся клиентов (False Negatives).
F1-Score:

Это гармоническое среднее между точностью и полнотой. Подходит для оценки моделей в случаях, когда важно иметь баланс между точностью и полнотой, особенно в ситуациях с несбалансированными классами.
ROC AUC: Площадь под кривой ROC, которая отображает способность модели различать положительные и отрицательные классы. Чем выше значение AUC, тем лучше модель справляется с разделением классов.

Регрессия (Прогноз расходов)
Целевая переменная — это числовое значение (расходы клиента). Для задач регрессии используются другие метрики:

Mean Absolute Error (MAE):

Это средняя абсолютная ошибка предсказания. Простой и интерпретируемый показатель, который описывает среднее отклонение предсказанных значений от фактических.
Mean Squared Error (MSE):

Это средняя квадратичная ошибка. Чувствителен к большим ошибкам, так как квадратичный штраф увеличивает вес больших отклонений, что полезно, если вы хотите минимизировать большие ошибки.
Root Mean Squared Error (RMSE):

Это квадратный корень из MSE. Подходит для задач, где важно учитывать большие ошибки, так как более чувствителен к выбросам.
R-squared (R²):

Это коэффициент детерминации, который показывает, какая доля дисперсии целевой переменной объясняется моделью. R² может быть полезен для оценки того, насколько хорошо модель объясняет вариацию целевой переменной, но не всегда подходит, если модель имеет много выбросов или некорректно подогнана.

9.Оценка

In [45]:
import numpy as np
from sklearn.metrics import mean_squared_error, accuracy_score

# Оценка смещения и дисперсии для классификации и регрессии
def evaluate_bias_variance(model, X_train, y_train, X_test, y_test, task='classification'):
    # Прогнозы на обучающих и тестовых данных
    y_train_pred = model.predict(X_train)
    y_test_pred = model.predict(X_test)

    if task == 'classification':
        # Для классификации считаем точность
        train_accuracy = accuracy_score(y_train, y_train_pred)
        test_accuracy = accuracy_score(y_test, y_test_pred)
        print(f"Train Accuracy: {train_accuracy:.4f}, Test Accuracy: {test_accuracy:.4f}")
    elif task == 'regression':
        # Для регрессии считаем среднеквадратичную ошибку (MSE)
        train_error = mean_squared_error(y_train, y_train_pred)
        test_error = mean_squared_error(y_test, y_test_pred)
        print(f"Train Error (MSE): {train_error:.4f}, Test Error (MSE): {test_error:.4f}")

    # Для оценки смещения и дисперсии на тестовых данных
    bias = np.mean(y_test_pred - y_train_pred[:len(y_test_pred)])  # Смещение: разница между тестом и обучением
    variance = np.var(y_test_pred - y_train_pred[:len(y_test_pred)])  # Дисперсия: варьирование прогнозов

    print(f"Bias: {bias:.4f}, Variance: {variance:.4f}")

# Оценим для каждой из моделей
for name, model in best_models.items():
    print(f"Evaluating model: {name}")
    # Для классификации
    evaluate_bias_variance(model, X_train_class, y_train_class, X_test_class, y_test_class, task='classification')  
    # Для регрессии
    evaluate_bias_variance(model, X_train_reg, y_train_reg, X_test_reg, y_test_reg, task='regression')
Evaluating model: Logistic Regression
Train Accuracy: 0.8476, Test Accuracy: 0.8586
Bias: 0.0000, Variance: 0.0000
Train Error (MSE): 732205.3240, Test Error (MSE): 723300.1101
Bias: 0.0000, Variance: 0.0000
Evaluating model: Random Forest
Train Accuracy: 0.8476, Test Accuracy: 0.8586
Bias: 0.0000, Variance: 0.0000
Train Error (MSE): 732205.3240, Test Error (MSE): 723300.1101
Bias: 0.0000, Variance: 0.0000
Evaluating model: SVM
Train Accuracy: 0.8476, Test Accuracy: 0.8586
Bias: 0.0000, Variance: 0.0000
Train Error (MSE): 732205.3240, Test Error (MSE): 723300.1101
Bias: 0.0000, Variance: 0.0000

Конец