【问题标题】:How do I generate Log Uniform Distribution in Python?如何在 Python 中生成日志均匀分布?
【发布时间】:2017-10-14 03:12:45
【问题描述】:

在给定最小值和最大值的情况下,我无法在 Python 中找到一个内置函数来生成对数均匀分布(R 等效项为 here),例如:loguni[n, exp(min), exp( max), base] 返回在 exp(min) 和 exp(max) 范围内均匀分布的 n 对数。

我找到的最接近的是numpy.random.uniform

【问题讨论】:

  • 您的链接无效。除此之外:查看scipy.stats(numpy 仅提供所需的常用 dist)。如果 scipy 没有提供它,请自己实现它,可能基于您的 R 等效项,或者做一些类似接受-拒绝之类的事情,这在大多数情况下都很容易(但不一定是最快的)。
  • 感谢您指出这一点!更改了链接,这应该可以工作。
  • 你可以对均匀分布求幂。
  • @aryamccarthy 使用 numpy.random.uniform [docs.scipy.org/doc/numpy/reference/generated/…?正确的!谢谢!
  • 您确实需要查看链接的 Markdown 语法。括号被解释为链接的一部分。

标签: python numpy uniform-distribution


【解决方案1】:

来自http://ecolego.facilia.se/ecolego/show/Log-Uniform%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's answer 也是正确的。

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

【讨论】:

  • 这很危险。它会给出一个RuntimeWarning,当绘制 0.0 时,您将除以零。
  • 谢谢!因此,如果我希望分布的最小值和最大值介于 1 到 1000 之间,它们是我的低点和高点还是它们的指数?
  • @aryamccarthy 真的!但是,我的分布值> 0.0,因此我可以将其作为异常处理。
  • 我建议@Scott 使用不同的默认值。我执行了他的代码,反复得到OverflowError: Range exceeds bounds.
  • @Anatoly-Alekseev 这真的应该是一个单独的问题。但是,如果您需要提示,您链接的页面底部有一个很好的代码示例。您只需将 pdf 替换为对数均匀分布的 pdf: $$f_{X}(x) = \frac{I_{[e^a, e^b]}(x)}{x(b - a) }$$。推导在这里:stats.stackexchange.com/questions/110070/…
【解决方案2】:

我相信scipy.stats.reciprocal 是您想要的发行版。
来自文档:

倒数的概率密度函数为:

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

对于 a 0

reciprocal 将ab 作为形状参数。

【讨论】:

  • 很快,这看起来不像是对数均匀分布,它更像是一个逆对数。如果我错了,请纠正我。
  • @GuillaumeChevalier 同意,这不是日志统一分布
  • 这个概率密度与this link(@ScottGigante 的回答中提到)中的概率密度有何不同?
  • 这是正确的答案:倒数分布的对数是均匀分布!
  • 这是正确答案。实验验证:import numpy as np; import matplotlib.pyplot as plt; import scipy.stats; plt.hist(loguniform(0, np.log(20), 20000), bins=50); plt.hist(scipy.stats.reciprocal(1, 20).rvs(20000), bins=50)
【解决方案3】:
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

【讨论】:

    【解决方案4】:

    这是一个:

    只需使用提供的.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 分布。

    来源:

    许可证:

    • Apache 许可证 2.0,版权所有 2019 Neuraxio Inc.

    【讨论】:

      【解决方案5】:
      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

      【讨论】:

        【解决方案6】:

        更好的方法不是直接从对数均匀生成样本,而是应该创建对数均匀密度。

        用统计学来说,这是一个倒数分布,它已经存在于 SciPy 中:scipy.stats.reciprocal。例如,要构建一个 10^{x~U[-1,1]} 的示例,您可以:

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

        另外,我编写并使用以下代码对任何scipy.stats-like (frozen) random-variable 进行对数转换

        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)
        

        【讨论】:

          【解决方案7】:

          SciPy v1.4 包含一个 loguniform 随机变量:https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.loguniform.html

          使用方法如下:

          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 的文档中。

          【讨论】:

            猜你喜欢
            • 2018-09-07
            • 2021-02-10
            • 1970-01-01
            • 2018-03-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-09-14
            • 1970-01-01
            相关资源
            最近更新 更多