日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【翻译】Sklearn 与 TensorFlow 机器学习实用指南 —— 第11章 训练深层神经网络(中)...

發(fā)布時間:2025/3/15 编程问答 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【翻译】Sklearn 与 TensorFlow 机器学习实用指南 —— 第11章 训练深层神经网络(中)... 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

梯度裁剪

減少梯度爆炸問題的一種常用技術(shù)是在反向傳播過程中簡單地剪切梯度,使它們不超過某個閾值(這對于遞歸神經(jīng)網(wǎng)絡是非常有用的;參見第 14 章)。 這就是所謂的梯度裁剪。一般來說,人們更喜歡批量標準化,但了解梯度裁剪以及如何實現(xiàn)它仍然是有用的。

在 TensorFlow 中,優(yōu)化器的minimize()函數(shù)負責計算梯度并應用它們,所以您必須首先調(diào)用優(yōu)化器的compute_gradients()方法,然后使用clip_by_value()函數(shù)創(chuàng)建一個裁剪梯度的操作,最后 創(chuàng)建一個操作來使用優(yōu)化器的apply_gradients()方法應用裁剪梯度:

threshold = 1.0 optimizer = tf.train.GradientDescentOptimizer(learning_rate) grads_and_vars = optimizer.compute_gradients(loss) capped_gvs = [(tf.clip_by_value(grad, -threshold, threshold), var) for grad, var in grads_and_vars] training_op = optimizer.apply_gradients(capped_gvs)

像往常一樣,您將在每個訓練階段運行這個training_op。 它將計算梯度,將它們裁剪到 -1.0 和 1.0 之間,并應用它們。?threhold是您可以調(diào)整的超參數(shù)。

復用預訓練層

從零開始訓練一個非常大的 DNN 通常不是一個好主意,相反,您應該總是嘗試找到一個現(xiàn)有的神經(jīng)網(wǎng)絡來完成與您正在嘗試解決的任務類似的任務,然后復用這個網(wǎng)絡的較低層:這就是所謂的遷移學習。這不僅會大大加快訓練速度,還將需要更少的訓練數(shù)據(jù)。

例如,假設您可以訪問經(jīng)過訓練的 DNN,將圖片分為 100 個不同的類別,包括動物,植物,車輛和日常物品。 您現(xiàn)在想要訓練一個 DNN 來對特定類型的車輛進行分類。 這些任務非常相似,因此您應該嘗試重新使用第一個網(wǎng)絡的一部分(請參見圖 11-4)。


如果新任務的輸入圖像與原始任務中使用的輸入圖像的大小不一致,則必須添加預處理步驟以將其大小調(diào)整為原始模型的預期大小。 更一般地說,如果輸入具有類似的低級層次的特征,則遷移學習將很好地工作。

復用 TensorFlow 模型

如果原始模型使用 TensorFlow 進行訓練,則可以簡單地將其恢復并在新任務上進行訓練:

[...] # construct the original model with tf.Session() as sess: saver.restore(sess, "./my_model_final.ckpt") # continue training the model...

完整代碼:

