Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Lab3_3352_ГарееваКР.docx
Скачиваний:
0
Добавлен:
24.01.2026
Размер:
60.95 Mб
Скачать

Кривые для оценки качества классификации бетона

Программа:

print("\nROC-КРИВЫЕ ДЛЯ ОЦЕНКИ КАЧЕСТВА КЛАССИФИКАЦИИ БЕТОНА")

if 'y_pred_proba_knn' not in locals() and 'y_pred_proba_knn' not in globals():

print("ОШИБКА: Вероятности предсказаний kNN не найдены")

print("Убедитесь, что модель kNN была обучена с predict_proba")

elif 'y_pred_proba_tree' not in locals() and 'y_pred_proba_tree' not in globals():

print("ОШИБКА: Вероятности предсказаний дерева не найдены")

print("Убедитесь, что модель дерева была обучена с predict_proba")

else:

print("✓ Вероятности предсказаний найдены для обеих моделей")

classes = np.unique(y_test)

y_test_bin = label_binarize(y_test, classes=classes)

n_classes = y_test_bin.shape[1]

print(f"\nПАРАМЕТРЫ АНАЛИЗА:")

print(f" Количество классов: {n_classes}")

print(f" Классы: {classes}")

print(f" Размер тестовой выборки: {len(y_test)}")

print("\nВЫЧИСЛЕНИЕ ROC-КРИВЫХ:")

fpr_knn = dict()

tpr_knn = dict()

roc_auc_knn = dict()

for i in range(n_classes):

fpr_knn[i], tpr_knn[i], _ = roc_curve(y_test_bin[:, i], y_pred_proba_knn[:, i])

roc_auc_knn[i] = auc(fpr_knn[i], tpr_knn[i])

print(f" kNN - Класс {i} (AUC = {roc_auc_knn[i]:.4f})")

fpr_tree = dict()

tpr_tree = dict()

roc_auc_tree = dict()

for i in range(n_classes):

fpr_tree[i], tpr_tree[i], _ = roc_curve(y_test_bin[:, i], y_pred_proba_tree[:, i])

roc_auc_tree[i] = auc(fpr_tree[i], tpr_tree[i])

print(f" Дерево - Класс {i} (AUC = {roc_auc_tree[i]:.4f})")

class_names = [str(cls) for cls in le_strength.classes_]

print("\nВИЗУАЛИЗАЦИЯ ROC-КРИВЫХ:")

fig, axes = plt.subplots(1, 2, figsize=(16, 6))

colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7']

ax1 = axes[0]

for i, color in zip(range(n_classes), colors):

ax1.plot(fpr_knn[i], tpr_knn[i], color=color, lw=2.5, alpha=0.8,

label=f'{class_names[i]} (AUC = {roc_auc_knn[i]:.2f})')

ax1.plot([0, 1], [0, 1], 'k--', lw=2, alpha=0.6)

ax1.set_xlim([0.0, 1.0])

ax1.set_ylim([0.0, 1.05])

ax1.set_xlabel('False Positive Rate (Ложноположительная доля)', fontsize=11)

ax1.set_ylabel('True Positive Rate (Истинноположительная доля)', fontsize=11)

ax1.set_title('ROC-кривые - kNN\n(Метод k-ближайших соседей)',

fontsize=13, fontweight='bold', pad=15)

ax1.legend(loc="lower right", fontsize=10)

ax1.grid(True, alpha=0.3)

mean_auc_knn = np.mean(list(roc_auc_knn.values()))

ax1.text(0.6, 0.1, f'Средний AUC: {mean_auc_knn:.3f}',

transform=ax1.transAxes, fontsize=11,

bbox=dict(boxstyle='round', facecolor='white', alpha=0.8))

ax2 = axes[1]

for i, color in zip(range(n_classes), colors):

ax2.plot(fpr_tree[i], tpr_tree[i], color=color, lw=2.5, alpha=0.8,

label=f'{class_names[i]} (AUC = {roc_auc_tree[i]:.2f})')

ax2.plot([0, 1], [0, 1], 'k--', lw=2, alpha=0.6)

ax2.set_xlim([0.0, 1.0])

ax2.set_ylim([0.0, 1.05])

ax2.set_xlabel('False Positive Rate (Ложноположительная доля)', fontsize=11)

ax2.set_ylabel('True Positive Rate (Истинноположительная доля)', fontsize=11)

ax2.set_title('ROC-кривые - Дерево решений\n(Метод дерева решений)',

fontsize=13, fontweight='bold', pad=15)

ax2.legend(loc="lower right", fontsize=10)

ax2.grid(True, alpha=0.3)

# Добавляем информацию о качестве

mean_auc_tree = np.mean(list(roc_auc_tree.values()))

ax2.text(0.6, 0.1, f'Средний AUC: {mean_auc_tree:.3f}',

transform=ax2.transAxes, fontsize=11,

bbox=dict(boxstyle='round', facecolor='white', alpha=0.8))

plt.suptitle('СРАВНЕНИЕ ROC-КРИВЫХ ДЛЯ КЛАССИФИКАЦИИ ПРОЧНОСТИ БЕТОНА',

fontsize=15, fontweight='bold', y=1.02)

plt.tight_layout()

plt.show()

print("\nСРАВНИТЕЛЬНЫЙ АНАЛИЗ AUC:")

print("=" * 40)

print(f"\n{'Класс':<15} {'kNN AUC':<12} {'Дерево AUC':<12} {'Разница':<10}")

print("-" * 55)

for i, cls_name in enumerate(class_names):

knn_auc = roc_auc_knn[i]

tree_auc = roc_auc_tree[i]

diff = knn_auc - tree_auc

diff_str = f"{diff:+.3f}"

if knn_auc > tree_auc:

best = "✓ kNN"

