Что такое лучший способ сортировки по рейтингу 5 звезд?


Я пытаюсь отсортировать кучу продуктов по рейтингам клиентов, используя 5-звездочную систему. Сайт, для которого я это настраиваю, не имеет большого количества рейтингов и продолжает добавлять новые продукты, поэтому обычно у него будет несколько продуктов с низким количеством рейтингов.

Я попытался использовать средний рейтинг звезд, но этот алгоритм не работает, когда есть небольшое количество рейтингов.

пример продукт, который имеет 3x 5 звезд рейтинги будет отображаться лучше, чем продукт, который имеет 100x 5 звезд рейтинги и 2x 2 звезд.

не должен ли второй продукт отображаться выше, потому что он статистически более надежен из-за большего количества рейтингов?

10 56

10 ответов:

для их топ-250 фильмов Список IMDB использует Байесовской оценке. Это хороший способ учесть количество избирателей.

С здесь:

формула для вычисления вершины Рейтинг 250 наименований дает настоящий Байесовский оценка:

взвешенная оценка (WR) = (v ÷ (v+m)) × R+(m ÷ (v + m)) × C

где:

* R = average for the movie (mean) = (Rating)
* v = number of votes for the movie = (votes)
* m = minimum votes required to be listed in the Top 250 (currently 1300)
* C = the mean vote across the whole report (currently 6.8)

для топ-250, только голоса регулярный избиратели считаются.

вы можете посмотреть на этой странице, чтобы получить хороший анализ для звезды:

http://www.evanmiller.org/ranking-items-with-star-ratings.html

и вы можете посмотреть на эту страницу, чтобы получить хороший анализ для голосования вверх и вниз:

http://www.evanmiller.org/how-not-to-sort-by-average-rating.html

для голосования вверх и вниз вы хотите оценить вероятность того, что с учетом рейтингов у вас есть" реальный " балл (если вы имел бесконечные рейтинги) больше, чем некоторое количество (например, аналогичное число для некоторого другого элемента, с которым вы сортируете.)

см. вторую статью для ответа, но вывод заключается в том, что вы хотите использовать уверенность Уилсона. В статье приводится уравнение и пример кода Ruby (легко переводится на другой язык).

Эван Миллер показывает байесовский подход к ранжированию 5-звездочных рейтингов: enter image description here

здесь

  • nk число k-Звездные рейтинги,
  • sk это "стоимость" (в пунктах)k звезды,
  • N это общее количество голосов
  • K максимальное количество звезд (например, K=5, а в 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 пятизвездочных, 80 четырехзвездочных, 75 трехзвездочных, 20 двухзвездочных и 25 однозвездочных, то его общий рейтинг звезд будет около 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, эта формула не зависит от среднего балла по всем пунктам, ни искусственное минимальное количество голосов значение отсечения.

кроме того, эта формула использует полное частотное распределение -- не только среднее количество звезд и количество голосов. И это имеет смысл, что это следует ли, поскольку элемент с десятью 5-звездами и десятью 1-звездами должен рассматриваться как имея больше неопределенности, чем (и поэтому не считается высоко как) элемент с двадцать 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 не учитывает этого.

вы можете сортировать по в среднем вместо среднего арифметического. В этом случае оба примера имеют медиану 5, поэтому оба будут иметь одинаковый вес в алгоритме сортировки.

вы могли бы использовать режим к тому же эффекту, но медиана, вероятно, лучшая идея.

Если вы хотите назначить дополнительный вес продукту с 100 5-звездочными рейтингами, вы, вероятно, захотите пойти с каким-то взвешенным режимом, назначив больше веса рейтингам с помощью та же медиана, но с более общим количеством голосов.

Ну, в зависимости от того, насколько сложно вы хотите сделать это, вы могли бы дополнительно взвешивать рейтинги на основе того, сколько рейтингов сделал человек, и каковы эти рейтинги. Если человек сделал только один рейтинг, это может быть рейтинг shill, и может рассчитывать на меньшее. Или если человек оценил много вещей в категории a, но мало в категории b, и имеет средний рейтинг 1,3 из 5 звезд, похоже, что категория a может быть искусственно отягощена низким средним баллом этого потребитель, и должен быть отрегулирован.

но достаточно, чтобы сделать его сложным. Давайте все упростим.

предполагая, что мы работаем только с двумя значениями, ReviewCount и AverageRating, для конкретного элемента, для меня было бы разумно смотреть ReviewCount как по существу являющееся значением "надежности". Но мы не просто хотим снизить баллы за низкие элементы ReviewCount: один рейтинг одной звезды, вероятно, столь же ненадежен, как и один рейтинг 5 звезд. Так что то, что мы хотим сделать, вероятно средний к середине: 3.

Итак, в основном, я думаю об уравнении что-то вроде X * AverageRating + Y * 3 = the-rating-we-want. Чтобы сделать это значение правильным, нам нужно X+Y равным 1. Также Нам нужно X, чтобы увеличить значение по мере увеличения ReviewCount...с количеством просмотров 0, x должно быть 0 (что дает нам уравнение "3"), а с бесконечным количеством просмотров X должно быть 1 (что делает уравнение = усреднение).

Итак, что такое X и Y уравнения? Для уравнения X требуется, чтобы зависимая переменная асимптотически приближалась к 1, поскольку независимая переменная приближается к бесконечности. Хороший набор уравнений-это что-то вроде: Y = 1/(коэффициент^RatingCount) и (используя тот факт, что X должен быть равен 1-Y) X = 1 – (1 / (фактор^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-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.2, в то время как продукты со средним баллом 1 и 1K+ рейтинг оценивают ближе к 1.05). Вы также можете утверждать, что он несправедливо наказывает высококачественные продукты с несколькими рейтингами.

эта диаграмма показывает, что происходит для всех 5 рейтингов более 1-1000 рейтингов: 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

вы можете увидеть опускайтесь вверх по самым нижним рейтингам, но в целом это справедливый рейтинг, я думаю. Вы также можете посмотреть на это так:

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

Если вы уроните мрамор в большинстве мест на этом графике, он автоматически скатится к продуктам с более высокими баллами и более высокими рейтингами.

очевидно, что низкое количество рейтингов ставит эту проблему в статистический гандикап. Однако...

ключевым элементом для улучшения качества агрегированного рейтинга является" оценка rater", т. е. вести учет рейтингов, которые каждый конкретный" rater " предоставил (относительно других). Это позволяет взвешивать их голоса в процессе агрегации.

другое решение, больше из справляется вне, поставить пользователей с отсчетом (или индикацией ряда голосов за основной пункт повестки дня.

один из вариантов-это что-то вроде системы Microsoft TrueSkill, где оценка задается mean - 3*stddev, где константы могут быть переделаны.

после поиска на некоторое время, я выбираю байесовскую систему. Если кто-то использует Рубин, вот драгоценный камень для него:

https://github.com/wbotelhos/rating

Я настоятельно рекомендую книгу Программирование коллективный разум Тоби Segaran (связанная) ISBN в 978-0-596-52932-1, которые рассматриваются как извлечь полезную информацию из поведения больших масс людей. Примеры на Python, но его достаточно легко преобразовать.