Je dois créer une liste de nombres aléatoires (avec décimales) compris entre -3 et 3. Le problème est que la liste doit avoir une moyenne de 0 et un écart-type de 1. Comment puis-je ajuster la moyenne et les paramètres d'écart type? Y a-t-il une fonction que je peux utiliser?
J'ai déjà pu créer une liste de nombres aléatoires entre -3 et 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 Réponses :
La fonction random.normalvariate (mu, sigma)
vous permet de spécifier la moyenne et le stdev pour des variables aléatoires normalement distribuées.
Merci! Mais comment pourrais-je contrôler la plage de -3 à 3 en utilisant cette fonction? Salutations!
Je remarque également qu'avec cette fonction ou avec random.gauss (mu, sigma), le sd et la moyenne se rapprochent des valeurs que j'indique. Néanmoins, ce ne sont pas exactement ceux que j'ai établis. Y a-t-il un moyen d'ajuster cela?
Utilisez random.gauss
, puis mettez à l'échelle:
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
Agréable! Merci mon pote!
1. Il est généralement appelé gaussien tronqué / normal tronqué. 2. Vous venez de créer deux conditions difficiles sur les RV générés - la somme est égale à 0 et la somme des carrés égale à une autre valeur fixe. Ce n'est généralement pas ce que les gens veulent dire quand ils disent que la moyenne est zéro. 3. Après le décalage et la remise à l'échelle avant le retour, vous obtiendrez parfois des numéros hors limites.
@SeverinPappadeux que proposez-vous alors?
Si vous souhaitez rester avec en.wikipedia.org/wiki/Truncated_normal_distribution , alors jetez un œil aux formules là-bas. Fondamentalement, vous avez des valeurs de distribution (\ mu, \ sigma) que vous ne connaissez pas, et que vous voulez atteindre. Vous attribuez une expression moyenne de TN à la moyenne souhaitée, une expression de variance à stddev souhaitée ^ 2, deux équations pour deux inconnues, il y aurait une solution. Heureusement, \ mu va être 0 parce que min / max est symétrique et que la moyenne souhaitée est 0. Pour \ sigma, il va y avoir une équation non linéaire, qui pourrait être résolue puis (mu, sigma) échantillonnée à partir de
en utilisant ceci - stackoverflow.com/questions/18441779/... . Je m'attendrais à ce que \ sigma soit un peu plus grand que 1, mais pas de beaucoup. Fondamentalement, vous coupez des queues de gaussien, ce qui signifie que les échantillons sigma élevés ont disparu maintenant - vous devez compenser en élargissant légèrement la distribution.
s'il vous plaît également jeter un oeil à la question que j'ai posée à @Help, il devrait clarifier ce qu'il / elle veut dire / stddev
@gmds Veuillez jeter un œil à la réponse que j'ai fournie - elle suit de très près les commentaires
Ok, voici une solution rapide (si vous voulez utiliser le gaussien tronqué). Définissez les limites et le stddev souhaité. Je suppose que la moyenne est égale à 0. Ensuite, un code rapide et grossier pour effectuer une recherche binaire pour la distribution sigma
, en résolvant la racine non linéaire ( brentq ()
doit être utilisé en production code). Toutes les formules sont tirées de la page Wiki sur Truncated Normal . Il (sigma) doit être plus grand que le stddev souhaité du fait que la troncature supprime les valeurs aléatoires qui contribuent à un grand stddev. Ensuite, nous faisons un test d'échantillonnage rapide - et mean et stddev sont proches des valeurs souhaitées mais jamais exactement égales à elles. Code (Python-3.7, Anaconda, Win10 x64)
1.0153870105743408 -0.00015923177289006116 0.9999974266369461
Pour moi, il a imprimé
sigma = 1.0153870105743408 mean = -0.000400729471992301 stddev = 1.0024267696681475
avec une longueur de graine ou de séquence différente que vous pourriez obtenir sortie comme
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))
Que voulez-vous dire exactement
une moyenne de 0
? La valeur moyenne de la distribution est différente de la valeur moyenne de l'échantillon - si je commence l'échantillonnage à partir de la gaussienne simple, N (0,1), sans limite, alors même si la moyenne de la distribution est 0, la moyenne d'échantillonnage serait différente et se fermerait à 0 lorsque le nombre de samples va à l'infini. Voulez-vous que la moyenne de distribution soit nulle? Ou vous voulez que la moyenne de l'échantillon (en fait, la somme) de toute séquence échantillonnée soit exactement zéro tout le temps? Ces deux conditions sont assez différentes