使用Clojure生成钟形曲线数据
如何使用Clojure生成值的正态分布?实际上不一定是真正的正态分布,而是一个可以被扭曲的分布使用Clojure生成钟形曲线数据,clojure,Clojure,如何使用Clojure生成值的正态分布?实际上不一定是真正的正态分布,而是一个可以被扭曲的分布 作为一个例子,我想创建一个函数,输出一个生成的(伪随机)数,表示空气中氧气的体积浓度。最低可能输出应为19.5%,最大可能输出应为23.5%,而模态值应为20.95%。该函数应适用于这种“偏正态”分布,其中尾部下部的范围为1.45%,较高部分的范围为2.55% 如果你能画出描述概率密度函数的函数y=f(x),有一种简单的方法可以得到你想要的任何分布 对于高斯函数,此函数为f(x)=exp(-(x-m)
作为一个例子,我想创建一个函数,输出一个生成的(伪随机)数,表示空气中氧气的体积浓度。最低可能输出应为19.5%,最大可能输出应为23.5%,而模态值应为20.95%。该函数应适用于这种“偏正态”分布,其中尾部下部的范围为1.45%,较高部分的范围为2.55% 如果你能画出描述概率密度函数的函数
y=f(x)
,有一种简单的方法可以得到你想要的任何分布
对于高斯函数,此函数为f(x)=exp(-(x-m)^2/(2*s^2))/sqrt(2pi s^2)(参见)
其中m是x的平均值,s是x的标准偏差
对于m=0和s=1的“正常”高斯分布,存在+/-3之外的“几乎从未”值(读者需要练习的确切数值)。在这种近似下,获得高斯距离的最简单方法是在区间[-3..3]中生成一个x浮点值,在区间[0..1]中生成一个y值。然后按上面的方法计算f(x):exp(…)等。如果你能画出描述概率密度函数的函数
y=f(x)
,那么IFF y有一个简单的方法可以得到你想要的任何分布
对于高斯函数,此函数为f(x)=exp(-(x-m)^2/(2*s^2))/sqrt(2pi s^2)(参见)
其中m是x的平均值,s是x的标准偏差
对于m=0和s=1的“正常”高斯分布,存在+/-3之外的“几乎从未”值(读者需要练习的确切数值)。在这种近似下,获得高斯距离的最简单方法是在区间[-3..3]中生成一个x浮点值,在区间[0..1]中生成一个y值。然后按照上面的公式计算f(x):exp(…)等。然后,IFF y这个实现是受Alan Thompson答案中的两个想法启发的:“拒绝采样”并使用三角形,而不是钟形曲线的形状,即缩放
(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))))))
此实现的灵感来自Alan Thompson回答中的两个想法:“拒绝采样”和使用三角形,而不是钟形曲线形状,即缩放
(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))))))
您可以使用白炽灯的
采样法线
生成(非扭曲)正态分布的数字。例如,这将生成20个正态分布值,平均值为2,标准偏差为5:
(ns foo
(:use [incanter.stats]))
(sample-normal 20 :mean 2 :sd 5)
您还可以使用Java或Java中更好的随机数生成器,如Sean Luke。例如,要使用MersenneTwisterFast
,请下载java源文件并将其放入Leiningen项目树中的src/java中。然后加上
类似于:java源代码的行将[“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.nextInt
s刷新Java的Random
(尽管您的随机数可能不像来自Mersenne Twister的随机数那样随机)
正如stats.SE所解释的,通过将上面的值乘以所需的标准偏差,然后添加所需的平均值,可以从标准正态分布中获得任意正态分布
Alan Thompson的回答解释了如何从正则正态分布生成截断分布
at stats.SE提供了与从正态分布生成偏态正态分布相关的建议
编辑(2021):SciCloj社区项目列出了一些值得探索的附加库。我没有使用过这些库中的大多数库,因此我无法给出更详细的建议,但它似乎值得一提。您可以使用Incanter的
样本正态
生成(非偏态)正态分布的数字。例如,这将生成20个正态分布值,平均值为2,标准偏差为5:
(ns foo
(:use [incanter.stats]))
(sample-normal 20 :mean 2 :sd 5)
您还可以使用Java或Java中更好的随机数生成器,如Sean Luke。例如,要使用MersenneTwisterFast
,请下载java源文件并将其放入Leiningen项目树中的src/java中。然后加上
类似于:java源代码的行将[“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.nextInt
s刷新Java的Random
(尽管您的随机数可能不像来自Mersenne Twister的随机数那样随机)
正如stats.SE所解释的,通过将上面的值乘以所需的标准偏差,然后添加所需的平均值,可以从标准正态分布中获得任意正态分布
Alan Thompson的回答解释了如何从正则正态分布生成截断分布
at stats.SE提供了与从正态分布生成偏态正态分布相关的建议
编辑(2021):SciCloj社区项目列出了一些值得探索的附加库。我没有使用过这些库中的大多数,因此我不能给出更详细的建议,但它似乎值得一提。fwiw,Clojure的
rand
基于Java的Random
,因此如果后者对于给定的用途来说不是一个足够高质量的随机数生成器,那么rand
也不会。但是在很多情况下,它已经足够好了。fwiw,Clojure的rand
是基于Java的Random
,因此,如果后者对于给定的用途来说不是一个足够高质量的随机数生成器,那么rand
也不会。不过,在很多情况下,这已经足够好了。