elif tree_auc > knn_auc:

best = "✓ Дерево"

else:

best = "≡ Одинаково"

print(f"{cls_name:<15} {knn_auc:<12.3f} {tree_auc:<12.3f} {diff_str:<10} {best}")

print("-" * 55)

print(f"{'Средний AUC':<15} {mean_auc_knn:<12.3f} {mean_auc_tree:<12.3f} "

f"{mean_auc_knn - mean_auc_tree:+.3f}")

print(f"\nИНТЕРПРЕТАЦИЯ AUC:")

def interpret_auc(auc_value):

if auc_value >= 0.9:

return "Отличное качество"

elif auc_value >= 0.8:

return "Хорошее качество"

elif auc_value >= 0.7:

return "Удовлетворительное качество"

elif auc_value >= 0.6:

return "Плохое качество"

else:

return "Очень плохое качество (не лучше случайного)"

print(f"kNN (средний AUC = {mean_auc_knn:.3f}): {interpret_auc(mean_auc_knn)}")

print(f"Дерево (средний AUC = {mean_auc_tree:.3f}): {interpret_auc(mean_auc_tree)}")

print(f"\nДОПОЛНИТЕЛЬНЫЙ АНАЛИЗ:")

y_test_bin_flat = y_test_bin.ravel()

y_pred_proba_knn_flat = y_pred_proba_knn.ravel()

y_pred_proba_tree_flat = y_pred_proba_tree.ravel()

fpr_knn_micro, tpr_knn_micro, _ = roc_curve(y_test_bin_flat, y_pred_proba_knn_flat)

roc_auc_knn_micro = auc(fpr_knn_micro, tpr_knn_micro)

fpr_tree_micro, tpr_tree_micro, _ = roc_curve(y_test_bin_flat, y_pred_proba_tree_flat)

roc_auc_tree_micro = auc(fpr_tree_micro, tpr_tree_micro)

print(f"Микро-усредненный AUC:")

print(f" kNN: {roc_auc_knn_micro:.4f}")

print(f" Дерево: {roc_auc_tree_micro:.4f}")

fig, ax = plt.subplots(figsize=(10, 8))

ax.plot(fpr_knn_micro, tpr_knn_micro,

label=f'kNN микро-усредненный (AUC = {roc_auc_knn_micro:.2f})',

color='blue', lw=3, alpha=0.7)

ax.plot(fpr_tree_micro, tpr_tree_micro,

label=f'Дерево микро-усредненный (AUC = {roc_auc_tree_micro:.2f})',

color='green', lw=3, alpha=0.7)

for i, color in zip(range(n_classes), colors):

ax.plot(fpr_knn[i], tpr_knn[i], color=color, lw=1, alpha=0.3, linestyle='--')

ax.plot(fpr_tree[i], tpr_tree[i], color=color, lw=1, alpha=0.3, linestyle='--')

ax.plot([0, 1], [0, 1], 'k--', lw=2, alpha=0.6, label='Случайный классификатор')

ax.set_xlim([0.0, 1.0])

ax.set_ylim([0.0, 1.05])

ax.set_xlabel('False Positive Rate', fontsize=12)

ax.set_ylabel('True Positive Rate', fontsize=12)

ax.set_title('Микро-усредненные ROC-кривые с индивидуальными кривыми классов',

fontsize=14, fontweight='bold', pad=15)

ax.legend(loc="lower right", fontsize=10)

ax.grid(True, alpha=0.3)

plt.tight_layout()

plt.show()

print(f"\nВЫВОДЫ И РЕКОМЕНДАЦИИ ДЛЯ БЕТОНА:")

print("=" * 40)

if mean_auc_knn > mean_auc_tree:

print("kNN показывает лучшее качество по ROC-кривым")

print(" Модель лучше различает классы прочности бетона")

print(" Рекомендуется использовать kNN для точной классификации")

elif mean_auc_tree > mean_auc_knn:

print("Дерево решений показывает лучшее качество по ROC-кривым")

print(" Модель лучше разделяет классы по пороговым значениям")

print(" Рекомендуется использовать дерево для интерпретируемости")

else:

print("Обе модели показывают схожее качество по ROC-кривым")

print(" Выбор модели зависит от конкретной задачи")

print(f"\nПРАКТИЧЕСКОЕ ПРИМЕНЕНИЕ:")

print("-" * 30)

print("• AUC > 0.9: Модель отлично подходит для контроля качества бетона")

print("• AUC 0.8-0.9: Модель можно использовать в производстве")

print("• AUC 0.7-0.8: Требуется дополнительная настройка или данные")

print("• AUC < 0.7: Модель не рекомендуется для практического применения")

print(f"\n" + "=" * 70)

print("АНАЛИЗ ROC-КРИВЫХ ЗАВЕРШЕН!")

print("=" * 70)

Результат:

ROC-КРИВЫЕ ДЛЯ ОЦЕНКИ КАЧЕСТВА КЛАССИФИКАЦИИ БЕТОНА

Вероятности предсказаний найдены для обеих моделей

ПАРАМЕТРЫ АНАЛИЗА:

Количество классов: 3

Классы: [0 1 2]

Размер тестовой выборки: 309

ВЫЧИСЛЕНИЕ ROC-КРИВЫХ:

kNN - Класс 0 (AUC = 0.8570)

kNN - Класс 1 (AUC = 0.8343)

kNN - Класс 2 (AUC = 0.7490)

Дерево - Класс 0 (AUC = 0.9006)

ROC-анализ независимо подтверждает вывод, сделанный ранее по F1-score. Класс "Средняя" прочность является наиболее сложным для дискриминации, вероятно, из-за перекрытия его характеристик с соседними классами. Однако дерево справляется с этой задачей заметно лучше (AUC выше на 0.04).