- •Распределение классов прочности
- •Визуализация распределения классов прочности бетона
- •Анализ сбалансированных классов
- •Визуализация взаимосвязей между признаками
- •Предобработка данных
- •Разделение данных и масштабирование
- •Визуализация распределения признаков:
- •Метод kNn для классификации прочности бетона
- •Метод дерева решений для классификации прочности бетона
- •Обучение и оценка дерева решений для классификации бетона
- •Обучение и оценка дерева решений
- •Визуализация дерева решений
- •Кривые для оценки качества классификации бетона
- •Визуализация roc-кривых для классификации прочности бетона
Обучение и оценка дерева решений для классификации бетона
Программа:
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("ОЦЕНКА ДЕРЕВА РЕШЕНИЙ ЗАВЕРШЕНА!")
