Регулировка среднего и стандартного отклонения списка случайных чисел? - PullRequest
1 голос
/ 30 марта 2019

Мне нужно создать список случайных чисел (с десятичными числами) в диапазоне от -3 до 3. Проблема в том, что в списке должно быть среднее значение 0 и стандартное отклонение 1. Как я могу настроить среднееа параметры стандартного отклонения?Есть ли функция, которую я могу использовать?

Мне уже удалось создать список случайных чисел в диапазоне от -3 до 3.

import random


def lista_aleatorios(n):
    lista = [0] * n
    for i in range(n):
        lista[i] = random.uniform(-3, 3)
    return lista

print("\nHow many numbers do you want?: ")
n = int(input())

print (lista_aleatorios(n))

Ответы [ 3 ]

1 голос
/ 30 марта 2019

Используйте random.gauss, затем масштаб:

import numpy as np

from random import gauss

def bounded_normal(n, mean, std, lower_bound, upper_bound):

    # generate numbers between lower_bound and upper_bound

    result = []
    for i in range(n):
        while True:
            value = gauss(mean, std)
            if lower_bound < value < upper_bound:
                break

        result.append(value)

    # modify the mean and standard deviation

    actual_mean = np.mean(result)
    actual_std = np.std(result)
    mean_difference = mean - actual_mean
    std_difference = std / actual_std
    new_result = [(element + mean_difference) * std_difference for element in result]

    return new_result
0 голосов
/ 31 марта 2019

Хорошо, вот быстрый способ решения (если вы хотите использовать усеченный гауссов). Установите границы и желаемый stddev. Я предполагаю, что среднее значение равно 0. Затем быстрый и сырой код для бинарного поиска для распределения sigma, решение для нелинейного корня (brentq() должен использоваться в производственном коде). Все формулы взяты со страницы вики на Усеченный нормальный . Это (сигма) должно быть больше, чем желаемый stddev из-за того, что усечение удаляет случайные значения, которые способствуют большому stddev. Затем мы делаем быструю выборочную проверку - и mean и stddev близки к желаемым значениям, но никогда точно не равны им. Код (Python-3.7, Анаконда, Win10 x64)

import numpy as np
from scipy.special import erf
from scipy.stats import truncnorm

def alpha(a, sigma):
    return a/sigma

def beta(b, sigma):
    return b/sigma

def xi(x, sigma):
    return x/sigma

def fi(xi):
    return 1.0/np.sqrt(2.0*np.pi) * np.exp(-0.5*xi*xi)

def Fi(x):
    return 0.5*(1.0 + erf(x/np.sqrt(2.0)))

def Z(al, be):
    return Fi(be) - Fi(al)

def Variance(sigma, a, b):
    al = alpha(a, sigma)
    be = beta(b, sigma)
    ZZ = Z(al, be)

    return sigma*sigma*(1.0 + (al*fi(al) - be*fi(be))/ZZ - ((fi(al)-fi(be))/ZZ)**2)

def stddev(sigma, a, b):
    return np.sqrt(Variance(sigma, a, b))

m = 0.0 # mean
s =  1.0 # this is what we want
a = -3.0 # left boundary
b =  3.0 # right boundary

#print(stddev(s , a, b))
#print(stddev(s + 0.1, a, b))

slo = 1.0
shi = 1.1

stdlo = stddev(slo, a, b)
stdhi = stddev(shi, a, b)

sigma = -1.0
while True: # binary search for sigma
    sme = (slo + shi) / 2.0
    stdme = stddev(sme, a, b)
    if stdme - s == 0.0:
        sigma = stdme
        break
    elif stdme - s < 0.0:
        slo = sme
    else:
        shi = sme

    if shi - slo < 0.0000001:
        sigma = (shi + slo) / 2.0
        break

print(sigma) # we got it, shall be slightly bigger than s, desired stddev

np.random.seed(73123457)

rvs = truncnorm.rvs(a, b, loc=m, scale=sigma, size=1000000) # quick sampling test

print(np.mean(rvs))
print(np.std(rvs))

Для меня это напечатано

sigma = 1.0153870105743408
mean = -0.000400729471992301
stddev = 1.0024267696681475

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

1.0153870105743408
-0.00015923177289006116
0.9999974266369461
0 голосов
/ 30 марта 2019

Функция random.normalvariate(mu, sigma) позволяет указать среднее значение и стандартное значение для нормально распределенных случайных величин.

...