
前言当下只要是一个初具规模的内容应用都具备个性化推荐系统。比如购物类的会有推荐商品模块搜索条下有个性化的搜索关键词或词条补全词社交类的有博主推荐视频或文章推荐等等。这些功能除了要有庞大的数据量还要有健全的数据存储仓库建设方案以及后面对数据的清洗排序训练后的推荐模型算法。但是对于小公司或者说是小项目在想法还未真正落地就设计大数据存储推荐算法和一系列大型架构的方案显然是不符合业务型产品开展的正常规律的。我想那些大厂早期开发应该也没有这么成熟的技术结构都是不断迭代或者推倒重来一步步走过来的。那么在小项目早期安排了有关于推荐功能的那要如何解决呢 如何做到下一次迭代在不重构的基础上添加协同过滤推荐 下面就从视频推荐和用户推荐两个功能展开用PHP和MySQL进行代码实现。视频推荐这里主要通过一个内容热度值进行排序推荐热度由内容质量和发布时间差决定时差越长热度越低内容质量越高热度越高。而内容质量由视频点赞数收藏数和评论数外带权重决定总体就是单位时间内点赞收藏评论越高热度提升视频就越往前靠。相对的就是发布时间越久热度就会逐步降低视频越往后靠。另外我们还要设计两个参数用于手动调节视频的热度提高就只需要增加内容质量所以额外加一个数可以说是初始值。降低可以对时间差添加一个指数也就是时间差的次方可以理解是重力也就是随着时间拉长重力增加则热度成倍降低。1. 公式1.1. ”H“视频热度值1.2. ”W“视频质量质量值自定(点赞数权重收藏数权重之和或者点赞率(点赞量/阅读量)收藏率(收藏量/阅读量)之和)等。1.3. ”I“初始值可以手动调节热度或者用于后期用户账号的权重。比如系统已经有了成长体系账号发育规则基本完善了用于实时计算账号的权重分配的流量池权重提升则后面发布的视频推荐力度大。1.4. ”T“时间差由当前时间 - 发布时间产生加一的原因是防止时间差为0(分母为零)不过有审核机制下这种情况并不存在。1.5. ”G热度衰减重力这个也是用于手动调节热度设置的控制参数。不过后期如果添加了举报或者智能复审等环节再随着诸如点赞和账户权重评估失控热度飙升的情况下对视频违规或不良表现或临时情况进行减小推荐。默认值最好是1这种情况就是在同等质量下新发布的越往前。2. 表结构123456789101112131415161718192021222324252627282930CREATETABLEhhyp_short_video (idint(11)NOTNULLAUTO_INCREMENT,hsvnvarchar(255)DEFAULTCOMMENT短视频编号,type tinyint(1)DEFAULT0COMMENT类型1. 视频 2.图文,user_idint(11)DEFAULT0,video_urlvarchar(255)DEFAULT,img_url jsonDEFAULTNULL,content text COMMENT内容,market_goods_idint(11)DEFAULT0,address_idint(11)DEFAULT0COMMENT地址ID,latdecimal(4,0)DEFAULT0COMMENT纬度,lngdecimal(4,0)DEFAULT0COMMENT经度,ipvarchar(100)CHARACTERSETutf8DEFAULTCOMMENTIP,channel tinyint(1)DEFAULT0COMMENT渠道,read_countint(11)DEFAULT0COMMENT浏览数,like_countint(11)DEFAULT0COMMENT点赞数,collect_countint(11)DEFAULT0COMMENT收藏数,comment_countint(11)DEFAULT0COMMENT评论数,share_countint(11)DEFAULT0COMMENT分享数,is_top tinyint(1)DEFAULT0COMMENT是否置顶0.否 1.是,statusint(11)DEFAULT0COMMENT0. 审核中 10. 推荐 20. 下架,hot_intint(11)DEFAULT1COMMENT热度初始值,gravityint(11)DEFAULT1COMMENT热度重力衰减值,audit_timeint(11)DEFAULT0COMMENT审核时间,remark text,create_timeint(11)DEFAULT0COMMENT创建时间,delete_timeint(11)DEFAULT0,update_timeint(11)DEFAULT0,PRIMARYKEY(id)) ENGINEInnoDB AUTO_INCREMENT107DEFAULTCHARSETutf8mb4;3. 代码1234567891011121314151617181920212223242526272829303132333435publicstaticfunctiongetList($map,$page 1,$size 20){// 数据指标权重配置$wcfg [like_weight 4,collect_weight 3,comment_weight 1];$timeUnit 3600;// 单位小时$where[] [delete_time,, 0];$maparray_merge($where,$map);// 单位小时内点赞/收藏/评论越多热度越高发布越久热度越低$alog(like_count*%scollect_count*%scomment_count*%shot_int)/pow((UNIX_TIMESTAMP(NOW())-create_time)/%s, gravity);$hotIndex sprintf($alog,$wcfg[like_weight],$wcfg[collect_weight],$wcfg[comment_weight],$timeUnit);$field [id, hsvn,type,user_id,video_url,img_url,content,market_goods_id,like_count,collect_count,address_id,comment_count,share_count,create_time,$hotIndexashot_index];$list self::field($field)-json([img_url], true)-with([userfunction($query) {$query-withField(id, nickname, mobile, avatar);},marketGoodsfunction($query) {$query-withField(id, content,freight,user_id);},addressfunction($query) {$query-withField(id, mername);}])-where($map)-page($page,$size)-order(hot_index desc)-select();return$list;}用户推荐推荐用户大部分是放在App里的个人中心感兴趣用户模块。有的是给用户推荐授权的通讯录好友有的是根据行为数据通过给用户打标签再推荐与自己标签相似的用户等等方式。而我这里的用户推荐是放在发布视频的用户面板里本来我想通过协同过滤的相似用户来做由于数据太有限加之我们业务本身就不能查看用户关注列表和粉丝列表所以就暂时用了一个折中的方法给用户推荐创作者关注的关注。根据当前面板用户关注的用户里挑出粉丝数最多的前十个然后再从这十个里分别挑出他们关注用户里粉丝最多的前十最后合并去重也就是给自己推荐打开用户关注的关注里粉丝最多的那批人。1. 表结构123456789CREATETABLEhhyp_user_attention (idint(11)NOTNULLAUTO_INCREMENT,user_idint(11)NOTNULLDEFAULT0COMMENT用户id,comcemed_user_idint(11)NOTNULLDEFAULT0COMMENT关注的用户id,create_timeint(11)DEFAULT0COMMENT创建时间,statussmallint(3)NOTNULLDEFAULT0COMMENT关注状态 0未关注 1已关注,update_timeint(11)DEFAULT0COMMENT更新时间,PRIMARYKEY(id)) ENGINEInnoDB AUTO_INCREMENT352DEFAULTCHARSETutf8mb4;2. 代码通过查询子查询里指定用户里粉丝最多的前十人(分组排序)然后递归往前查询就形成关注链条最后再合并查询结果。其实这个也很看数据的当我真正把这个方法放上去的时候会发现很多面板里没有用户推荐的数据因为很多用户根据就没关注几个人。所以通过深度学习或者协同过滤做用户推荐可能要等待一段时间等用户行为数据产生差不多的时候我再出一下协同过滤的用户相似度推荐吧。12345678910111213141516171819202122232425// 关注链列表publicstaticfunctiongrandadList($userIds [], $allList [], $level 1){$field [comcemed_user_id, count(*) as fans_count, {$level} as level];$list self::field($field)-where(comcemed_user_id,in,function($query)use($userIds) {$query-table(hhyp_user_attention)-where(user_id,in,$userIds)-where(status,, 1)-field(comcemed_user_id);})-where(status,, 1)-group(comcemed_user_id)-order(fans_count desc)-limit(10)-select()-toArray();if($list$level 4) {$level;$comcemedUserIds array_column($list,comcemed_user_id);$list self::grandadList($comcemedUserIds,$list,$level);}$listarray_merge($allList,$list);return$list;}以上就是使用PHP MySQL实现数据量小的内容推荐方法的详细内容