丁香五月天婷婷久久婷婷色综合91|国产传媒自偷自拍|久久影院亚洲精品|国产欧美VA天堂国产美女自慰视屏|免费黄色av网站|婷婷丁香五月激情四射|日韩AV一区二区中文字幕在线观看|亚洲欧美日本性爱|日日噜噜噜夜夜噜噜噜|中文Av日韩一区二区

您正在使用IE低版瀏覽器,為了您的雷峰網(wǎng)賬號安全和更好的產(chǎn)品體驗,強烈建議使用更快更安全的瀏覽器
此為臨時鏈接,僅用于文章預(yù)覽,將在時失效
人工智能開發(fā)者 正文
發(fā)私信給崔靜闖
發(fā)送

0

用深度學(xué)習(xí)每次得到的結(jié)果都不一樣,怎么辦?

本文作者: 崔靜闖 2017-06-20 20:33
導(dǎo)語:如何用Keras從神經(jīng)網(wǎng)絡(luò)得到可重復(fù)的結(jié)果。

用深度學(xué)習(xí)每次得到的結(jié)果都不一樣,怎么辦?

雷鋒網(wǎng)按:本文作者 Jason Brownlee 為澳大利亞知名機器學(xué)習(xí)專家、教育者,對時間序列預(yù)測尤有心得。原文發(fā)布于其博客。雷鋒網(wǎng)崔靜闖、朱婷編譯。

神經(jīng)網(wǎng)絡(luò)算法利用了隨機性,比如初始化隨機權(quán)重,因此用同樣的數(shù)據(jù)訓(xùn)練同一個網(wǎng)絡(luò)會得到不同的結(jié)果。

初學(xué)者可能會有些懵圈,因為算法表現(xiàn)得不太穩(wěn)定。但實際上它們就是這么設(shè)計的。隨機初始化可以讓網(wǎng)絡(luò)通過學(xué)習(xí),得到一個所學(xué)函數(shù)的很好的近似。

然而, 有時候用同樣的數(shù)據(jù)訓(xùn)練同一個網(wǎng)絡(luò),你需要每次都得到完全相同的結(jié)果。例如在教學(xué)和產(chǎn)品上。

在這個教程中,你會學(xué)到怎樣設(shè)置隨機數(shù)生成器,才能每次用同樣的數(shù)據(jù)訓(xùn)練同一網(wǎng)絡(luò)時,都能得到同樣的結(jié)果。

我們開始。

教程概覽

這個教程分為六部分:

  1. 為啥我每次得到的結(jié)果都不一樣?

  2. 不同結(jié)果的演示

  3. 解決方法

  4. 用Theano 后端設(shè)置隨機數(shù)種子

  5. 用TensorFlow 后端設(shè)置隨機數(shù)種子

  6. 得到的結(jié)果還是不同,咋辦?

運行環(huán)境

  • 該教程需要你安裝了Python SciPy。你能用Python2或3來演示這個例子

  • 需要你安裝Keras (v2.0.3+),后臺為TensorFlow (v1.1.0+)或Theano (v0.9+)

  • 還需要你安裝了scikit-learn,Pandas,NumPy以及Matplotlib

如果在Python環(huán)境的設(shè)置方面需要幫助,請看下面這個帖子:

How to Setup a Python Environment for Machine Learning and Deep Learning with Anaconda

為啥我每次得到的結(jié)果都不一樣?

我發(fā)現(xiàn)這對神經(jīng)網(wǎng)絡(luò)和深度學(xué)習(xí)的初學(xué)者而言是個常見問題。

這種誤解可能出于以下問題:

  • 我如何得到穩(wěn)定的結(jié)果?

  • 我如何得到可重復(fù)的結(jié)果

  • 我應(yīng)該如何設(shè)置種子點

神經(jīng)網(wǎng)絡(luò)特意用隨機性來保證,能通過有效學(xué)習(xí)得到問題的近似函數(shù)。采用隨機性的原因是:用它的機器學(xué)習(xí)算法,要比不用它的效果更好。

