Как рандомизировать значения между 1 и 10 для реалистичных оценок? - PullRequest
5 голосов
/ 30 декабря 2010

У меня есть база данных фильмов, где мне нужно заполнить данными, чтобы стало проще тестировать и разрабатывать приложение.Есть таблицы для хранения рейтингов фильмов и учетных записей пользователей, пользователи оценивают фильмы.

Я начал разрабатывать скрипт для заполнения базы данных поддельными и общими данными, но я не знаю, как рандомизировать рейтинг,Для каждого фильма я выбираю случайное количество пользователей: 100, 500, 1000, что угодно.И для каждого из этих пользователей я рандомизирую рейтинг от 1 до 10. Но эти оценки приводят к одному и тому же среднему значению, около 5. Что означает, что распределение оценок (от 1 до 10) для конкретного фильма в основном одинаково.Это вовсе не «реалистично», так как все фильмы с подобными рейтингами будут иметь одинаковое среднее значение, поэтому одинаковые оценки от разных пользователей и разного количества пользователей не имеют значения.

Я хотел фильмА иметь среднее значение 7, фильм В среднее значение 5, фильм С среднее значение 8 и т. Д. Но я просто не хочу, чтобы среднее значение было разным для каждого фильма.Я имею в виду, что было бы неплохо составить рейтинг, подобный этому (для определенного числа пользователей): http://www.imdb.com/title/tt1046173/ratings или это http://www.imdb.com/title/tt0486640/ratings

Вы знаете, что-то случайное, что может привести к двум различным вариациям, таким какте, что выше.Я нажимаю «Обновить» и получаю первый график, нажимаю «Обновить» и получаю второй, снова нажимаю и получаю что-то другое или похожее, что-то «случайное» и «реалистичное».

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

Как я могу решить это?Может быть, это слишком много работы, не стоит того?

Может быть, что-то попроще, например, выбрать точку (между 1 и 10), а затем создать нормальное распределение оценок, где эта выбранная точка является самой высокой, которая будет работать дляя.

Ответы [ 6 ]

4 голосов
/ 30 декабря 2010

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

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

Edit: На самом деле, если вы думаете об этом, это можно легко решить: причина, по которой ваши числа стремятся к 5, в том, что ваша шкала находится в диапазоне от 1 до 10 (поэтому среднее значение равно 5).

Просто возьмите ваши случайные числа, добавьте 8 ко всем из них и округлите любое число больше 10 до 10, и вы получите что-то с центром около 8-ти (но с перекосом выше). Наверное, достаточно хорош для ваших целей?

3 голосов
/ 30 декабря 2010

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

Выберите случайное число, которое будет выступать в качестве среднего балла за фильм.Затем сгенерируйте набор случайных чисел в верхней границе этого среднего.Например, если вы случайным образом генерируете 7, генерируйте случайные числа от 5 до 9. Затем добавьте пару значений от 1 до 6 и от 8 до 10, чтобы создать видимость выбросов.

РЕДАКТИРОВАТЬ:

Этот ответ может быть тем, что вы ищете, с кодом на Java.

Пример четного распределения:

Ваш код, вероятно, похож наследующее:

public class EvenDistribution
{
    private static Random random = new Random();

    public static void main(String[] args)
    {
        int maxValue = 20;

        int[] distribution = new int[maxValue];

        int iterations = 1000;

        for (int i = 0; i < iterations; i++)
        {
            int rand = random.nextInt(maxValue);
            distribution[rand]++;
        }

        for (int i = 0; i < distribution.length; i++)
        {
            System.out.println(i+1+": "+distribution[i]);
        }
    }
}

Этот класс имел следующий вывод:

1: 47
2: 45
3: 59
4: 52
5: 54
6: 52
7: 49
8: 49
9: 49
10: 48
11: 40
12: 43
13: 42
14: 61
15: 43
16: 55
17: 47
18: 55
19: 64
20: 46

Распределение очень равномерное.19 выглядит немного ненормально, но в целом можно сказать, что этот метод ГСЧ дает предсказуемые результаты.

Используя библиотеку Math Uncommons, упомянутую выше, я использовал аналогичный код, используя GaussianGenerator.

public class RandomDistribution {
    private static MersenneTwisterRNG random = new MersenneTwisterRNG();
    private static GaussianGenerator gen = new GaussianGenerator(7, 3, random);

    public static void main(String[] args)
    {
        int maxValue = 20;

        int[] distribution = new int[maxValue];

        int iterations = 1000;

        for (int i = 0; i < iterations; i++)
        {
            int rand = Math.abs(gen.nextValue().intValue());
            distribution[rand]++;
        }

        for (int i = 0; i < distribution.length; i++)
        {
            System.out.println(i+1+": "+distribution[i]);
        }
    }
}

Было получено следующее:

1: 19
2: 27
3: 41
4: 68
5: 110
6: 111
7: 125
8: 138
9: 125
10: 85
11: 64
12: 32
13: 32
14: 14
15: 5
16: 2
17: 1
18: 0
19: 1
20: 0

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

1 голос
/ 30 декабря 2010

Попробуйте алгоритм Мерсена Твистера для случайных чисел хорошего качества.

http://en.wikipedia.org/wiki/Mersenne_twister

Я думаю, что есть некоторые реализации php этого плохого парня:

http://www.phpdig.net/ref/rn35re672.html

Хорошая реализация PHP: D

0 голосов
/ 30 декабря 2010

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

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

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

1,2,4,8,16,16,8,4,2,1

Вышеупомянутые 10 элементов суммируют до 64, и поэтому хорошо подходят для отображения 64 на 10 (это просто иллюстрация). Реализации, которые я видел, хотели бы, чтобы распределение всегда суммировалось с определенным числом, но если вы инкапсулируете получение случайного числа от 1 до 10, то вы можете иметь распределения, которые суммируют по-разному.

Создав только несколько таких распределений, вы потенциально можете создать много разумных распределений, суммируя векторы вероятности (рассмотрите распределение, сильно локализованное около 3, и распределение, сильно локализованное около 8, возможно, это последний зомби-слешер, и все любители зомби проголосовали 8 потому что в фильмах про зомби это было довольно хорошо, и остальная часть фильма, ставшая достоянием общественности, проголосовала 3, потому что ... в общем, это более менее отстойно).

0 голосов
/ 30 декабря 2010

Как предполагает Кенни, вы хотите взглянуть на нормальное распределение. Если вы посмотрите на рейтинги IMDB, вы увидите, что большинство фильмов следуют нормальному распределению. Исключение составляют самые верхние и нижние рейтинги. Многие люди скажут, что они ненавидят или любят фильм - они преувеличивают свое истинное чувство, отсюда и эти спайки. Таким образом, для точного набора данных вам нужно будет добавить их. Возможно, пусть самый низкий рейтинг = (сумма следующих двух самых низких) * константа?

0 голосов
/ 30 декабря 2010

Мой пример: вовлекайте время в генерацию случайных чисел, также используйте такие функции, как mt_rand, для улучшения генерации случайных чисел.Попробуйте выполнить несколько сложных операций с плавающей точкой и приведение к int и, наконец, применить% max_value, чтобы результат соответствовал вашему ограничению.

Пример:

function x()
{
 return (time() * 7.3333333333 * mt_rand(0.1 , 10.1));
}

$rank = (x() + 3.99999) % 10);

Я не говорю, что это работает, но иллюстрируетидея.Надеюсь, это поможет!

...