532. OTTO – Multi-Objective Recommender System | otto-recommender-system
首先,感谢竞赛主办方举办了一场精彩的比赛。
我非常高兴能赢得我的第一枚金牌🥇
以下是我的解决方案!p>
最佳单模型
| Orders CV | LB |
|---|---|
| 0.67087 | 0.602 |
(我还没有计算所有 orders/carts/clicks 组合的 CV 分数。)
可能和许多其他参赛者一样,我使用了候选生成 & 重排序的方法。
平均每个 session 选择了 180 个候选。(orders recall: 0.725)
将由 14 种基于物品的 CF 模式和 2 种基于用户的 CF 模式生成的候选汇总,创建最终的候选集。
由于测试数据中包含更多 aids 的 session 往往在预测期内有更多的事件,因此为测试数据中包含更多 aids 的 session 生成了更多的候选。
df = test_df[test_df["session"].isin(target_session)].groupby("session")["aid"].count().reset_index()
df.columns = ["session", "count"]
df["count"] = (df["count"]**0.5*10).astype("int32")
df["aid"] = df.progress_apply(lambda row:list(dict(rec[row["session"]].most_common(row["count"])).keys()),axis=1)
df = df.explode(["aid"])
df = df[df["aid"].notnull()].reset_index(drop=True)
总共创建了 226 个特征。
首先,创建了 59 种模式的基于物品的 CF。
例) 模式1
def get_aid_similarity1(df, topk=200):
session_info = df.drop_duplicates(["session", "aid"], keep="last")\
.groupby("session", as_index=False)[["aid", "type", "ts"]].agg(list)
aid_similarity = {}
for session, aids, tps, tss in tqdm(zip(session_info["session"],
session_info["aid"],
session_info["type"],
session_info["ts"]),
total=len(session_info)):
for aid1, tp1, ts1 in zip(aids, tps, tss):
session_length = math.sqrt(len(aids))
aid_similarity.setdefault(aid1, Counter())
for aid2, tp2, ts2 in zip(aids, tps, tss):
if (aid1 == aid2):
continue
aid_similarity[aid1][aid2] += (1/session_length)
# 只保留 topK 以节省时间和内存
for aid1, aid2_dict in tqdm(aid_similarity.items()):
relations = dict(aid2_dict.most_common(topk))
# 归一化
if len(relations) == 0:
continue
max_num = relations[max(relations, key=relations.get)]
if max_num == 0:
continue
aid_similarity[aid1] = {k: v / max_num for k, v in relations.items()}
del session_info; gc_clear()
return aid_similarity
例) 模式2
def make_real_session(df, hours=2):
df["lag"] = df["ts"] - df.groupby("session")["ts"].shift(1)
df["real_session"] = (df["lag"] > 1000*60*60*hours).astype('int8').fillna(0)
df["real_session"] = df.groupby("session")["real_session"].cumsum()
del df["lag"]; gc_clear()
return df
def get_aid_similarity2(df, topk=200):
df = make_real_session(df, hours=4)
session_info = df.groupby(["session", "real_session"], as_index=False)[["aid", "type", "ts"]].agg(list)
aid_similarity = {}
aid_cnt = defaultdict(int)
for session, real_session, aids, tps, tss in tqdm(zip(session_info["session"],
session_info["real_session"],
session_info["aid"],
session_info["type"],
session_info["ts"]),
total=len(session_info)):
for aid1, tp1, ts1 in zip(aids, tps, tss):
aid_similarity.setdefault(aid1, Counter())
for aid2, tp2, ts2 in zip(aids, tps, tss):
if (abs(ts1-ts2)>24*60*60*1000) or (aid1 == aid2):
continue
aid_cnt[aid1] += 1
if min(tp1, tp2)==0:
aid_similarity[aid1][aid2] += 1