在神經(jīng)網(wǎng)絡(luò)中,最常見的利用隨機性的方式是網(wǎng)絡(luò)權(quán)值的隨機初始化,盡管在其他地方也能利用隨機性,這有一個簡短的清單:

  • 初始化的隨機性,比如權(quán)值

  • 正則化的隨機性,比如dropout

  • 層的隨機性,比如詞嵌入

  • 最優(yōu)化的隨機性,比如隨機優(yōu)化

這些甚至更多的隨機性來源意味著,當(dāng)你對同一數(shù)據(jù)運行同一個神經(jīng)網(wǎng)絡(luò)算法時,注定得到不同的結(jié)果。

想了解更多關(guān)于隨機算法的原委,參考下面的帖子

Embrace Randomness in Machine Learning

不同結(jié)果的演示

我們可以用一個小例子來演示神經(jīng)網(wǎng)絡(luò)的隨機性.

在這一節(jié)中,我們會建立一個多層感知器模型來學(xué)習(xí)一個以0.1為間隔的從0.0到0.9的短序列。給出0.0,模型必須預(yù)測出0.1;給出0.1,模型必須預(yù)測出0.2;以此類推。

下面是準(zhǔn)備數(shù)據(jù)的代碼

 # create sequence
length = 10
sequence = [i/float(length) for i in range(length)]
# create X/y pairs
df = DataFrame(sequence)
df = concat([df.shift(1), df], axis=1)
df.dropna(inplace=True)
# convert to MLPfriendly format
values = df.values
X, y = values[:,0], values[:,1]    

我們要用的網(wǎng)絡(luò),有1個輸入,10個隱層節(jié)點和1個輸出。這個網(wǎng)絡(luò)將采用均方差作為損失函數(shù),用高效的ADAM算法來訓(xùn)練數(shù)據(jù)

這個網(wǎng)絡(luò)需要約1000輪才能有效的解決這個問題,但我們只對它訓(xùn)練100輪。這樣是為了確保我們在預(yù)測時能得到一個有誤差的模型。

網(wǎng)絡(luò)訓(xùn)練完之后,我們要對數(shù)據(jù)集進行預(yù)測并且輸出均方差

建立網(wǎng)絡(luò)的代碼如下

 # design network
model = Sequential()
model.add(Dense(10, input_dim=1))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
# fit network
model.fit(X, y, epochs=100, batch_size=len(X), verbose=0)
# forecast
yhat = model.predict(X, verbose=0)
print(mean_squared_error(y, yhat[:,0]))    

在這個例子中,我們要建立10次網(wǎng)絡(luò)并且輸出10個不同的網(wǎng)絡(luò)得分

完整的代碼如下

from pandas import DataFrame
from pandas import concat
from keras.models import Sequential
from keras.layers import Dense
from sklearn.metrics import mean_squared_error

# fit MLP to dataset and print error
def fit_model(X, y):
# design network
model = Sequential()
model.add(Dense(10, input_dim=1))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
# fit network
model.fit(X, y, epochs=100, batch_size=len(X), verbose=0)
# forecast
yhat = model.predict(X, verbose=0)
print(mean_squared_error(y, yhat[:,0]))

# create sequence
length = 10
sequence = [i/float(length) for i in range(length)]
# create X/y pairs
df = DataFrame(sequence)
df = concat([df.shift(1), df], axis=1)
df.dropna(inplace=True)
# convert to MLP friendly format
values = df.values
X, y = values[:,0], values[:,1]
# repeat experiment
repeats = 10
for _ in range(repeats):
fit_model(X, y)    

運行這個例子會在每一行輸出一個不同的精確值,具體結(jié)果也都不同。

下面是一個輸出的示例

0.0282584265697
0.0457025913022
0.145698137198
0.0873461454407
0.0309397604521
0.046649185173
0.0958450337178
0.0130660263779
0.00625176026631
0.00296055161492    

解決方案

下面是兩個主要的解決方案。

解決方案#1:重復(fù)實驗

解決這個問題傳統(tǒng)且切實可行的方法是多次運行網(wǎng)絡(luò)(30+),然后運用統(tǒng)計學(xué)方法概括模型的性能,并與其他模型作比較。

我強烈推薦這種方法,但是由于有些模型的訓(xùn)練時間太長,這種方法并不總是可行的。

