前面第一章,我們在不控制隨機產生器本身的情況下,探討機率相關應用,第二章,我們從機率產生器本身做了一點研究,總結了在第二章中所期望的是「混亂」的機率,談論的是可測與不可測的問題,回到這篇文章,主題是希望按照分佈去生產一個亂數,也就是在「可測」範圍內探討機率分佈的問題。
我們需要搞懂一些東西
對於一般的亂數產生器來說,都是使用均勻分佈的機率 (Uniform) ,我們可以透過第一篇研究的方法,很輕易的決定:
有五個武器 A,B,C,D,E ,這五個武器各自被抽中的機率是多少。
這是一個離散型隨機分布。
回到各種層面的應用上,我們會需要依照各種不同的情境,應用【連續型隨機分布】,
首先,我們得先搞懂要做一個特定分佈的亂數產生器,跟預期的結果是什麼關係。
釐清過程、結果、反推
對於一正一反的硬幣,一次投擲五個,其正反面的個數的機率是多少,這是一個從【結果】反推整個機率系統的過程,也就是統計,但從統計反推回原本的機率,該如何做到,如果硬幣不公平,我們可以怎麼設計。
對於我們需要控制機率,最常見的方式就是從 CDF 機率累積函數反推(機率密度函數的積分就是機率累積函數),他的演算法叫做 Inverse Transform,是基於把均勻分布的 1x1 正方形,做線性變換映射到 CDF 函數上,這會需要主動拆解 CDF 的反函數,所以要確定函數可逆,也要找到解析解、級數解去把它做映射,得到一個偽隨機數產生器(Random Number Generator: RNG),且服從你指定的分佈,詳細的數學探討,會在下一篇文章解釋。
import numpy as np from pylab import * # Create some test data dx = 0.01 X = np.arange(-2, 2, dx) Y = exp(-X ** 2) # Normalize the data to a proper PDF Y /= (dx * Y).sum() # Compute the CDF CY = np.cumsum(Y * dx) # Plot both plot(X, Y) plot(X, CY, 'r--')
常態分佈 RNG Algorithm - Box Muller Transform
在這篇文章中,會稍微詳細解釋常態分佈的常見隨機數產生器做法,用於把常態分佈取線下方到 x 水平軸所有的均勻分佈機率生成,常見有好幾種演算法:
- Inverse Transform
- Rejection Sampling
- Importance Sampling
- Sampling-Importance-Resampling
- Markov Chain Monte Carlo
在下一篇文章會詳細說明到 Inverse Transform 的推演,在處理【常態分佈】情況下,會看到有兩大演算法:
- Box Muller
- Ziggurat [14][15][16]
- Marsaglia polar method (避免 Box-Muller 做三角函數運算帶來的系統負載的演算法)
Inverse Transform Method
Box-Muller Transform
u1 = random() print(sqrt(-2*log(u1))*cos(2*pi*u1)) # pi 是預設就有的
破除迷思
上一節提到了眾多可以從分佈函數中逆推機率產生器的方式,顯然都不簡單,要求一個【簡單的廣義分佈隨機數生成作法】並不存在,每個分佈都有它的挑戰。
在以上的例子及推演,展示手作分佈的難點,就是在生成分佈的演算法這件事,要操作機率,你需要了解的事實上比操作 uniform 來得更複雜一些。
常態分佈,以及其他的分佈
常態分佈
from numpy import random import matplotlib.pyplot as plt import seaborn as sns sns.distplot(random.normal(size=1000), hist=False) plt.show()
Bernoulli / Binomial 機率分佈生成 (Matlab)
第一章,我們見過 Bernoulli 的 PMF 樣子,現在,希望從生成器中產生一個相似的機率分佈:
N = 10:10:100
r1 = binornd( N, 1./N )
從 10 ~ 100,每次增長 10 的陣列做為事件個數 N。
輸出後:
N =
10 20 30 40 50 60 70 80 90 100
r1 =
0 3 0 0 1 1 0 1 0 3
要觀察結果,可以從 sort 後看到圖形:
plot(sort( r1 ))
Bernoulli / Binomial 分佈生成 (Python)
from numpy import random import matplotlib.pyplot as plt import seaborn as sns sns.distplot(random.normal(loc=50, scale=5, size=1000), hist=False, label='normal') sns.distplot(random.binomial(n=100, p=0.5, size=1000), hist=False, label='binomial') plt.show()
Poisson 分佈生成 (Python)
from numpy import random import matplotlib.pyplot as plt import seaborn as sns sns.distplot(random.normal(loc=50, scale=7, size=1000), hist=False, label='normal') sns.distplot(random.poisson(lam=50, size=1000), hist=False, label='poisson') plt.show()
均勻分佈生成 (Python)
from numpy import random import matplotlib.pyplot as plt import seaborn as sns sns.distplot(random.uniform(size=1000), hist=False) plt.show()
Logistic 分佈生成 (Python)
from numpy import random import matplotlib.pyplot as plt import seaborn as sns sns.distplot(random.normal(scale=2, size=1000), hist=False, label='normal') sns.distplot(random.logistic(size=1000), hist=False, label='logistic') plt.show()
多項式分佈生成 (Python)
from numpy import random import matplotlib.pyplot as plt import seaborn as sns sns.distplot(random.multinomial(n=6, pvals=[1/6, 1/6, 1/6, 1/6, 1/6, 1/6]), hist=False, label='multinomial') plt.show()
指數分佈生成 (Python)
from numpy import random import matplotlib.pyplot as plt import seaborn as sns sns.distplot(random.exponential(size=1000), hist=False) plt.show()
卡方分佈生成 (Python)
from numpy import random import matplotlib.pyplot as plt import seaborn as sns sns.distplot(random.chisquare(df=1, size=1000), hist=False) plt.show()
Rayleigh 分佈生成 (Python)
Pareto 分佈生成 (Python)
Zipf 分佈生成 (Python)
幾何分佈生成 (Python)
Gamma 分佈生成 (Python)
分佈產生關係圖:
Reference:
[1] https://blog.csdn.net/GregoryHanson/article/details/77823081
[2] https://blog.csdn.net/ljyljyok/article/details/86657942
[3] https://cn.comsol.com/blogs/sampling-random-numbers-from-probability-distribution-functions/
[4] https://www.itl.nist.gov/div898/handbook/eda/section3/eda3667.htm
[5] https://ivanky.wordpress.com/2014/05/23/random-numbers-in-matlab/
[6] https://stackoverflow.com/questions/26099170/bernuli-geometric-simulation-on-matlab
[7] https://www.cnblogs.com/xingshansi/p/6539319.html
[8] https://www.math.pku.edu.cn/teachers/lidf/docs/statcomp/html/_statcompbook/rng-nonuni.html
[9] https://blog.codinglabs.org/articles/methods-for-generating-random-number-distributions.html
[10] https://www.thinbug.com/q/25471457
[11] https://blog.csdn.net/fengying2016/article/details/80593266
[12] https://blog.csdn.net/wangyangzhizhou/article/details/80088490
[13] https://blog.pluskid.org/?p=430
[14] https://en.wikipedia.org/wiki/Ziggurat_algorithm
[15] https://blog.csdn.net/Real_Myth/article/details/51013680
[17] https://zhuanlan.zhihu.com/p/32578539
[18] https://medium.com/mti-technology/how-to-generate-gaussian-samples-3951f2203ab0
[19] http://4rdp.blogspot.com/2008/06/random-variable-of-normal-distribution.html
[20] 中大: http://www.math.ncu.edu.tw/~yu/sc97/boards/lec11_sc1_97.pdf
[21] http://financelab.nctu.edu.tw/www/course/QF/NormalGen.pdf
[22] https://ichi1234567.github.io/2012/07/21/box-muller/
[23] https://glowingpython.blogspot.com/2013/01/box-muller-transformation.html
[24] https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform
[25] http://www.math.ncu.edu.tw/~yu/sc97/boards/lec11_sc1_97.pdf
[26] https://zhuanlan.zhihu.com/p/38638710
[27] Box-Muller方法的证明
[28] Random variable of normal distribution (作者:Bridan) - 刊載於程式人雜誌 -- 2014 年 9 月號
[29] https://blog.csdn.net/weixin_39910711/article/details/101773776
[30] https://stackoverflow.com/questions/57335218/how-to-generate-random-x-and-y-coordinates-using-box-muller-transformation
[31] https://www.w3schools.com/python/numpy_random.asp
[32] http://www.hmwu.idv.tw/web/R_AI_M/AI-M1-hmwu_R_Stat&Prob_v2.pdf
沒有留言:
張貼留言