acc定义代码 神经网络_神经网络的这几个坑,你都躲过了吗
因為AI這兩年的火爆,大家拿著錘子到處找釘子,錘子當然也砸到了我頭上,有很多做業務的同事嘗試通過AI的方法解決需要一些很復雜的業務邏輯算法,同時需要很多參數組合才能搞定的問題。但因為都是非科班出身也沒有系統學習,所以遇到不少問題,所以在這里一一列出來,并且持續更新,希望能夠總結出一些經驗,在后續的應用中能夠跳過這些坑,把更多精力集中在數據和業務問題上。
關于神經網絡為什么不工作,有一篇非常實用的指南,在訓練過程中遇到問題可以首先參考這個指南。傳送門。
問題1、沒有激活函數,你是認真的嗎
真的會發生這樣的問題,尤其是直接用tensorflow寫模型的時候。同事前幾天寫了段代碼,搭了一個單隱層的模型來近似一個產品中的算法,但是怎么訓練都不收斂,按說那個算法是復雜,但也沒有必要整一個十好幾層的模型來模擬,嘗試了種種手段也還是沒用,最后仔細一看模型代碼,所有層都沒有激活函數,相當于費很大勁寫了個線性回歸還要擬合出產品算法(/攤手)。所以對于大多數的應用,不涉及復雜的網絡結構或初始化、loss函數的,就用keras吧,畢竟人生苦短。
當然,無激活函數,也就是單位激活函數,在一些場景下也會使用,通常這種使用能夠帶來減少訓練參數的好處。所以除非是有意的設計來簡化網絡,否則激活函數可不能忘掉。
問題2、還是激活函數,選對了沒有
很多指南上也都說過,一般情況下,分類器隱層的激活函數用relu,輸出層用sigmoid或softmax就八九不離十了,但是這里也有坑。許多的例子中使用的數據集是離我們面臨的問題比較遠的,最近被問到一個回歸任務的問題,由于是原型嘗試沒有做數據規范化,訓練的時候發現模型不收斂,或是不管多大的batch都在一個epoch中間波動非常大,打印出來才發現輸出值區間和目標值區間都差老遠,很明顯是激活函數限制了輸出范圍。所以選激活函數,尤其是回歸任務或者autoencoder,在寫最后一層的時候停一下,回憶回憶每個激活函數的范圍,如果都不合適,那就做一下數據預處理。
激活函數還有一個問題就是sigmoid函數用在隱層的時候,要注意梯度消失的問題,sigmoid在x=±5的附近就基本沒有梯度了,如果輸入值很大或權重初始化函數比較另類,那妥妥的訓練效率會比較差。
問題3、損失函數和輸出層激活函數,請尊重原配
對于sigmoid輸出單元,如果使用非交叉熵損失函數,損失函數就會在sigmoid飽和時飽和,從而導致梯度消失。而最大似然給出的交叉熵損失函數中的log能夠抵消sigmoid中的exp,因此sigmoid要搭配交叉熵給出的損失函數。
對數似然之外的許多目標函數對softmax函數不起作用,具體來說,那些不使用對數來抵消softmax中的指數的目標函數,當指數的變量取非常小的負值時會造成梯度消失,從而無法學習。對于softmax函數,當輸入值之間的差異變得極端時,輸出值會飽和。當softmax飽和時,基于softmax的許多代價函數也會飽和,除非它們能夠轉化飽和的激活函數,也就是說交叉熵類的損失函數能和輸出層的softmax搭配。
線性單元不會飽和,所以和relu系列的激活函數,不挑損失函數。另外對于relu,在初始化參數時,可以將b的所有元素設置成一個小小的正值,這使得relu在初始時就對訓練集中的大多數輸入呈現激活狀態,并且允許導數通過。
問題4、學習率,初始化模型時不要改默認參數
學習率基本上是新手最想調整的一個高參,容易理解,改起來也最方便。但是在初始化網絡的時候,還是不要動人家的默認值,除非你對這個問題的損失函數空間和形態非常了解(那就不用黑盒算法了),在其他方面不出問題的情況下,學習率默認值基本上能讓網絡有一個基本靠譜的收斂,在對問題的收斂水平、精度有一定認識之后再去修改默認值也不遲。默認值一般在1e-3到1e-4的范圍內,對于MNIST數據集,不同的學習率對應的loss變化趨勢如下,從圖中也可以看到,使用默認的學習率能得到一個基本夠看的結果:
不同學習率下的loss
問題5、網絡規模應該如何選擇,參考如何將大象裝冰箱
網絡規模的選擇是個頭疼的問題,沒有確定的指導思想或策略,花書中也有具體的篇幅講這個:
“萬能近似定理表明,一個前饋神經網絡如果具有線性輸出層和至少一層具有任何一種“擠壓”性質的激活函數的隱藏層,只要給予網絡足夠數量的隱藏單元,它可以以任意的精度來近似任何從一個有限空間到另一個有限空間的Borel可測函數。前饋網絡的導數也可以任意好地來近似函數的導數”
“具有單層的前饋網絡足以表示任何函數,但是網絡層可能大得不可實現,并且可能無法正確地學習和泛化”
什么意思呢?理論上單層網絡干啥都夠,但是隨著要擬合的目標函數越來越復雜,需要的神經元和參數是指數級增加的。所以我們要視問題的復雜度來確定網絡的層數,問題復雜度是個什么呢,其實就是“要把大象裝冰箱,總共分幾步”。我們可以結合對于問題的理解,感受下要擬合的這個目標函數都干了些什么事,分了幾步,比如大象裝冰箱這個問題它就分了三步,三層左右應該就差不多。更深層的網絡通常能夠對每一層使用更少的單元數和更少的參數,并且經常容易泛化到測試集,但是通常也更難以優化。
問題6、南轅北轍,訓練測試集劃分要小心
還是同事在擬合產品算法時遇到的問題,拿到的數據是一個持續數小時的記錄,系統每隔xxx ms會報一條消息,所以有幾萬條的樣本。他在訓練的時候沒有做數據的shuffle,僅僅按照時間維度劃分了訓練集和測試集,結果發現很早就出現了“過擬合”——測試集誤差很快就上去了,而且還沒收斂到理想的水平就上去了。在這里的問題就在于劃分訓練集測試集的方式,其實從問題背景出發,這個數小時的記錄在時間變化的過程中所反映的環境也肯定是在變化的,所以訓練集和測試集所代表的環境不一定會一樣。一定要有一個mindset,要保證train-dev-test三個集合都是同分布的,脫離了這個前提,訓練就是做樣子。所以要shuffle數據,要保證三個集合同分布,或者最好是劃分完之后train和dev用k-fold的方法來訓練。
不對數據進行shuffle還有一個問題就是,我們拿到的數據很多是順序數據,在劃分batch之后大多數batch對應的目標值很可能都是單一的,這樣在訓練過程中會出現很大的波動,甚至會導致完全無法收斂
問題7、數據特征的維度夠不夠
網絡是通過輸入的特征來學習的,所以要解決一個問題,業務經驗在這里十分重要,即使是E2E不考慮特征抽取的神經網絡,也需要確保所需要的信息全都輸入進來了。在考慮數據特征的時候,可以分為兩個階段:第一個階段需要業務專家的深度參與,從傳統業務的角度看,做這個事情需要哪些輸入,能從什么渠道獲取這些輸入等,這些必須要進行一個完備的分析;第二個階段就是對這些輸入進行必要的處理,以便后續設計網絡結構,當然輸入形式、網絡結構、網絡性能這是一個反饋的閉環,需要不斷進行更新以達到最好的目標性能。
問題8、性能標準是什么,keras自帶的acc合適不
使用keras訓練時,一般我們會在compile里定義相關的metrics,有時候犯個懶就直接用系統給的acc了。但是在用了幾回吃了幾回土之后發現,keras自帶的acc,實際上對分類任務更友好一些,對于多維輸出的回歸問題(我所在的行業涉及的大部分都是這類問題),acc就很容易把人整蒙圈了。有時候訓練半天,看著acc一直在0.2左右晃蕩,就開始懷疑人生了,但是看著mse loss的值感覺也不應該這么離譜,結果自己結合業務定義一個性能函數,發現已經達到九十好幾的精度了。所以對于回歸問題,尤其是多維的、稀疏的場景,一開始就要想好性能指標怎么定義,不要犯懶,自己手寫一個,這樣往后優化模型,目標感也會更強。
問題9、最好把Model的生成封裝在一個函數中
還有一個實用的經驗是對于模型初始化后調參和ensemble模型優化的場景,把模型的定義、構建等放在一個函數中,每次使用不同參數、不同數據集時調用函數生成模型再進行訓練,這樣可以避免使用上次訓練后遺留的網絡權重和偏置等信息,避免因為歷史遺留參數而導致收斂問題或無用的性能提升。具體的原因和案例可以參考《為什么Recompile之后你的網絡不收斂了》
總結
以上是生活随笔為你收集整理的acc定义代码 神经网络_神经网络的这几个坑,你都躲过了吗的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 以下对c语言函数的描述中正确的是,以下对
- 下一篇: google 浏览器默认打开控制台_ch