解決方案#2:設(shè)置隨機數(shù)字生成器的種子

另一種解決方案是為隨機數(shù)字生成器使用固定的種子。

隨機數(shù)由偽隨機數(shù)生成器生成。一個隨機生成器就是一個數(shù)學(xué)函數(shù),該函數(shù)將生成一長串?dāng)?shù)字,這些數(shù)字對于一般目的的應(yīng)用足夠隨機。

隨機生成器需要一個種子點開啟該進程,在大多數(shù)實現(xiàn)中,通常默認(rèn)使用以毫秒為單位的當(dāng)前時間。這是為了確保,默認(rèn)情況下每次運行代碼都會生成不同的隨機數(shù)字序列。該種子點可以是指定數(shù)字,比如“1”,來保證每次代碼運行時生成相同的隨機數(shù)序列。只要運行代碼時指定的種子的值不變,它是什么并不重要。

設(shè)置隨機數(shù)生成器的具體方法取決于后端,我們將探究下在Theano和TensorFlow后端下怎樣做到這點。

用Theano后端設(shè)置隨機數(shù)種子

通常,Keras從NumPy隨機數(shù)生成器中獲得隨機源。

大部分情況下,Theano后端也是這樣。

我們可以通過從random模塊中調(diào)用seed()函數(shù)的方式,設(shè)置NumPy隨機數(shù)生成器的種子,如下面所示:

 from numpy.random import seed
seed(1)    

最好在代碼文件的頂部導(dǎo)入和調(diào)用seed函數(shù)。

這是最佳的實現(xiàn)方式(best practice),這是因為當(dāng)各種各樣的Keras或者Theano(或者其他的)庫作為初始化的一部分被導(dǎo)入時,甚至在直接使用他們之前,可能會用到一些隨機性。

我們可以在上面示例的頂端再加兩行,并運行兩次。

每次運行代碼時,可以看到相同的均方差值的列表(在不同的機器上可能會有一些微小變化,這取決于機器的精度),如下面的示例所示:

0.169326527063
2.75750621228e-05
0.0183287291562
1.93553737255e-07
0.0549871087449
0.0906326807824
0.00337575114075
0.00414857518259
8.14587362008e-08
0.0522927019639    

你的結(jié)果應(yīng)該跟我的差不多(忽略微小的精度差異)。

用TensorFlow后端設(shè)置隨機數(shù)種子

Keras從NumPy隨機生成器中獲得隨機源,所以不管使用Theano或者TensorFlow后端的哪一個,都必須設(shè)置種子點。

必須在其他模塊的導(dǎo)入或者其他代碼之前,文件的頂端部分通過調(diào)用seed()函數(shù)設(shè)置種子點。

from numpy.random import seed
seed(1)    

另外,TensorFlow有自己的隨機數(shù)生成器,該生成器也必須在NumPy隨機數(shù)生成器之后通過立馬調(diào)用 set_random_seed() 函數(shù)設(shè)置種子點。

from tensorflow import set_random_seed
set_random_seed(2)    

要明確的是,在代碼文件的頂端,在其他之前,一定要有以下4行:

from numpy.random import seed
seed(1)
from tensorflow import set_random_seed
set_random_seed(2)    

你可以使用兩個相同或者不同的種子。我認(rèn)為這不會造成多大差別,因為隨機源進入了不同的進程。

在以上示例中增加這4行,可以使代碼每次運行時都產(chǎn)生相同的結(jié)果。你應(yīng)該看到與下面列出的相同的均方差值(也許有一些微小差別,這取決于不同機器的精度):

0.224045112999
0.00154879478823
0.00387589994044
0.0292376881968
0.00945528404353
0.013305765525
0.0206255228201
0.0359538356108
0.00441943512128
0.298706569397    

你的結(jié)果應(yīng)該與我的差不多(忽略精度的微小差異)。

如果我仍然得到不同的結(jié)果,怎么辦?

為了重復(fù)迭代,報告結(jié)果和比較模型魯棒性最好的做法是多次(30+)重復(fù)實驗,并使用匯總統(tǒng)計。如果這是不可行的,你可以通過為代碼使用的隨機數(shù)發(fā)生器設(shè)置種子來獲得100%可重復(fù)的結(jié)果。

