2012-06-20 15 views
15

アイテムの年齢とアイテムが受け取る投票数、クリック数、または購入数に基づいて人気度を計算するためには、多くのものがあります(suggested algorithms)。しかし、私が見てきたよりロバストな方法は、過度に複雑な計算や複数の格納された値を必要とすることが多く、データベースが乱雑になります。私は、変数(人気値そのもの以外)を格納する必要がなく、の1つだけの計算が必要な非常に単純なアルゴリズムを検討しています。それは途方もなく簡単です:単純な人気アルゴリズム

p = (p + t)/2

ここで、pはデータベースに保存されている人気の値であり、tは現在のタイムスタンプです。項目を最初に作成するときは、pを初期化する必要があります。

  1. 初期データベース

注全てP値の平均値と現在のタイムスタンプとPT

  • 初期P:二つの可能な初期化方法があります初期化メソッド(1)は、最近追加されたアイテムに履歴アイテムよりも明確な利点を与えて、relevan ce。一方、初期化方法(2)は、履歴項目と比較して新しい項目を等価として扱います。

    初期化方法(1)を使用して、pを現在のタイムスタンプで初期化したとします。アイテムが最初の投票を受け取ると、pが作成時間と投票時間の平均になります。したがって、人気値pは有効なタイムスタンプを表します(最も近い整数に丸めたと仮定します)。ただし、実際の時刻が抽象化されています。

    この方法では、単純な計算が1つだけ必要で、データベースに格納する必要がある値は1つだけです(p)。この方法はまた、特定のアイテムの人気が現在の時間を決して超えることができないので、暴走値を防止する。

    1日の期間にわたり職場でのアルゴリズムの例:http://jsfiddle.net/q2UCn/
    1年間の期間にわたり職場でのアルゴリズムの例:http://jsfiddle.net/tWU9y/

    あなたが投票は着実にサブででストリーミングすることが予想される場合秒間隔を使用する場合は、PHP microtime()関数などのマイクロ秒のタイムスタンプを使用する必要があります。それ以外の場合は、PHP time()のような標準のUNIXタイムスタンプが機能します。

    私の質問のために:あなたはこのアプローチで大きな欠陥を見ますか?

  • +0

    人が「違う」アイテムを許可した場合、これはデータベースにpを格納することのみを必要としません。あなたはまた、今まで作られたすべてのLikeのレコードを保存しなければなりません。そうでなければ、ユーザーは好き、好き、好き、好き、好き、好き嫌い、好き嫌い、投票違反を繰り返すことができます。 あなたが言ったように、アイテムの最初の投票を受け取ったときにアイテムのpを変更したいだけです。意味することは、すべての投票を追跡する必要があるということです。 –

    +0

    @AlSweigart良い点。このアルゴリズムは、単方向投票システム(例えば、ページビューが正の 方向の1つの「投票」であるなど)にのみ適していると考えられます。おそらく双方向投票システムとの互換性は低いでしょう。 –

    答えて

    7

    私はこれが非常に良いアプローチだと考えています。非常に興味深い結果です。

    私は簡単な計算を行い、このアルゴリズムは「人気度」が何を意味するのかを理解しているようです。その問題は、このような最近の投票を支持する明らかな傾向があることです。

    時間をかけて100から1000までの離散タイムスタンプ値に分解したとします。t = 100ではAとBの両方アイテムは)同じPを持つ= 100

    A gets voted 7 times on 200, 300, 400, 500, 600, 700 and 800 
    resulting on a final Pa(800) = 700 (aprox). 
    
        B gets voted 4 times on 300, 500, 700 and 900 
    resulting on a final Pb(900) = 712 (aprox). 
    

    トン= 1000が来て、両方のAとBは、そう、票を受け取る:

    Pa(1000) = 850 with 8 votes 
    Pb(1000) = 856 with 5 votes 
    

    なぜ?そのアルゴリズムはアイテムがにすぐにがより最近の票を受け取った場合(たとえそのアイテムの投票総数が少なくても)履歴リーダーを打ち負かすことができるからです。 、私は一つの問題を参照してください

    http://jsfiddle.net/wBV2c/6/

    Item A receives one vote each day from 1970 till 2012 (15339 votes) 
    Item B receives one vote each month from Jan to Jul 2012 (7 votes) 
    

    The result: B is more popular than A.

    +2

    偉大な分析!あなたはアルゴリズムが最近のアクティビティを優先していることは間違いありません。これはアプリケーションによっては望ましいかもしれないし、そうでないかもしれません。私の意見では、この動作はほとんどのアプリケーションに適しています。それでも、実装の容易さのために支払う小さな価格。 –

    +0

    @danielfaraday:32ビットタイプを使用している場合、オーバーフローする可能性があるため、一時的にレートを大幅に下げて更新してください。 –

    +0

    @MooingDuck:私は従いません。 Pは丸められていると仮定しているので、サイズはタイムスタンプのサイズと常に同じです(タイムスタンプの粒度が秒、ミリ秒、またはマイクロ秒のいずれであるかにかかわらず)。 –

    1

    この欠陥は、100票のものが最近の投票が1つしかないものより意味があるということです。しかし、合理的にうまく動作するあなたのスキームの変種を考え出すのは難しいことではありません。

    +0

    最近の1つの投票のタイムスタンプは額面では取られません。代わりに、それはもっと古い投票で*平均*されます。これにより、アイテムが100票のアイテムよりも低いランクになる可能性が高くなります(100票がすべて非常に長い*前に発生した場合を除く)。 –

    +0

    また、100票が実際に*非常に*前に発生した場合、時間依存の人気の定義では、100票*の項目が最近の1票よりも低くランクされる必要があります。その最後の文に対しては –

    +0

    +1、私はあなたに同意します。 – daniloquio

    3

    :SIMULATION

    含む

    EDITはOPは、私は次のような結果を得るために変え素敵なフィドルを作成しました最後の〜24票だけがカウントされます。 2票については

    p_i+1 = (p + t)/2 
    

    我々は32票のためにそれを拡大

    p2 = (p1 + t2)/2 = ((p0 + t1) /2 + t2)/2 = p0/4 + t1/4 + t2/2 
    

    を持っています:

    p32 = t*2^-32 + t0*2^-32 + t1*2^-31 + t2*2^-30 + ... + t31*2^-1 
    

    だから、符号付き32ビット値のため、T0は、結果には影響しません。 t0は2^32で割られるので、p32に何も寄与しません。

    2つのアイテムAとBがある場合(同じように大きな違いがあっても)、両方とも同じ32票を取得すると、同じ人気を持ちます。だから歴史は32票だけ戻ってきます。最後の32票が同じであれば、2032票と32票に違いはありません。

    差が1日未満の場合は、17票の後で同じになります。

    +1

    これは間違っています。私はあなたがここで間違っていることを証明します:http://jsfiddle.net/q2UCn/。これは、あなたが上記で概説した正確な分析の実際の計算です(アイテムAは、アイテムBが17票を受け取る同じ日に217票を受け取ります)。私は同様の結果をもたらす1年以上にわたる25票(http://jsfiddle.net/tWU9y/)でこの分析を行った。 –

    +0

    おっと、そうです。私は結果を正しく解釈しなかった。修正しました。 – Ishtar

    +0

    Ishtar:それは正しいです。 2つの商品が両方とも*正確に*同じ時刻に32票を受け取った場合、丸めはその人気度を同じにします。ここに証拠があります:http://jsfiddle.net/c4RVr/。しかし、このようなことが起こる可能性は、投票が1秒未満の間隔で着実にストリーミングされない限り、極端に小さい*である。この場合、単にマイクロ秒のタイムスタンプ(PHPの 'microtime()'関数など)を使用することができます。これは問題を解決します。ここに証拠があります:http://jsfiddle.net/k8HXu/。これはちょうどあなたが期待しているトラフィックの量に依存します。 –