查看原文
其他

R&S | 手把手搞推荐[4]:打分预估模型

机智的叉烧 CS的陋室 2022-08-08

【R&S】

本栏目从原来的【RS】改为【R&S】,意为“recommend and search”,即推荐和搜索,结合本人近期的工作方向、最近上的七月在线的课、自己自学、而退出的特别栏目。当然,按照我往期的风格,更加倾向于去讨论一些网上其实讲得不够的东西,非常推荐大家能多看看并且讨论,欢迎大家给出宝贵意见,觉得不错请点击推文最后的好看,感谢各位的支持。

另外,【手把手搞推荐】是我近期开始的连载,结合自己所学,带上代码的手把手和大家分享一些模型和数据处理方式,欢迎关注。

往期回顾:

内容接着前面的讲,如果觉得有点问题请看前面的篇章,后续我也会进行整理回顾。

在前序章节中,已经详细阐述了有关特征工程、数据集存取等方面内容,万事俱备,现在只需要进行模型设计,即可建模的流程,这绝对是觉得最为刺激的重头戏,当然这绝对不是就完事了,后续还有评估、诊断、监控、迭代等内容,后面的事后面再说吧。

模型设计思路

首先再次确认本次建模目标——就是根据给定用户,提供尽可能好的推荐内容,好的标准在于给他推荐的内容(测试集下)评分较高,而此处,作为打分预估,其实就是希望我们对用户A和电影B,能够更为准确地预测打分,所以说白了,就是为了"预测打分"。

此处的打分是1-5一共5个等级的打分,没有半分,与学校课程打分等方面不同,打分的区间小、等级少,相比回归模型,分类模型更为简单直接,而且实际上并非要求要准确预测到分数,其实就是一个准确到整数的问题,因此分类模型更合适,选择通过分类方法处理问题,因此可以处理为一个5分类问题。

在选择分类模型时,需要考虑如下几个方面:

  • 第一个版本的模型要求尽可能简单,快速完成功能

  • 测试或预测阶段效率尽可能高(毕竟涉及上线,响应时间非常重要),KNN之类的肯定要抛弃

  • 准确性达到基本标注

  • 当前数据集内特征大都是离散型特征(已经全部onehot化了,就全都是离散特征了)

所以,此处我选择logistic regression作为此处的模型。补充一下,一般工业界的基线模型,非常喜欢用LR,满足上述特点,非常简单,后续会尝试FM、GDBT等,然后才是深度学习。

开始实现

首先肯定是加载数据了,这块代码上一篇也放过,这里就不赘述细节啦,大写的是自定义的路径。有关hash技巧方面,我还在学习和探索,有关内容可以大家自行了解,也可以期待我的文章,上次谈到的文章在这里:

转 | 数据集存取新方案-认识feature hashing

继续代码!

  1. from scipy.sparse import load_npz

  2. def load_dataset(x_path, y_path):

  3. y_ = []

  4. y_oh = []

  5. idx = 0

  6. with open(y_path, encoding="utf8") as f:

  7. for line in f:

  8. ll = line.strip().split(",")

  9. y_item = max([idx * int(float(ll[idx])) for idx in range(5)]) + 1

  10. y_oh_item = [int(float(item)) for item in ll[:5]]

  11. y_.append(y_item)

  12. y_oh.append(y_oh_item)

  13. idx = idx + 1

  14. x_ = load_npz(x_path)

  15. return x_, y_, y_oh

  16. x_train, y_train, y_train_oh = load_dataset(GEN_DATA_TRAIN_X_PATH, GEN_DATA_TRAIN_Y_PATH)

然后就轮到模型的初始化和训练了,这块相比大家非常熟悉,没错,所以用模型就是这么简单,所以才说前面的工作和后面的工作才是重头戏,基线模型本身操作真的少之又少。

  1. from sklearn.linear_model import LogisticRegression

  2. clf = LogisticRegression(penalty="l1",n_jobs=-1)

  3. clf.fit(x_train, y_train)

后续应有模型评估,此处直接给出可供参考的指标,后面会有篇章详细讨论评价指标设计

  1. from sklearn.metrics import precision_score, recall_score, f1_score

  2. from sklearn.metrics import mean_absolute_error, mean_squared_error


  3. def model_rep(y_true, y_pred, average="micro"):

  4. p = precision_score(y_true, y_pred, average=average)

  5. r = recall_score(y_true, y_pred, average=average)

  6. f1score = f1_score(y_true, y_pred, average=average)

  7. return p, r, f1score


  8. def eu_distances(array1, array2):

  9. res = 0.0

  10. for idx in range(len(array1)):

  11. res = res + (array1[idx] - array2[idx]) ** 2

  12. return res / len(array1)



  13. def average_distance(y_true_prod, y_pred_prod):

  14. res = 0.0

  15. for idx in range(len(y_true_prod)):

  16. res = res + eu_distances(y_true_prod[idx], y_pred_prod[idx])

  17. return res / len(y_true_prod)

  18. p, r, f1score = model_rep(y_train, y_pred) # 分类预测结果

  19. mae = mean_absolute_error(y_train, y_pred) # mae

  20. mse = mean_squared_error(y_train, y_pred) # mse

  21. ad = average_distance(y_train_oh, y_prod) # 平均距离

简单说几个这里用到的思路吧:

  • 这里首先用的是分类的指标,毕竟我们把它当做分类问题来解决,即查准率、查全率、F1值(我个人不太喜欢叫精确率召回率,有时候含义不明确,查准和查全更直观表示precision和recall的含义)

  • mae和mse都是回归问题用到的指标,因为这里的实质是打分预估,所以这里我就考虑把这个指标也放进去了

  • 平均距离是算实际打分(onehot)和实际打分(各个打分的概率)查看距离,了解相似度,以确认这个打分与实际接近程度

  • AUC是二分类指标,此处使用并不合适,已经考虑用上面的平均距离代替其相关功能

小结

没错,就讲完了,就这么简单,是不是会觉得还没开始就结束了?事实确实如此,上一期也提到了,算法项目远远不止机器学习,机器学习在这里就几行代码,但是前后的数据操作和监控则需要花费很多时间,而且才是能提升结果的,后续慢慢和大家谈吧,敬请期待!

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存