创新实训(38)——修改基于流行度和新鲜度的推荐(热榜)的算法

前言

昨天同学用定时任务重新抽取了博客的文章,大概有3500条,然后今天发现热榜的评分好像不太好,所以对热榜进行了很多次的调整。
原本热榜文章评分的算法是:将博客发布的时间转化为10位的时间戳 +4000博客的点赞量 +2000博客的阅读量
这两个权重参数的设置也是很不好把握的。
之后将热榜的评分修改成 :10位的时间戳截取掉第一位变成9位 +8000博客的点赞量 +3000博客的阅读量
发现效果还是不理想。
然后同学给我推荐了一个算法——Hacker News的热门排名算法,我在项目中实现了这种计算方法,然后发现,效果还是不错的,所以直接将热榜的算法替换成了Hacker News算法。

Hacker News算法介绍

他的数学公式其实很简单:
在这里插入图片描述
(1)得票数P
在其他条件不变的情况下,得票越多,排名越高。
在这里插入图片描述
为什么是P-1?网络上的一种解释是,很多文章作者在提交的时候会给自己投上一票。其实更重要的原因是文章发布初期的投票数对排名影响非常的,仅仅是自己给自己投的一票,也占非常大的作用。

假设P不去减去1,那公式为: p / (t + 2)^1.5

如果一个作者发布完就给自己投票,那么文章的得分为1/(0+2)^1.5=0.3535 。假设另外一篇文章发布了8小时,那么需要多少的投票呢?x/(8+2)^1.5>0.3535 X>11.17~ 即一天前的帖子要有12票才能超过新提交的文章,这显然不合理。

这个具体减多少还要视网络环境而定,要是换在国内,估计P-100还不够。另外如果你不期望“高投票文章”与“低投票文章差距过大,可以在得票数上加一个小于1的指数,比如(P-1)^0.8。
这里我使用的参数是点赞量*3+浏览量 作为p值,并且没有加指数进行缩减
(2)距离发帖时间T
在其他条件不变的情况下,越是新发表的帖子,排名越高。或者说,一个帖子的排名,会随着时间不断下降。

从前一张图可以看到,经过24小时之后,所有帖子的得分基本上都小于1,这意味着它们都将跌到排行榜的末尾,保证了排名前列的都将是较新的内容。

如果,用户的第一个投票是在当前,1小时,2小时获得时,这个曲线的变化是什么呢?如下图,曲线斜率从大到小分别是当前、1小时、2小时。可以看到第一个投票的作用不断弱化,其权重不断降低。
在这里插入图片描述
由于文章的发布,多半是要差距很多天的,所以我这里T的选择是与当前时间相差了多少周,如果用小时的话,会导致评分非常的小
(3)重力因子G
它的数值大小决定了排名随时间下降的速度。从下图可以看到,三根曲线的其他参数都一样,G的值分别为1.5、1.8和2.0。G值越大,曲线越陡峭,排名下降得越快。
在这里插入图片描述
为什么G=1.5,首先,G是干嘛的。毫无疑问,G这个数字既非时间,也非评价,其实它的主要目的是控制更新频率。G的值越大,score的衰减速度越快,排行的更新越频繁。所以,确定G值需要观察系统内部投票数在时间上的分布,然后根据需要的更新频次确定G的合理取值。越火爆、用户互动越频繁的社区,为了保证排行的稳定性(不要频繁大量的刷新),G值趋向于比较低。这就是为什么Hacker News从一开始的1.8修改成1.5,过段时间可能就变成1.2了。

算法的实现

    //一次点击率可以增加的得分
    private static int READ_COUNT_K = 1;
    //一次点赞增加的评分
    private static int LIKE_COUNT_K = 3;
  public double calculateHackerNewsScore(Article article)
    {
        String updateTime = article.getUpdateTime();
        int readCount = article.getReadCount();
        int likeCount = article.getLikeCount();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = null;
        try {
            date = formatter.parse(updateTime);
        } catch (ParseException e) {
            date = new Date();
        }

        //发帖时间的时间戳
        double updateTimeStamp = date.getTime() ;
        System.out.println("发帖时间的时间戳"+updateTimeStamp);
        //当前时间的时间戳
        double nowTimeStamp = System.currentTimeMillis();
        System.out.println("当前时间的时间戳"+nowTimeStamp);
        //用来获取两个时间相差的毫秒数
        double l=nowTimeStamp -updateTimeStamp;

        //相差的天
        double day=l/(24*60*60*1000);
        //相差的小时
        double hour=(day*24);

        double week = day/7;
        double month = week/4;
        /**
         * HackerNews评分   分子  点击权重为1    点赞权重为3    分母为 距离发帖时间相差的时间+2的G次方
         */
        double score =  ((readCount *READ_COUNT_K + likeCount *LIKE_COUNT_K) -1)/Math.pow((week +2),G);
        score *= 10000;
        System.out.println("文章" +article.getId() +"    发帖时间为" +updateTime +"    与当前时间相差" + week +"星期     评分为"+score);
        return score;
    }

用Hacker News算法算出分数后,发现分数特别小
在这里插入图片描述
所以就讲所有分数都乘了10000,得到最后的得分

最后的效果

在这里插入图片描述

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值