TF1 Hub 格式

TensorFlow Hub 在 2018 年推出時,只提供一種資產類型:TF1 Hub 格式,以便匯入 TensorFlow 1 程式。

本頁說明如何在 TF1 (或 TF2 的 TF1 相容模式) 中使用 TF1 Hub 格式,搭配 hub.Module 類別和相關 API。(一般用法是建構 tf.Graph,可能在 TF1 Estimator 內,方法是將一或多個 TF1 Hub 格式的模型與 tf.compat.layerstf.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.FtrlOptimizertf.train.ProximalGradientDescentOptimizer 和其他近端最佳化工具的 l1_l2_regularization_strength 參數定義 L1/L2 正規化。這些不會與模組一起匯出,而且全域設定正規化強度可能不適合消費者。除了寬廣 (亦即稀疏線性) 或寬廣且深度模型中的 L1 正規化之外,應該可以使用個別的正規化損失。

  • 如果您使用 dropout、批次正規化或類似的訓練技術,請將其超參數設定為在許多預期用途中都有意義的值。dropout 率可能必須根據目標問題的過度擬合傾向進行調整。在批次正規化中,動量 (又稱衰減係數) 應夠小,才能使用小型資料集和/或大型批次進行微調。對於進階消費者,請考慮新增可控制重要超參數的簽名。