推荐系统学习总结

总体架构

  • 用户的历史记录/数据(点赞、阅读、转发、评论、收藏),传到数据库(离线层),期间可以使用kafka作为消息中转(kafka是消息队列,通过消息队列可以将数据分批次、分流地存储到MongoDB数据库中。当然数据量小的时候也可以不使用kafka)。
  • 数据中台(data platform)从MongoDB读取数据并存到数据中台,数据中台还要存储内容画像、用户画像、用户信息等数据,此时数据中台就有了可以收集到的所有数据。
  • 现在就要利用这些数据。首先要利用这些数据做模型训练(常见的有协同过滤、NMF、FM、YouTuBe的DNN),产生一个模型文件model file。模型文件如何使用?就涉及到了离线计算offline computation,离线计算还要用到用户画像及用户信息(取决于模型的复杂度,比如协同过滤只需要用户id,而YoutuBe的DNN三个都需要用到)。
  • 之后可以进行排序,然后将排序的结果存到redis中(效率高),再推给用户(更简单点就不做排序)。【到这里就是最简单的推荐系统】

以上就是离线层的操作,离线层一般做的就是召回,也是一个最简单的推荐系统
离线层的特点和功能:1、用作召回数据,产生召回集;2、不需要实时,可以每隔几个小时或几天跑一次(数据量比较少,几个小时一条、一天几条,没必要实时做召回,否则会增加算力,而且效果不大)

召回集数据形式:

{
    
    
	{
    
    user_id:"1"}:[{
    
    'a':0.001},{
    
    'b':0.005},{
    
    'c':0.00001}]
}

但是仅使用离线计算会导致模型排序的同质化严重:比如如果国内的新闻比较多,可能会导致排序的结果全都是国内新闻;或者是前十个是国内新闻,后三个是电影,再后两个是综艺,不同种类的新闻堆叠在了一起,用户感观体验差。所以添加Online Service 将三类新闻岔开推送,Online Service阶段还可以再整合用户实时数据和用户画像、内容画像等进行一次实时计算,但一般来说没有必要。

但是此时还没有用到用户的实时数据,仅仅使用了排序层产生的数据,这样就导致一个问题:如果用户的行为或兴趣点突然发生了变化,这样是捕捉不到的。所以在Online Service和Offline Computation间添加近似在线层(可以使用GBDT+LR模型),用于收集用户的行为。近似在线层一般在3-5分钟内可以计算好。近似在线层与离线层或在线层最大的区别是可以拿到实时收集的用户反馈。

推送内容越来越窄:感兴趣的推,不感兴趣的就不推。解决办法:用户history做一部分,内容相似度做一部分,基于热度和时间的混合召回


数据中台可以理解为一个数据库、数据文件、分布式的文件系统
近似在线层也要做排序,排序模型也是要提前离线训练的,目的是为了拿到内容的特征。
离线层做召回,近似在线层和在线层做排序。
业务逻辑的处理一般在Online Service中做


scheduler 用于存放定时任务
labels 画像相关

爬虫基础与scrapy

什么是爬虫

增量更新
定时任务:python定时器会一直占用线程;linux服务器本身有定时器

爬虫的原理

抓取网页,数据存储,预处理,提供相关服务
cookies: 用来保存登录信息。保存在用户本地,而不是服务器。session是保存在服务器上。

什么是scrapy框架

创建scrapy工程

(recommendation) D:\Code\PycharmProjects\scrapy_project>scrapy startproject sina
(recommendation) D:\Code\PycharmProjects\scrapy_project>cd sina
(recommendation) D:\Code\PycharmProjects\scrapy_project\sina>scrapy genspider sina2 sina.com.cn
Created spider 'sina2' using template 'basic' in module:
  sina.spiders.sina2

BeautifulSoup框架

实战:利用爬虫爬取网站内容

定时任务 crontab

*	每隔多少分钟
*	小时
*	一个月中的第几天
*	每个月运行一次
*	一周的某一天

原定时任务:
0 1 * * * cd /home/docker-volume/scrapy_project/sina;scrapy crawl sina2 -a page=5 -a flag=1 >> /home/data/sheduler.log

新定时任务(使用shell脚本)/home/data/cron.sh:
#! /bin/sh
export PATH=$PATH:/usr/local/bin

echo$PATH
cd /home/docker-volume/scrapy_project/sina
/usr/local/bin/scrapy crawl sina2 -a page=5 -a flag=1 >> /home/data/sheduler.log 2>&1 &

#/usr/local/bin/scrapy命令的绝对路径应该是必要的


内容画像

画像系统的运行流程

在这里插入图片描述

内容画像的构建

什么是内容画像

能够用来描述一个内容的特征的集合

  • 关键词
  • 主题
  • 实体词
  • 分类
  • 电影的时长
  • 文章的作者

内容的热度处理

对热度进行手动处理。当热点逐渐不被人们所关注时,要手动降低热度值。
在这里插入图片描述
是基于规则的召回(基于热度的,基于时间的召回)的一种。遵循牛顿冷却定律:温度高于周围环境的物体向周围媒质传递热量逐渐冷却时所遵循的规律。
在这里插入图片描述

内容的热度更新具体做法

