TensorFlow Hub 在 2018 年推出時,只提供一種資產類型:TF1 Hub 格式,以便匯入 TensorFlow 1 程式。
本頁說明如何在 TF1 (或 TF2 的 TF1 相容模式) 中使用 TF1 Hub 格式,搭配 hub.Module
類別和相關 API。(一般用法是建構 tf.Graph
,可能在 TF1 Estimator
內,方法是將一或多個 TF1 Hub 格式的模型與 tf.compat.layers
或 tf.layers
結合使用)。
TensorFlow 2 的使用者 (TF1 相容模式以外) 必須使用新的 API,搭配 hub.load()
或 hub.KerasLayer
。新的 API 會載入新的 TF2 SavedModel 資產類型,但也對將 TF1 Hub 格式載入 TF2 提供有限的支援。
在 TF1 Hub 格式中使用模型
在 TF1 Hub 格式中執行個體化模型
TF1 Hub 格式的模型會匯入 TensorFlow 程式,方法是從字串 (包含其網址或檔案系統路徑) 建立 hub.Module
物件,例如
m = hub.Module("path/to/a/module_dir")
注意:如要進一步瞭解其他有效的控制代碼類型,請參閱這裡。
這會將模組的變數新增至目前的 TensorFlow 圖表。執行其初始化工具將會從磁碟讀取其預先訓練的值。同樣地,表格和其他狀態也會新增至圖表。
快取模組
從網址建立模組時,模組內容會下載並快取在本地系統暫存目錄中。可以使用 TFHUB_CACHE_DIR
環境變數覆寫模組快取的位置。如需詳細資訊,請參閱快取。
套用模組
執行個體化後,模組 m
可以像 Python 函式一樣呼叫零次或多次,從張量輸入到張量輸出
y = m(x)
每次這類呼叫都會將運算新增至目前的 TensorFlow 圖表,以根據 x
計算 y
。如果這牽涉到具有已訓練權重的變數,則這些變數會在所有應用程式之間共用。
模組可以定義多個具名的簽名,以便以多種方式套用 (類似於 Python 物件具有方法的方式)。模組的文件應說明可用的簽名。上述呼叫會套用名為 "default"
的簽名。可以將簽名名稱傳遞至選用的 signature=
引數來選取任何簽名。
如果簽名有多個輸入,則必須以字典形式傳遞,金鑰由簽名定義。同樣地,如果簽名有多個輸出,則可以透過傳遞 as_dict=True
以字典形式擷取這些輸出 (在簽名定義的金鑰下;金鑰 "default"
適用於在 as_dict=False
時傳回的單一輸出)。因此,套用模組最常見的形式如下
outputs = m(dict(apples=x1, oranges=x2), signature="fruit_to_pet", as_dict=True)
y1 = outputs["cats"]
y2 = outputs["dogs"]
呼叫者必須提供簽名定義的所有輸入,但沒有規定必須使用模組的所有輸出。TensorFlow 只會執行模組中最終成為 tf.Session.run()
中目標依附項目的部分。實際上,模組發布者可能會選擇提供各種輸出,以供進階使用 (例如中繼層的啟動) 以及主要輸出。模組消費者應妥善處理其他輸出。
試用替代模組
每當同一個工作有多個模組時,TensorFlow Hub 鼓勵為這些模組配備相容的簽名 (介面),如此一來,試用不同的模組就像變化字串值超參數一樣容易。
為此,我們維護了常用工作的建議通用簽名集合。
建立新模組
相容性注意事項
TF1 Hub 格式適用於 TensorFlow 1。TensorFlow 2 中的 TF Hub 僅部分支援此格式。請考慮改用新的 TF2 SavedModel 格式發布。
TF1 Hub 格式在語法層面 (相同檔案名稱和通訊協定訊息) 上與 TensorFlow 1 的 SavedModel 格式相似,但在語意上有所不同,以允許模組重複使用、組合和重新訓練 (例如,資源初始化工具的不同儲存方式、中繼圖的不同標記慣例)。在磁碟上區分兩者的最簡單方法是 tfhub_module.pb
檔案是否存在。
一般方法
如要定義新模組,發布者會使用函式 module_fn
呼叫 hub.create_module_spec()
。此函式會建構圖表,代表模組的內部結構,並針對呼叫者提供的輸入使用 tf.placeholder()
。然後,它會呼叫 hub.add_signature(name, inputs, outputs)
一次或多次來定義簽名。
例如
def module_fn():
inputs = tf.placeholder(dtype=tf.float32, shape=[None, 50])
layer1 = tf.layers.dense(inputs, 200)
layer2 = tf.layers.dense(layer1, 100)
outputs = dict(default=layer2, hidden_activations=layer1)
# Add default signature.
hub.add_signature(inputs=inputs, outputs=outputs)
...
spec = hub.create_module_spec(module_fn)
hub.create_module_spec()
的結果可以用來取代路徑,以便在特定的 TensorFlow 圖表中執行個體化模組物件。在這種情況下,沒有檢查點,而模組執行個體會改用變數初始化工具。
任何模組執行個體都可以透過其 export(path, session)
方法序列化到磁碟。匯出模組會將其定義及其變數在 session
中的目前狀態一起序列化到傳遞的路徑中。這可用於第一次匯出模組,以及在匯出微調模組時使用。
為了與 TensorFlow Estimator 相容,hub.LatestModuleExporter
會從最新的檢查點匯出模組,就像 tf.estimator.LatestExporter
從最新的檢查點匯出整個模型一樣。
模組發布者應盡可能實作通用簽名,讓消費者可以輕鬆交換模組,並找到最適合其問題的模組。
實際範例
請參閱我們的文字嵌入模組匯出工具,以取得如何從通用文字嵌入格式建立模組的實際範例。
微調
將匯入模組的變數與周圍模型的變數一起訓練稱為微調。微調可以產生更好的品質,但會增加新的複雜性。我們建議消費者在探索更簡單的品質調整後,再研究微調,而且僅在模組發布者建議時才進行微調。
適用於消費者
如要啟用微調,請使用 hub.Module(..., trainable=True)
執行個體化模組,使其變數可訓練,並匯入 TensorFlow 的 REGULARIZATION_LOSSES
。如果模組有多個圖表變體,請務必選取適用於訓練的變體。通常,該變體的標記為 {"train"}
。
選擇不會破壞預先訓練權重的訓練機制,例如,比從頭開始訓練更低的學習率。
適用於發布者
為了讓消費者更容易進行微調,請注意以下事項
微調需要正規化。您的模組會隨著
REGULARIZATION_LOSSES
集合匯出,這會將您選擇的tf.layers.dense(..., kernel_regularizer=...)
等放入消費者從tf.losses.get_regularization_losses()
取得的內容中。偏好使用這種定義 L1/L2 正規化損失的方式。在發布者模型中,避免透過
tf.train.FtrlOptimizer
、tf.train.ProximalGradientDescentOptimizer
和其他近端最佳化工具的l1_
和l2_regularization_strength
參數定義 L1/L2 正規化。這些不會與模組一起匯出,而且全域設定正規化強度可能不適合消費者。除了寬廣 (亦即稀疏線性) 或寬廣且深度模型中的 L1 正規化之外,應該可以使用個別的正規化損失。如果您使用 dropout、批次正規化或類似的訓練技術,請將其超參數設定為在許多預期用途中都有意義的值。dropout 率可能必須根據目標問題的過度擬合傾向進行調整。在批次正規化中,動量 (又稱衰減係數) 應夠小,才能使用小型資料集和/或大型批次進行微調。對於進階消費者,請考慮新增可控制重要超參數的簽名。