5つ星のシステムを使用して、お客様の評価ごとに一連の製品を分類しようとしています。私がこれを設定しているサイトには多くの評価がなく、新しい製品を追加し続けているため、通常は評価の数が少ない製品がいくつかあります。
平均的な星の評価を使用してみましたが、評価の数が少ないとそのアルゴリズムは失敗します。
たとえば、3つ星の5つ星評価を持つ製品は、100x 5つ星の評価および2x 2つ星評価を持つ製品よりもよく表示されます。
評価の数が多いため統計的に信頼できるので、2番目の製品が高く表示されるべきではありませんか?
2015年以前は、インターネットムービーデータベース(IMDb)は、 上位25 映画リストのランク付けに使用される式を公開していました。引用するには:
トップ250のタイトルを計算する式は、真のベイズ推定値を示します。
weighted rating (WR) = (v ÷ (v+m)) × R + (m ÷ (v+m)) × C
どこ:
- 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);
変数は次のとおりです。
[1, 5]
の平均です。したがって、オン。)[2, 3, 5, 5]
であるとします。Cは3.75で、これらの数値の平均です。)計算式は次のとおりです。平均を計算する前に、それぞれCの値を持つm個の虚数票を追加します。最初は、十分なデータがない場合(つまり、投票数がmを大幅に下回る場合)、平均データで空白が埋められます。ただし、投票数が増えると、最終的には架空の投票数が実際の投票数に追い込まれます。
このシステムでは、投票によって格付けが大きく変動することはありません。代わりに、彼らはそれをある方向に少し混乱させるだけです。
投票数がゼロの場合、架空の投票のみが存在し、それらはすべてCです。したがって、各項目はCの評価で始まります。
以下も参照してください。
Evan Millerが示す 5つ星の評価をランク付けするベイジアンアプローチ:
どこ
nk
はk
つ星評価の数、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)]
これは、より多くの評価が全体的なスター値に与える影響を示しています。
この式は、特に投票数が少ない(300未満など)場合に、Amazon、Ebay、Wal-martなどのサイトによって報告される総合評価よりも少し低い総合評価を与える傾向があることがわかります。これは、投票数が少ないことによる不確実性の高さを反映しています。投票数が(数千に)増加すると、これらの評価式はすべて(加重)平均評価になる傾向があります。
式はアイテム自体の5つ星評価の度数分布にのみ依存するため、複数のソースからのレビューを結合するのは簡単です(またはupdate新しい投票を考慮した総合評価)度数分布を単に加算するだけです。
IMDbの式とは異なり、この式はすべてのアイテムの平均スコアや、人為的な最小投票数のカットオフ値には依存しません。
さらに、この式は、平均的な星の数や投票数だけでなく、完全な頻度分布を利用しています。そして、5つ星が10個、1つ星が10個のアイテムは、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つ星の評価は、おそらく単一の5つ星の評価ほど信頼性が低くなります。ですから、私たちがしたいのは、おそらく中央に向かう平均です:3。
つまり、基本的に、X * AverageRating + Y * 3 = the-rating-we-wantのような方程式を考えています。この値を正しくするには、X + Yを1にする必要があります。また、ReviewCountが増加するにつれてXも増加する必要があります。レビューカウントが0の場合、xは0になるはずです(「 3インチ)、レビュー回数が無限の場合、Xは1になります(これにより、方程式= AverageRatingになります)。
では、X方程式とY方程式とは何でしょうか。 X方程式では、独立変数が無限大に近づくにつれて、従属変数が漸近的に1に近づくことを望みます。 Y = 1 /(factor ^ RatingCount)および(Xが1-Yに等しくなければならないという事実を利用して)X = 1 –(1 /(factor ^ RatingCount)
次に、探している範囲に合わせて「係数」を調整できます。
この簡単な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つのオプションがあります(1〜5の評価スケールを想定)。
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
一番下の評価で下落を見ることができますが、全体としては公平なランキングだと思います。次のように表示することもできます。
このグラフのほとんどの場所にビー玉を落とすと、より高いスコアとより高い評価の両方を持つ製品に向かって自動的に回転します。
しばらく見てから、ベイジアン方式を選びました。誰かがRubyを使用している場合は、ここにその宝石があります。
1つのオプションはMicrosoftのTrueSkillシステムのようなもので、スコアはmean - 3*stddev
によって与えられ、定数を調整できます。
明らかに、評価の数が少ないと、この問題は統計的にハンディキャップになります。決して少ない...
総合評価の品質を改善するための重要な要素は、「評価者を評価する」ことです。つまり、各特定の「評価者」が提供した評価(他の人との比較)を把握することです。これにより、集計プロセス中に投票を比較検討できます。
別の解決策は、より多くの対処法として、基になるアイテムに対する投票の数(またはその範囲の表示)をエンドユーザーに提供することです。