如果你已經(jīng)按照上面的說明去做,仍然用相同的數(shù)據(jù)從相同的算法中獲得了不同的結(jié)果,怎么辦?

這可能是有其他的隨機源你還沒有考慮到。

來自第三方庫的隨機性

也許你的代碼使用了另外的庫,該庫使用不同的也必須設(shè)置種子的隨機數(shù)生成器。

試著將你的代碼簡化到最低要求(例如,一個數(shù)據(jù)樣本,一輪訓(xùn)練等等),并仔細(xì)閱讀API文檔,盡力減少可能引入隨機性的第三方庫。

使用GPU產(chǎn)生的隨機性

以上所有示例都假設(shè)代碼是在一個CPU上運行的。

這種情況也是有可能的,就是當(dāng)使用GPU訓(xùn)練模型時,可能后端設(shè)置的是使用一套復(fù)雜的GPU庫,這些庫中有些可能會引入他們自己的隨機源,你可能會或者不會考慮到這個。

例如,有證據(jù)顯示如果你在堆棧中使用了 Nvidia cuDNN,這可能引入額外的隨機源( introduce additional sources of randomness),并且使結(jié)果不能準(zhǔn)確再現(xiàn)。

來自復(fù)雜模型的隨機性

由于模型的復(fù)雜性和訓(xùn)練的并行性,你可能會得到不可復(fù)現(xiàn)的結(jié)果。

這很可能是由后端庫的效率造成的,或者是不能在內(nèi)核中使用隨機數(shù)序列。我自己沒有遇到過這個,但是在一些GitHub問題和StackOverflowde問題中看到了一些案例。

如果只是縮小成因的范圍的話,你可以嘗試降低模型的復(fù)雜度,看這樣是否影響結(jié)果的再現(xiàn)。

我建議您閱讀一下你的后端是怎么使用隨機性的,并看一下是否有任何選項向你開放。在Theano中,參考:

在TensorFlow中,參考:

Constants, Sequences, and Random Values

tf.set_random_seed

另外,為了更深入地了解,考慮一下尋找擁有同樣問題的其他人。一些很好的搜尋平臺包括GitHub、StackOverflow 和 CrossValidated。

總 結(jié)

在本教程中,你了解了如何在Keras上得到神經(jīng)網(wǎng)絡(luò)模型的可重復(fù)結(jié)果。特別是,你學(xué)習(xí)到了:

  • 神經(jīng)網(wǎng)絡(luò)是有意設(shè)計成隨機的,固定隨機源可以使結(jié)果可復(fù)現(xiàn)。

  • 你可以為NumPy和TensorFlow的隨機數(shù)生成器設(shè)置種子點,這將使大多數(shù)的Keras代碼100%的可重復(fù)使用。

  • 在有些情況下存在另外的隨機源,并且你知道如何找出他們,或許也是固定它們。

via machine learning mastery,雷鋒網(wǎng)崔靜闖、朱婷編譯

相關(guān)文章:

不到 200 行代碼,教你如何用 Keras 搭建生成對抗網(wǎng)絡(luò)(GAN)

Keras 之父講解 Keras:幾行代碼就能在分布式環(huán)境訓(xùn)練模型 | Google I/O 2017

雷峰網(wǎng)版權(quán)文章,未經(jīng)授權(quán)禁止轉(zhuǎn)載。詳情見轉(zhuǎn)載須知

用深度學(xué)習(xí)每次得到的結(jié)果都不一樣,怎么辦?

分享:
相關(guān)文章
當(dāng)月熱門文章
最新文章
請?zhí)顚懮暾埲速Y料
姓名
電話
郵箱
微信號
作品鏈接
個人簡介
為了您的賬戶安全,請驗證郵箱
您的郵箱還未驗證,完成可獲20積分喲!
請驗證您的郵箱
立即驗證
完善賬號信息
您的賬號已經(jīng)綁定,現(xiàn)在您可以設(shè)置密碼以方便用郵箱登錄
立即設(shè)置 以后再說