[譯]深度學習模型的簡單優化技巧

機器之心發表於2019-01-29

選自toward data science,作者:Jonathan Balaban,機器之心編譯。

本文介紹了幾個深度學習模型的簡單優化技巧,包括遷移學習、dropout、學習率調整等,並展示瞭如何用 Keras 實現。

以下是我與同事和學生就如何優化深度模型進行的對話、訊息和辯論的摘要。如果你發現了有影響力的技巧,請分享。

首先,為什麼要改進模型?

像卷積神經網路(CNN)這樣的深度學習模型具有大量的引數;實際上,我們可以呼叫這些超引數,因為它們原本在模型中並沒有被優化。你可以網格搜尋這些超引數的最優值,但需要大量硬體計算和時間。那麼,一個真正的資料科學家能滿足於猜測這些基本引數嗎?

改進模型的最佳方法之一是基於在你的領域進行過深入研究的專家的設計和體系結構,他們通常擁有強大的硬體可供使用。而且,他們經常慷慨地開源建模架構和原理。

深度學習技術

以下是一些通過預訓練模型來改善擬合時間和準確性的方法:

  1. 研究理想的預訓練體系架構:瞭解遷移學習的好處,或瞭解一些功能強大的 CNN 體系架構。考慮那些看起來不太適合但具有潛在共享特性的領域。
  2. 使用較小的學習率:由於預訓練的權重通常優於隨機初始化的權重,因此修改要更為精細!你在此處的選擇取決於學習環境和預訓練的表現,但請檢查各個時期的誤差,以瞭解距離收斂還要多久。
  3. 使用 dropout:與迴歸模型的 Ridge 和 LASSO 正則化一樣,沒有適用於所有模型的優化 alpha 或 dropout。這是一個超引數,取決於具體問題,必須進行測試。從更大的變化開始——用更大的網格搜尋跨越幾個數量級,如 np.logspace() 所能提供的那樣——然後像上面的學習率一樣下降。
  4. 限制權重大小:可以限制某些層的權重的最大範數(絕對值),以泛化我們的模型。
  5. 不要動前幾層:神經網路的前幾個隱藏層通常用於捕獲通用和可解釋的特徵,如形狀、曲線或跨域的相互作用。我們應該經常把這些放在一邊,把重點放在進一步優化元潛在級別的特徵上。這可能意味著新增隱藏層,這樣我們就不需要匆忙處理了!
  6. 修改輸出層:使用適合你的領域的新啟用函式和輸出大小替換模型預設值。不過,不要把自己侷限於最明顯的解決方案。儘管 MNIST 看起來似乎需要 10 個輸出類,但有些數字有共同的變數,允許 12-16 個類可能會更好地解決這些變數,並提高模型效能!與上面提到的提示一樣,深度學習模型應該隨著我們接近輸出而不斷修改和定製。

Keras 中的技術

在 Keras 中修改 MNIST 的 dropout 和限制權重大小的方法如下:

# dropout in input and hidden layers
# weight constraint imposed on hidden layers
# ensures the max norm of the weights does not exceed 5
model = Sequential()
model.add(Dropout(0.2, input_shape=(784,))) # dropout on the inputs
# this helps mimic noise or missing data
model.add(Dense(128, input_dim=784, kernel_initializer=`normal`, activation=`relu`, kernel_constraint=maxnorm(5)))
model.add(Dropout(0.5))
model.add(Dense(128, kernel_initializer=`normal`, activation=`tanh`, kernel_constraint=maxnorm(5)))
model.add(Dropout(0.5))
model.add(Dense(1, kernel_initializer=`normal`, activation=`sigmoid`))
複製程式碼

dropout 最佳實踐

  • 使用 20-50 % 的 dropout,建議輸入 20%。太低,影響可以忽略;太高,可能欠擬合。
  • 在輸入層和隱藏層上使用 dropout。這已被證明可以提高深度學習的效能。
  • 使用伴有衰減的較大的學習速率,以及較大的動量。
  • 限制權重!較大的學習速率會導致梯度爆炸。通過對網路權值施加約束(如大小為 5 的最大範數正則化)可以改善結果。
  • 使用更大的網路。在較大的網路上使用 dropout 可能會獲得更好的效能,從而使模型有更多的機會學習獨立的表徵。

