|
Логистическая регрессия. Бинарная и многоклассовая классификация
ОП.10 Машинное обучение
Практическая работа №4
Тема: Логистическая регрессия. Бинарная и многоклассовая классификация
Цель работы: Научиться применять логистическую регрессию для задач бинарной и многоклассовой классификации, интерпретировать результаты, настраивать параметры.
Время выполнения: 2 академических часа
Инструменты: Python + Jupyter Notebook, sklearn, matplotlib, seaborn
ЗАДАНИЕ ДЛЯ СТУДЕНТА
Этап 1. Бинарная классификация на датасете Breast Cancer (15 минут)
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score, roc_curve, confusion_matrix
from sklearn.preprocessing import StandardScaler
# Загрузка данных
data = load_breast_cancer()
X = data.data
y = data.target
feature_names = data.feature_names
print(f"Размер данных: {X.shape}")
print(f"Классы: 0 - {data.target_names[0]}, 1 - {data.target_names[1]}")
print(f"Распределение классов:\n{pd.Series(y).value_counts()}")
# Нормализация
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# Разделение
X_train, X_test, y_train, y_test = train_test_split(
X_scaled, y, test_size=0.3, random_state=42, stratify=y
)
# Обучение модели
model = LogisticRegression(random_state=42, max_iter=1000)
model.fit(X_train, y_train)
# Предсказания
y_pred = model.predict(X_test)
y_pred_proba = model.predict_proba(X_test)[:, 1]
# Метрики
print("Результаты бинарной классификации:")
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-score: {f1_score(y_test, y_pred):.4f}")
print(f"AUC: {roc_auc_score(y_test, y_pred_proba):.4f}")
Вопрос: Какая метрика самая высокая? О чём это говорит?
Этап 2. Анализ коэффициентов модели (15 минут)
# Коэффициенты модели
coefficients = pd.DataFrame({
'feature': feature_names,
'coefficient': model.coef_[0]
})
coefficients = coefficients.sort_values('coefficient', ascending=False)
print("Топ-5 признаков, увеличивающих вероятность злокачественной опухоли:")
print(coefficients.head())
print("\nТоп-5 признаков, уменьшающих вероятность злокачественной опухоли:")
print(coefficients.tail())
# Визуализация коэффициентов
plt.figure(figsize=(12, 8))
plt.barh(coefficients['feature'].head(10), coefficients['coefficient'].head(10), color='red', alpha=0.7)
plt.barh(coefficients['feature'].tail(10), coefficients['coefficient'].tail(10), color='green', alpha=0.7)
plt.xlabel('Коэффициент')
plt.title('Влияние признаков на предсказание')
plt.axvline(x=0, color='black', linestyle='-', linewidth=0.5)
plt.tight_layout()
plt.show()
# Интерпретация
print("Интерпретация:")
print("Положительный коэффициент → увеличение признака → выше вероятность класса 1 (malignant)")
print("Отрицательный коэффициент → увеличение признака → ниже вероятность класса 1")
Вопрос: Какой признак сильнее всего влияет на предсказание? Как это интерпретировать?
Этап 3. Вероятности и порог принятия решений (15 минут)
# Предсказанные вероятности для первых 10 тестовых образцов
probas = y_pred_proba[:10]
preds = y_pred[:10]
true = y_test[:10]
print("Вероятности и предсказания:")
for i, (prob, pred, true_val) in enumerate(zip(probas, preds, true)):
print(f"Образец {i+1}: вероятность класса 1 = {prob:.3f}, предсказание = {pred}, истина = {true_val}")
# Анализ уверенности модели
plt.figure(figsize=(12, 5))
plt.subplot(1, 2, 1)
plt.hist(y_pred_proba[y_test == 0], bins=20, alpha=0.7, label='Класс 0 (benign)', color='green')
plt.hist(y_pred_proba[y_test == 1], bins=20, alpha=0.7, label='Класс 1 (malignant)', color='red')
plt.axvline(x=0.5, color='black', linestyle='--', label='Порог 0.5')
plt.xlabel('Вероятность класса 1')
plt.ylabel('Частота')
plt.title('Распределение предсказанных вероятностей')
plt.legend()
plt.subplot(1, 2, 2)
fpr, tpr, thresholds = roc_curve(y_test, y_pred_proba)
plt.plot(fpr, tpr, linewidth=2)
plt.plot([0, 1], [0, 1], 'r--')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC-кривая')
plt.show()
# Изменение порога
thresholds_to_try = [0.3, 0.4, 0.5, 0.6, 0.7]
print("\nВлияние порога классификации:")
for thresh in thresholds_to_try:
y_pred_thresh = (y_pred_proba >= thresh).astype(int)
acc = accuracy_score(y_test, y_pred_thresh)
print(f"Порог = {thresh}: Accuracy = {acc:.3f}, Precision = {precision_score(y_test, y_pred_thresh):.3f}, Recall = {recall_score(y_test, y_pred_thresh):.3f}")
Вопросы:
• Что произойдёт с Precision и Recall при понижении порога?
• Какой порог лучше выбрать, если важнее найти все злокачественные случаи?
Этап 4. Многоклассовая классификация (20 минут)
from sklearn.datasets import load_wine
from sklearn.metrics import classification_report
# Загрузка данных (3 класса)
wine = load_wine()
X_wine = wine.data
y_wine = wine.target
print("Датасет Wine (качество вина):")
print(f"Размер: {X_wine.shape}")
print(f"Классы: {wine.target_names}")
print(f"Распределение классов: {np.bincount(y_wine)}")
# Нормализация
X_wine_scaled = scaler.fit_transform(X_wine)
# Разделение
X_train_w, X_test_w, y_train_w, y_test_w = train_test_split(
X_wine_scaled, y_wine, test_size=0.3, random_state=42, stratify=y_wine
)
# Многоклассовая логистическая регрессия
# multi_class='ovr' - один против всех
model_ovr = LogisticRegression(multi_class='ovr', max_iter=1000, random_state=42)
model_ovr.fit(X_train_w, y_train_w)
y_pred_ovr = model_ovr.predict(X_test_w)
# multi_class='multinomial' - softmax
model_multinomial = LogisticRegression(multi_class='multinomial', max_iter=1000, random_state=42)
model_multinomial.fit(X_train_w, y_train_w)
y_pred_multinomial = model_multinomial.predict(X_test_w)
print("\nРезультаты (One-vs-Rest):")
print(f"Accuracy: {accuracy_score(y_test_w, y_pred_ovr):.4f}")
print(classification_report(y_test_w, y_pred_ovr, target_names=wine.target_names))
print("\nРезультаты (Multinomial / Softmax):")
print(f"Accuracy: {accuracy_score(y_test_w, y_pred_multinomial):.4f}")
print(classification_report(y_test_w, y_pred_multinomial, target_names=wine.target_names))
# Матрица ошибок
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
from sklearn.metrics import ConfusionMatrixDisplay
ConfusionMatrixDisplay.from_predictions(y_test_w, y_pred_ovr, ax=axes[0], cmap='Blues')
axes[0].set_title('One-vs-Rest')
ConfusionMatrixDisplay.from_predictions(y_test_w, y_pred_multinomial, ax=axes[1], cmap='Blues')
axes[1].set_title('Multinomial (Softmax)')
plt.tight_layout()
plt.show()
Вопросы:
• В чём разница между подходами 'ovr' и 'multinomial'?
• Какой подход показал лучший результат на этом датасете?
Этап 5. Кросс-валидация и подбор параметра C (20 минут)
from sklearn.model_selection import GridSearchCV
# Подбор параметра C
C_values = [0.001, 0.01, 0.1, 1, 10, 100, 1000]
cv_scores = []
for C in C_values:
model = LogisticRegression(C=C, max_iter=1000, random_state=42)
scores = cross_val_score(model, X_train, y_train, cv=5, scoring='accuracy')
cv_scores.append(scores.mean())
print(f"C={C}: CV accuracy = {scores.mean():.4f} (+/- {scores.std():.4f})")
# Визуализация
plt.figure(figsize=(10, 5))
plt.semilogx(C_values, cv_scores, 'o-', linewidth=2)
plt.xlabel('Параметр C (логарифмическая шкала)')
plt.ylabel('Средняя точность (CV)')
plt.title('Выбор оптимального параметра C')
plt.grid(True, alpha=0.3)
best_C = C_values[np.argmax(cv_scores)]
plt.axvline(x=best_C, color='r', linestyle='--', label=f'Лучший C = {best_C}')
plt.legend()
plt.show()
# Обучение с лучшим параметром
best_model = LogisticRegression(C=best_C, max_iter=1000, random_state=42)
best_model.fit(X_train, y_train)
y_pred_best = best_model.predict(X_test)
print(f"\nРезультаты с лучшим параметром C={best_C}:")
print(f"Accuracy: {accuracy_score(y_test, y_pred_best):.4f}")
print(f"F1-score: {f1_score(y_test, y_pred_best):.4f}")
Вопрос: Какой параметр C оказался оптимальным? Что означает малое и большое значение C?
Этап 6. Практическое задание (20 минут)
# Задание: предсказание класса ириса по признакам
from sklearn.datasets import load_iris
# Загрузка данных Iris
iris = load_iris()
X_iris = iris.data
y_iris = iris.target
print("Датасет Iris:")
print(f"Размер: {X_iris.shape}")
print(f"Классы: {iris.target_names}")
# Задание 1: Создайте DataFrame для удобного анализа
iris_df = pd.DataFrame(X_iris, columns=iris.feature_names)
iris_df['species'] = y_iris
print(iris_df.head())
# Задание 2: Нормализуйте данные и разделите на train/test (80/20)
X_iris_scaled = scaler.fit_transform(X_iris)
X_train_i, X_test_i, y_train_i, y_test_i = train_test_split(
X_iris_scaled, y_iris, test_size=0.2, random_state=42, stratify=y_iris
)
# Задание 3: Обучите модель логистической регрессии (multinomial)
model_iris = LogisticRegression(multi_class='multinomial', max_iter=1000, random_state=42)
model_iris.fit(X_train_i, y_train_i)
y_pred_i = model_iris.predict(X_test_i)
# Задание 4: Оцените качество
print(f"\nAccuracy на тесте: {accuracy_score(y_test_i, y_pred_i):.4f}")
print("Classification Report:")
print(classification_report(y_test_i, y_pred_i, target_names=iris.target_names))
# Задание 5: Матрица ошибок
ConfusionMatrixDisplay.from_predictions(y_test_i, y_pred_i, cmap='Blues')
plt.title('Матрица ошибок (Iris)')
plt.show()
# Задание 6: Предсказание для нового цветка
new_flower = np.array([[5.5, 2.8, 4.0, 1.2]]) # пример
new_flower_scaled = scaler.transform(new_flower)
prediction = model_iris.predict(new_flower_scaled)
print(f"Предсказание для нового цветка: {iris.target_names[prediction[0]]}")
Вопрос: Какой вид ириса был предсказан для нового цветка? Совпадает ли с вашей интуицией?
Этап 7. Выводы (10 минут)
Напишите вывод, ответив на вопросы:
1. Чем бинарная классификация отличается от многоклассовой?
2. Как интерпретировать коэффициенты логистической регрессии?
3. Как выбор порога классификации влияет на Precision и Recall?
4. Что даёт подбор параметра регуляризации C?
КРИТЕРИИ ОЦЕНКИ
Критерий |
Макс. балл |
|---|
Бинарная классификация выполнена |
2 |
Анализ коэффициентов проведён |
2 |
Анализ вероятностей и порога выполнен |
2 |
Многоклассовая классификация выполнена |
2 |
Кросс-валидация и подбор C выполнены |
1 |
Практическое задание выполнено и выводы написаны |
1 |
Итого |
10 |
Автор: УМК СПО
Лицензия: Бесплатное использование с указанием источника
|
|
|