/
Vladimir_Py
/
cp_generator
Обзор
Документация
Войти
/
Vladimir_Py
/
cp_generator
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
evaluate.py
99 строк
5 KB
Test Bot
добавил проверку результатов классификации
25 апр 2026, 12:20
25 апр 2026, 12:20
5f6adc0
Код
Авторство
О чём код?
import pandas as pd import logging logger = logging.getLogger(__name__) def evaluate_classification(ground_truth_path: str, predictions_path: str): """ Сравнивает предсказания с эталонной разметкой. Считает Precision и Recall. """ print("\n" + "="*50) print("📊 ОЦЕНКА КАЧЕСТВА КЛАССИФИКАЦИИ") print("="*50) try: # Загружаем данные df_ground = pd.read_csv(ground_truth_path) df_pred = pd.read_csv(predictions_path) # Приводим project_id к строке, чтобы избежать проблем с типами df_ground['project_id'] = df_ground['project_id'].astype(str).str.strip() df_pred['project_id'] = df_pred['project_id'].astype(str).str.strip() # Приводим is_target к булевому типу (True/False) на всякий случай df_ground['is_target'] = df_ground['is_target'].astype(str).str.lower().isin(['true', '1', 't', 'y', 'yes']) df_pred['is_target'] = df_pred['is_target'].astype(str).str.lower().isin(['true', '1', 't', 'y', 'yes']) # Объединяем таблицы по project_id (inner join оставит только те, что есть в обоих файлах) df = pd.merge( df_ground, df_pred, on='project_id', suffixes=('_true', '_pred') ) total_matched = len(df) if total_matched == 0: print("❌ Ошибка: Не найдено совпадающих project_id в обоих файлах.") return print(f"✅ Найдено {total_matched} совпадающих проектов для оценки.\n") # ========================================== # 1. ОЦЕНКА is_target # ========================================== # True Positive: В разметке True, и модель сказала True tp = len(df[(df['is_target_true'] == True) & (df['is_target_pred'] == True)]) # False Negative: В разметке True, но модель сказала False (НАШ ГЛАВНЫЙ ВРАГ) fn = len(df[(df['is_target_true'] == True) & (df['is_target_pred'] == False)]) # False Positive: В разметке False, но модель сказала True (Мусор прошел фильтр) fp = len(df[(df['is_target_true'] == False) & (df['is_target_pred'] == True)]) # True Negative: В разметке False, и модель сказала False tn = len(df[(df['is_target_true'] == False) & (df['is_target_pred'] == False)]) recall_target = tp / (tp + fn) if (tp + fn) > 0 else 0.0 precision_target = tp / (tp + fp) if (tp + fp) > 0 else 0.0 print("--- МЕТРИКИ is_target (Бинарная классификация) ---") print(f"🎯 RECALL (Охват целевых): {recall_target:.1%} <-- Наша главная метрика!") print(f"🎯 PRECISION (Точность): {precision_target:.1%}") print(f"Детали: TP={tp}, FN={fn} (пропустили), FP={fp} (взяли мусор), TN={tn}\n") # Если есть пропущенные целевые, выводим их для анализа if fn > 0: print("🚨 ВНИМАНИЕ! Модель ошибочно отбраковала следующие целевые проекты (False Negatives):") fn_df = df[(df['is_target_true'] == True) & (df['is_target_pred'] == False)] for _, row in fn_df.iterrows(): print(f" - ID: {row['project_id']} | Ожидали: {row['category_true']} | Выдало: {row['category_pred']}") print("\n") # ========================================== # 2. ОЦЕНКА category (Мультиклассовая) # ========================================== print("--- МЕТРИКИ category (Мультиклассовая) ---") # Считаем точность совпадения категорий в целом exact_category_matches = len(df[df['category_true'] == df['category_pred']]) accuracy_category = exact_category_matches / total_matched print(f"Общая точность совпадения категорий: {accuracy_category:.1%}") # Считаем Recall по каждой категории categories = df['category_true'].unique() for cat in categories: cat_total = len(df[df['category_true'] == cat]) cat_correct = len(df[(df['category_true'] == cat) & (df['category_pred'] == cat)]) cat_recall = cat_correct / cat_total if cat_total > 0 else 0 # Для наглядности выводим только если это целевая категория (не skip_) if not str(cat).startswith('skip_'): print(f" - Категория '{cat}': Recall = {cat_recall:.1%} ({cat_correct}/{cat_total})") except Exception as e: logger.exception("Ошибка при оценке результатов") if __name__ == "__main__": evaluate_classification( ground_truth_path="_data/classifications/classified_ground.csv", predictions_path="_data/classifications/classified_orders_1_gpt4.csv" )