下面是 Keras 中的最終層修改示例,其中包含 14 個 MNIST 類:

from keras.layers.core import Activation, Dense
model.layers.pop() # defaults to last
model.outputs = [model.layers[-1].output]
model.layers[-1].outbound_nodes = []
model.add(Dense(14, activation=`softmax`))
複製程式碼

以及如何凍結前五層權重的示例:

for layer in model.layers[:5]:
    layer.trainable = False
複製程式碼

或者,我們可以將該層的學習速率設為零,或者使用每個引數的自適應學習演算法,如 Adadelta 或 Adam。這有點複雜,在其他平臺(如 Caffe)中實現得更好。

預訓練網路庫

Keras

TensorFlow

Torch

Caffe

在 Jupyter 中檢視你的 TensorBoard 圖

模型的視覺化通常很重要。如果你用 Keras 編寫模型,它的抽象很好,但不允許你深入到模型的各個部分進行更細緻的分析。幸運的是,下面的程式碼可以讓我們直接使用 Python 視覺化模型:

# From: http://nbviewer.jupyter.org/github/tensorflow/tensorflow/blob/master/tensorflow/examples/tutorials/deepdream/deepdream.ipynb
# Helper functions for TF Graph visualization
from IPython.display import clear_output, Image, display, HTML
def strip_consts(graph_def, max_const_size=32):
    """Strip large constant values from graph_def."""
    strip_def = tf.GraphDef()
    for n0 in graph_def.node:
        n = strip_def.node.add() 
        n.MergeFrom(n0)
        if n.op == `Const`:
            tensor = n.attr[`value`].tensor
            size = len(tensor.tensor_content)
            if size > max_const_size:
                tensor.tensor_content = bytes("<stripped %d bytes>"%size, `utf-8`)
    return strip_def

def rename_nodes(graph_def, rename_func):
    res_def = tf.GraphDef()
    for n0 in graph_def.node:
        n = res_def.node.add() 
        n.MergeFrom(n0)
        n.name = rename_func(n.name)
        for i, s in enumerate(n.input):
            n.input[i] = rename_func(s) if s[0]!=`^` else `^`+rename_func(s[1:])
    return res_def

def show_graph(graph_def, max_const_size=32):
    """Visualize TensorFlow graph."""
    if hasattr(graph_def, `as_graph_def`):
        graph_def = graph_def.as_graph_def()
    strip_def = strip_consts(graph_def, max_const_size=max_const_size)
    code = """
        <script>
          function load() {{
            document.getElementById("{id}").pbtxt = {data};
          }}
        </script>
        <link rel="import" href="https://tensorboard.appspot.com/tf-graph-basic.build.html" onload=load()>
        <div style="height:600px">
          <tf-graph-basic id="{id}"></tf-graph-basic>
        </div>
    """.format(data=repr(str(strip_def)), id=`graph`+str(np.random.rand()))

    iframe = """
        <iframe seamless style="width:800px;height:620px;border:0" srcdoc="{}"></iframe>
    """.format(code.replace(`"`, `&quot;`))
    display(HTML(iframe))
# Visualizing the network graph. Be sure expand the "mixed" nodes to see their 
# internal structure. We are going to visualize "Conv2D" nodes.
graph_def = tf.get_default_graph().as_graph_def()
tmp_def = rename_nodes(graph_def, lambda s:"/".join(s.split(`_`,1)))
show_graph(tmp_def)
複製程式碼

使用 Keras 視覺化你的模型

這一步將繪製模型的圖並將其儲存為 png 檔案:

from keras.utils.visualize_util import plot
plot(model, to_file=`model.png`)
複製程式碼

plot 採用兩個可選引數:

  • show_shapes(預設為 False)控制輸出形狀是否顯示在圖中。
  • show_layer_names(預設為 True)控制層命名是否顯示在圖中。

也可以直接獲得 pydot.Graph 物件並自己對其進行渲染,如在 iPython notebook 中顯示它:

from IPython.display import SVG
from keras.utils.visualize_util import model_to_dot
SVG(model_to_dot(model).create(prog=`dot`, format=`svg`))
複製程式碼

原文連結:towardsdatascience.com/deep-learni…

相關文章