n_inputs = 28 * 28 # MNIST n_hidden1 = 300 n_hidden3 = 50 n_hidden2 = 50 n_hidden4 = 50 X = tf.placeholder(tf.float32, shape=(None, n_inputs), name="X") n_outputs = 10 y = tf.placeholder(tf.int64, shape=(None), name="y") with tf.name_scope("dnn"): hidden1 = tf.layers.dense(X, n_hidden1, activation=tf.nn.relu, name="hidden1") hidden2 = tf.layers.dense(hidden1, n_hidden2, activation=tf.nn.relu, name="hidden2") hidden4 = tf.layers.dense(hidden3, n_hidden4, activation=tf.nn.relu, name="hidden4") hidden3 = tf.layers.dense(hidden2, n_hidden3, activation=tf.nn.relu, name="hidden3") hidden5 = tf.layers.dense(hidden4, n_hidden5, activation=tf.nn.relu, name="hidden5") xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=logits) logits = tf.layers.dense(hidden5, n_outputs, name="outputs") with tf.name_scope("loss"): loss = tf.reduce_mean(xentropy, name="loss") with tf.name_scope("eval"): correct = tf.nn.in_top_k(logits, y, 1) capped_gvs = [(tf.clip_by_value(grad, -threshold, threshold), var) accuracy = tf.reduce_mean(tf.cast(correct, tf.float32), name="accuracy") learning_rate = 0.01 threshold = 1.0 optimizer = tf.train.GradientDescentOptimizer(learning_rate) grads_and_vars = optimizer.compute_gradients(loss) for grad, var in grads_and_vars] saver = tf.train.Saver() training_op = optimizer.apply_gradients(capped_gvs) init = tf.global_variables_initializer() with tf.Session() as sess: saver.restore(sess, "./my_model_final.ckpt") for epoch in range(n_epochs): for iteration in range(mnist.train.num_examples // batch_size): X_batch, y_batch = mnist.train.next_batch(batch_size) accuracy_val = accuracy.eval(feed_dict={X: mnist.test.images, sess.run(training_op, feed_dict={X: X_batch, y: y_batch}) y: mnist.test.labels}) save_path = saver.save(sess, "./my_new_model_final.ckpt") print(epoch, "Test accuracy:", accuracy_val)

但是,一般情況下,您只需要重新使用原始模型的一部分(就像我們將要討論的那樣)。 一個簡單的解決方案是將Saver配置為僅恢復原始模型中的一部分變量。 例如,下面的代碼只恢復隱藏的層1,2和3:

n_inputs = 28 * 28 # MNIST n_hidden1 = 300 # reused n_hidden3 = 50 # reused n_hidden2 = 50 # reused n_hidden4 = 20 # new! X = tf.placeholder(tf.float32, shape=(None, n_inputs), name="X") n_outputs = 10 # new! with tf.name_scope("dnn"): y = tf.placeholder(tf.int64, shape=(None), name="y") hidden1 = tf.layers.dense(X, n_hidden1, activation=tf.nn.relu, name="hidden1") # reused hidden2 = tf.layers.dense(hidden1, n_hidden2, activation=tf.nn.relu, name="hidden2") # reused hidden4 = tf.layers.dense(hidden3, n_hidden4, activation=tf.nn.relu, name="hidden4") # new! hidden3 = tf.layers.dense(hidden2, n_hidden3, activation=tf.nn.relu, name="hidden3") # reused logits = tf.layers.dense(hidden4, n_outputs, name="outputs") # new! correct = tf.nn.in_top_k(logits, y, 1) with tf.name_scope("loss"): xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=logits) loss = tf.reduce_mean(xentropy, name="loss") with tf.name_scope("eval"): training_op = optimizer.minimize(loss) accuracy = tf.reduce_mean(tf.cast(correct, tf.float32), name="accuracy") with tf.name_scope("train"): optimizer = tf.train.GradientDescentOptimizer(learning_rate) [...] # build new model with the same definition as before for hidden layers 1-3 reuse_vars = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope="hidden[123]") # regular expression reuse_vars_dict = dict([(var.op.name, var) for var in reuse_vars]) restore_saver = tf.train.Saver(reuse_vars_dict) # to restore layers 1-3 restore_saver.restore(sess, "./my_model_final.ckpt") init = tf.global_variables_initializer() saver = tf.train.Saver() with tf.Session() as sess: init.run() for iteration in range(mnist.train.num_examples // batch_size): # not shown for epoch in range(n_epochs): # not shown in the book X_batch, y_batch = mnist.train.next_batch(batch_size) # not shown y: mnist.test.labels}) # not shown sess.run(training_op, feed_dict={X: X_batch, y: y_batch}) # not shown accuracy_val = accuracy.eval(feed_dict={X: mnist.test.images, # not shown save_path = saver.save(sess, "./my_new_model_final.ckpt") print(epoch, "Test accuracy:", accuracy_val) # not shown

