web-dev-qa-db-fra.com

Comment générer une distribution uniforme de journaux en Python?

Je n'ai pas pu trouver de fonction intégrée dans Python pour générer une distribution uniforme de log donnée une valeur min et max (l'équivalent R est ici ), quelque chose comme: loguni [n, exp (min), exp (max), base] qui renvoie n log uniformément réparti dans la plage exp (min) et exp (max).

Le plus proche que j'ai trouvé était numpy.random.uniform .

14
jkrish

De http://ecolego.facilia.se/ecolego/show/Log-Uniform%20Distribution :

Dans une distribution loguniforme, la variable aléatoire logtransformée est supposée être uniformément distribuée.

Donc

logU(a, b) ~ exp(U(log(a), log(b))

Ainsi, nous pourrions créer une distribution log-uniforme en utilisant numpy:

def loguniform(low=0, high=1, size=None):
    return np.exp(np.random.uniform(low, high, size))

Si vous souhaitez choisir une base différente, nous pourrions définir une nouvelle fonction comme suit:

def lognuniform(low=0, high=1, size=None, base=np.e):
    return np.power(base, np.random.uniform(low, high, size))
15
Scott Gigante

Je crois que le scipy.stats.reciprocal est la distribution que vous souhaitez.
D'après la documentation:

La fonction de densité de probabilité pour réciproque est:

f(x, a, b) = \frac{1}{x \log(b/a)}

pour a <= x <= b et a, b> 0

réciproque prend a et b comme paramètres de forme.

2
joaoFaria

Une meilleure approche serait au lieu de générer directement un échantillon à partir d'un log-uniforme, vous devriez créer la densité log-uniforme.

En termes statistiques, c'est une distribution réciproque qui est déjà dans SciPy: scipy.stats.reciprocal. Par exemple, pour créer un exemple qui est 10^{x~U[-1,1]}, vous feriez:

rv = scipy.stats.reciprocal(a=0.1,b=10)
x = rv.rvs(N)

Alternativement, j'ai écrit et utilisé le code suivant pour prendre la transformation de journal de tout scipy.stats- variable aléatoire (figée)

class LogTransformRV(scipy.stats.rv_continuous):
    def __init__(self,rv,base=10):
        self.rv = rv
        self.base = np.e if base in {'e','E'} else base
        super(LogTransformRV, self).__init__()
        self.a,self.b = self.base ** self.rv.ppf([0,1])

    def _pdf(self,x):
        return self.rv.pdf(self._log(x))/(x*np.log(self.base)) # Chain rule

    def _cdf(self,x):
        return self.rv.cdf(self._log(x)) 

    def _ppf(self,y):
        return self.base ** self.rv.ppf(y)

    def _log(self,x):
        return np.log(x)/np.log(self.base)
0
Justin Winokur

En voici un:

Utilisez simplement la méthode .rvs() fournie:

class LogUniform(HyperparameterDistribution):
    """Get a LogUniform distribution.
    For example, this is good for neural networks' learning rates: that vary exponentially."""

    def __init__(self, min_included: float, max_included: float):
        """
        Create a quantized random log uniform distribution.
        A random float between the two values inclusively will be returned.
        :param min_included: minimum integer, should be somehow included.
        :param max_included: maximum integer, should be somehow included.
        """
        self.log2_min_included = math.log2(min_included)
        self.log2_max_included = math.log2(max_included)
        super(LogUniform, self).__init__()

    def rvs(self) -> float:
        """
        Will return a float value in the specified range as specified at creation.
        :return: a float.
        """
        return 2 ** random.uniform(self.log2_min_included, self.log2_max_included)

    def narrow_space_from_best_guess(self, best_guess, kept_space_ratio: float = 0.5) -> HyperparameterDistribution:
        """
        Will narrow, in log space, the distribution towards the new best_guess.
        :param best_guess: the value towards which we want to narrow down the space. Should be between 0.0 and 1.0.
        :param kept_space_ratio: what proportion of the space is kept. Default is to keep half the space (0.5).
        :return: a new HyperparameterDistribution that has been narrowed down.
        """
        log2_best_guess = math.log2(best_guess)
        lost_space_ratio = 1.0 - kept_space_ratio
        new_min_included = self.log2_min_included * kept_space_ratio + log2_best_guess * lost_space_ratio
        new_max_included = self.log2_max_included * kept_space_ratio + log2_best_guess * lost_space_ratio
        if new_max_included <= new_min_included or kept_space_ratio == 0.0:
            return FixedHyperparameter(best_guess).was_narrowed_from(kept_space_ratio, self)
        return LogUniform(2 ** new_min_included, 2 ** new_max_included).was_narrowed_from(kept_space_ratio, self)

Le projet d'origine comprend également une distribution LogNormal si cela vous intéresse également.

La source:

Licence:

  • Apache License 2.0, Copyright 2019 Neuraxio Inc.
0
Guillaume Chevalier
from neuraxle.hyperparams.distributions import LogUniform

# Create a Log Uniform Distribution that ranges from 0.001 to 0.1: 
learning_rate_distribution = LogUniform(0.001, 0.1)

# Get a Random Value Sample (RVS) from the distribution: 
learning_rate_sample = learning_rate_distribution.rvs()

print(learning_rate_sample)

Exemple de sortie:

0,004532

Cela utilise Neuraxle .

0