Почему результат всегда составляет около 2,87 - PullRequest
1 голос
/ 07 июня 2019

У меня есть код ниже

result=0
loop_n=10000
for i in range(loop_n):
    result+=np.random.rand(3,4,10).std()
result=result/loop_n
print(result)

Как я понимаю, если я запускаю несколько раз, результат должен быть другим, потому что результат получается случайным, но на самом деле результат всегда около 0,287

Есть ли какая-то теория за этим?

Ответы [ 4 ]

6 голосов
/ 07 июня 2019

Это просто доказательство того, что np.random.rand хороший униформа генератор случайных чисел.У вас есть 10000 наблюдений за стандартным отклонением распределения по тому же закону.Стандартное отклонение - это квадратный корень из дисперсии, или, как правило, теоретическое (вероятностное) стандартное отклонение составляет (max - min) / sqrt(12).У вас довольно большой размер выборки, поэтому наблюдаемая оценка будет близка к теоретическому стандартному отклонению, равному 1/sqrt(12), примерно 0,28867513459481287.Но теперь это становится математическим вопросом: -)


Предполагая равномерное распределение на [0,1], вероятностное (теоретическое) среднее E (X) является интегралом от x на отрезке [0-1], что составляет 0,5.Дисперсия по определению E ((XE (X)) 2 ), которая может быть вычислена как интеграл от x 2 на отрезке [-0,5,0,5] и его квадратном корнедает результат, написанный выше.

3 голосов
/ 07 июня 2019

1.Почему так мало изменчивости?

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

https://en.wikipedia.org/wiki/Law_of_large_numbers

2.Почему 0,287?

rand возвращает равномерно распределенные числа от 0 до 1, поэтому истинное среднее значение равно 1/2, а истинная дисперсия равна целому [-1 / 2..1 / 2] x ^ 2 dx, чтоВы можете проверить, чтобы быть 1/12.Std является квадратным корнем этого ~0.289.

3.Почему не совсем sqrt (1/12) ~ 0,289?

Но подождите, это немного не так.Зачем?Поскольку numpy возвращает образец var / std, который является искаженной оценкой реальной вещи, он систематически недооценивает их.Когда вы производите выборку в сравнительно небольших партиях размером N=120, это дает небольшую, но последовательную разницу.Как только мы добавим поправку N / (N-1) (в пересчете на стандартное значение), мы получим лучшее соответствие.Вы можете попробовать это в своем коде, передав ключевое слово ddof=1 std.

4.Но с поправкой результат кажется слишком малым?

Это правильно.Поправочный коэффициент N/(N-1) дает непредвзятую оценку для var, но не для std, в основном потому, что взятие среднего значения, а затем sqrt не совпадает с взятием sqrt и среднего значения.

Вы можете проверить это, используя var (все еще с аргументом ddof=1) вместо std и взяв sqrt после получения среднего значения:

loop_n=1000000
result=0
print_at = 1
for i in range(1, loop_n+1):
    result+=np.random.rand(3,4,10).var(ddof=1)
    if i == print_at:
        print(math.sqrt(result/i))
        print_at *= 10

print("...")
print(math.sqrt(1/12))

Пример прогона:

0.28103387158480164
0.2952158859220745
0.2902562660869275
0.28882685146952614
0.2887019908636715
0.2886783761564752
0.2886714244895549
...
0.28867513459481287
1 голос
/ 07 июня 2019

Давайте посмотрим, что вы делаете:

  • На каждом шаге вы np генерируете 120 случайных значений от 0 до 1 и получаете их стандартное отклонение.Это всегда около 0,2887, иногда больше, иногда меньше.Объяснение см. Ниже.
  • Вы складываете все эти стандартные отклонения и делите их на их количество.По сути, вы получаете их среднее значение.
  • Поскольку их так много, они все ближе и ближе приближаются к ожидаемому значению 0.2887.

Объяснение:

Если вы выполните while 1: np.random.rand(3,4,10).std() в консоли Python, вы увидите, что выбрасывается много чисел (пока вы не нажмете Ctrl-C), и иногда они .266, иногда .297 и т. Д.

Но что они значат?Ну, стандартное отклонение - это (очень грубо) среднее значение расстояний набора значений от их среднего значения.

  • Если вы берете [.5, .5, .5], среднее значение составляет .5стандартное значение равно 0.
  • Но с [0, .5, 1] среднее значение равно .5, но стандартное значение равно .408248.
  • С np.f64([.0, .1, .2, .3, .4, .5, .6, .7, .8, .9, 1]).std(), выget .316.
  • С np.random.rand(300,300,300).std() вы получите примерно тот же результат, что и вы: всегда что-то около .2887.Почему ожидаемое значение точно .2887 вытекает из определения стандартного отклонения.По сути, это связано с ожидаемым равномерным распределением того, что производит np.random.rand().
0 голосов
/ 07 июня 2019

Функция numpy rand извлекает случайное число из равномерного распределения [0, 1), что означает, что существует равная вероятность получить любое число от 0 до 1. Ваш код извлекает из этого распределения 120 случайных чисел и вычисляет Оценка стандартного отклонения по формуле

std = sqrt(mean(abs(x - x.mean())**2))

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

Чтобы вычислить теоретическое значение, мы можем использовать это variance(x) = 1/12 для случайной величины X в равномерном распределении. Это означает, что std(x) = sqrt(1/12) = 0.2887, что близко к результату моделирования.

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