Bounnded Gaussian Generator

53 views
Skip to first unread message

Sylvain Ductor

unread,
Jun 15, 2018, 2:41:05 PM6/15/18
to Scala Breeze
Hi,

I' not expert in statistic but I have a problem to solve.
I need to produce a distribution of number within the [0,1] range, like RandBasis.uniform is doing.
However, I want to specify a mean and a standard deviation to this distribution.
Is there a trick to do it?

Regards,
S.D.
Message has been deleted
Message has been deleted

Sylvain Ductor

unread,
Jun 15, 2018, 5:20:14 PM6/15/18
to Scala Breeze
Here as far as I went, does not seems correct though…


 
case class ApproxGaussian(
  val μ /*mean*/: Double, val σ /*standard deviation*/: Double
) ) {

    private val distrib =  breeze.stats.distributions.
    Gaussian(μ, σ)
 
   /*
   We want to normalize so that the results is within 0,1
   In this class we exploit the fact that 97%
    of the values are within  [μ-3σ,μ+3σ]
    we so map this interval map to 0 and compress the remaining values to [0,1]
   */

    /* Resolving :
   a * (μ - 3σ) + b = 0
    a * (μ + 3σ) + b = 1
   */
  val a = 1 / (6 * σ)
  val b = 0.5 - / (6 * σ))

    def draw  = {
    val comp = a * distrib.draw - b
    if (comp < 0 || 1 < comp) {
      println(s"Ha! $comp")
      Math.max(1,Math.min(0,comp))
    } else {
      comp
    }
  } ensuring {v => v >= 0 && v <= 1}
 
 }

  case class FiniteGaussian(
  val μ /*mean*/: Double, val σ /*standard deviation*/: Double
)(
  nbElems : Int
) {
  /*
   We want to normalize so that the results is within 0,1
   In this class we generate the set of elements and take its max and min in order to normalize
   */
  private val distrib =
    Gaussian(μ, σ).sample(nbElems)

    val max = distrib.max
  val min = distrib.min

    /* Resolving
   a * max + b = 1
   a * min + b = 0
   */
  val a = 1 / (max - min)
  val b = -min / (max - min)

    /* */

    val distribIt = distrib.iterator

    def draw  = (a * distribIt.next - b) ensuring {v => v >= 0 && v <= 1}
 
 }

Sylvain Ductor

unread,
Jun 15, 2018, 5:29:08 PM6/15/18
to Scala Breeze
my bad … i put «- b» and not «+ b»
Did someone used to statistic can please confirm the soundness of those solutions?
<span style="color: rgb(0, 0,

Jeremy

unread,
Jun 15, 2018, 6:19:49 PM6/15/18
to Scala Breeze
Hey Sylvain,

The Beta Distribution (wikipedia page) from the breeze library does just that. It's always between [0,1] and it takes two parameters a and b that define the shape of the graph. You can mess around with this widget to get a feel for what the parameters do. 
If you would like to supply a mean and standard deviation instead of the parameters, you'll have to do some math. The mean (or Expected value E(X)) is a / (a +b) and the variance V(X) is a*b/( (a+b+1)(a+b)^2 ). With some tricky algebra, you can solve for a and b in terms of the mean and standard deviation. 

You should get:
a = mean * (mean*(1-mean) / sd^2 -1) and b = (1-mean) * (mean*(1-mean)/sd^2 - 1)

Plug in your desired mean and standard deviation and you'll get the right parameters. I have tested a few values and it seems to work great. 

One thing to note about the beta distribution is that since it's bounded between 0 and 1, the maximum variance (assuming everything is thrown in the tails) is 1/4, so don't try to give it a standard deviation larger than 1/2. Also, as the parameters a and b get large, it looks/behaves very similar to a Gaussian curve. Although the beta distribution is not an exact "gaussian generator", it's pretty darn close, and you won't have to worry about truncating values outside of [0,1]. Let me know if you have any other questions.

Jeremy 

David Hall

unread,
Jun 15, 2018, 6:24:59 PM6/15/18
to scala-...@googlegroups.com
Do you actually need a distribution? if you just need to sample (i.e. you need a Rand), you can do Gaussian(µ, σ).filter(x => x < 1 && x > 0), which uses rejection sampling.  Otherwise, you could implement https://en.wikipedia.org/wiki/Truncated_normal_distribution. We have the building blocks in terms of the special functions (erf is available in numerics)

-- David

--
You received this message because you are subscribed to the Google Groups "Scala Breeze" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-breeze...@googlegroups.com.
To post to this group, send email to scala-...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/scala-breeze/c16304bc-9db7-4397-aac4-b85838115c51%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Sylvain Ductor

unread,
Jun 15, 2018, 6:32:33 PM6/15/18
to Scala Breeze
Thank you David and Jeremy!!
Both your answer are really usefull for me.
I will process those information!
Thank you!


Em sexta-feira, 15 de junho de 2018 15:41:05 UTC-3, Sylvain Ductor escreveu:
Reply all
Reply to author
Forward
0 new messages