前言
對於隨機數平時我們還是比較常用的,一般都會直接通過各種語言原生自帶的隨機函式,比如 c++ 中有random()
函式,java 中有 Random 類,python 有 random 模組等等。都能很方便生成隨機變數,但它們有一個特點,那就是都服從均勻分佈,而有些場景需要要生成不同分佈的隨機變數。
隨機變數
隨機變數即隨機函式,通過該函式能生成每個可能事件對應的一個值。比如我們擲骰子,每次按一定的概率生成一個值。有兩種型別變數,
- 離散型隨機變數,能取到的不相同的值是有限個或可列無限多個。
- 連續型隨機變數,能取到的值可以是連續的,在某個區間內可取任意一實數。
概率密度函式
主要用來表示不同點對應的概率大小,即X軸上每個單位長度對應的概率大小。概率等於面積,當某區間長度趨於0時則變為一個點,此時概率大小為f(x)。
常見分佈
- 伯努利分佈,即0-1分佈,隨機變數為0或為1,概率為p和1-p。
- 二項分佈,進行n次伯努利實驗,相對於不同成功次數對應的概率。
- 泊松分佈,是二項分佈的極限形式。
- 均勻分佈,在相同長度間隔的分佈概率是等可能的。
- 正態分佈,又名高斯分佈,正態曲線呈鍾型,兩頭低,中間高。
- 指數分佈,描述事件以恆定平均速率連續且獨立地發生的過程的概率分佈。
- 邏輯斯蒂分佈,增長分佈,形狀有點像正態分佈。
生成分佈演算法
- Inverse Transform Method,首先生成一個均勻分佈的隨機數,再求指定分佈的分佈函式F(x),然後求得F(x)的逆函式G(x),將隨機數帶入逆函式得到的即為指定分佈的隨機數。
- Acceptance-Rejection Method,首先生成一個均勻分佈隨機數a,設概率密度函式為f(x),然後再生成一個均勻分佈隨機數b,若b<=f(a),則成功得到指定分佈的隨機數,否則從頭開始。
實現
兩種演算法都比較容易理解,第一個需要求逆函式,有時並不好求,而第二個基本沒什麼限制,對於任何分佈都能很完成任務。下面就用第二種方法實現生成幾種分佈的隨機數。
正態分佈
def normal_pdf(x, mu=0, sigma=1):
return (1 / (math.sqrt(2 * math.pi) * sigma)) * (math.exp(-math.pow(x - mu, 2) / (2 * math.pow(sigma, 2))))
def standard_normal_rand():
while True:
a = random.uniform(-4.0, 4.0)
b = random.uniform(0.0, 3.0)
if b < normal_pdf(a):
return a, b
複製程式碼
指數分佈
def exponential_pdf(x, lam=1):
return lam * math.exp(-lam * x)
def exponential_rand():
while True:
a = random.uniform(0.0, 100.0)
b = random.uniform(0.0, 3.0)
if b <= exponential_pdf(a):
return a, b
複製程式碼
泊松分佈
def poisson_pdf(x, lam=1):
return (math.pow(lam, x) / math.factorial(x)) * math.exp(-lam)
def poisson_rand():
while True:
a = random.randint(0, 50)
b = random.uniform(0.0, 1.0)
if b <= poisson_pdf(a):
return a, b
複製程式碼
github
https://github.com/sea-boat/MachineLearning_Lab/blob/master/distribution_gen.py
-------------推薦閱讀------------
跟我交流,向我提問:
公眾號的選單已分為“分散式”、“機器學習”、“深度學習”、“NLP”、“Java深度”、“Java併發核心”、“JDK原始碼”、“Tomcat核心”等,可能有一款適合你的胃口。
歡迎關注: