5つ星の評価で並べ替えるより良い方法は何ですか?
-
05-07-2019 - |
質問
5つ星のシステムを使用して、顧客の評価で多数の製品を並べ替えようとしています。私がこれを設定しているサイトには多くの評価がなく、新しい製品を追加し続けているため、通常は評価の少ない製品がいくつかあります。
平均の星評価を使用しようとしましたが、評価の数が少ないとそのアルゴリズムは失敗します。
5つ星の評価が3つある製品は、5つ星の評価が100つあり、2つ星の評価が2つある製品よりもよく表示されます。
2番目の製品は、評価の数が多いため統計的に信頼できるため、より高く表示されるべきではありませんか?
解決
2015年以前、インターネットムービーデータベース(IMDb)は、トップ250 の映画リスト。引用するには:
上位250件のタイトルの計算式により、真のベイズ推定値が得られます。
weighted rating (WR) = (v ÷ (v+m)) × R + (m ÷ (v+m)) × C
where:
- R =映画の平均(平均)
- v =映画の投票数
- m =上位250にリストするために必要な最低投票数(現在25000)
- C =レポート全体の平均投票(現在7.0)
上位250人については、通常の有権者からの投票のみが考慮されます。
理解するのはそれほど難しくありません。式は次のとおりです。
rating = (v / (v + m)) * R +
(m / (v + m)) * C;
次のように数学的に単純化できます:
rating = (R * v + C * m) / (v + m);
変数は次のとおりです。
- R–アイテムの独自の評価。 Rは、アイテムの投票の平均です。 (たとえば、アイテムに投票がない場合、Rは0です。誰かが5つ星を与えると、Rは5になります。他の誰かが1つ星を与えると、Rは3になり、
[1、5]の平均
など)。 - C–平均アイテムの評価。データベース内の現在のアイテムを含むすべてのアイテムのRを見つけ、それらの平均を取ります。それはCです(データベースに4つのアイテムがあり、それらの評価が
[2、3、5、5]
であると仮定します。Cはそれらの数の平均である3.75です。) - v–アイテムの投票数。 (別の例を挙げると、5人がアイテムに投票した場合、vは5です。)
- m–調整可能なパラメーター。 「スムージング」の量評価に適用されるのは、mに対する投票数(v)に基づきます。結果が満足するまでmを調整します。また、IMDbのmの説明を「リストに必要な最低限の投票」と誤解しないでください。 –このシステムは、mより少ない票数でアイテムをランク付けできます。
式が行うことは、平均を計算する前に、それぞれCの値を持つm個の仮想投票を追加することです。最初は、十分なデータがない場合(つまり、投票数がmより劇的に少ない場合)、これにより、空白が平均データで埋められます。ただし、票が蓄積されると、最終的には架空の票が実際の票によって消されます。
このシステムでは、投票によって格付けが大きく変動することはありません。代わりに、彼らはそれをある方向に少し混乱させるだけです。
ゼロ票がある場合、架空の票のみが存在し、それらはすべてCです。したがって、各項目はCの評価で始まります。
参照:
他のヒント
エヴァンミラーは、5位のベイジアンアプローチを示しています。星評価:
where
-
nk
は、k
-starレーティングの数です。 -
sk
は「価値」です(ポイント単位)k
星、 -
N
は総投票数です -
K
は星の最大数です(5つ星の評価システムではK = 5など) -
z_alpha / 2
は、正規分布の1-alpha / 2
分位数です。実際のソート基準が計算されたソート基準と少なくとも同じ大きさであるという(ベイジアン事後分布に基づく)95%の信頼度が必要な場合は、z_alpha / 2
= 1.65を選択します。
Pythonでは、ソート基準は次の方法で計算できます
def starsort(ns):
"""
http://www.evanmiller.org/ranking-items-with-star-ratings.html
"""
N = sum(ns)
K = len(ns)
s = list(range(K,0,-1))
s2 = [sk**2 for sk in s]
z = 1.65
def f(s, ns):
N = sum(ns)
K = len(ns)
return sum(sk*(nk+1) for sk, nk in zip(s,ns)) / (N+K)
fsns = f(s, ns)
return fsns - z*math.sqrt((f(s2, ns)- fsns**2)/(N+K+1))
たとえば、アイテムに60個の5つ星、80個の4つ星、75個の3つ星、20個の2つ星、25個の1つ星がある場合、全体的な星評価は約3.4になります:
x = (60, 80, 75, 20, 25)
starsort(x)
# 3.3686975120774694
そして5つ星評価のリストをソートできます
sorted([(60, 80, 75, 20, 25), (10,0,0,0,0), (5,0,0,0,0)], key=starsort, reverse=True)
# [(10, 0, 0, 0, 0), (60, 80, 75, 20, 25), (5, 0, 0, 0, 0)]
これは、より多くの評価が全体的な星の値に与える影響を示しています。
この式は少し全体的な評価を与える傾向があることがわかります Amazon、Ebay、Wal-martなどのサイトで報告された総合評価よりも低い 特に投票数が少ない場合(たとえば、300未満)。これは 不確実性が高く、票数が少ない。投票数が増えると (数千に)すべてのこれらの評価式は全体的に傾向があるはずです (加重)平均評価。
式は5つ星の評価の頻度分布のみに依存するため アイテム自体については、複数のソースからのレビューを組み合わせするのは簡単です(または、 頻度を追加するだけで、新しい投票に照らして全体の評価を更新する 一緒に配布します。
IMDb式とは異なり、この式は平均スコアに依存しません すべてのアイテムにまたがる、または人工の最低投票数カットオフ値。
さらに、この式は、完全な頻度分布を利用しています-だけではありません 星の平均数と投票数。そして、それはそれが理にかなっています 10個の5つ星と10個の1つ星を持つアイテムは、 の項目よりも不確実性が高い(したがって、その項目ほど高く評価されていない) 20の3つ星評価:
In [78]: starsort((10,0,0,0,10))
Out[78]: 2.386028063783418
In [79]: starsort((0,0,20,0,0))
Out[79]: 2.795342687927806
IMDbの式はこれを考慮していません。
まあ、どの程度複雑にしたいかによっては、その人が行った評価の数とその評価に基づいて、評価にさらに重みを付けることができます。その人が評価を1つしか行っていない場合、それはシリングの評価である可能性があり、それよりも少なくカウントされる可能性があります。または、カテゴリaで多くの項目を評価したが、カテゴリbで評価したものが少なく、5つ星の平均評価が1.3である場合、カテゴリaはこのユーザーの低い平均スコアによって人為的に評価されているように聞こえます。調整する必要があります。
しかし、それを十分に複雑にします。簡単にしましょう。
特定のアイテムについてReviewCountとAverageRatingの2つの値のみを操作していると仮定すると、ReviewCountが本質的に“信頼性”であると考えるのは理にかなっています。値。ただし、ReviewCountの低いアイテムのスコアを下げるだけではありません。1つの1つ星の評価は、1つの5つ星の評価と同じくらい信頼性が低いでしょう。したがって、私たちがやりたいことは、おそらく中間の平均です:3.
つまり、基本的に、X * AverageRating + Y * 3 = the-rating-we-wantのような方程式を考えています。この値を正しくするには、X + Yを1にする必要があります。また、ReviewCountが増加するにつれて値を増やす必要があります...レビューカウントが0の場合、xは0である必要があります(& #8220; 3”)、および無限のレビューカウントでは、Xは1である必要があります(式= AverageRatingになります)。
では、XおよびY方程式とは何ですか? X方程式では、独立変数が無限に近づくにつれて、従属変数が漸近的に1に近づくようにします。方程式の良いセットは次のようなものです: Y = 1 /(factor ^ RatingCount) および(Xが1-Yに等しくなければならないという事実を利用して) X = 1– (1 /(factor ^ RatingCount)
その後、" factor"を調整できます。探している範囲に合うように。
この単純なC#プログラムを使用して、いくつかの要因を試しました:
// We can adjust this factor to adjust our curve.
double factor = 1.5;
// Here's some sample data
double RatingAverage1 = 5;
double RatingCount1 = 1;
double RatingAverage2 = 4.5;
double RatingCount2 = 5;
double RatingAverage3 = 3.5;
double RatingCount3 = 50000; // 50000 is not infinite, but it's probably plenty to closely simulate it.
// Do the calculations
double modfactor = Math.Pow(factor, RatingCount1);
double modRating1 = (3 / modfactor)
+ (RatingAverage1 * (1 - 1 / modfactor));
double modfactor2 = Math.Pow(factor, RatingCount2);
double modRating2 = (3 / modfactor2)
+ (RatingAverage2 * (1 - 1 / modfactor2));
double modfactor3 = Math.Pow(factor, RatingCount3);
double modRating3 = (3 / modfactor3)
+ (RatingAverage3 * (1 - 1 / modfactor3));
Console.WriteLine(String.Format("RatingAverage: {0}, RatingCount: {1}, Adjusted Rating: {2:0.00}",
RatingAverage1, RatingCount1, modRating1));
Console.WriteLine(String.Format("RatingAverage: {0}, RatingCount: {1}, Adjusted Rating: {2:0.00}",
RatingAverage2, RatingCount2, modRating2));
Console.WriteLine(String.Format("RatingAverage: {0}, RatingCount: {1}, Adjusted Rating: {2:0.00}",
RatingAverage3, RatingCount3, modRating3));
// Hold up for the user to read the data.
Console.ReadLine();
だからあなたはそれをわざわざコピーする必要はありません、それはこの出力を与えます:
RatingAverage: 5, RatingCount: 1, Adjusted Rating: 3.67
RatingAverage: 4.5, RatingCount: 5, Adjusted Rating: 4.30
RatingAverage: 3.5, RatingCount: 50000, Adjusted Rating: 3.50
そのような何か?もちろん、「ファクター」を調整できます。必要な種類の重みを取得するために必要な値。
高速で安価なソリューションが必要な場合、多くの計算を使用せずにほとんどの場合に機能します(1〜5の評価スケールを想定)。1つのオプションがあります
SELECT Products.id, Products.title, avg(Ratings.score), etc
FROM
Products INNER JOIN Ratings ON Products.id=Ratings.product_id
GROUP BY
Products.id, Products.title
ORDER BY (SUM(Ratings.score)+25.0)/(COUNT(Ratings.id)+20.0) DESC, COUNT(Ratings.id) DESC
25を加算し、合計評価+ 20で割ると、基本的に合計評価に10個の最悪のスコアと10個の最高のスコアが追加され、それに応じて並べ替えられます。
これには既知の問題があります。たとえば、評価の少ない低スコアの製品に不当に報いる(このグラフは、平均スコアが1で評価スコアが1つの商品を示しています1.2の場合、平均スコアが1および1k +の評価スコアが1.05に近い製品)。また、評価がほとんどない高品質の製品を不当に罰するという主張もできます。
このチャートは、1-1000評価を超える5つの評価すべてで何が起こるかを示しています。 http://www.wolframalpha.com/input/?i=Plot3D%5B%2825%2Bxy%29/%2820%2Bx%29%2C%7Bx %2C1%2C1000%7D%2C%7By%2C0%2C6%7D%5D
一番下の格付けで下落が見られますが、全体としては公平なランキングだと思います。次の方法でも見ることができます:
このグラフのほとんどの場所に大理石をドロップすると、より高いスコアと高い評価の両方を持つ製品に自動的に転がります。
明らかに、評価の数が少ないため、この問題は統計的な障害になります。決して少ない...
総合評価の品質を改善するための重要な要素は、「評価者を評価する」ことです。つまり、各特定の「評価者」評価のタブを保持することです。 (他に対して)提供しています。これにより、集計プロセス中に投票を重み付けできます。
もう1つの解決策は、より多くの対処方法として、基礎となるアイテムの投票数(またはその範囲表示)をエンドユーザーに提供することです。
1つのオプションは、スコアが mean-3 * stddev
で与えられるMicrosoftのTrueSkillシステムのようなもので、定数を調整できます。
しばらく見てから、ベイジアンシステムを選択します。 誰かがRubyを使用している場合、ここにgemがあります:
Toby Segaran(OReilly)ISBN 978-0-596-52932-1の著書 『Programming Collective Intelligence』を強くお勧めします。例はPythonで記述されていますが、変換するのに十分簡単です。