matlab中的偽隨機數原理
要說matlab的隨機函數,就得先說說偽隨機數。不過我也隻能從matlab 應用的角度,從使用時的概念角度講講,梳理一下自己粗淺的理解。至於數理方麵的,就沒認真看過。真正的隨機數是得通過現實世界中隨機發生的物理事件來產生的,如放射性物質隨機數發生器是通過某種放射性物質放射出的粒子數來獲得隨機數,還有通過電路產生高頻噪聲來獲得隨機數等。不過這種硬件隨機數發生器價格都比較貴,如使用比較廣泛的ComScire的隨機數發生器價格在895美元,約合人民幣6000元以上。但是很多軟件,PC機都需要使用隨機數,這麼貴的價格對一般應用來說不能每台PC都買一個硬件隨機數發生器。在這種原因下,就出現了使用軟件方法來產生隨機數的算法。通過軟件方法產生的隨機數都成為偽隨機數,因為它們都不是真正的隨機數。所謂偽隨機數,就是找到一組數目巨大的數,這組數的出現符合一定的概率分布,並且這組數能通過相應的隨機性測試,這樣我們就能使用這組數來湊合“頂替”真正的隨機數來應用了。但是由於其本質僅僅是用一組確定的數對真隨機數所表現出來的相關性質的近似,在有些場合下就無法滿足應用要求,或者說是“隨機性質不夠了”,如現在使用最廣泛的一種偽隨機數產生算法,線性同餘算法,無法滿足蒙特卡羅模擬對隨機性的要求。matlab默認使用的隨機數生成算法 Mersenne twister是目前較好的一種偽隨機數產生算法,可以滿足很多場合的應用,如蒙特卡羅模擬等。所有滿足不同分布的偽隨機數,都可以通過對均勻分布偽隨機數的數學變換得到,均勻分布偽隨機數的產生算法,是偽隨機數產生算法的根基,前麵的線性同餘算法,Mersenne twister算法,都是均勻分布偽隨機數的產生算法。
偽隨機數的產生,一般都是這樣的情況,首先是選取種子,然後是在此種子基礎上根據具體的生成算法計算得到一個偽隨機數,然後利用此偽隨機數再根據生成算法遞歸計算出下一個偽隨機數,直到將所有不重複出現的偽隨機數全部計算出來。這個偽隨機數序列就是我們以後要用到的偽隨機數序列。上麵的計算過程可以一次性計算完畢,也可以使用一次遞歸計算一次,每次生成的偽隨機數就是這個偽隨機數序列中的一個,不過不管怎麼樣,隻要確定了種子,確定了生成算法,這個序列就是確定的了。所謂種子,就是一個對偽隨機數計算的初始值。既然是確定的了,那麼當我們使用某種算法計算給出一個偽隨機數,那麼下一次計算時出現的數也就是固定的,有人可能會問,既然是固定的,還有什麼隨機性?這就是偽隨機數的“偽”所在了。偽隨機數的“隨機”在於,雖然下次計算產生的數是一個固定的數,但是這種出現的模式,以及整個偽隨機數序列,卻能通過大部分隨機性測試實驗,這說明對隨機性測試實驗來說,偽隨機數的表現同真隨機數接近,這樣我們在一些不是很苛刻的應用場合,就能拿這組偽隨機數來用,使用時的外在表現同真隨機數是較近似的。
好了,現在才要說matlab的隨機函數,matlab的隨機函數產生的隨機數都是根據偽隨機數序列獲取的,在v7.7以上的版本中,有如下的偽隨機數產生器:Mersenne twister,Multiplicative congruential generator,Multiplicative lagged Fibonacci generator,Combined multiple recursive generator,Shift-register generator summed with linear congruential generator,Modified subtract with borrow generator。相關的指令即可選擇不同的產生器。默認的情況下,matlab在啟動時總是將各個產生器的種子設為0,這樣造成編寫的包含隨機函數的程序每次運行的結果都是固定的,為了改變這種情況,可以將係統時間設置為種子(RandStream.setDefaultStream(RandStream('mt19937ar','Seed',sum(100*clock)))),這樣每次matlab啟動時種子設置的不同會使得計算得到的隨機序列不同。在7.7版本以上,隨機序列的生成通過RandStream對象來實現,與 7.7以前的版本不同。
RandStream對象的使用可簡單總結如下:要生成一個隨機數,首先需要一個偽隨機數序列,這個序列通過設定種子和生成算法來確定,RandStream的構造函數或RandStream.create方法即用來完成此任務。然後我們需要使用 RandStream.setDefaultStream函數將確定好的序列對象設置為當前matlab使用的序列。然後通過rand等函數就可以用此序列生成隨機數了。當然也可以不用將其設置為默認序列,使用rand函數可以指定從哪個序列中生成隨機數:
stream=RandStream('mrg32k3a');
rand(stream,1,5)
使用RandStream.create函數可以創建獨立同分布的隨機序列,如
[s1,s2,s3] = RandStream.create('mrg32k3a','NumStreams',3);
r1 = rand(s1,100000,1); r2 = rand(s2,100000,1); r3 = rand(s3,100000,1);
corrcoef([r1,r2,r3])
要使得前後兩次生成的隨機數保持一樣,可以將遞歸計算的過程中的偽隨機數狀態記錄下來,然後下一次計算總是基於這個記錄下來的偽隨機數狀態來進行,這樣每次計算得到的隨機數就總是相同的:
defaultStream = RandStream.getDefaultStream;
savedState = defaultStream.State;
u1 = rand(1,5)
defaultStream.State = savedState;
u2 = rand(1,5)
各個指令具體的使用方法可以通過helpdesk命令,搜索RandStream來查看。v7.7以上版本為了與舊版本保持兼容,保留了原來如 rand('state',0)這種偽隨機序列設置方法,稱之為legacy mode,有關legacy mode的內容也可以在RandStream項中找到。
最後更新:2017-04-03 14:54:27
上一篇:
微軟,Win8 OUT啦!
下一篇:
git 刪除分支和刪除文件夾
MySQL如何對主從數據不一致的情況進行校驗並繼續同步
阿裏雲啟動天池電力AI大賽:用AI解千萬企業“用電之痛”
USRP 問題——輸 出“O”“U”"u“”a"的意義
CCAI 2017 演講實錄 | 周登勇:眾包中的統計推斷與激勵機製
雲效平台:企業級互聯網架構下的持續集成與持續交付實踐
centos 6 apt.sw.be 錯誤 無法yum安裝軟件解決方案
64位win7下PL/SQL Developer 報“ORA-12154: TNS:無法解析指定的連接標識符”問題的一個解決辦法
基於zookeeper的分布式並發鎖實踐
在PHP中使用全局變量【一】
九度題目1184:二叉樹遍曆