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

Обучение и оценка дерева решений для классификации бетона

Программа:

print("ОБУЧЕНИЕ И ОЦЕНКА ДЕРЕВА РЕШЕНИЙ ДЛЯ КЛАССИФИКАЦИИ БЕТОНА")

print(f"\nОБУЧЕНИЕ МОДЕЛИ С ОПТИМАЛЬНОЙ ГЛУБИНОЙ ({optimal_depth}):")

tree_model = DecisionTreeClassifier(max_depth=optimal_depth, random_state=42)

tree_model.fit(X_train_scaled, y_train)

print(f"Параметры обученного дерева:")

print(f" Глубина дерева: {tree_model.get_depth()}")

print(f" Количество листьев: {tree_model.get_n_leaves()}")

print(f" Количество узлов: {tree_model.tree_.node_count}")

print(f" Критерий разделения: {tree_model.criterion}")

y_pred_tree = tree_model.predict(X_test_scaled)

y_pred_proba_tree = tree_model.predict_proba(X_test_scaled)

accuracy_tree = accuracy_score(y_test, y_pred_tree)

precision_tree = precision_score(y_test, y_pred_tree, average='weighted')

recall_tree = recall_score(y_test, y_pred_tree, average='weighted')

f1_tree = f1_score(y_test, y_pred_tree, average='weighted')

print("\n" + "=" * 40)

print("МЕТРИКИ КАЧЕСТВА ДЕРЕВА РЕШЕНИЙ")

print("=" * 40)

metrics_data = [

["Accuracy", f"{accuracy_tree:.4f}", "Точность предсказаний"],

["Precision", f"{precision_tree:.4f}", "Точность положительных прогнозов"],

["Recall", f"{recall_tree:.4f}", "Полнота обнаружения классов"],

["F1-Score", f"{f1_tree:.4f}", "Гармоническое среднее Precision и Recall"]

]

print("\n" + "-" * 70)

print(f"{'Метрика':<15} {'Значение':<12} {'Описание':<40}")

print("-" * 70)

for metric, value, description in metrics_data:

print(f"{metric:<15} {value:<12} {description:<40}")

print("-" * 70)

print("\nИНТЕРПРЕТАЦИЯ РЕЗУЛЬТАТОВ:")

print("-" * 30)

if accuracy_tree >= 0.9:

print("Отличная точность! Модель хорошо предсказывает классы прочности бетона.")

elif accuracy_tree >= 0.8:

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

elif accuracy_tree >= 0.7:

print("Удовлетворительная точность. Модель требует улучшений.")

else:

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

print("\nДЕТАЛЬНЫЙ АНАЛИЗ ПО КЛАССАМ ПРОЧНОСТИ:")

report = classification_report(y_test, y_pred_tree,

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

output_dict=True)

report_df = pd.DataFrame(report).transpose().round(4)

print("\nОтчет классификации по классам:")

print(report_df.to_string())

print("\nАНАЛИЗ ПРОБЛЕМНЫХ КЛАССОВ:")

problem_classes = []

for cls in le_strength.classes_:

cls_str = str(cls)

if cls_str in report and report[cls_str]['f1-score'] < 0.7:

problem_classes.append({

'Класс': cls_str,

'Precision': report[cls_str]['precision'],

'Recall': report[cls_str]['recall'],

'F1-Score': report[cls_str]['f1-score'],

'Support': report[cls_str]['support']

})

if problem_classes:

print("Классы с низким качеством классификации (F1-Score < 0.7):")

for problem in problem_classes:

print(f"\n Класс: '{problem['Класс']}'")

print(f" Precision: {problem['Precision']:.3f}")

print(f" Recall: {problem['Recall']:.3f}")

print(f" F1-Score: {problem['F1-Score']:.3f}")

print(f" Количество образцов: {problem['Support']}")

# Анализ возможных причин

if problem['Precision'] < problem['Recall']:

print(f" Проблема: много ложных срабатываний")

elif problem['Precision'] > problem['Recall']:

print(f" Проблема: много пропусков класса")

else:

print(f" Проблема: сбалансированная низкая точность")

else:

print("Все классы имеют приемлемое качество классификации (F1-Score >= 0.7)")

print("\nВИЗУАЛИЗАЦИЯ МАТРИЦЫ ОШИБОК:")

cm_tree = confusion_matrix(y_test, y_pred_tree)

fig, axes = plt.subplots(1, 2, figsize=(14, 5))

im = axes[0].imshow(cm_tree, interpolation='nearest', cmap='Blues')

axes[0].set_title(f'Матрица ошибок дерева решений\n(глубина={optimal_depth})',

fontsize=12, fontweight='bold')

axes[0].set_ylabel('Истинные классы')

axes[0].set_xlabel('Предсказанные классы')

tick_marks = np.arange(len(le_strength.classes_))

axes[0].set_xticks(tick_marks)

axes[0].set_yticks(tick_marks)

axes[0].set_xticklabels([str(cls) for cls in le_strength.classes_], rotation=45)

axes[0].set_yticklabels([str(cls) for cls in le_strength.classes_])

thresh = cm_tree.max() / 2.

for i in range(cm_tree.shape[0]):

for j in range(cm_tree.shape[1]):

axes[0].text(j, i, format(cm_tree[i, j], 'd'),

ha="center", va="center",

color="white" if cm_tree[i, j] > thresh else "black",

fontweight='bold')

cm_normalized = cm_tree.astype('float') / cm_tree.sum(axis=1)[:, np.newaxis]

im2 = axes[1].imshow(cm_normalized, interpolation='nearest', cmap='Blues', vmin=0, vmax=1)

axes[1].set_title('Нормированная матрица ошибок\n(по строкам)',

fontsize=12, fontweight='bold')

axes[1].set_ylabel('Истинные классы')

axes[1].set_xlabel('Предсказанные классы')

axes[1].set_xticks(tick_marks)

axes[1].set_yticks(tick_marks)

axes[1].set_xticklabels([str(cls) for cls in le_strength.classes_], rotation=45)

axes[1].set_yticklabels([str(cls) for cls in le_strength.classes_])

for i in range(cm_normalized.shape[0]):

for j in range(cm_normalized.shape[1]):

axes[1].text(j, i, format(cm_normalized[i, j], '.2f'),

ha="center", va="center",

color="white" if cm_normalized[i, j] > 0.5 else "black",

fontweight='bold')

plt.colorbar(im, ax=axes[0], fraction=0.046, pad=0.04)

plt.colorbar(im2, ax=axes[1], fraction=0.046, pad=0.04)

plt.tight_layout()

plt.show()

print("\nСТАТИСТИКА ПРЕДСКАЗАНИЙ:")

total_samples = len(y_test)

correct_predictions = (y_test == y_pred_tree).sum()

incorrect_predictions = total_samples - correct_predictions

print(f"Всего тестовых образцов: {total_samples}")

print(f"Правильно классифицировано: {correct_predictions} ({correct_predictions/total_samples*100:.1f}%)")

print(f"Ошибочно классифицировано: {incorrect_predictions} ({incorrect_predictions/total_samples*100:.1f}%)")

print("\nАНАЛИЗ УВЕРЕННОСТИ ПРЕДСКАЗАНИЙ:")

if y_pred_proba_tree is not None:

max_probs = np.max(y_pred_proba_tree, axis=1)

confidence_stats = {

'Очень высокая (>0.9)': (max_probs > 0.9).sum(),

'Высокая (0.7-0.9)': ((max_probs >= 0.7) & (max_probs <= 0.9)).sum(),

'Средняя (0.5-0.7)': ((max_probs >= 0.5) & (max_probs < 0.7)).sum(),

'Низкая (<0.5)': (max_probs < 0.5).sum()

}

print("Распределение по уверенности модели:")

for category, count in confidence_stats.items():

percentage = count / len(max_probs) * 100

print(f" {category}: {count} образцов ({percentage:.1f}%)")

correct_mask = (y_test == y_pred_tree)

high_confidence_mask = (max_probs > 0.7)

if high_confidence_mask.sum() > 0:

high_conf_accuracy = correct_mask[high_confidence_mask].sum() / high_confidence_mask.sum()

print(f"\nТочность для уверенных предсказаний (>0.7): {high_conf_accuracy:.1%}")

plt.figure(figsize=(10, 6))

plt.hist(max_probs[correct_mask], bins=20, alpha=0.7, label='Правильные', color='green')

plt.hist(max_probs[~correct_mask], bins=20, alpha=0.7, label='Ошибочные', color='red')

plt.xlabel('Максимальная вероятность', fontsize=12)

plt.ylabel('Количество образцов', fontsize=12)

plt.title('Распределение уверенности модели', fontsize=14, fontweight='bold')

plt.legend()

plt.grid(True, alpha=0.3)

plt.show()

print("\nПРИМЕРЫ ПРЕДСКАЗАНИЙ (первые 5 тестовых образцов):")

for i in range(min(5, len(X_test_scaled))):

true_class = le_strength.inverse_transform([y_test.iloc[i]])[0] if hasattr(y_test, 'iloc') else le_strength.inverse_transform([y_test[i]])[0]

pred_class = le_strength.inverse_transform([y_pred_tree[i]])[0]

print(f"\nОбразец #{i+1}:")

print(f" Истинный класс: '{true_class}'")

print(f" Предсказанный класс: '{pred_class}'")

if y_pred_proba_tree is not None:

probabilities = y_pred_proba_tree[i]

print(f" Вероятности классов:")

for cls_idx, prob in enumerate(probabilities):

cls_name = le_strength.inverse_transform([cls_idx])[0]

print(f" '{cls_name}': {prob:.2%}")

if true_class == pred_class:

print(f" Результат: ✓ ПРАВИЛЬНО")

else:

print(f" Результат: ✗ ОШИБКА")

# Показываем значения признаков для ошибочного предсказания

print(f" Значения признаков:")

for j, feature in enumerate(features):

original_value = X_test_scaled[i, j] * scaler.scale_[j] + scaler.mean_[j]

print(f" {feature}: {original_value:.1f}")

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

print("ОЦЕНКА ДЕРЕВА РЕШЕНИЙ ЗАВЕРШЕНА!")