goon/scripts/edge_tuning_analysis.py
goon-foss 251032a13b chore(edge): skrypty odtworzenia i oceny punktacji feedu
edge_replay_features.py liczy na prodzie cechy znane w chwili kazdego
wyswietlenia, edge_tuning_analysis.py ocenia formuly (AUC w obrebie
urzadzenia, podzial w czasie). Na nich dobrana punktacja z 4666fcb.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 11:48:17 +02:00

82 lines
3.4 KiB
Python

"""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}")