Question

J'essaie de trier une série de produits en fonction des évaluations de clients à l'aide d'un système 5 étoiles. Le site pour lequel je suis en train de créer n'a pas beaucoup de notes et continue d'ajouter de nouveaux produits, de sorte qu'il aura généralement quelques produits avec un nombre de notes faible.

J'ai essayé d'utiliser le nombre moyen d'étoiles, mais cet algorithme échoue lorsqu'il existe un petit nombre d'évaluations.

Par exemple, un produit avec 3 x 5 étoiles apparaît mieux qu'un produit avec 100 x 5 étoiles et 2x 2 étoiles.

Le deuxième produit ne devrait-il pas apparaître plus haut, car il est statistiquement plus fiable en raison du nombre plus important d’évaluations?

Était-ce utile?

La solution

Avant 2015, Internet Movie Database (IMDb) répertoriait publiquement la formule utilisée pour classer leurs Liste des 250 meilleurs films . Pour citer:

  

La formule de calcul des 250 meilleurs titres donne une véritable estimation bayésienne :

weighted rating (WR) = (v ÷ (v+m)) × R + (m ÷ (v+m)) × C
     

où:

     
      
  • R = moyenne pour le film (moyenne)
  •   
  • v = nombre de votes pour le film
  •   
  • m = nombre minimum de votes requis pour figurer dans le Top 250 (actuellement 25 000)
  •   
  • C = le vote moyen sur l'ensemble du rapport (actuellement 7,0)
  •   
     

Pour le Top 250, seuls les votes des électeurs ordinaires sont pris en compte.

Ce n'est pas si difficile à comprendre. La formule est la suivante:

rating = (v / (v + m)) * R +
         (m / (v + m)) * C;

Ce qui peut être simplifié mathématiquement à:

rating = (R * v + C * m) / (v + m);

Les variables sont:

  • R & # 8211; La propre note de l'article. R est la moyenne des votes de l'article. (Par exemple, si un élément n'a pas de voix, son R est 0. Si quelqu'un lui attribue 5 étoiles, R devient 5. Si quelqu'un d'autre lui attribue 1 étoile, R devient 3, la moyenne de [1, 5] . Et ainsi de suite.)
  • C & # 8211; La note moyenne de l'article. Trouvez le R de chaque élément de la base de données, y compris celui en cours, et prenez la moyenne d'entre eux. c'est-à-dire C. (Supposons que la base de données contient 4 éléments et que leur classement est [2, 3, 5] . C est 3,75, la moyenne de ces nombres.)
  • v & # 8211; Le nombre de votes pour un article. (Pour donner un autre exemple, si 5 personnes ont exprimé un vote, v est 5.)
  • m & # 8211; Le paramètre ajustable. La quantité de "lissage" appliqué à la notation est basé sur le nombre de votes (v) par rapport à m. Ajustez m jusqu'à ce que les résultats vous satisfont. Et n'interprétez pas de manière erronée la description faite par IMDb de m comme "nombre minimum de votes requis pour figurer dans la liste". & # 8211; ce système est parfaitement capable de classer les éléments avec moins de votes que m.

La formule est la suivante: ajoutez m votes imaginaires, chacun avec une valeur de C, avant de calculer la moyenne. Au début, quand il n’ya pas assez de données (c’est-à-dire que le nombre de votes est considérablement inférieur à m), les blancs sont remplis avec des données moyennes. Cependant, au fur et à mesure que les votes s'accumulent, les votes imaginaires seront finalement noyés dans les vrais.

Dans ce système, les votes ne provoquent pas une fluctuation importante de la note. Au lieu de cela, ils ne font que le perturber un peu dans une certaine direction.

Lorsqu'il n'y a aucun vote, il n'y a que des votes imaginaires, et ils sont tous de type C. Ainsi, chaque élément commence par une note de C.

Voir aussi:

Autres conseils

Voir cette page pour une bonne analyse de star systèmes de notation basés sur, et celui-ci pour une bonne analyse des systèmes basés sur les votes positifs / négatifs.

Pour les votes à la hausse et à la baisse, vous voulez estimer la probabilité que, compte tenu de votre classement, le "réel" Le score (si vous aviez un nombre infini d’évaluations) est supérieur à une certaine quantité (comme, par exemple, un nombre similaire pour un autre élément que vous triez).