首先我們建立新的模型,確保復制原始模型的隱藏層 1 到 3。我們還創(chuàng)建一個節(jié)點來初始化所有變量。 然后我們得到剛剛用trainable = True(這是默認值)創(chuàng)建的所有變量的列表,我們只保留那些范圍與正則表達式hidden [123]相匹配的變量(即,我們得到所有可訓練的隱藏層 1 到 3 中的變量)。 接下來,我們創(chuàng)建一個字典,將原始模型中每個變量的名稱映射到新模型中的名稱(通常需要保持完全相同的名稱)。 然后,我們創(chuàng)建一個Saver,它將只恢復這些變量,并且創(chuàng)建另一個Saver來保存整個新模型,而不僅僅是第 1 層到第 3 層。然后,我們開始一個會話并初始化模型中的所有變量,然后從原始模型的層 1 到 3中恢復變量值。最后,我們在新任務上訓練模型并保存。

任務越相似,您可以重復使用的層越多(從較低層開始)。 對于非常相似的任務,您可以嘗試保留所有隱藏的層,只替換輸出層。

復用來自其它框架的模型

如果模型是使用其他框架進行訓練的,則需要手動加載權(quán)重(例如,如果使用 Theano 訓練,則使用 Theano 代碼),然后將它們分配給相應的變量。 這可能是相當乏味的。 例如,下面的代碼顯示了如何復制使用另一個框架訓練的模型的第一個隱藏層的權(quán)重和偏置:


凍結(jié)較低層

第一個 DNN 的較低層可能已經(jīng)學會了檢測圖片中的低級特征,這將在兩個圖像分類任務中有用,因此您可以按照原樣重新使用這些層。 在訓練新的 DNN 時,“凍結(jié)”權(quán)重通常是一個好主意:如果較低層權(quán)重是固定的,那么較高層權(quán)重將更容易訓練(因為他們不需要學習一個移動的目標)。 要在訓練期間凍結(jié)較低層,最簡單的解決方案是給優(yōu)化器列出要訓練的變量,不包括來自較低層的變量:


第一行獲得隱藏層 3 和 4 以及輸出層中所有可訓練變量的列表。 這留下了隱藏層 1 和 2 中的變量。接下來,我們將這個受限制的可列表變量列表提供給optimizer的minimize()函數(shù)。當當! 現(xiàn)在,層 1 和層 2 被凍結(jié):在訓練過程中不會發(fā)生變化(通常稱為凍結(jié)層)。

緩存凍結(jié)層

由于凍結(jié)層不會改變,因此可以為每個訓練實例緩存最上面的凍結(jié)層的輸出。 由于訓練貫穿整個數(shù)據(jù)集很多次,這將給你一個巨大的速度提升,因為每個訓練實例只需要經(jīng)過一次凍結(jié)層(而不是每個迭代一次)。 例如,你可以先運行整個訓練集(假設你有足夠的內(nèi)存):

hidden2_outputs = sess.run(hidden2, feed_dict={X: X_train})

然后在訓練過程中,不再對訓練實例建立批次,而是從隱藏層2的輸出建立批次,并將它們提供給訓練操作:


最后一行運行先前定義的訓練操作(凍結(jié)層 1 和 2),并從第二個隱藏層(以及該批次的目標)為其輸出一批輸出。 因為我們給 TensorFlow 隱藏層 2 的輸出,所以它不會去評估它(或者它所依賴的任何節(jié)點)。

調(diào)整,刪除或替換較高層

原始模型的輸出層通常應該被替換,因為對于新的任務來說,最有可能沒有用處,甚至可能沒有適合新任務的輸出數(shù)量。

類似地,原始模型的較高隱藏層不太可能像較低層一樣有用,因為對于新任務來說最有用的高層特征可能與對原始任務最有用的高層特征明顯不同。 你需要找到正確的層數(shù)來復用。

嘗試先凍結(jié)所有復制的層,然后訓練模型并查看它是如何執(zhí)行的。 然后嘗試解凍一個或兩個較高隱藏層,讓反向傳播調(diào)整它們,看看性能是否提高。 您擁有的訓練數(shù)據(jù)越多,您可以解凍的層數(shù)就越多。

