Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement a log uniform distribution in Scipy?

I don't understand how to implement the log-uniform probability distribution in Scipy. According to the comments of this post, it is possible to do so by defining only _pdf. Also, I know from this source the actual derivation for the pdf.

However, I can't figure out where to put the a and b parameters and how to set a such that a>0. Also, please note that I want a and b to be the actual minimum and maximum values of the range. Please also note that, in the end, I really just want to be able to use the .rvs() method so any trick with the uniform distribution is acceptable.

Here is my curent (non-working) code:

from scipy.stats import rv_continuous
import numpy as np

class log_uniform_gen(rv_continuous):
    "Log-uniform distribution"
    def _pdf(self, x):
        if np.exp(self.a) <= x <= np.exp(self.b):
            temp = x / (self.b - self.a)
        else:
            temp = 0.

        return temp
log_uniform = log_uniform_gen(a=0.1, b=1.0, name='log-uniform')
like image 728
marty Avatar asked Mar 28 '18 15:03

marty


1 Answers

Here is my trick to obtain an instance of the log-uniform distribution with the .rvs() method:

import numpy as np
import scipy as sp

class log_uniform():        
    def __init__(self, a=-1, b=0, base=10):
        self.loc = a
        self.scale = b - a
        self.base = base

    def rvs(self, size=None, random_state=None):
        uniform = sp.stats.uniform(loc=self.loc, scale=self.scale)
        if size is None:
            return np.power(self.base, uniform.rvs(random_state=random_state))
        else:
            return np.power(self.base, uniform.rvs(size=size, random_state=random_state))

It can be called with log_uniform(a=2, b=10).rvs(size=10) where a is the exponent of the beginning of the range and b is the exponent of the end of range. The base can be modified by using the base argument.

like image 74
marty Avatar answered Nov 01 '22 10:11

marty