簡體   English   中英

如何在 Python 中生成對數均勻分布?

[英]How do I generate Log Uniform Distribution in Python?

我在 Python 中找不到內置函數來生成給定最小值和最大值的對數均勻分布(R 等價物在這里),例如:loguni[n, exp(min), exp(max), base]返回在 exp(min) 和 exp(max) 范圍內均勻分布的 n 對數。

我發現的最接近的是numpy.random.uniform

來自http://ecolego.facilia.se/ecolego/show/Log-Uni​​form%20Distribution

在對數均勻分布中,假設對數變換的隨機變量是均勻分布的。

因此

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

因此,我們可以使用numpy創建對數均勻分布:

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

如果你想選擇不同的基數,我們可以定義一個新函數,如下所示:

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

編輯: @joaoFaria 的回答也是正確的。

def loguniform(low=0, high=1, size=None):
    return scipy.stats.reciprocal(np.exp(low), np.exp(high)).rvs(size)

SciPy v1.4 包含一個loguniform隨機變量: https : loguniform

以下是如何使用它:

from scipy.stats import loguniform

rvs = loguniform.rvs(1e-2, 1e0, size=1000)

這將創建均勻分布在 0.01 和 1 之間的隨機變量。 通過可視化對數縮放直方圖可以最好地展示這一點:

無論基數如何,這種“日志縮放”都有效; loguniform.rvs(2**-2, 2**0, size=1000)也產生對數均勻隨機變量。 更多細節在loguniform的文檔中。

我相信scipy.stats.reciprocal是您想要的分布。
從文檔:

倒數的概率密度函數為:

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

對於 a <= x <= b 和 a, b > 0

倒數將ab作為形狀參數。

from random import random
from math import log

def loguniform(lo,hi,seed=random()):
    return lo ** ((((log(hi) / log(lo)) - 1) * seed) + 1)

您可以使用特定的種子值進行檢查: lognorm(10,1000,0.5)返回100.0

這是一個:

只需使用提供的.rvs()方法:

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)

如果您也感興趣的話,原始項目還包括一個 LogNormal 發行版。

來源:

  • Neuraxle,一個超參數調整和機器學習管道框架, https: //www.neuraxio.com/en/neuraxle/stable/api/neuraxle.hyperparams.distributions.html#neuraxle.hyperparams.distributions.LogUniform

執照:

  • Apache 許可證 2.0,版權所有 2019 Neuraxio Inc.
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)

示例輸出:

0.004532

這是使用Neuraxle

更好的方法不是直接從對數均勻生成樣本,而是應該創建對數均勻密度。

在統計學中,這是一個已經在 SciPy 中的倒數分布: scipy.stats.reciprocal 例如,要構建一個10^{x~U[-1,1]}的樣本,您可以執行以下操作:

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

或者,我編寫並使用以下代碼對任何scipy.stats類(凍結)隨機變量進行對數變換

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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM