Вопрос

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

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

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

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

Это было полезно?

Решение

До 2015 года в базе данных интернет-фильмов (IMDb) публично указывалась формула, используемая для ранжирования их Топ - 250 список фильмов.Процитировать:

Формула для расчета 250 названий с самым высоким рейтингом дает истинная байесовская оценка:

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

где:

  • R = среднее значение по фильму (mean)
  • 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 каждого отдельного элемента в базе данных, включая текущий, и возьмите среднее значение по ним;это и есть С.(Предположим, в базе данных есть 4 элемента, и их рейтинги равны [2, 3, 5, 5].C равно 3,75, среднему значению этих чисел.)
  • v – Количество голосов, поданных за какой-либо пункт.(Чтобы привести другой пример, если 5 человек проголосовали по какому-либо вопросу, v равно 5.)
  • m – настраиваемый параметр.Величина "сглаживания", применяемая к рейтингу, основана на количестве голосов (v) по отношению к m.Регулируйте m до тех пор, пока результаты вас не удовлетворят.И не истолковывайте неправильно описание IMDb для m как "минимальное количество голосов, необходимое для включения в список" – эта система вполне способна ранжировать материалы с меньшим количеством голосов, чем m.

Все, что делает формула, это:сложите m воображаемых голосов, каждый со значением C, прежде чем вычислять среднее значение.Вначале, когда недостаточно данных (т.е.количество голосов значительно меньше m), это приводит к заполнению пробелов средними данными.Однако по мере накопления голосов воображаемые голоса в конце концов будут заглушены реальными.

В этой системе голоса не приводят к резким колебаниям рейтинга.Вместо этого они просто немного нарушают его в каком-то направлении.

Когда голосов ноль, существуют только воображаемые голоса, и все они равны C.Таким образом, каждый элемент начинается с рейтинга C.

Смотрите также:

Другие советы

Смотрите эту страницу для хорошего анализа звезды рейтинговые системы и эта для хорошего анализа систем, основанных на повышении / понижении.

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

См. вторую статью для ответа, но вывод заключается в том, что вы хотите использовать доверие Уилсона. В статье приводится уравнение и пример кода 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-звездочными рейтингами, вам, вероятно, следует перейти к некоторому взвешенному режиму, назначив больший вес рейтингам с той же медианой, но с большим количеством общих голосов.

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

Но достаточно сделать его сложным. Давайте сделаем это проще.

Если предположить, что мы работаем только с двумя значениями, ReviewCount и AverageRating, для конкретного элемента, для меня будет иметь смысл рассматривать ReviewCount как, по сути, & # 8220; надежность & # 8221; значение. Но мы не хотим просто снижать баллы за низкие элементы ReviewCount: один рейтинг в одну звезду, вероятно, столь же ненадежен, как и один рейтинг в 5 звезд. Итак, то, что мы хотим сделать, это, вероятно, среднее значение к середине: 3.

Итак, в общем, я думаю об уравнении, похожем на X * AverageRating + Y * 3 = рейтинг, который мы хотим. Чтобы сделать это значение правильным, нам нужно, чтобы X + Y было равно 1. Также нам нужно, чтобы значение X увеличивалось по мере увеличения ReviewCount ... со счетчиком обзора 0, x должно быть 0 (что дает нам уравнение & # 8220; 3 & # 8221;) и с бесконечным счетом обзора X должно быть 1 (что делает уравнение = AverageRating).

Итак, что такое уравнения X и Y? Для уравнения X необходимо, чтобы зависимая переменная асимптотически приближалась к 1, когда независимая переменная приближается к бесконечности Хороший набор уравнений выглядит примерно так: Y = 1 / (коэффициент ^ RatingCount) и (используя тот факт, что X должен быть равен 1-Y) Х = 1 & # 8211; (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

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

Очевидно, что небольшое количество оценок ставит эту проблему в статистический ущерб. Тем не менее ...

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

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

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

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

https://github.com/wbotelhos/rating

Я очень рекомендую книгу «Программирование коллективного интеллекта» Тоби Сегарана (Ореилли) ISBN 978-0-596-52932-1, в которой обсуждается, как извлечь значимые данные из поведения толпы. Примеры написаны на Python, но его достаточно легко конвертировать.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top