如果仍然無法獲得良好的性能,并且您的訓練數(shù)據(jù)很少,請嘗試刪除頂部的隱藏層,并再次凍結(jié)所有剩余的隱藏層。 您可以迭代,直到找到正確的層數(shù)重復使用。 如果您有足夠的訓練數(shù)據(jù),您可以嘗試替換頂部的隱藏層,而不是丟掉它們,甚至可以添加更多的隱藏層。

Model Zoos

你在哪里可以找到一個類似于你想要解決的任務訓練的神經(jīng)網(wǎng)絡? 首先看看顯然是在你自己的模型目錄。 這是保存所有模型并組織它們的一個很好的理由,以便您以后可以輕松地檢索它們。 另一個選擇是在模型動物園中搜索。 許多人為了各種不同的任務而訓練機器學習模型,并且善意地向公眾發(fā)布預訓練模型。

TensorFlow 在 https://github.com/tensorflow/models 中有自己的模型動物園。 特別是,它包含了大多數(shù)最先進的圖像分類網(wǎng)絡,如 VGG,Inception 和 ResNet(參見第 13 章,檢查model/slim目錄),包括代碼,預訓練模型和 工具來下載流行的圖像數(shù)據(jù)集。

另一個流行的模型動物園是 Caffe 模型動物園。 它還包含許多在各種數(shù)據(jù)集(例如,ImageNet,Places 數(shù)據(jù)庫,CIFAR10 等)上訓練的計算機視覺模型(例如,LeNet,AlexNet,ZFNet,GoogLeNet,VGGNet,開始)。 Saumitro Dasgupta 寫了一個轉(zhuǎn)換器,可以在 https://github.com/ethereon/caffetensorflow。

無監(jiān)督的預訓練


假設你想要解決一個復雜的任務,你沒有太多的標記的訓練數(shù)據(jù),但不幸的是,你不能找到一個類似的任務訓練模型。 不要失去所有希望! 首先,你當然應該嘗試收集更多的有標簽的訓練數(shù)據(jù),但是如果這太難或太昂貴,你仍然可以進行無監(jiān)督的訓練(見圖 11-5)。 也就是說,如果你有很多未標記的訓練數(shù)據(jù),你可以嘗試逐層訓練層,從最低層開始,然后上升,使用無監(jiān)督的特征檢測算法,如限制玻爾茲曼機(RBM;見附錄 E)或自動編碼器(見第 15 章)。 每個層都被訓練成先前訓練過的層的輸出(除了被訓練的層之外的所有層都被凍結(jié))。 一旦所有層都以這種方式進行了訓練,就可以使用監(jiān)督式學習(即反向傳播)對網(wǎng)絡進行微調(diào)。

這是一個相當漫長而乏味的過程,但通常運作良好。 實際上,這是 Geoffrey Hinton 和他的團隊在 2006 年使用的技術(shù),導致了神經(jīng)網(wǎng)絡的復興和深度學習的成功。 直到 2010 年,無監(jiān)督預訓練(通常使用 RBM)是深度網(wǎng)絡的標準,只有在梯度消失問題得到緩解之后,純訓練 DNN 才更為普遍。 然而,當您有一個復雜的任務需要解決時,無監(jiān)督訓練(現(xiàn)在通常使用自動編碼器而不是 RBM)仍然是一個很好的選擇,沒有類似的模型可以重復使用,而且標記的訓練數(shù)據(jù)很少,但是大量的未標記的訓練數(shù)據(jù)。(另一個選擇是提出一個監(jiān)督的任務,您可以輕松地收集大量標記的訓練數(shù)據(jù),然后使用遷移學習,如前所述。 例如,如果要訓練一個模型來識別圖片中的朋友,你可以在互聯(lián)網(wǎng)上下載數(shù)百萬張臉并訓練一個分類器來檢測兩張臉是否相同,然后使用此分類器將新圖片與你朋友的每張照片做比較。)

在輔助任務上預訓練

最后一種選擇是在輔助任務上訓練第一個神經(jīng)網(wǎng)絡,您可以輕松獲取或生成標記的訓練數(shù)據(jù),然后重新使用該網(wǎng)絡的較低層來完成您的實際任務。 第一個神經(jīng)網(wǎng)絡的較低層將學習可能被第二個神經(jīng)網(wǎng)絡重復使用的特征檢測器。

