如何在 Python 中生成对数均匀分布?
How do I generate Log Uniform Distribution in Python?
我无法在 Python 中找到一个内置函数来生成给定最小值和最大值的对数均匀分布(R 等价物是 here),例如:loguni[n , exp(min), exp(max), base] 表示 returns n log 在 exp(min) 和 exp(max) 范围内均匀分布。
我找到的最接近的是 numpy.random.uniform
。
来自http://ecolego.facilia.se/ecolego/show/Log-Uniform%20Distribution:
In a loguniform distribution, the logtransformed random variable is assumed to be uniformly distributed.
因此
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))
编辑: 也是正确的。
def loguniform(low=0, high=1, size=None):
return scipy.stats.reciprocal(np.exp(low), np.exp(high)).rvs(size)
我相信 scipy.stats.reciprocal
是您想要的分布。
来自文档:
The probability density function for reciprocal is:
f(x, a, b) = \frac{1}{x \log(b/a)}
for a <= x <= b and a, b > 0
reciprocal takes a
and b
as shape parameters.
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)
returns 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)
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
的文档中有更多详细信息。
我无法在 Python 中找到一个内置函数来生成给定最小值和最大值的对数均匀分布(R 等价物是 here),例如:loguni[n , exp(min), exp(max), base] 表示 returns n log 在 exp(min) 和 exp(max) 范围内均匀分布。
我找到的最接近的是 numpy.random.uniform
。
来自http://ecolego.facilia.se/ecolego/show/Log-Uniform%20Distribution:
In a loguniform distribution, the logtransformed random variable is assumed to be uniformly distributed.
因此
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))
编辑:
def loguniform(low=0, high=1, size=None):
return scipy.stats.reciprocal(np.exp(low), np.exp(high)).rvs(size)
我相信 scipy.stats.reciprocal
是您想要的分布。
来自文档:
The probability density function for reciprocal is:
f(x, a, b) = \frac{1}{x \log(b/a)}
for a <= x <= b and a, b > 0
reciprocal takes
a
andb
as shape parameters.
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)
returns 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)
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
的文档中有更多详细信息。