"""Ocena punktacji feedu Edge na cechach z scripts/edge_replay_features.py. Trening na 70% najstarszych wyswietlen, test na reszcie. Glowna miara: AUC W OBREBIE URZADZENIA (czy wyzszy wynik u tego samego urzadzenia znaczy lepsza reakcje), bo globalne AUC miesza aktywnych z nowymi. Dwie etykiety: lajk albo >= 10 s ogladania (odporna na dlugosc klipu) oraz dokonczenie albo lajk. F5 to formula wdrozona 2026-10-02. Wymaga pandas i scikit-learn (lokalnie, nie w kontenerze). """ import sys import numpy as np import pandas as pd from sklearn.linear_model import LogisticRegression from sklearn.metrics import roc_auc_score df = pd.read_csv(sys.argv[1], parse_dates=["ts"]) A = 10.0 P_LIKE, P_SKIP = 0.03, 0.5 df["like_rate"] = (df.c_like + A * P_LIKE) / (df.c_seen + A) df["skip_rate"] = (df.c_skip + A * P_SKIP) / (df.c_seen + A) df["popul"] = df["pop"] slog = lambda x: np.sign(x) * np.log1p(np.abs(x)) # noqa: E731 for c in ["tag_sum", "tag_idf_sum", "creator_w", "niche_sum"]: df["s_" + c] = slog(df[c]) def within(d, col): num = den = 0.0 for _, g in d.groupby("dev"): if len(g) < 30 or g.y.nunique() < 2 or g[col].nunique() < 2: continue num += roc_auc_score(g.y, g[col]) * len(g) den += len(g) return num / den if den else float("nan") def labelled(kind): if kind == "dwell": good = (df.liked == 1) | (df.dwell >= 10000) else: good = (df.kind == "complete") | (df.liked == 1) bad = df.kind == "skip" d = df[good | bad].copy() d["y"] = good[good | bad].astype(int) return d.sort_values("ts") def cur(d): return d.tag_sum + 2 * d.niche_sum + 3 * d.creator_w + 0.3 * d.popul + 0.5 * d.fresh def formula(d, w): return (w["tag"] * d.s_tag_idf_sum + w["creator"] * d.s_creator_w + w["pop"] * d.popul + w["like"] * (d.like_rate - P_LIKE) - w["skip"] * (d.skip_rate - P_SKIP)) for kind in ("dwell", "complete"): d = labelled(kind) cut = int(len(d) * 0.7) tr, te = d.iloc[:cut].copy(), d.iloc[cut:].copy() print(f"\n===== etykieta {kind}: trening {len(tr)}, test {len(te)}") print(" AUC w obrebie urzadzenia (test):") for f in ["s_tag_sum", "s_tag_idf_sum", "tag_idf_pos", "s_creator_w", "s_niche_sum", "popul", "like_rate"]: print(f" {f:14s} {within(te, f):.3f}") cols = ["s_tag_idf_sum", "s_creator_w", "s_niche_sum", "popul", "like_rate", "skip_rate"] m = LogisticRegression(max_iter=3000).fit(tr[cols], tr.y) coef = dict(zip(cols, m.coef_[0])) base = coef["s_tag_idf_sum"] print(" wspolczynniki w jednostkach tagu:", {c: round(v / base, 2) for c, v in coef.items()}) te["cur"] = cur(te) te["model"] = m.decision_function(te[cols]) for name, w in { "F1": {"tag": 1.0, "creator": 1.0, "pop": 0.3, "like": 20.0, "skip": 2.0}, "F2": {"tag": 1.0, "creator": 1.5, "pop": 0.5, "like": 30.0, "skip": 3.0}, "F3": {"tag": 1.0, "creator": 1.0, "pop": 0.5, "like": 40.0, "skip": 4.0}, "F4": {"tag": 1.0, "creator": 2.5, "pop": 0.8, "like": 120.0, "skip": 15.0}, }.items(): te[name] = formula(te, w) print(" porownanie (test): AUC globalnie / w obrebie urzadzenia") te["F5"] = formula(te, {"tag": 1.0, "creator": 2.5, "pop": 0.8, "like": 120.0, "skip": 15.0}) + 0.25 * te.s_niche_sum + 0.3 * te.fresh for f in ["cur", "model", "F1", "F2", "F3", "F4", "F5"]: print(f" {f:6s} {roc_auc_score(te.y, te[f]):.3f} / {within(te, f):.3f}")