From db21c2c2851e9c7cf61881616e6f14aa366cff90 Mon Sep 17 00:00:00 2001 From: RuyiLuo Date: Wed, 27 Apr 2022 17:04:16 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=96=B0=E9=97=BB=E6=8E=A8?= =?UTF-8?q?=E8=8D=90=E7=B3=BB=E7=BB=9F=E5=AE=9E=E8=B7=B5=E5=86=85=E5=AE=B9?= =?UTF-8?q?=E8=AF=B4=E6=98=8E=E3=80=81=E9=87=8D=E8=A6=81=E8=B4=A1=E7=8C=AE?= =?UTF-8?q?=E8=80=85=E7=AD=89=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 10 +- docs/_sidebar.md | 3 +- docs/ch03/ch3.2/3.2.5.md | 253 +++++++++++++++++++++++++++++++++++++++ docs/ch03/ch3.2/3.2.md | 17 +++ 4 files changed, 279 insertions(+), 4 deletions(-) create mode 100644 docs/ch03/ch3.2/3.2.5.md create mode 100644 docs/ch03/ch3.2/3.2.md diff --git a/docs/README.md b/docs/README.md index 4b8c402f..48708fb6 100644 --- a/docs/README.md +++ b/docs/README.md @@ -95,6 +95,7 @@ - [排序模型&模型融合](ch03/ch3.1/markdown/ch3.1.5) #### 新闻推荐系统实践 +- [3.2.0 特别说明(必看)](ch03/ch3.2/3.2) - **视频** - [新闻推荐系统流程的构建视频讲解](https://datawhale.feishu.cn/minutes/obcnzns778b725r5l535j32o) - **文档** @@ -114,7 +115,7 @@ - 地域召回 - [YoutubeDNN召回](ch03/ch3.2/3.2.4.3) - [DSSM召回](ch03/ch3.2/3.2.4.4) - - DeepFM排序模型 + - [DeepFM排序模型](ch03/ch3.2/3.2.5) - 规则与重排 - 任务监控与调度 - **当前问题汇总** @@ -156,9 +157,12 @@ - 汪志鸿(Datawhale成员-东北大学-算法工程师) - 王辰玥(Datawhale意向成员-中国地质大学(武汉)-在校生) -**其他** +**重要贡献者(根据内容+社区贡献程度筛选)** +- 唐鑫(Datawhale意向成员-西安电子科技大学-在校生) +- 王宇宸(Datawhale意向成员-上海科技大学-在校生) -感谢徐何军,李万业,陈琰钰,陈锴,梁家晖,王贺,宁彦吉,田雨,唐鑫,宋禹成,刘雯静,吕豪杰,张汉隆,吴丹飞,王云川,肖桐,管柯琴,陈雨龙,宋禹成等在最早期的时候对fun-rec所做的贡献! +**其他** +感谢徐何军,李万业,陈琰钰,陈锴,梁家晖,王贺,宁彦吉,田雨,宋禹成,刘雯静,吕豪杰,张汉隆,吴丹飞,王云川,肖桐,管柯琴,陈雨龙,宋禹成等在最早期的时候对fun-rec所做的贡献! ## 关注我们
diff --git a/docs/_sidebar.md b/docs/_sidebar.md index c6a7359a..0207f3b6 100644 --- a/docs/_sidebar.md +++ b/docs/_sidebar.md @@ -63,6 +63,7 @@ - [3.1.4 特征工程](ch03/ch3.1/markdown/ch3.1.4) - [3.1.5 排序模型&模型融合](ch03/ch3.1/markdown/ch3.1.5) - 3.2 新闻推荐系统的实践 + - [3.2.0 特别说明(必看)](ch03/ch3.2/3.2) - 3.2.1 离线物料系统的构建 - [Mysql](ch03/ch3.2/3.2.1.1) - [MongoDB](ch03/ch3.2/3.2.1.2) @@ -79,7 +80,7 @@ - 地域召回 - [YouTubeDNN召回](ch03/ch3.2/3.2.4.3) - [DSSM召回](ch03/ch3.2/3.2.4.4) - - 3.2.5 DeepFM排序 + - [3.2.5 DeepFM排序](ch03/ch3.2/3.2.5) - 3.2.6 规则与重排 - 3.2.7 任务调度与监控 - 3.2.8 当前问题汇总 diff --git a/docs/ch03/ch3.2/3.2.5.md b/docs/ch03/ch3.2/3.2.5.md new file mode 100644 index 00000000..10afda16 --- /dev/null +++ b/docs/ch03/ch3.2/3.2.5.md @@ -0,0 +1,253 @@ +# 数据集介绍 + +原始数据集共包含3个,实验时存放在目录`rank/examples/dataset/raw_data/`下。 + ++ **user_info_5w.csv** + + 该文件共包含了5万条用户的个人数据; + + 特征分别包括了:['user_id', 'device', 'os', 'province', 'city', 'age', 'gender']; + + 各特征的含义为:['用户id', '设备名称', '操作系统', '所在省', '所在市', '年龄', '性别']; ++ **doc_info.txt** + + 该文件包含了所有新闻的特征数据; + + 各特征的含义为:['文档id', '标题', '发文时间', '图片数量', '一级分类', '二级分类', '关键词']; + ++ **train_data_5w.csv** + + 该文件为用户点击数据,包含了5万个用户在过去13天的点击数据; + + 各特征的含义为:['用户id', '文档id', '展现时间', '网路环境', '刷新次数', '展现位置', '是否点击', '消费时长(秒)']; + + + +# 数据处理 + +数据处理的文件存放在`rank/examples/dataset/data_process/`下。 + +## 训练集和测试集的划分 + +训练集和测试集的划分程序为:**train&test_data_split.py** + ++ 训练集:将所有用户在前12天的点击行为划为训练集; ++ 测试集: + + 将所有用户在第13天的点击行为化为测试集; + + 测试集丢弃特征:消费时长(秒),展现位置,是否点击; + ++ 测试标签: + + 将测试集的真实标签单独进行存储; + +其他特征处理: + ++ 选中消费时长小于0的样本,并将其消费时长设置为0; ++ 对所有样本的展现时间进行了格式处理,并新增了特征展现日期; ++ 新增特征index,目的是为了后续对测试集进行评估; + +## 特征处理 + +### 用户和文档特征 + +用户数据和文档数据的处理程序为:**user&doc_data_process.py** + +**用户数据处理** + ++ 性别特征:原始的用户性别数据为用户对应不同性别的概率,这里直接将概率最高的性别作为用户的实际性别; + ++ 年龄数据:原始的用户年龄数据为用户对应不同年龄段的概率,这里将概率最高的年龄段作为用户所处的年龄段; + +**文档数据处理** + ++ 发文时间:对于部分发文时间异常或者为空的数据,使用已有文档中最早的发文时间进行填充; ++ 发文日期:将文档的发文时间,提取出对应的发文日期(年-月-日); ++ 图片数量:对部分异常的脏数据,使用 $0$ 进行填充处理; ++ 二级分类:对于存在多个二级分类的文档,从其选取一个作为其二级分类。优先选择不等于一级分类的二级分类,对于二级分类为空的文档使用一级分类进行填充; ++ 关键词: + + 每篇文档均存在多个关键词,每个关键词也会对应一个权重,这里选取权重最高的关键词作为文章的唯一关键词; + + 文档中不同的关键词及权重是采用逗号进行隔开的,但部分关键词本来就包含逗号(如==你好,李焕英==),故相关函数还对此进行了特殊处理; + +### 统计特征 + +统计特征的生成的程序为:**news_data_process.py** + ++ 从文档发文到展示的时间差:对于每一个样本,统计对应文档从发文到展示的日期差; ++ 用户特征统计: + + + 统计每个用户过去几天,所展现的文档总数; + + 统计每个用户过去几天,在不同类别文档(一级分类)上的展现总数; + + 统计每个用户过去几天,在不同类别文档(二级分类)上的展现总数; + + 统计每个用户过去几天,整体的点击率; + + 统计每个用户过去几天,对不同类别文档(一级分类)上的点击率; + + 统计每个用户过去几天,对不同类别文档(二级分类)上的点击率; + + 统计每个用户过去几天,消费时长的总和; + + 统计每个用户过去几天,在不同类别文档(一级分类)上的总消费时长; + + 统计每个用户过去几天,在不同类别文档(二级分类)上的总消费时长; + + 统计每个用户过去几天,在不同类别文档(一级分类)上的平均消费时长; + + 统计每个用户过去几天,在不同类别文档(二级分类)上的平均消费时长; + + 统计每个用户过去几天,在不同类别文档(一级分类)上的消费时长的方差; + + 统计每个用户过去几天,在不同类别文档(二级分类)上的消费时长的方差; ++ 文档特征统计: + + + 统计每篇文档在过去几天,被展示的总次数; + + 统计各类别(一级分类)文档在过去几天,被展示的总次数; + + 统计各类别(二级分类)文档在过去几天,被展示的总次数; + + 统计每篇文档在过去几天,平均的被点击率; + + 统计各类别(一级分类)文档在过去几天,平均被点击率; + + 统计各类别(二级分类)文档在过去几天,平均被点击率; + + 统计每篇文档在过去几天,总的被消费时长; + + 统计每篇文档在过去几天,平均的被消费时长; + + 统计每篇文档在过去几天,被消费时长的方差; + + 统计各类别(一级分类)文档在过去几天,总的被消费时长; + + 统计各类别(一级分类)文档在过去几天,平均的被消费时长; + + 统计各类别(一级分类)文档在过去几天,被消费时长的方差; + + 统计各类别(二级分类)文档在过去几天,总的被消费时长; + + 统计各类别(二级分类)文档在过去几天,平均的被消费时长; + + 统计各类别(二级分类)文档在过去几天,被消费时长的方差; + + +### 特征归一化和编码 + ++ 连续型特征: + + 连续型特征包含的主要是统计特征,这里对于空值统一使用 $0$ 进行填充; + + 之后,对所有的连续型特征进行对数归一化, 即取 $log$ 对数; + ++ 类别型特征: + + + 类别型特征这里主要是通过 $LabelEncoder$ 的方式进行编码,以便后续模型处理为相应的 $Embedding$; + + + +# 排序模型 + +排序模型的执行程序存放在`rank/examples/`下,分别为`deepfm_news.py`和`deepfm_ppnet_news.py`。 + +## DeepFM + +DeepFM是2017年由华为与哈工大提出的排序模型,,模型主要包含两部分:FM部分+Deep部分。 + ++ FM部分:对不同特征域的Embedding进行两两交叉,以加强模型在浅层网络中的特征组合能力。 ++ Deep部分:多层感知机网络模型。通过对特征各个维度进行充分的特征交叉组合,来学习到更多非线性以及组合特征的信息。 + +论文链接:[[DeepFM: A Factorization-Machine based Neural Network for CTR Prediction (arxiv.org)](https://arxiv.org/abs/1703.04247) + +**实验结果** + +1. 参数设置 + +```yaml +# data para +seed: 48 +# model para +embed_dim: 32 +drop_rate: 0.5 +use_bn: Ture +hidden_units: [64, 128, 64] +# compile para +learning_rate: 0.001 +epochs: 20 +batch_size: 2048 +val_splite: 0.1 +patience: 5 +restore_best_weights: True +``` + +2. 运行结果 + +```bash +Epoch 1/20 +2653/2653 [==============================] - 47s 17ms/step - loss: 0.3921 - auc: 0.7287 - val_loss: 0.3628 - val_auc: 0.7588 +Epoch 2/20 +2653/2653 [==============================] - 44s 17ms/step - loss: 0.3619 - auc: 0.7616 - val_loss: 0.3581 - val_auc: 0.7647 +Epoch 3/20 +2653/2653 [==============================] - 44s 17ms/step - loss: 0.3569 - auc: 0.7705 - val_loss: 0.3561 - val_auc: 0.7682 +Epoch 4/20 +2653/2653 [==============================] - 47s 18ms/step - loss: 0.3548 - auc: 0.7754 - val_loss: 0.3557 - val_auc: 0.7699 +Epoch 5/20 +2653/2653 [==============================] - 47s 18ms/step - loss: 0.3540 - auc: 0.7777 - val_loss: 0.3560 - val_auc: 0.7702 +Epoch 6/20 +2653/2653 [==============================] - 46s 18ms/step - loss: 0.3536 - auc: 0.7788 - val_loss: 0.3557 - val_auc: 0.7708 +Epoch 7/20 +2653/2653 [==============================] - 45s 17ms/step - loss: 0.3533 - auc: 0.7797 - val_loss: 0.3556 - val_auc: 0.7714 +Epoch 8/20 +2653/2653 [==============================] - 45s 17ms/step - loss: 0.3532 - auc: 0.7802 - val_loss: 0.3558 - val_auc: 0.7712 +Epoch 9/20 +2653/2653 [==============================] - 46s 17ms/step - loss: 0.3530 - auc: 0.7806 - val_loss: 0.3560 - val_auc: 0.7713 +Epoch 10/20 +2653/2653 [==============================] - 46s 17ms/step - loss: 0.3530 - auc: 0.7808 - val_loss: 0.3560 - val_auc: 0.7711 +Epoch 11/20 +2653/2653 [==============================] - 45s 17ms/step - loss: 0.3529 - auc: 0.7811 - val_loss: 0.3560 - val_auc: 0.7715 +Epoch 12/20 +2653/2653 [==============================] - 46s 17ms/step - loss: 0.3528 - auc: 0.7813 - val_loss: 0.3557 - val_auc: 0.7718 +251/251 [==============================] - 3s 11ms/step - loss: 0.3719 - auc: 0.7508 +test AUC: 0.750784 +``` + +## DeepFM+PPNet + +将DeepFM模型中,DNN 模块替换为PPNet模型: + ++ 在语音识别领域中,2014 年和 2016 年提出的 LHUC 算法(learning hidden unit contributions)核心思想是做说话人自适应(speaker adaptation),其中一个关键突破是在 DNN 网络中,为每个说话人学习一个特定的隐式单位贡献(hidden unit contributions),来提升不同说话人的语音识别效果。 ++ 借鉴 LHUC 的思想,快手推荐团队在精排模型上展开了尝试。经过多次迭代优化,推荐团队设计出一种 gating 机制,可以增加 DNN 网络参数个性化并能够让模型快速收敛。快手把这种模型叫做 **PPNet(Parameter Personalized Net)**。 + +参考链接:[1.9万亿参数量,快手落地业界首个万亿参数推荐精排模型](https://mp.weixin.qq.com/s?__biz=MzA3MzI4MjgzMw==&idx=4&mid=2650808254&scene=21&sn=6c295c8306b7339858f8ecfadfc9d698#wechat_redirect) + +**实验结果:** + +1. 参数设置 + +```yaml +# data para +seed: 48 +# model para +embed_dim: 32 +drop_rate: 0.5 +ppnet_size: 256 +ppnet_features: ['user_id', '一级分类', '年龄'] +use_bn: Ture +hidden_units: [64, 128, 64] +# compile para +learning_rate: 0.001 +epochs: 20 +batch_size: 2048 +val_splite: 0.1 +patience: 5 +restore_best_weights: True +``` + +2. 运行结果 + +```bash +Epoch 1/20 +2653/2653 [==============================] - 56s 20ms/step - loss: 0.3929 - auc: 0.7303 - val_loss: 0.3648 - val_auc: 0.7568 +Epoch 2/20 +2653/2653 [==============================] - 53s 20ms/step - loss: 0.3620 - auc: 0.7622 - val_loss: 0.3591 - val_auc: 0.7651 +Epoch 3/20 +2653/2653 [==============================] - 55s 21ms/step - loss: 0.3578 - auc: 0.7706 - val_loss: 0.3580 - val_auc: 0.7690 +Epoch 4/20 +2653/2653 [==============================] - 53s 20ms/step - loss: 0.3560 - auc: 0.7755 - val_loss: 0.3587 - val_auc: 0.7701 +Epoch 5/20 +2653/2653 [==============================] - 54s 20ms/step - loss: 0.3551 - auc: 0.7787 - val_loss: 0.3580 - val_auc: 0.7706 +Epoch 6/20 +2653/2653 [==============================] - 55s 21ms/step - loss: 0.3545 - auc: 0.7809 - val_loss: 0.3587 - val_auc: 0.7718 +Epoch 7/20 +2653/2653 [==============================] - 54s 20ms/step - loss: 0.3541 - auc: 0.7829 - val_loss: 0.3586 - val_auc: 0.7720 +Epoch 8/20 +2653/2653 [==============================] - 53s 20ms/step - loss: 0.3538 - auc: 0.7842 - val_loss: 0.3587 - val_auc: 0.7721 +251/251 [==============================] - 4s 13ms/step - loss: 0.3686 - auc: 0.7543 +test AUC: 0.754304 +``` + + +# 程序执行 + +```bash +# 数据预处理 +1. user&doc_data_process.py +2. train&test_data_split.py +3. news_data_process.py + +# 排序模型 +4. deepfm_news.py 或 deepfm_ppnet_news.py +``` + +# Requirements + +- Tensorflow2.5 (GPU) +- Numpy +- Pandas +- Swifter +- Sklearn diff --git a/docs/ch03/ch3.2/3.2.md b/docs/ch03/ch3.2/3.2.md new file mode 100644 index 00000000..7fd1cad8 --- /dev/null +++ b/docs/ch03/ch3.2/3.2.md @@ -0,0 +1,17 @@ +# 特别说明 + +早期的新闻推荐系统实践内容中使用数据库(Mysql/Mongo/Redis)+ 前端(Vue)+ 后端(Flask)实+ 推荐策略,实现了推荐系统的基本流程。下面简单对该系统进行总结,看完之后看大家是能从中获取到相应的内容。 + +- 系统将新闻的爬取、预处理、入库等事情都串在了一起,并将整个过程都自动化的执行 +- 对于展示的新闻内容,没有使用复杂的推荐算法,仅仅是通过简单的策略实现了热门打分,然后按照热度分进行排序。此外,考虑到展示的内容可能同类别的都排在了一起,实现了一个简单的类别打散的策略。(注意:整个系统中都没有排序相关的模型,只有简单的规则类召回) +- 当前系统虽然能够实现用户的注册,点击等交互功能,但是由于使用的用户很少,很难得到一个比较好的用户行为数据,也就无法有效的将该系统迭代起来,甚至都无法很好的对推荐效果进行评估。 +- 为了实现能够对系统中的推荐算法进行有效的评估,我们在代码中还想嵌入一个现有的公开新闻推荐数据集,这个数据集是科大讯飞的一个竞赛数据集。所以在代码中的recall和rank目录下添加了一部分处理竞赛数据集的代码,目前由于时间原因,还没有把整个竞赛数据集全部迁入到数据库、前端展示等环节。也就是说基于竞赛数据集的系统和上面提到的(已经完全可以运行的基于规则的新闻推荐系统),是完全脱节的,后面会花时间把整个流程给串起来。 + +该新闻推荐系统只是基于现有的技术,实现了推荐系统的基本流程,对于架构是否合理,技术选型是否合理都没有深入研究,这也是未来该项目的优化方向,会结合实际工业的推荐系统对其进行不断的迭代优化。 + +**新闻推荐系统实践前端展示和后端逻辑(项目没有任何商用价值仅供入门者学习)** +
+ image-20211205142026937 + Fun-Rec新闻推荐系统 +
+