记一个神经网络中出现的混沌图样
?作者 |?葉耿杰
單位 |?武漢大學(xué)
研究方向 |?凝聚態(tài)物理
自己寫的 numpy BP 神經(jīng)網(wǎng)絡(luò)(擬合 [0,2] 上的函數(shù) sin(2 pi x)/4+0.5 )第一次跑通,興奮之余胡亂修改了網(wǎng)絡(luò)結(jié)構(gòu)。看著 loss 曲線時(shí)而下降,時(shí)而振蕩,突然,有一個(gè)網(wǎng)絡(luò)(代碼附在文末)啥也沒(méi)學(xué)到,但給出了熟悉的圖案:
趕緊把 loss 曲線的數(shù)據(jù)小心翼翼的導(dǎo)出來(lái),作散點(diǎn)圖,果不其然:
原來(lái)訓(xùn)練集為間隔 0.1 采樣,反復(fù)試驗(yàn)均無(wú)分岔圖案;當(dāng)訓(xùn)練集改為間隔 0.05 采樣時(shí),出現(xiàn)了分岔圖案。
反復(fù)運(yùn)行了好幾次,都能出現(xiàn)這種圖樣,說(shuō)明與參數(shù)初始化無(wú)關(guān)。
抽去了一個(gè) 2 節(jié)點(diǎn) /sigmoid 激活函數(shù)的層,仍然出現(xiàn)了類似的分岔圖(代碼是抽去之后的)。
沒(méi)有照抄大佬的代碼,以下代碼說(shuō)不定有錯(cuò);但經(jīng)過(guò)試驗(yàn),取間隔 0.1 采樣的數(shù)據(jù)集,很小的網(wǎng)絡(luò)規(guī)模(1,3,3,1,全 sigmoid),還是能看出它在試圖擬合一個(gè)函數(shù)的。
第一次更新:
補(bǔ)充一些實(shí)驗(yàn)結(jié)果:
@Horizony大佬 和 @鎮(zhèn)戎大佬 所言甚妙:將待擬合的函數(shù)換成常函數(shù) y=0.5,仍然出現(xiàn)相同的圖樣。
分岔的發(fā)生與采樣點(diǎn)的密度有關(guān);而分岔“合并”的速率與學(xué)習(xí)率的衰減有關(guān):學(xué)習(xí)率衰減越快,分岔合并得也越快。不負(fù)責(zé)任地推測(cè),假設(shè)那兒已經(jīng)有了一張完整的分岔圖,而加密采樣點(diǎn)起“平移”作用,加快/減慢學(xué)習(xí)率衰減起伸/縮作用。
注意到上圖的散點(diǎn)圖出現(xiàn)了一些臺(tái)階的特征,這是不必要的設(shè)置——每 100 次迭代衰減一次學(xué)習(xí)率造成的。去除這個(gè)設(shè)置后,散點(diǎn)圖顯得更平滑(相應(yīng)地可以將迭代次數(shù)減少到百分之一)。
混沌很可能是 sigmoid 激活函數(shù)導(dǎo)致的,而 relu 不起作用:單層,甚至單個(gè) sigmoid 神經(jīng)元足以產(chǎn)生分岔圖樣,雖然并不像 Logistic。
解析計(jì)算似乎有希望了?
目前為止,最令我驚訝的是,我本以為最無(wú)關(guān)的參數(shù)——采樣間隔,反而是控制著分岔圖樣出現(xiàn)的最關(guān)鍵參數(shù),實(shí)在匪夷所思。
會(huì)不會(huì)有這么一種可能:每個(gè)神經(jīng)網(wǎng)絡(luò)的 loss 曲線都是某個(gè)混沌映射的反向的圖樣,只是平時(shí)因?yàn)槲恢没蛏炜s不合適而看不出來(lái)?
第二次更新:
非常感謝各位大佬推薦的論文和從動(dòng)力系統(tǒng)的角度做出的解答…… 同時(shí)深刻地意識(shí)到自己實(shí)在太菜,看懂它們可能還得幾年。(′;ω;`)
再補(bǔ)充一些現(xiàn)象層面的東西:
正如?@年輕詩(shī)人?所說(shuō)的,學(xué)習(xí)率增長(zhǎng)就能得到正向的分岔圖。
學(xué)習(xí)率和采樣間隔似乎滿足某種尺度不變性。比如下面四張圖:
分別是固定學(xué)習(xí)率每次迭代增長(zhǎng) 0.01%,而樣本間距與初始學(xué)習(xí)率的組合分別為
(0.05,0.3),
(0.005,0.03),
(0.0005,0.003),
(0.00005,0.0003)
的 loss 曲線(只使用單個(gè)神經(jīng)元)。雖然 3 -周期的位置有細(xì)微的差別,但是比起其他的參數(shù)組合,它們確實(shí)非常相似。
如果這樣的假設(shè)是正確的,那么一方面,分岔可能在學(xué)習(xí)率很低的情況下發(fā)生,只要訓(xùn)練集密度夠高;另一方面,訓(xùn)練集的元素甚至可以只有一個(gè),只要學(xué)習(xí)率高到離譜,同樣可以觸發(fā)分岔。
對(duì)于后者,實(shí)驗(yàn)表明確實(shí)如此。由于不用迭代上百次就能求得周期點(diǎn)(中的一個(gè))的位置,這可能可以用于編寫快速生成分岔圖的算法。鑒于其只有一個(gè)神經(jīng)元、過(guò)高學(xué)習(xí)率以及不再要求網(wǎng)絡(luò)學(xué)到訓(xùn)練集的特征的特點(diǎn),可能已經(jīng)偏離了神經(jīng)網(wǎng)絡(luò)的問(wèn)題,因此,請(qǐng)?jiān)斠?jiàn):https://zhuanlan.zhihu.com/p/567118016
第三次更新:
上面那個(gè)算法并不準(zhǔn)確,大家還是忘了它吧
按照@年輕詩(shī)人的意見(jiàn),訓(xùn)練集大小與學(xué)習(xí)率之間的關(guān)系是因?yàn)槲以趯?duì) MSE 求導(dǎo)的時(shí)候沒(méi)有正確地歸一化(忘記除以樣本數(shù)目 n),導(dǎo)致訓(xùn)練集擴(kuò)大等效于學(xué)習(xí)率增大相同的倍數(shù)。
同時(shí)他敏銳地發(fā)現(xiàn)起作用的是最后一層,并給出了權(quán)重 迭代的表達(dá)式(見(jiàn)評(píng)論區(qū))。這個(gè)迭代之所以能生成(類似)Logistic 映射的分岔圖,是因?yàn)樗旧?#xff0c;在 取絕對(duì)值的意義下,與 Logistic 映射的迭代式 的圖象非常接近,而學(xué)習(xí)率恰好占據(jù)了 Logistic 映射中參數(shù) 的位置。
@Peter Griffin 的回答對(duì)我大有啟發(fā)。對(duì)于一個(gè)優(yōu)化問(wèn)題,大的步長(zhǎng)確實(shí)會(huì)帶來(lái)混沌的可能。以一維梯度下降為例,在極值點(diǎn)的附近,我們可以對(duì)勢(shì)函數(shù)做簡(jiǎn)諧近似,即展開(kāi)到二階項(xiàng)。由于常數(shù)項(xiàng)、一次項(xiàng)系數(shù)可以通過(guò)平移消去,二次項(xiàng)系數(shù)可以通過(guò)重新選取長(zhǎng)度量綱而歸一,我們實(shí)際上只要考慮
代入梯度下降的公式
可得
這個(gè)數(shù)列的命運(yùn)隨 取值不同,只有單調(diào)收斂、振蕩收斂、周期為 2 的振蕩( ),和振蕩發(fā)散四種。
而在極值點(diǎn)附近稍遠(yuǎn)一點(diǎn)的地方,簡(jiǎn)諧近似失效,我們可以將勢(shì)函數(shù)展到三次項(xiàng),考慮
其極小值點(diǎn)仍為 ,迭代關(guān)系為
可以看到,適當(dāng)選取系數(shù),它完全可以變成 Logistic 映射。用 Mathematica 硬解方程 ,這是一個(gè) 8 次方程,其中兩個(gè)根是不動(dòng)點(diǎn),兩個(gè)根是周期 2 的點(diǎn),4 個(gè)根是周期 3 的點(diǎn)。決定周期 3 有實(shí)根的條件是,根式中的
其解為 大于等于有關(guān) 的某個(gè)值。這就說(shuō)明,當(dāng)學(xué)習(xí)率 足夠大時(shí),我們就得到了產(chǎn)生任意周期和產(chǎn)生混沌的充分條件——實(shí)的、連續(xù)的、在極值點(diǎn)附近有界的、具有周期 3 的映射。
(用這種方式算出的 值似乎大于模擬出來(lái)的出現(xiàn)混沌時(shí)對(duì)應(yīng)的 值)
而 值在一段時(shí)間中不變,給了 充足的時(shí)間,以演化到收斂、周期或混沌的軌道上,從而形成清晰的分岔圖。
由此可以猜測(cè),在一個(gè)優(yōu)化問(wèn)題中,目標(biāo)附近的非諧效應(yīng)(幾乎總是存在)、過(guò)大的學(xué)習(xí)率和過(guò)慢的學(xué)習(xí)率下降是產(chǎn)生分岔和混沌的誘因。
import?numpy?as?np import?copy?as?cp import?matplotlib.pyplot?as?pltdef?sig(x):return?1?/?(1?+?np.exp(-x))def?dsig(x):s?=?sig(x)return?np.exp(-x)?*?s?*?sdef?relu(x):if?x?<?0:?return?0.1?*?xreturn?xdef?drelu(x):if?x?>=?0:?return?1return?0.1Sig?=?(sig,?dsig) Relu?=?(np.vectorize(relu),?np.vectorize(drelu))class?ConnectLayer:def?__init__(self,?inp,?output,?func_tup,?lrate_tup):self.inp?=?inpself.output?=?outputself.func?=?func_tup[0]self.dfunc?=?func_tup[1]self.lrate?=?lrate_tup[0]self.lrate_decay?=?lrate_tup[1]self.decay_cnt?=?0self.w?=?np.random.random((output,?inp))self.b?=?np.random.random((output,?1))self.yjs_cache?=?Noneself.xjs_cache?=?Nonedef?forward(self,?xs):#?n?=?xs.shape[1]?self.xjs_cache?=?xsyjs?=?self.w?@?xs?+?self.bself.yjs_cache?=?yjsreturn?self.func(yjs)def?backF(self,?upstream):??#?f對(duì)y求導(dǎo)return?self.dfunc(self.yjs_cache)?*?upstreamdef?backPass(self,?upstream):??#?y對(duì)x求導(dǎo)return?self.w.T?@?upstreamdef?refw(self,?upstream):??#?y對(duì)w求導(dǎo)return?upstream?@?self.xjs_cache.T?def?refb(self,?upstream):??#?y對(duì)b求導(dǎo)#?注意:不要直接使用np.sum,否則行列不穩(wěn)定db?=?np.sum(upstream,?axis=1)return?db.reshape(self.b.shape)def?backward(self,?upstream):?M?=?self.backF(upstream)self.w?-=?self.lrate?*?self.refw(M)self.b?-=?self.lrate?*?self.refb(M)self.decay_cnt?+=?1if?self.decay_cnt?==?100:self.lrate?*=?self.lrate_decayself.decay_cnt?=?0return?self.backPass(M)def?g(x):return?np.sin(2?*?np.pi?*?x)?/?4?+?0.5def?genData():xs?=?np.arange(0,?2.001,?0.05)n?=?len(xs)ys?=?[]for?x?in?xs:ys.append(g(x))ys?=?np.array(ys)return?xs.reshape(1,?n),?ys.reshape(1,?n)def?mse(fjs,?yjs):?m,?n?=?yjs.shapedelta?=?fjs?-?yjsreturn?np.sum(delta?*?delta)?/?m?/?ndef?dmse(fjs,?yjs):return?2?*?(fjs?-?yjs)Mse?=?(mse,?dmse)class?ScalarLayer:def?__init__(self,?inp,?answer,?loss_tup):self.inp?=?inpself.answer?=?answerself.loss?=?loss_tup[0]self.dloss?=?loss_tup[1]def?forward(self,?fyjs):return?self.loss(fyjs,?self.answer)def?backward(self,?fyjs):??#?L對(duì)f求導(dǎo)return?self.dloss(fyjs,?self.answer)class?nn:def?__init__(self,?layer_msg,?funcs_msg,?loss,?xs,?ys,?lrate):self.layer_msg?=?layer_msgself.layers?=?[]self.xs?=?xsself.ys?=?ysfor?i?in?range(len(layers_msg)?-?1):self.layers.append(ConnectLayer(inp=layers_msg[i],output=layers_msg[i?+?1],func_tup=funcs_msg[i],lrate_tup=lrate))self.outlet?=?ScalarLayer(1,?ys,?loss)def?train(self,?TURNS):ls?=?[]for?t?in?range(TURNS):#?單步訓(xùn)練data?=?cp.deepcopy(self.xs)for?lay?in?self.layers:data?=?lay.forward(data)L?=?self.outlet.forward(data)data?=?self.outlet.backward(data)for?lay?in?self.layers[::-1]:data?=?lay.backward(data)ls.append(L)return?lsdef?test(self):newxs?=?np.hstack((self.xs?-?1,?self.xs?+?1))data?=?cp.deepcopy(newxs)for?lay?in?self.layers:data?=?lay.forward(data)return?newxs,?dataif?__name__?==?'__main__':xs,?ys?=?genData()layers_msg?=?[1,?4,?2,?2,?1]funcs_msg?=?[Relu,?Sig,?Sig,?Sig]model?=?nn(layers_msg,?funcs_msg,?Mse,?xs,?ys,?lrate=(0.3,?0.999))ls?=?model.train(40000)plt.plot(ls)plt.show()print('end')更多閱讀
#投 稿?通 道#
?讓你的文字被更多人看到?
如何才能讓更多的優(yōu)質(zhì)內(nèi)容以更短路徑到達(dá)讀者群體,縮短讀者尋找優(yōu)質(zhì)內(nèi)容的成本呢?答案就是:你不認(rèn)識(shí)的人。
總有一些你不認(rèn)識(shí)的人,知道你想知道的東西。PaperWeekly 或許可以成為一座橋梁,促使不同背景、不同方向的學(xué)者和學(xué)術(shù)靈感相互碰撞,迸發(fā)出更多的可能性。?
PaperWeekly 鼓勵(lì)高校實(shí)驗(yàn)室或個(gè)人,在我們的平臺(tái)上分享各類優(yōu)質(zhì)內(nèi)容,可以是最新論文解讀,也可以是學(xué)術(shù)熱點(diǎn)剖析、科研心得或競(jìng)賽經(jīng)驗(yàn)講解等。我們的目的只有一個(gè),讓知識(shí)真正流動(dòng)起來(lái)。
📝?稿件基本要求:
? 文章確系個(gè)人原創(chuàng)作品,未曾在公開(kāi)渠道發(fā)表,如為其他平臺(tái)已發(fā)表或待發(fā)表的文章,請(qǐng)明確標(biāo)注?
? 稿件建議以?markdown?格式撰寫,文中配圖以附件形式發(fā)送,要求圖片清晰,無(wú)版權(quán)問(wèn)題
? PaperWeekly 尊重原作者署名權(quán),并將為每篇被采納的原創(chuàng)首發(fā)稿件,提供業(yè)內(nèi)具有競(jìng)爭(zhēng)力稿酬,具體依據(jù)文章閱讀量和文章質(zhì)量階梯制結(jié)算
📬?投稿通道:
? 投稿郵箱:hr@paperweekly.site?
? 來(lái)稿請(qǐng)備注即時(shí)聯(lián)系方式(微信),以便我們?cè)诟寮x用的第一時(shí)間聯(lián)系作者
? 您也可以直接添加小編微信(pwbot02)快速投稿,備注:姓名-投稿
△長(zhǎng)按添加PaperWeekly小編
🔍
現(xiàn)在,在「知乎」也能找到我們了
進(jìn)入知乎首頁(yè)搜索「PaperWeekly」
點(diǎn)擊「關(guān)注」訂閱我們的專欄吧
·
·
總結(jié)
以上是生活随笔為你收集整理的记一个神经网络中出现的混沌图样的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: maya支持的音频格式和时间线显示方法
- 下一篇: IPFS技术逐渐走到关键时刻!留给散户的