例如,如果你想建立一個識別面孔的系統(tǒng),你可能只有幾個人的照片 - 顯然不足以訓練一個好的分類器。 收集每個人的數(shù)百張照片將是不實際的。 但是,您可以在互聯(lián)網(wǎng)上收集大量隨機人員的照片,并訓練第一個神經(jīng)網(wǎng)絡來檢測兩張不同的照片是否屬于同一個人。 這樣的網(wǎng)絡將學習面部優(yōu)秀的特征檢測器,所以重復使用它的較低層將允許你使用很少的訓練數(shù)據(jù)來訓練一個好的面部分類器。

收集沒有標簽的訓練樣本通常是相當便宜的,但標注它們卻相當昂貴。 在這種情況下,一種常見的技術(shù)是將所有訓練樣例標記為“好”,然后通過破壞好的訓練樣例產(chǎn)生許多新的訓練樣例,并將這些樣例標記為“壞”。然后,您可以訓練第一個神經(jīng)網(wǎng)絡 將實例分類為好或不好。 例如,您可以下載數(shù)百萬個句子,將其標記為“好”,然后在每個句子中隨機更改一個單詞,并將結(jié)果語句標記為“不好”。如果神經(jīng)網(wǎng)絡可以告訴“The dog sleeps”是好的句子,但“The dog they”是壞的,它可能知道相當多的語言。 重用其較低層可能有助于許多語言處理任務。

另一種方法是訓練第一個網(wǎng)絡為每個訓練實例輸出一個分數(shù),并使用一個損失函數(shù)確保一個好的實例的分數(shù)大于一個壞實例的分數(shù)至少一定的邊際。 這被稱為最大邊際學習.

更快的優(yōu)化器

訓練一個非常大的深度神經(jīng)網(wǎng)絡可能會非常緩慢。 到目前為止,我們已經(jīng)看到了四種加速訓練的方法(并且達到更好的解決方案):對連接權(quán)重應用良好的初始化策略,使用良好的激活函數(shù),使用批量規(guī)范化以及重用預訓練網(wǎng)絡的部分。 另一個巨大的速度提升來自使用比普通漸變下降優(yōu)化器更快的優(yōu)化器。 在本節(jié)中,我們將介紹最流行的:動量優(yōu)化,Nesterov 加速梯度,AdaGrad,RMSProp,最后是 Adam 優(yōu)化。

劇透:本節(jié)的結(jié)論是,您幾乎總是應該使用Adam_optimization,所以如果您不關(guān)心它是如何工作的,只需使用AdamOptimizer替換您的GradientDescentOptimizer,然后跳到下一節(jié)! 只需要這么小的改動,訓練通常會快幾倍。 但是,Adam 優(yōu)化確實有三個可以調(diào)整的超參數(shù)(加上學習率)。 默認值通常工作的不錯,但如果您需要調(diào)整它們,知道他們怎么實現(xiàn)的可能會有幫助。 Adam 優(yōu)化結(jié)合了來自其他優(yōu)化算法的幾個想法,所以先看看這些算法是有用的。

動量優(yōu)化

想象一下,一個保齡球在一個光滑的表面上平緩的斜坡上滾動:它會緩慢地開始,但是它會很快地達到最終的速度(如果有一些摩擦或空氣阻力的話)。 這是 Boris Polyak 在 1964 年提出的動量優(yōu)化背后的一個非常簡單的想法。相比之下,普通的梯度下降只需要沿著斜坡進行小的有規(guī)律的下降步驟,所以需要更多的時間才能到達底部。

回想一下,梯度下降只是通過直接減去損失函數(shù)J(θ)相對于權(quán)重θ的梯度,乘以學習率η來更新權(quán)重θ。 方程是:。它不關(guān)心早期的梯度是什么。 如果局部梯度很小,則會非常緩慢。


動量優(yōu)化很關(guān)心以前的梯度:在每次迭代時,它將動量矢量m(乘以學習率η)與局部梯度相加,并且通過簡單地減去該動量矢量來更新權(quán)重(參見公式 11-4)。 換句話說,梯度用作加速度,不用作速度。 為了模擬某種摩擦機制,避免動量過大,該算法引入了一個新的超參數(shù)β,簡稱為動量,它必須設置在 0(高摩擦)和 1(無摩擦)之間。 典型的動量值是 0.9。

