#P3588. 第2题-评分预测
-
1000ms
Tried: 150
Accepted: 17
Difficulty: 5
所属公司 :
美团
时间 :2025年9月6日-算法岗
-
算法标签>协同过滤
第2题-评分预测
思路
对每个测试对 (u, i),按以下优先级产生预测:
- 命中原始评分:若训练集中存在该
(u,i)的真实评分,直接返回该分数。 - 用户均值:否则,若用户
u有其他历史评分,则返回其历史评分均值。 - 全局均值:否则(冷启动用户),返回训练集全局均值。
最后将结果四舍五入为两位小数(正数域可用 floor(x*100+0.5)/100 实现“真正四舍五入”),并截断到 [1.00, 5.00],以两位小数的字符串输出(含末尾 0)。
复杂度:
- 预处理:一次分组求均值 + 构造
(user,item)→rating的索引(O(N))。- 预测:对测试集向量化 merge / map(O(M))。 整体线性且稳定,满足“测试集不参与参数更新”的要求。
参考实现
import sys
import numpy as np
import pandas as pd
def predict_user_mean_baseline(train, test):
"""
参数:
train: List[List[user_id, item_id, rating]]
test: List[List[user_id, item_id]]
返回:
List[str],每个元素为两位小数的字符串(区间限定在[1.00, 5.00])
"""
# --- 构建训练集 DataFrame ---
df = pd.DataFrame(train, columns=["user", "item", "rating"]).astype({
"user": "int64", "item": "int64", "rating": "float64"
})
# 1) 预计算结构
# (a) 精确 (user,item) -> rating
exact_s = df.set_index(["user", "item"])["rating"]
# (b) 用户均分
user_mean = df.groupby("user")["rating"].mean()
# (c) 全局均分
global_mean = df["rating"].mean()
# --- 逐条预测 ---
preds = []
for u, it in test:
# 优先:精确命中
val = exact_s.get((u, it), np.nan)
# 其次:用户均分
if pd.isna(val):
val = user_mean.get(u, np.nan)
# 最后:全局均分
if pd.isna(val):
val = global_mean
# 区间裁剪 + 四舍五入到 2 位 + 格式化为字符串
val = float(np.clip(val, 1.0, 5.0))
# 使用格式化展示两位小数(含尾随 0)
preds.append(f"{val:.2f}")
return preds
# ---- 若需要从标准输入读取题目指定 JSON 格式,可使用下述轻量解析 ----
# 说明:有的评测只允许第三方库使用 numpy/pandas;Python 标准库通常不受限。
# 如平台限制极严,可直接把解析后的 dict 传给函数 predict_user_mean_baseline 即可。
if __name__ == "__main__":
raw = sys.stdin.read().strip()
if raw:
# 使用 pandas 的读法做一个鲁棒解析:先转成单行 DataFrame 再取出字典
# 思路:把整段 JSON 当作一行 Series 读入,再用 pd.json_normalize/astype(object) 取值
# 实际上最直接的是用 json.loads,这里避免额外导入,给出一个简单备选实现:
try:
import json # 标准库,一般不计入第三方限制
data = json.loads(raw)
except Exception:
# 退路:若平台不允许 import json,请手动在此处把 raw 转成 dict
raise
train = data["train"]
test = data["test"]
ans = predict_user_mean_baseline(train, test)
print(pd.Series(ans).to_json(orient="values")) # 单行 JSON 数组输出
题目内容
请在仅使用 numpy/pandas 的前提下,实现一个 Deterministic User−Mean Baseline 用于评分预测。
对给定 (user,item) 测试对,输出预测评分(保留 2 位小数)。
算法要求简单却体现推荐系统常见的缺失值填补/冷启动逻辑。
预测规则
1.若用户 u 在训练集中已评价 item i
- 直接返回该真实评分
2.否则若用户 u 有其他历史评分
- 参考用户历史平均评分
3.否则(冷启动用户)
- 以全局平均评分代替个体分数
4.结果四舍五入保留 2 位小数,以字符串形式输出,限定区间 [1.00,5.00]
备注:训练集中不会出现重复的 (user,item) ,评分均在 1−5 间。
输入描述
输入格式
{
"train":[[user_id,item_id,rating],...],
"test":[[user_id,item_id],...]
}
-
user_ id, item_ id 为整数
-
rating 为浮点 (1−5)
-
无缺失值、无额外字段
输出描述
单行 JSON 数组:[“3.00",“3.00”,“3.50”]
-
顺序与输入 test 完全一致
-
每个值为两位小数,含尾部 0 ,以字符串形式出书。
补充说明
1.为了确保通过测试用例,仅允许使用 Numpy 与 Pandas 库实现
2.测试集不用于更新该推荐系统
样例1
输入
{"train":[[1,1,5],[1,2,3],[2,1,4],[2,2,2]],"test":[[1,2],[2,3],[3,1]]}
输出
["3.00","3.00","3.50"]