Voir le deuxième article pour la réponse, mais la conclusion est que vous souhaitez utiliser la confiance de Wilson. L'article donne l'équation et un exemple de code Ruby (traduit facilement dans une autre langue).

Evan Miller montre une approche bayésienne du classement 5- classement par étoiles: entrer la description de l'image ici

  • nk est le nombre d'attributs k -star,
  • sk est la "valeur". (en points) sur k étoiles,
  • N est le nombre total de votes
  • K est le nombre maximal d'étoiles (par exemple, K = 5, dans un système de notation à 5 étoiles)
  • z_alpha / 2 est le quantile 1 - alpha / 2 d'une distribution normale. Si vous souhaitez que 95% (sur la base de la distribution bayésienne postérieure) sachent que le critère de tri réel est au moins aussi grand que le critère de tri calculé, choisissez z_alpha / 2 = 1.65.

En Python, le critère de tri peut être calculé avec

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))

Par exemple, si un élément a 60 étoiles cinq étoiles, 80 quatre étoiles, 75 trois étoiles, 20 deux étoiles et 25 une étoile, sa note globale en étoiles serait d'environ 3,4:

x = (60, 80, 75, 20, 25)
starsort(x)
# 3.3686975120774694

et vous pouvez trier une liste de classements 5 étoiles avec

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)]

Ceci montre l'effet qu'un plus grand nombre d'évaluations peut avoir sur la valeur globale de l'étoile.

Vous constaterez que cette formule a tendance à donner une note globale un peu inférieur à la note globale indiquée par des sites tels qu'Amazon, Ebay ou Wal-Mart particulièrement quand il y a peu de votes (disons, moins de 300). Cela reflète la plus grande incertitude qui vient avec moins de votes. Au fur et à mesure que le nombre de votes augmente (dans les milliers) toutes ces formules de notation devraient tendre à la Note moyenne (pondérée).

Puisque la formule dépend uniquement de la distribution de fréquence des cotes 5 étoiles pour l’article même, il est facile de combiner des avis provenant de plusieurs sources (ou, mettez à jour la note globale à la lumière des nouveaux votes) en ajoutant simplement la fréquence distributions ensemble.

Contrairement à la formule IMDb, cette formule ne dépend pas du score moyen dans tous les éléments, ni une valeur limite artificielle pour le nombre minimal de votes.

De plus, cette formule utilise la distribution de fréquence complète - pas seulement le nombre moyen d'étoiles et le nombre de votes. Et il est logique que cela devrait depuis un article avec dix 5 étoiles et dix 1 étoiles devrait être traité comme ayant plus d’incertitude que (et n’est donc pas classé aussi haut que) un élément avec vingt évaluations 3 étoiles:

In [78]: starsort((10,0,0,0,10))
Out[78]: 2.386028063783418

In [79]: starsort((0,0,20,0,0))
Out[79]: 2.795342687927806

La formule IMDb ne prend pas cela en compte.

Vous pouvez trier par médian au lieu de la moyenne arithmétique. Dans ce cas, les deux exemples ont une médiane de 5, ils auraient donc le même poids dans un algorithme de tri.

Vous pouvez utiliser un mode dans le même sens, mais la médiane est probablement un meilleure idée.

Si vous souhaitez attribuer un poids supplémentaire au produit avec 100 évaluations 5 étoiles, optez plutôt pour un mode pondéré, attribuant plus de poids aux évaluations avec la même médiane, mais avec plus de votes globaux.

Eh bien, selon le degré de complexité de votre stratégie, vous pouvez également pondérer les cotes en fonction du nombre de cotes attribuées par la personne et de leur classement. Si la personne n'a établi qu'une seule note, il pourrait s'agir d'une note en shill et compter moins. Ou si la personne a évalué beaucoup de choses dans la catégorie a, mais peu dans la catégorie b, et a une note moyenne de 1,3 étoiles sur 5, il semblerait que la catégorie a puisse être artificiellement alourdie par le faible score moyen de cet utilisateur, et devrait être ajusté.

Mais assez de le rendre complexe. Soyons simples.

