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