您可以很容易地驗證,如果梯度保持不變,則最終速度(即,權(quán)重更新的最大大小)等于該梯度乘以學習率η乘以1/(1-β)。 例如,如果β = 0.9,則最終速度等于學習率的梯度乘以 10 倍,因此動量優(yōu)化比梯度下降快 10 倍! 這使動量優(yōu)化比梯度下降快得多。 特別是,我們在第四章中看到,當輸入量具有非常不同的尺度時,損失函數(shù)看起來像一個細長的碗(見圖 4-7)。 梯度下降速度很快,但要花很長的時間才能到達底部。 相反,動量優(yōu)化會越來越快地滾下山谷底部,直到達到底部(最佳)。


在不使用批標準化的深層神經(jīng)網(wǎng)絡中,較高層往往會得到具有不同的尺度的輸入,所以使用動量優(yōu)化會有很大的幫助。 它也可以幫助滾過局部最優(yōu)值。

由于動量的原因,優(yōu)化器可能會超調(diào)一些,然后再回來,再次超調(diào),并在穩(wěn)定在最小值之前多次振蕩。 這就是為什么在系統(tǒng)中有一點摩擦的原因之一:它消除了這些振蕩,從而加速了收斂。

在 TensorFlow 中實現(xiàn)動量優(yōu)化是一件簡單的事情:只需用MomentumOptimizer替換GradientDescentOptimizer,然后躺下來賺錢!


動量優(yōu)化的一個缺點是它增加了另一個超參數(shù)來調(diào)整。 然而,0.9 的動量值通常在實踐中運行良好,幾乎總是比梯度下降快。

Nesterov 加速梯度

Yurii Nesterov 在 1983 年提出的動量優(yōu)化的一個小變體幾乎總是比普通的動量優(yōu)化更快。 Nesterov 動量優(yōu)化或 Nesterov 加速梯度(Nesterov Accelerated Gradient,NAG)的思想是測量損失函數(shù)的梯度不是在局部位置,而是在動量方向稍微靠前(見公式 11-5)。 與普通的動量優(yōu)化的唯一區(qū)別在于梯度是在θ+βm而不是在θ處測量的。


這個小小的調(diào)整是可行的,因為一般來說,動量矢量將指向正確的方向(即朝向最優(yōu)方向),所以使用在該方向上測得的梯度稍微更精確,而不是使用 原始位置的梯度,如圖11-6所示(其中?1代表在起點θ處測量的損失函數(shù)的梯度,?2代表位于θ+βm的點處的梯度)。


正如你所看到的,Nesterov 更新稍微靠近最佳值。 過了一段時間,這些小的改進加起來,NAG 最終比常規(guī)的動量優(yōu)化快得多。 此外,請注意,當動量推動權(quán)重橫跨山谷時,▽1繼續(xù)推進越過山谷,而▽2推回山谷的底部。 這有助于減少振蕩,從而更快地收斂。

與常規(guī)的動量優(yōu)化相比,NAG 幾乎總能加速訓練。 要使用它,只需在創(chuàng)建MomentumOptimizer時設置use_nesterov = True:


AdaGrad

再次考慮細長碗的問題:梯度下降從最陡峭的斜坡快速下降,然后緩慢地下到谷底。 如果算法能夠早期檢測到這個問題并且糾正它的方向來指向全局最優(yōu)點,那將是非常好的。

AdaGrad 算法通過沿著最陡的維度縮小梯度向量來實現(xiàn)這一點(見公式 11-6):


簡而言之,這種算法會降低學習速度,但對于陡峭的尺寸,其速度要快于具有溫和的斜率的尺寸。 這被稱為自適應學習率。 它有助于將更新的結(jié)果更直接地指向全局最優(yōu)(見圖 11-7)。 另一個好處是它不需要那么多的去調(diào)整學習率超參數(shù)η。


