使用Clojure生成钟形曲线数据

时间:2016-11-11 23:02:02

标签: clojure

如何使用Clojure生成正常的值分布?实际上不一定是真正的正态分布,而是可以偏斜的分布。

作为一个例子,我想创建一个函数,输出生成的(伪随机)数字,用于按体积计算空气中的氧浓度。最低可能输出应为19.5%,最大可能为23.5%,而模态值应为20.95%。该函数应适用于这种“偏斜的正常”分布,其中尾部的下部的范围为1.45%,而较高的部分的范围为2.55%。

3 个答案:

答案 0 :(得分:2)

如果可以绘制描述概率密度函数的函数y=f(x),有一种简单的方法可以获得所需的任何分布。

对于高斯函数,此函数为f(x)= exp( - (xm)^ 2 /(2 * s ^ 2))/ sqrt(2 * pi * s ^ 2)(参见https://en.wikipedia.org/wiki/Gaussian_function

其中m是x的平均值,s是x的std dev。

对于m = 0且s = 1的“正常”高斯,在+/- 3之外存在“几乎从不”的值(作为练习留给读者的确切数量)。给定这种近似,获得高斯dist的最简单方法是在区间[-3..3]中生成x浮点值,并在区间[0..1]中生成y值。然后如上所述计算f(x):exp(...)等。然后,IFF y< = f(x),使用值x作为随机值。否则,丢弃x和y并重新开始。

虽然这种技术会抛弃一些(或许多)值,但它非常简单且防弹。

您可以使用类似的方法进行“偏斜高斯”近似,只需按照您的描述定义自己的f(x)即可。对于一个非常简单的近似,您甚至可以使用从(19.5,0)到(20.95,1)到(23.5,0)的直线近似,其中这为f(x)形成三角形。在这种情况下,在区间[19.5..23.5]中绘制x并计算左边和右边的直线公式。 f(x)的右半部分。像以前一样在[0..1]中绘制y。

我刚刚发现维基百科更详细地描述了这一点:https://en.wikipedia.org/wiki/Rejection_sampling

答案 1 :(得分:2)

您可以使用Incanter的sample-normal生成(非偏斜的)正态分布数字。例如,这将生成20个正态分布值,平均值为2,标准差为5:

(ns foo 
  (:use [incanter.stats]))

(sample-normal 20 :mean 2 :sd 5)

你也可以在Java中使用Java的Random或更好的随机数生成器,例如Sean Luke的MersenneTwisterFast。例如,要使用MersenneTwisterFast,请下载java源文件并将其放置,例如在您的Leiningen项目树中的src / java中。然后加 像:java-source-paths ["src/java"]到project.clj这样的行。在Clojure源文件中:

(ns foo
  (:import [ec.util MersenneTwisterFast]))

(defn make-rng
  "Make an instance of a MersenneTwisterFast RNG and flush out its initial
  minimal lack of entropy."
  [seed]
  (let [rng (MersenneTwisterFast. seed)]
    (dotimes [_ 1500] (.nextInt rng)) ; needed because of a quirk of Mersenne Twisters
    rng))

(def my-rng (make-rng 42))

;; Now call this as many times as you want to generate standard Normal data:
(.nextGaussian my-rng)

使用Java Random是类似的,没有下载并转移到src / java等,但我认为你不需要用1500 {{1}来刷新Java的Random s(虽然你的随机数可能不像Mersenne Twister那样随机)。

如stats.SE中的this answer所述,您可以通过将上面的值乘以您想要的标准偏差,然后添加所需的平均值,从标准正态分布中获得任意正态分布。

Alan Thompson的答案解释了如何从常规正态分布中产生截断分布。

stats.SE中的

This answer给出了与正态分布产生偏态正态分布相关的建议。

答案 2 :(得分:0)

这个实现的灵感来自Alan Thompson的回答中的两个想法:'拒绝采样'并使用三角形,而不是钟形曲线形状,即缩放。

RemoteController

可以像这样使用:

(defn generator [modal-val low-val high-val]
  (fn []
    (let [gen-val (fn []
                    (let [diff-range (- high-val low-val)
                          picked-in-range (rand diff-range)
                          perhaps-res (+ low-val picked-in-range)
                          ;; partial distance left or right, that will be negative if to left
                          modal-delta (- perhaps-res modal-val)
                          extremity (if (neg? modal-delta) low-val high-val)
                          ;; full distance left or right, that will be negative if to left
                          total-dist (- extremity modal-val)
                          closeness-to-modal (- 1 (/ modal-delta total-dist))
                          ]
                      (when (<= (rand) closeness-to-modal)
                        perhaps-res)))]
      (first (drop-while nil? (repeatedly gen-val))))))