En supposant que nous travaillions avec seulement deux valeurs, ReviewCount et AverageRating, pour un élément particulier, il serait logique pour moi de considérer ReviewCount comme étant essentiellement la "fiabilité" & # 8221; valeur. Mais nous ne voulons pas simplement réduire les scores des éléments peu nombreux dans ReviewCount: un classement à une étoile est probablement aussi peu fiable qu'un classement à 5 étoiles. Donc, ce que nous voulons faire est probablement moyenne vers le milieu: 3.

Donc, en gros, je pense à une équation qui ressemble à X * AverageRating + Y * 3 = the-rating-we-want. Pour que cette valeur soit correcte, nous avons besoin que X + Y soit égal à 1. Nous devons également augmenter la valeur de X à mesure que ReviewCount augmente ... avec un nombre de révisions égal à 0, x doit être 0 (nous donnant une équation de & # 8220; 3 & # 8221;), et avec un nombre de révisions infini, X doit être égal à 1 (ce qui donne l'équation = AverageRating).

Alors, quelles sont les équations X et Y? Pour l'équation X, vous souhaitez que la variable dépendante approche asymptotiquement de 1 à mesure que la variable indépendante approche l'infini. Un bon jeu d’équations est quelque chose comme: Y = 1 / (facteur ^ RatingCount) et (en utilisant le fait que X doit être égal à 1-Y) X = 1 & # 8211; (1 / (factor ^ RatingCount)

Ensuite, nous pouvons ajuster le "facteur". pour correspondre à la gamme que nous recherchons.

J'ai utilisé ce simple programme C # pour essayer quelques facteurs:

        // 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();

Ainsi, vous ne vous inquiétez pas de le copier, il donne cette sortie:

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

Quelque chose comme ça? Vous pouvez évidemment ajuster le "facteur". valeur au besoin pour obtenir le type de pondération que vous souhaitez.

Si vous avez simplement besoin d'une solution rapide et peu coûteuse, qui fonctionnera généralement sans beaucoup de calculs, voici une option (en supposant une échelle d'évaluation de 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

En additionnant 25 et en divisant par le nombre total de notes + 20, vous ajoutez en gros 10 scores les plus mauvais et les 10 meilleurs scores au nombre total de notes, puis vous effectuez un tri en conséquence.

Cela a des problèmes connus. Par exemple, il récompense injustement les produits à faible score avec peu d’évaluations (comme ce graphique illustre les produits avec un score moyen de 1 et un seul score. un 1,2 tandis que les produits avec un score moyen de 1 et 1k + notes se rapprochent de 1,05). Vous pourriez également dire que cela punit injustement les produits de haute qualité avec peu d’évaluations.

Ce graphique montre ce qui se passe pour les 5 évaluations de plus de 1-1000 évaluations: 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

Vous pouvez voir le creux à la hausse dans les notes les plus basses, mais dans l'ensemble, le classement est correct, je pense. Vous pouvez également le regarder de cette façon:

http://www.wolframalpha.com/input/?i=Plot3D%5B6-%28%2825%2Bxy%29 /% 2820% 2Bx% 29% 29% 2C% 7Bx% 2C1% 2C1000% 7D% 2C% 7By% 2C0% 2C6% 7D% 5D

Si vous déposez une bille sur la plupart des endroits de ce graphique, il se dirigera automatiquement vers les produits affichant des scores plus élevés et des notes plus élevées.

De toute évidence, le faible nombre d’évaluations fait de ce problème un handicap statistique. Jamais le moins ...

Pour améliorer la qualité d’une note globale, il est essentiel de "noter l’évaluateur", c’est-à-dire de garder une trace de la note attribuée à chaque "évaluateur". a fourni (par rapport aux autres). Cela permet de peser leurs votes pendant le processus d'agrégation.

Une autre solution, plus efficace, consiste à fournir aux utilisateurs finaux un décompte (ou une indication de la plage correspondante) de votes pour l'élément sous-jacent.

Une option ressemble au système TrueSkill de Microsoft, dans lequel le score est donné par mean - 3 * stddev , où les constantes peuvent être modifiées.

Après un moment, j’ai choisi le système bayésien. Si quelqu'un utilise Ruby, voici un petit bijou:

https://github.com/wbotelhos/rating

Je recommanderais vivement le livre Programming Collective Intelligence de Toby Segaran (OReilly) ISBN 978-0-596-52932-1, qui explique comment extraire des données significatives du comportement de la foule. Les exemples sont en Python, mais il est assez facile à convertir.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top