Spaces:
Sleeping
Sleeping
File size: 5,063 Bytes
bcb314a |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# src/analyze_results.py
from __future__ import annotations
from pathlib import Path
import argparse
import sys
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
def _read_csv_safely(path: Path) -> pd.DataFrame:
"""
Устойчивое чтение CSV: пробуем ; , и авто. Выбираем тот, где получилось >= 5 колонок.
"""
tries = [
("utf-8-sig", ","), # СНАЧАЛА КОММА — чаще для наших predicted.csv
("utf-8-sig", ";"),
("utf-8", ","),
("utf-8", ";"),
("utf-8-sig", None),
("utf-8", None),
]
last_err = None
best_df = None
best_info = None
for enc, sep in tries:
try:
if sep is None:
df = pd.read_csv(path, encoding=enc, sep=None, engine="python")
got = f"auto"
else:
df = pd.read_csv(path, encoding=enc, sep=sep)
got = sep
# эвристика: нормальные файлы имеют >= 5 колонок
if df.shape[1] >= 5:
print(f"[i] CSV прочитан с encoding='{enc}', sep='{got}'")
return df
# запомним самый «лучший» (по числу колонок), если ни один не пройдёт порог
if best_df is None or df.shape[1] > best_df.shape[1]:
best_df, best_info = df, (enc, got)
except Exception as e:
last_err = e
if best_df is not None:
enc, got = best_info
print(f"[!] Не удалось надёжно определить разделитель, взят лучший вариант encoding='{enc}', sep='{got}' (cols={best_df.shape[1]})")
return best_df
raise last_err if last_err else RuntimeError("Не удалось прочитать CSV")
def _resolve_col(df: pd.DataFrame, candidates) -> str:
for c in candidates:
if c in df.columns:
return c
raise KeyError(f"Не удалось найти колонку из вариантов: {candidates}\nИмеющиеся колонки: {list(df.columns)}")
def mae(y_true: np.ndarray, y_pred: np.ndarray) -> float:
return float(np.mean(np.abs(y_true - y_pred)))
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--input", type=str, default="data/processed/predicted.csv", help="Путь к CSV с колонкой pred_score")
args = ap.parse_args()
in_path = Path(args.input)
if not in_path.exists():
print(f"❌ Не найден файл с предсказаниями: {in_path}")
sys.exit(1)
df = _read_csv_safely(in_path)
# Колонки
y_col = _resolve_col(df, ["Оценка экзаменатора", "оценка экзаменатора", "score", "y", "target"])
p_col = _resolve_col(df, ["pred_score", "pred", "prediction"])
# Колонка номера вопроса: поддержим оба варианта
if "№ вопроса" in df.columns:
q_col = "№ вопроса"
else:
q_col = _resolve_col(df, ["question_number", "q", "номер вопроса", "№ вопроса"])
# Числовые массивы
y = pd.to_numeric(df[y_col], errors="coerce").to_numpy()
p = pd.to_numeric(df[p_col], errors="coerce").to_numpy()
# Общая MAE
m_all = mae(y, p)
print(f"MAE (вся выборка): {m_all:.3f}\n")
# MAE по вопросам
g = (df[[q_col]].copy())
g["y"] = y
g["p"] = p
mae_by_q = (
g.groupby(q_col, as_index=True)
.apply(lambda s: mae(s["y"].to_numpy(), s["p"].to_numpy()))
.to_frame("MAE")
)
print("MAE по вопросам:")
print(mae_by_q)
out_dir = Path("reports"); out_dir.mkdir(parents=True, exist_ok=True)
mae_by_q.to_csv(out_dir / "metrics_summary.csv", encoding="utf-8-sig")
print(f"\n✅ Сохранено: {out_dir / 'metrics_summary.csv'}")
# Графики
# 1) гистограмма ошибок
err = np.abs(y - p)
plt.figure()
plt.hist(err[~np.isnan(err)], bins=30)
plt.title("Absolute Error Histogram")
plt.xlabel("|y - pred|"); plt.ylabel("count")
plt.tight_layout(); plt.savefig(out_dir / "error_hist.png"); plt.close()
print(f"📊 Гистограмма: {out_dir / 'error_hist.png'}")
# 2) mae_by_q барплот
plt.figure()
mae_by_q["MAE"].plot(kind="bar")
plt.ylabel("MAE"); plt.title("MAE by question")
plt.tight_layout(); plt.savefig(out_dir / "mae_by_q.png"); plt.close()
print(f"📊 MAE по вопросам: {out_dir / 'mae_by_q.png'}")
# 3) scatter
plt.figure()
plt.scatter(y, p, alpha=0.3)
plt.xlabel("true"); plt.ylabel("pred"); plt.title("Pred vs True")
plt.tight_layout(); plt.savefig(out_dir / "pred_vs_true.png"); plt.close()
print(f"📊 Scatter: {out_dir / 'pred_vs_true.png'}")
if __name__ == "__main__":
main()
|