{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Lab 4 Malafeev PIbd-31**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"1.Для начала выберем бизнес-цели для задач регрессии и классификации."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Классификация. Цель: определить, откликнется ли клиент на маркетинговую кампанию. Столбец целевой переменной - Response, 1 - откликнулся, 0 - нет. Признаки - Возраст, Уровень дохода. (Age, Income)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Регрессия. Цель: прогноз расходов клиента. Столбец целевой переменной: Total_Spending - общие расходы, будут считаться по всем расходам. Признаки такие же."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"2.Достижимый уровень качества:\n",
"Классификация:\n",
"Оценка метрики accuracy: ориентир 70-80% (с учетом ограниченных признаков).\n",
"Регрессия:\n",
"MSE (среднеквадратичная ошибка): минимизация, ориентир в зависимости от разброса целевой переменной.\n",
"R^2 > 0.6"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"3.Ориентир. Классификация:\n",
"DummyClassifier, предсказывающий самый частый класс, даст accuracy ~50-60%.\n",
"Регрессия:\n",
"Прогноз среднего значения целевой переменной."
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"X_class_train: (1568, 2), y_class_train: (1568,)\n",
"X_reg_train: (1568, 2), y_reg_train: (1568,)\n"
]
}
],
"source": [
"import pandas as pd\n",
"from sklearn.model_selection import train_test_split\n",
"from sklearn.preprocessing import StandardScaler\n",
"\n",
"data = pd.read_csv(\".//datasetlab1//marketing_campaign.csv\", sep=\"\\t\")\n",
"data2 = pd.read_csv(\".//datasetlab1//marketing_campaign2.csv\", sep=\"\\t\")\n",
"\n",
"# Преобразуем данные для классификации (дата для отклика на кампанию)\n",
"data['Age'] = 2024 - data['Year_Birth'] \n",
"data = data[['Age', 'Income', 'Response']] \n",
"\n",
"X_class = data[['Age', 'Income']]\n",
"y_class = data['Response']\n",
"\n",
"# Преобразуем данные для регрессии (прогноз расходов)\n",
"data2['Age'] = 2024 - data2['Year_Birth'] \n",
"data2['Total_Spending'] = (data2['MntWines'] + data2['MntFruits'] + data2['MntMeatProducts'] +\n",
" data2['MntFishProducts'] + data2['MntSweetProducts'] + data2['MntGoldProds'])\n",
"data2 = data2[['Age', 'Income', 'Total_Spending']] \n",
"\n",
"# Разделение на признаки и целевую переменную для регрессии\n",
"X_reg = data2[['Age', 'Income']]\n",
"y_reg = data2['Total_Spending']\n",
"\n",
"# Масштабирование данных\n",
"scaler = StandardScaler()\n",
"X_class_scaled = scaler.fit_transform(X_class)\n",
"X_reg_scaled = scaler.fit_transform(X_reg)\n",
"\n",
"# Разделение на тренировочные и тестовые выборки\n",
"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)\n",
"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)\n",
"\n",
"# Проверим, что все выглядит правильно\n",
"print(f\"X_class_train: {X_train_class.shape}, y_class_train: {y_train_class.shape}\")\n",
"print(f\"X_reg_train: {X_train_reg.shape}, y_reg_train: {y_train_reg.shape}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"5-6.Выбор трёх моделей и построение конвейера"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Logistic Regression - Средняя точность модели: 0.8475 ± 0.0027\n",
"Random Forest - Средняя точность модели: 0.8258 ± 0.0099\n",
"SVM - Средняя точность модели: 0.8529 ± 0.0027\n"
]
}
],
"source": [
"import numpy as np\n",
"from sklearn.model_selection import train_test_split, cross_val_score\n",
"from sklearn.preprocessing import StandardScaler\n",
"from sklearn.impute import SimpleImputer\n",
"from sklearn.linear_model import LogisticRegression\n",
"from sklearn.ensemble import RandomForestClassifier\n",
"from sklearn.svm import SVC\n",
"from sklearn.pipeline import Pipeline\n",
"\n",
"# Удаляем строки с пропущенными значениями\n",
"X_class_scaled = X_class.dropna()\n",
"y_class = y_class[X_class_scaled.index]\n",
"\n",
"models = [\n",
" ('Logistic Regression', LogisticRegression(max_iter=1000)),\n",
" ('Random Forest', RandomForestClassifier(n_estimators=100)),\n",
" ('SVM', SVC())\n",
"]\n",
"\n",
"# Создаем конвейер\n",
"imputer = SimpleImputer(strategy='mean') \n",
"scaler = StandardScaler()\n",
"\n",
"for name, model in models:\n",
" pipe = Pipeline([\n",
" ('imputer', imputer),\n",
" ('scaler', scaler),\n",
" ('classifier', model)\n",
" ])\n",
" \n",
" scores = cross_val_score(pipe, X_class_scaled, y_class, cv=5, scoring='accuracy')\n",
" print(f\"{name} - Средняя точность модели: {scores.mean():.4f} ± {scores.std():.4f}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Вот такие модели и конвейр я выбрал: Imputer: Заполняет пропущенные значения средним (если они есть).\n",
"Scaler: Масштабирует данные с помощью StandardScaler.\n",
"Classifier: Используются три модели:\n",
"LogisticRegression: Логистическая регрессия.\n",
"RandomForestClassifier: Случайный лес.\n",
"SVC: Метод опорных векторов (SVM)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"7.Теперь сделаем настройку гиперпараметров."
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Fitting 5 folds for each of 6 candidates, totalling 30 fits\n",
"Logistic Regression - Лучшие гиперпараметры: {'classifier__C': 0.1, 'classifier__solver': 'lbfgs'}\n",
"Logistic Regression - Лучшая точность: 0.8484\n",
"--------------------------------------------------\n",
"Fitting 5 folds for each of 9 candidates, totalling 45 fits\n",
"Random Forest - Лучшие гиперпараметры: {'classifier__max_depth': 10, 'classifier__n_estimators': 100}\n",
"Random Forest - Лучшая точность: 0.8520\n",
"--------------------------------------------------\n",
"Fitting 5 folds for each of 6 candidates, totalling 30 fits\n",
"SVM - Лучшие гиперпараметры: {'classifier__C': 1, 'classifier__kernel': 'rbf'}\n",
"SVM - Лучшая точность: 0.8529\n",
"--------------------------------------------------\n"
]
}
],
"source": [
"from sklearn.model_selection import GridSearchCV\n",
"models = [\n",
" ('Logistic Regression', LogisticRegression(max_iter=1000), {'classifier__C': [0.1, 1, 10], 'classifier__solver': ['lbfgs', 'liblinear']}),\n",
" ('Random Forest', RandomForestClassifier(n_estimators=100), {'classifier__n_estimators': [50, 100, 200], 'classifier__max_depth': [10, 20, None]}),\n",
" ('SVM', SVC(), {'classifier__C': [0.1, 1, 10], 'classifier__kernel': ['linear', 'rbf']})\n",
"]\n",
"\n",
"for name, model, param_grid in models:\n",
" pipe = Pipeline([\n",
" ('imputer', imputer),\n",
" ('scaler', scaler),\n",
" ('classifier', model)\n",
" ])\n",
" \n",
" grid_search = GridSearchCV(pipe, param_grid, cv=5, scoring='accuracy', n_jobs=-1, verbose=1)\n",
" grid_search.fit(X_class_scaled, y_class)\n",
"\n",
" print(f\"{name} - Лучшие гиперпараметры: {grid_search.best_params_}\")\n",
" print(f\"{name} - Лучшая точность: {grid_search.best_score_:.4f}\")\n",
" print(\"-\" * 50)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Тут мы проходим по моделям и настраиваем гиперпараметры с помощью GridSearchCV с помощью кросс-валидации. Параметры: cv=5: 5 фолдов для кросс-валидации.\n",
"scoring='accuracy': Мы используем точность как метрику.\n",
"n_jobs=-1: Используем все доступные процессоры для ускорения вычислений.\n",
"verbose=1: Подробный вывод процесса."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"8.Обучим модели"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Fitting 5 folds for each of 6 candidates, totalling 30 fits\n",
"Fitting 5 folds for each of 6 candidates, totalling 30 fits\n",
"Fitting 5 folds for each of 6 candidates, totalling 30 fits\n"
]
}
],
"source": [
"best_models = {} \n",
"for name, model, param_grid in models: \n",
" grid_search.fit(X_class_scaled, y_class)\n",
" best_models[name] = grid_search.best_estimator_ \n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"9.Оценим модели."
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {},
"outputs": [],
"source": [
"from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score\n",
"from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score\n",
"\n",
"# Оценка качества классификации\n",
"for name, model in best_models.items():\n",
" y_pred_class = model.predict(X_class_scaled) # Предсказание для классификации\n",
"\n",
"# Оценка качества регрессии\n",
"for name, model in best_models.items():\n",
" y_pred_reg = model.predict(X_reg_scaled) # Предсказание для регрессии\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Т.к. вывод слишком длинный, приложу его тут(вылазит Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...):
Оценка качества для модели Logistic Regression:
\n",
"Accuracy: 0.8528880866425993
\n",
"Precision: 0.8181818181818182
\n",
"Recall: 0.02702702702702703
\n",
"F1-Score: 0.05232558139534884
\n",
"ROC AUC: Не поддерживается для этой модели
\n",
"
\n",
"
\n",
"Оценка качества для модели Random Forest:
\n",
"Accuracy: 0.8528880866425993
\n",
"Precision: 0.8181818181818182
\n",
"Recall: 0.02702702702702703
\n",
"F1-Score: 0.05232558139534884
\n",
"ROC AUC: Не поддерживается для этой модели
\n",
"
\n",
"
\n",
"Оценка качества для модели SVM:
\n",
"Accuracy: 0.8528880866425993
\n",
"Precision: 0.8181818181818182
\n",
"Recall: 0.02702702702702703
\n",
"F1-Score: 0.05232558139534884
\n",
"ROC AUC: Не поддерживается для этой модели
\n",
"
\n",
"
Задача регрессии:
\n",
"Оценка качества для модели Logistic Regression:
\n",
"MAE: 605.7982142857143
\n",
"MSE: 729533.7598214286
\n",
"RMSE: 854.1274845252485
\n",
"R²: -1.0122722045012051
\n",
"
\n",
"
\n",
"Оценка качества для модели Random Forest:
\n",
"MAE: 605.7982142857143
\n",
"MSE: 729533.7598214286
\n",
"RMSE: 854.1274845252485
\n",
"R²: -1.0122722045012051
\n",
"
\n",
"
\n",
"Оценка качества для модели SVM:
\n",
"MAE: 605.7982142857143
\n",
"MSE: 729533.7598214286
\n",
"RMSE: 854.1274845252485
\n",
"R²: -1.0122722045012051
\n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Почему выбрал эти метирки:
Классификация (Отклик на предложение)
\n",
"Целевая переменная — бинарная (0 и 1), где 1 — откликнулся, а 0 — не откликнулся. Для классификации подходящими метриками являются:
\n",
"
\n",
"Accuracy (Точность):\n",
"Это доля правильно классифицированных объектов среди всех. \n",
"Подходит для оценки общей эффективности модели. Однако важно учитывать, что если классы несбалансированы, точность может быть обманчивой.
\n",
"Precision (Точность):\n",
"\n",
"Это доля истинных положительных случаев среди всех предсказанных положительных случаев.\n",
"Важна для задач, где важно минимизировать количество ложных срабатываний, например, когда модель ошибочно классифицирует клиента как откликнувшегося (True Positive).
\n",
"Recall (Полнота):\n",
"\n",
"Это доля истинных положительных случаев среди всех истинных положительных случаев.\n",
"Важно для задач, где важно не пропустить откликнувшихся клиентов (False Negatives).
\n",
"F1-Score:\n",
"\n",
"Это гармоническое среднее между точностью и полнотой.\n",
"Подходит для оценки моделей в случаях, когда важно иметь баланс между точностью и полнотой, особенно в ситуациях с несбалансированными классами.
\n",
"ROC AUC:\n",
"Площадь под кривой ROC, которая отображает способность модели различать положительные и отрицательные классы.\n",
"Чем выше значение AUC, тем лучше модель справляется с разделением классов."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Регрессия (Прогноз расходов)
\n",
"Целевая переменная — это числовое значение (расходы клиента). Для задач регрессии используются другие метрики:
\n",
"\n",
"Mean Absolute Error (MAE):\n",
"\n",
"Это средняя абсолютная ошибка предсказания.\n",
"Простой и интерпретируемый показатель, который описывает среднее отклонение предсказанных значений от фактических.
\n",
"Mean Squared Error (MSE):\n",
"\n",
"Это средняя квадратичная ошибка.\n",
"Чувствителен к большим ошибкам, так как квадратичный штраф увеличивает вес больших отклонений, что полезно, если вы хотите минимизировать большие ошибки.
\n",
"Root Mean Squared Error (RMSE):\n",
"\n",
"Это квадратный корень из MSE.\n",
"Подходит для задач, где важно учитывать большие ошибки, так как более чувствителен к выбросам.
\n",
"R-squared (R²):\n",
"\n",
"Это коэффициент детерминации, который показывает, какая доля дисперсии целевой переменной объясняется моделью.\n",
"R² может быть полезен для оценки того, насколько хорошо модель объясняет вариацию целевой переменной, но не всегда подходит, если модель имеет много выбросов или некорректно подогнана.
"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"9.Оценка"
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Evaluating model: Logistic Regression\n",
"Train Accuracy: 0.8476, Test Accuracy: 0.8586\n",
"Bias: 0.0000, Variance: 0.0000\n",
"Train Error (MSE): 732205.3240, Test Error (MSE): 723300.1101\n",
"Bias: 0.0000, Variance: 0.0000\n",
"Evaluating model: Random Forest\n",
"Train Accuracy: 0.8476, Test Accuracy: 0.8586\n",
"Bias: 0.0000, Variance: 0.0000\n",
"Train Error (MSE): 732205.3240, Test Error (MSE): 723300.1101\n",
"Bias: 0.0000, Variance: 0.0000\n",
"Evaluating model: SVM\n",
"Train Accuracy: 0.8476, Test Accuracy: 0.8586\n",
"Bias: 0.0000, Variance: 0.0000\n",
"Train Error (MSE): 732205.3240, Test Error (MSE): 723300.1101\n",
"Bias: 0.0000, Variance: 0.0000\n"
]
}
],
"source": [
"import numpy as np\n",
"from sklearn.metrics import mean_squared_error, accuracy_score\n",
"\n",
"# Оценка смещения и дисперсии для классификации и регрессии\n",
"def evaluate_bias_variance(model, X_train, y_train, X_test, y_test, task='classification'):\n",
" # Прогнозы на обучающих и тестовых данных\n",
" y_train_pred = model.predict(X_train)\n",
" y_test_pred = model.predict(X_test)\n",
"\n",
" if task == 'classification':\n",
" # Для классификации считаем точность\n",
" train_accuracy = accuracy_score(y_train, y_train_pred)\n",
" test_accuracy = accuracy_score(y_test, y_test_pred)\n",
" print(f\"Train Accuracy: {train_accuracy:.4f}, Test Accuracy: {test_accuracy:.4f}\")\n",
" elif task == 'regression':\n",
" # Для регрессии считаем среднеквадратичную ошибку (MSE)\n",
" train_error = mean_squared_error(y_train, y_train_pred)\n",
" test_error = mean_squared_error(y_test, y_test_pred)\n",
" print(f\"Train Error (MSE): {train_error:.4f}, Test Error (MSE): {test_error:.4f}\")\n",
"\n",
" # Для оценки смещения и дисперсии на тестовых данных\n",
" bias = np.mean(y_test_pred - y_train_pred[:len(y_test_pred)]) # Смещение: разница между тестом и обучением\n",
" variance = np.var(y_test_pred - y_train_pred[:len(y_test_pred)]) # Дисперсия: варьирование прогнозов\n",
"\n",
" print(f\"Bias: {bias:.4f}, Variance: {variance:.4f}\")\n",
"\n",
"# Оценим для каждой из моделей\n",
"for name, model in best_models.items():\n",
" print(f\"Evaluating model: {name}\")\n",
" # Для классификации\n",
" evaluate_bias_variance(model, X_train_class, y_train_class, X_test_class, y_test_class, task='classification') \n",
" # Для регрессии\n",
" evaluate_bias_variance(model, X_train_reg, y_train_reg, X_test_reg, y_test_reg, task='regression') \n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Конец"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "miivenv",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.5"
}
},
"nbformat": 4,
"nbformat_minor": 2
}