推荐系统中的热度:
热度衰减
1、牛顿冷却定律
2、自定义热度衰减公式

  • 什么时候需要增加热度:
    • 1、用户对文章进行操作(点赞、评论、收藏)
      a. 当有用户请求,直接对数据库操作,修改热度
      b. 当有用户请求,在MongoDB里,记录点赞、收藏的次数,然后通过次数来进行计算,从而改变热度
      热度更新的几种方法:
      a. 直接去MongoDB对数据进行操作 (效率较低,不适合对数据频繁操作,影响QPS)
      b. 通过kafka操作数据 (kafka是一个中间件,用管道的方式获取数据,再传到相应程序进行批量处理,但会导致MongoDB中数据不能实时改变,可以做到基本实时(1分钟、30秒、5分钟))
      c. 先操作redis的数据,然后再定时更新到MongoDB数据库
    • 2、运营指定(1、把热度值临时调整到最高状态 2、设置运营指定池)
    • 3、公式计算

redis挂了怎么办:1、做集群,分片存储 2、使用pika做落地
除了运营指定池之外,还可以增加2个池子:
1、热度池(hot_pool)
2、最新池(last_pool)
rec_pool = rec_list - rec_list_for_bussiness - hot_pool - last_pool

rec_list = rec_list_for_bussiness[:2] + hot_pool[:3] + last_pool[:2] + recommendation_system[8]

内容画像的基本技术点

  1. 关键词提取:是最基础的物品画像的标签来源,也为其他文本分析提供数据基础,如TF-IDF,TextRank;
  2. 实体识别:人、位置、地点、著作、影视剧、历史事件和热点事件等,最长基于词典的方法结合CRF模型;类比分词和词性标注,实体识别是指对每一个分好的词,识别为定义好的命名实体类集合之一。
  3. 内容分类:将文本按照分类体系分类,用分类来表达较粗粒度的结构化信息;SVM, FastText。
  4. 文本聚类:在无人制定分类体系的前提下,无监督地将文本划分成多个类簇也很常见,别看不是标签,类簇编号也是用户画像的常见构成;
  5. 主题模型:从大量已有文本中学习主题向量,然后再预测新的文本在各个主题上的概率分布情况,也很实用,其实这也是一种聚类思想,主题向量也不是标签形式,也是用户画像的常用构成;LDA主题模型,给出文章的topic。
  6. 词嵌入:也就是Word Embedding,从词到篇章,无不可以学习这种嵌入表达。嵌入表达是为了挖掘出字面意思之下的语义信息,并且用有限的维度表达出来。得到稠密的词向量。

内容画像细节构建

关键词提取 : TF-IDF

词频、去停用词、逆文档频率

词频(Term Frequency, TF):

T F ω , 0 = count ⁡ ( ω ) ∣ D 1 ∣ \mathrm{TF}_{\omega, 0}=\frac{\operatorname{count}(\omega)}{\left|D_{1}\right|} TFω,0=D1count(ω)
即:
词 频 ( T F ) = 某个词在文章中出现的次数 ⁡ 文 章 中 词 的 总 数 \mathrm{词频(TF)}=\frac{\operatorname{某个词在文章中出现的次数}}{文章中词的总数} TF=

去停用词:

“的”,“是”,“在”等
一般分词是用jieba函数(jieba分词库),有三种模式:普通、搜索引擎、全切分full模式。搜索引擎和全切分差别不大。

逆文档频率(Inverse Document Frequency, IDF):

某些词虽然是该篇文章中的关键词,但并不能代表整篇文章的特性,因为这类词在其他文章中也是高频词。
这时需要找到既是关键词又能代表文章的特征的词。 (考虑词在单个文章中的重要程度)
文档总数n与词w所出现文件数docs(w,D)比值的对数,可表示为:
I D F ω = log ⁡ 2 ( n docs ⁡ ( ω , D ) ) \mathrm{IDF}_{\omega}=\log _{2}\left(\frac{n}{\operatorname{docs}(\omega, D)}\right) IDFω=log2(docs(ω,D)n)
文字化表示为:
逆 文 档 频 率 ( I D F ) = log ⁡ ( 语 料 库 的 文 档 总 数 包含该词的文档数+1 ⁡ ) \mathrm{逆文档频率(IDF)}=\log\left(\frac{语料库的文档总数}{\operatorname{包含该词的文档数+1}}\right) IDF=log(+1)
即如果一个词越常见,那么其逆文档频率就会越小(即重要性越低),也就是说,逆文档频率越大,关键词在其他文档中出现几率越小,意味着越是这篇文章的关键词。

那么,一篇文档的TF-IDF值就与一个词在文档中出现的次数成正比,与改词在其他文档中出现的次数成反比
T F − I D F = 词 频 ( T F ) ∗ 逆 文 档 频 率 ( I D F ) \mathrm{TF-IDF} = 词频(TF) * 逆文档频率(IDF) TFIDF=(TF)(IDF)
因此,TF-IDF算法即对关键词的TF-IDF值降序排序,最后取前N个关键词作为最终的结果。

TextRank

构建流程

将Mysql中新闻数据经过TF-IDF提取关键词,将其特征存入Mongodb,再将mongodb中内容转到Redis,按时间排序用于冷启动。

简单工程化

使用flask

猜你喜欢

转载自blog.csdn.net/Saker__/article/details/107734144