【32】人気ランキングのHackerNewsランキングのアルゴリズム


前のランキングのアルゴリズムはあまり安定していません.推計したランキングのリストはよくないです.
前の問題
主に以下の方面で体現しています.時間因子が占める割合が大きすぎて、文章の発表が少ない時にはしばしば2位になります.時間の影響は直線的で、ニーズに合わない.ポイントの評価と読書量の比率が低い
検索アルゴリズム
上記の問題を受けて困った時、インターネットで大手会社を検索しましたが、どうやってランキングのアルゴリズムを実現しますか?有名で優秀なのはHackerNews、RedditとNetflixの3社のランキング推薦アルゴリズムです.
この3つの会社のアルゴリズムは、アルゴリズムエンジニアが大量のデータ統計に基づいて専門的に設計したもので、時間、賞賛などの要素の影響を十分に考慮し、十数年にわたるオンライン最適化と検証を行い、効果が非常に良く、好評を得ました.
アルゴリズム自体を少し深く理解した後、HackerNewsのアルゴリズムをチームに紹介し、ホットランキングアルゴリズムを再構築することにしました.
ワンポイント最適化
翌日の午前、Reviewコードの時、アルゴリズムの実現に問題があることが分かりました.ここで私の考えと解決策を示します.
Hacker Newsは、公式(p–1)/(t+2)^1.5をランキングの根拠として採用しています.ここでPは投票数で、tは発表以来の時間、時間計です.その後、AMIX.DKは公式スコア=(P-1)/(T+2)^Gを提示し、上記の数式を紹介しました.Hacker Newsの公式は例外となり、G=1.5時の応用となりました.歴史上、Hacker NewsにはG=1.8があります.
ここの時間tは実は時間差です.単位は時間差です.もし私達がリアルタイムで計算する方法を取らないなら、この時間差は更新されません.だから、いくつかの文章の点数は変わらないです.この時間差は更新されていないので、最終順位は非常に上位になります.これは明らかに私たちの期待に合わないです.
このリストをリアルタイムで計算すると、私たちのサーバーはこの圧力に耐えられないです.文章ごとの点数を計算する必要があるからです.
前に読んだ関連記事によると、いくつかの折衷的な方法があります.例えば、大きな時間帯で採点ファイルを保存して、訪問量が一番低い時にスコアを大量に更新します.例えば、展示する文章の点数を更新して、古い文章を展示する最後のステップでそれをブロックします.
検討した結果、私は段階別アーカイブを使う方法を選択しました.
まず朝のタイムミッションを追加して、データベースの文章を再計算します.
    @Scheduled(cron = "0 0 0 * * ?")
    public void reCalcArticleScore() {
        //                  
//        articleService.reCalcAllArticlesScore();
        try {
            freshPopularRecommended.init();
        } catch (java.text.ParseException e) {
//            e.printStackTrace();
        } catch (InterruptedException e) {
//            e.printStackTrace();
        }
        System.out.println("                :" + LocalDateTime.now());
    }
現在のアルゴリズムの中で時間の計算は現在の時間を利用して文章の発表時間を減らせば、異なる文章が入庫時間の違いによって計算された成績に大きな差があります.これは不公平です.ここで時間を翌日の午前0時まで補充することを選択します.これはタイミングタスクの運行時間と同じで、点数の公平に役立ちます.
Date nowFuture = new Date();
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(nowFuture);
        //     0                 
        //        ,                  0     
        calendar.add(Calendar.DATE, 1);
        calendar.set(Calendar.HOUR, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        double nowTimeStamp = calendar.getTimeInMillis();

        //              
        double l = nowTimeStamp - updateTimeStamp;