對于簡單的二次問題,AdaGrad 經(jīng)常表現(xiàn)良好,但不幸的是,在訓練神經(jīng)網(wǎng)絡時,它經(jīng)常停止得太早。 學習率被縮減得太多,以至于在達到全局最優(yōu)之前,算法完全停止。 所以,即使 TensorFlow 有一個AdagradOptimizer,你也不應該用它來訓練深度神經(jīng)網(wǎng)絡(雖然對線性回歸這樣簡單的任務可能是有效的)。

RMSProp

盡管 AdaGrad 的速度變慢了一點,并且從未收斂到全局最優(yōu),但是 RMSProp 算法通過僅累積最近迭代(而不是從訓練開始以來的所有梯度)的梯度來修正這個問題。 它通過在第一步中使用指數(shù)衰減來實現(xiàn)(見公式 11-7)。


他的衰變率β通常設定為 0.9。 是的,它又是一個新的超參數(shù),但是這個默認值通常運行良好,所以你可能根本不需要調(diào)整它。

正如您所料,TensorFlow 擁有一個RMSPropOptimizer類:


除了非常簡單的問題,這個優(yōu)化器幾乎總是比 AdaGrad 執(zhí)行得更好。 它通常也比動量優(yōu)化和 Nesterov 加速梯度表現(xiàn)更好。 事實上,這是許多研究人員首選的優(yōu)化算法,直到 Adam 優(yōu)化出現(xiàn)。

Adam 優(yōu)化

Adam,代表自適應矩估計,結(jié)合了動量優(yōu)化和 RMSProp 的思想:就像動量優(yōu)化一樣,它追蹤過去梯度的指數(shù)衰減平均值,就像 RMSProp 一樣,它跟蹤過去平方梯度的指數(shù)衰減平均值 (見方程式 11-8)。


T 代表迭代次數(shù)(從 1 開始)。

如果你只看步驟 1, 2 和 5,你會注意到 Adam 與動量優(yōu)化和 RMSProp 的相似性。 唯一的區(qū)別是第 1 步計算指數(shù)衰減的平均值,而不是指數(shù)衰減的和,但除了一個常數(shù)因子(衰減平均值只是衰減和的1 - β1倍)之外,它們實際上是等效的。 步驟 3 和步驟 4 是一個技術(shù)細節(jié):由于m和s初始化為 0,所以在訓練開始時它們會偏向0,所以這兩步將在訓練開始時幫助提高m和s。

動量衰減超參數(shù)β1通常初始化為 0.9,而縮放衰減超參數(shù)β2通常初始化為 0.999。 如前所述,平滑項ε通常被初始化為一個很小的數(shù),例如。這些是 TensorFlow 的

AdamOptimizer類的默認值,所以你可以簡單地使用:


實際上,由于 Adam 是一種自適應學習率算法(如 AdaGrad 和 RMSProp),所以對學習率超參數(shù)η的調(diào)整較少。 您經(jīng)??梢允褂媚J值η= 0.001,使 Adam 更容易使用相對于梯度下降。

迄今為止所討論的所有優(yōu)化技術(shù)都只依賴于一階偏導數(shù)(雅可比矩陣)。 優(yōu)化文獻包含基于二階偏導數(shù)(海森矩陣)的驚人算法。 不幸的是,這些算法很難應用于深度神經(jīng)網(wǎng)絡,因為每個輸出有n ^ 2個海森值(其中n是參數(shù)的數(shù)量),而不是每個輸出只有n個雅克比值。 由于 DNN 通常具有數(shù)以萬計的參數(shù),二階優(yōu)化算法通常甚至不適合內(nèi)存,甚至在他們這樣做時,計算海森矩陣也是太慢了。


原文發(fā)布時間為:2018-06-24

本文作者:ApacheCN【翻譯】


本文來自云棲社區(qū)官方釘群“Python技術(shù)進階”,了解相關(guān)信息可以關(guān)注“Python技術(shù)進階”。


Python技術(shù)進階交流群


總結(jié)

以上是生活随笔為你收集整理的【翻译】Sklearn 与 TensorFlow 机器学习实用指南 —— 第11章 训练深层神经网络(中)...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。