matlab中奇妙的rand隨機數(shù),解決你的疑惑
隨機數(shù)是大家在學習算法的過程中經(jīng)常遇到的一個名詞,在尋優(yōu)算法和機器學習算法中出現(xiàn)的頻率很高,隨機數(shù)正因為其隨機的特性每次運行結果生成的值都不一樣,因此含有大量隨機數(shù)的尋優(yōu)算法以及機器學習算法每次運行的結果都會有一定的差異性。(所以很多同學問我每次運行遺傳算法或者bp神經(jīng)網(wǎng)絡結果為什么不一樣呢,隨機數(shù)就是原因;如果算法中不存在隨機數(shù),那么每次運行的結果就應該是一樣的。)
在matlab中隨機數(shù)的生成主要依靠兩個函數(shù),一個是rand(滿足均勻分布)一個是randn(滿足正態(tài)分布),其他大部分與隨機數(shù)相關的函數(shù)都是由這兩個函數(shù)衍生出來的。
那么我們這里就以rand函數(shù)為例子,首先我們生成一個隨機數(shù),并且多次運行,如下圖
可以看到,3次運行每次生成的結果都是不一樣的;然后我們試著在一個文件中生成3個隨機數(shù),如下圖
從工作區(qū)可以看到3次生成的值是不一樣的,本質上和運行三次每次只生成一個隨機數(shù)原理一致。因為每一次的生成都是隨機的,并且三次生成彼此沒有關系,所以能生成出完全一樣的值的可能性幾乎沒有。衍生到生成n個隨機數(shù),道理是一樣的.........
如上圖,一行代碼中有兩個rand,相當于按照從左到右的順序依次生成了兩個隨機數(shù),與上圖中的c1,c2同理。
如果程序中存在循環(huán)結構(如for、while),那么情況如何呢?
從上圖中可以看到,每一次循環(huán)都生成了一個隨機數(shù),一共生成了10次,生成的順序為y1,y2....y10,等同于寫了10遍的y=rand;
那么當程序中存在子函數(shù),子函數(shù)里面又有隨機數(shù),那么是怎么個情況呢,如下圖:
以上述兩個圖中的程序為例,隨機數(shù)生成的順序應該為:y1,y2,c1,c2,c3 也就是說程序執(zhí)行完第6行之后,就執(zhí)行第7行的子函數(shù),執(zhí)行完子函數(shù)內的所有代碼之后才會執(zhí)行第8行。所以總結一下就是,隨機數(shù)的生成的順序是按照代碼的執(zhí)行順序來實施的。
當我們要生成多個隨機數(shù)的時候(如5乘以3的矩陣,矩陣里的每個數(shù)都是隨機數(shù)),可以執(zhí)行下面的命令
由于rand函數(shù)是均勻生成,因此矩陣里的每個數(shù)的生成理論上也是獨立的,沒有任何關聯(lián)。如果是randn函數(shù)生成,那么生成的數(shù)據(jù)是滿足正態(tài)分布的,也就是說矩陣里的每個數(shù)是有一定關聯(lián)的,并不完全獨立。
由于隨機數(shù)本身隨機的特性,也給編程過程帶來了一些麻煩。比如我們運行了一次腳本,生成的結果是我們滿意的,但時候如果我們下次再運行就很難再復現(xiàn)出之前的效果,那么我們該怎么辦呢?在matlab中是通過‘state’關鍵字或者rng函數(shù)來控制,如下圖:
從圖中可以看到,代碼開頭加了兩個命令,加了這個命令后我們可以多次運行代碼,可以發(fā)現(xiàn)在不改變代碼內容的前提下每次運行生成的隨機數(shù)和上一次運行的結果都是一樣的,這個時候不要認為是代碼錯了,而是我們通過認為的手段對隨機數(shù)進行了復現(xiàn)。rand('state',1)和randn('state',1)分別控制的是rand和randn生成的隨機數(shù),也就是說加了rand('state',1)命令,沒加randn('state',1),那么通過randn生成的隨機數(shù)每次運行還是不同的,反過來也是如此。如果我們想要在加了這個命令的前提下讓生成的隨機數(shù)變一變該怎么辦呢?這個時候我們可以通過改變'state'后面的序列數(shù)(狀態(tài)數(shù))來使得運行的結果發(fā)生變化,如下圖
從上圖看出,序列數(shù)改成2之后,生成的結果和為1時候的結果是不同的。有的同學會問這個1或者2表示什么含義呢,和生成的隨機數(shù)有什么關聯(lián)呢?這邊呢,小豬老師直接讓大家記住,這個1和2本身沒有含義的,只是區(qū)分狀態(tài)的不同,這個1和2與生成的隨機數(shù)也沒有聯(lián)系,只是給大家區(qū)分出狀態(tài)1生成的隨機數(shù)的值是某一組,而狀態(tài)2生成的隨機數(shù)又是另一組值。如果我們序列數(shù)改成2之后覺得效果沒有1時候的好,我們可以再改回來,那么生成的隨機數(shù)的值還是會和之前序列數(shù)為1時候生成的值一致..............
最后,還有一個很多同學同意踩坑的點,就是當設置了隨機數(shù)序列數(shù)而程序中又有循環(huán)結構時,很多同學就會認為每一次循環(huán)生成的隨機數(shù)和之前循環(huán)生成的一樣,那么事實如何呢?我們看下圖
可以發(fā)現(xiàn),10次運行每次生成的結果是不一樣的,生成的順序為c1,d1,c2,d2.....c10,d10,相當于生成了20個隨機數(shù),這個時候同學們又疑惑了rand('state',1)的意義何在呢。設置序列數(shù)的意義其實就在于控制腳本的多次運行的結果不變,而不是讓腳本中循環(huán)執(zhí)行的代碼中的隨機數(shù)不變。如果情況再復雜一點,此時程序中又有子函數(shù)呢?其實道理一致,如果設置了序列數(shù),多次運行腳本的前提下本次運行過程中子函數(shù)生成的結果也是一致的。也就是說rand('state',1)的控制范圍包含當前腳本中的代碼,還控制代碼中子函數(shù)內的代碼,這一點99%的同學都會忽略掉.........................
所以隨機數(shù)的情況還是比較復雜的,弄清楚各種情況下的生成規(guī)律才能對我們調試代碼、寫代碼提供幫助...............................