使用自訂訓練的 TensorFlow 模型時,您需要提供特定資訊才能儲存模型並設定說明。
如果您想搭配 AutoML 表格型模型使用 Vertex Explainable AI,則無需執行任何設定;Vertex AI 會自動為 Vertex Explainable AI 設定模型。請略過這份文件,改為閱讀取得說明。
本指南提供訓練 TensorFlow 模型時所需的資訊,確保您能將模型與 Vertex Explainable AI 搭配使用。具體來說,指南涵蓋下列主題:
在訓練期間找出輸入和輸出張量名稱,您需要在為 Vertex Explainable AI 設定
Model資源時指定這些名稱。這包括在特殊情況下 (一般情況下無法運作) 為 Vertex Explainable AI 建立及尋找適當的張量。將 TensorFlow 模型匯出為與 Vertex Explainable AI 相容的 TensorFlow SavedModel。
從已匯出的 TensorFlow SavedModel 中找出輸入和輸出張量名稱。如果您無法存取模型的訓練程式碼,這項功能可能會有所幫助。
在訓練期間找出輸入和輸出張量名稱
使用 TensorFlow 預先建構的容器提供預測結果時,您必須知道模型的輸入張量和輸出張量名稱。為 Vertex Explainable AI 設定 Model時,您會在 ExplanationMetadata 訊息中指定這些名稱
如果您的 TensorFlow 模型符合下列條件,您就可以使用下一節所述的「基本方法」,在訓練期間判斷這些張量名稱:
- 輸入內容並未以序列化格式輸入
- 模型
SignatureDef的每個輸入內容都直接包含功能的值 (可以是數值或字串) - 輸出內容是數字值,會視為數值資料。這項設定會排除課程 ID,因為課程 ID 屬於類別資料。
如果模型不符合這些條件,請參閱「在特殊情況下調整訓練程式碼和查找張量名稱」一節。
基本方法
在訓練期間,請列印模型輸入張量和輸出張量的 name 屬性。在以下範例中,Keras 層的 name 欄位會產生 ExplanationMetadata 所需的基礎張量名稱:
bow_inputs = tf.keras.layers.Input(shape=(2000,))
merged_layer = tf.keras.layers.Dense(256, activation="relu")(bow_inputs)
predictions = tf.keras.layers.Dense(10, activation="sigmoid")(merged_layer)
model = tf.keras.Model(inputs=bow_inputs, outputs=predictions)
print('input_tensor_name:', bow_inputs.name)
print('output_tensor_name:', predictions.name)
執行這個 Python 程式碼會輸出以下內容:
input_tensor_name: input_1:0
output_tensor_name: dense_1/Sigmoid:0
接著,您可以設定 Model 以便解釋,使用 input_1:0 做為輸入張量名稱,並使用 dense_1/Sigmod:0 做為輸出張量名稱。
調整訓練程式碼,並在特殊情況下尋找張量名稱
在以下幾種常見情況下,ExplanationMetadata 的輸入和輸出張量「不應」與服務 SignatureDef 中的相同:
- 您已序列化輸入內容
- 圖表包含預先處理作業
- 您的服務輸出不是機率、邏輯值或其他類型的浮點張量
在這種情況下,您應使用其他方法找出正確的輸入和輸出張量。整體目標是找出與您要解釋的輸入特徵值相關的張量,以及與對數 (預先啟用)、機率 (後續啟用) 或任何其他輸出表示法相關的張量。
輸入張量的特殊情況
如果您使用序列化的輸入內容來提供模型,或是圖表包含預先處理作業,說明中繼資料中的輸入內容就會與服務 SignatureDef 中的輸入內容不同。
已序列化的輸入內容
TensorFlow SavedModel 可接受各種複雜的輸入內容,包括:
- 序列化的 tf.Example 訊息
- JSON 字串
- 已編碼的 Base64 字串 (用於代表圖片資料)
如果模型接受這類序列化的輸入內容,直接將這些張量做為說明的輸入內容可能會失敗,或產生毫無意義的結果。您應該要找出後續輸入張量,這些張量會饋送至模型中的特徵欄。
匯出模型時,您可以在服務輸入函式中呼叫剖析函式,藉此將剖析作業新增至 TensorFlow 圖表。您可以在 tf.io 模組中找到解析函式。這些剖析函式通常會傳回張量做為回應,而這些張量是說明中繼資料的最佳選擇。
舉例來說,您可以在匯出模型時使用 tf.parse_example()。它會擷取已序列化的 tf.Example 訊息,並輸出張量字典,將其餵入特徵欄。您可以使用該工具的輸出內容填入說明中繼資料。如果其中部分輸出內容是 tf.SparseTensor,也就是由 3 個張量組成的命名元組,則您應取得索引、值和 dense_shape 張量的名稱,並填入中繼資料中的對應欄位。
以下範例說明如何在解碼作業後取得輸入張量的名稱:
float_pixels = tf.map_fn(
lambda img_string: tf.io.decode_image(
img_string,
channels=color_depth,
dtype=tf.float32
),
features,
dtype=tf.float32,
name='input_convert'
)
print(float_pixels.name)
預先處理輸入內容
如果模型圖包含一些預處理運算,您可能會想在預處理步驟之後取得張量的說明。在這種情況下,您可以使用 tf.Tensor 的 name 屬性取得這些張量的名稱,並將這些名稱放入說明中繼資料:
item_one_hot = tf.one_hot(item_indices, depth,
on_value=1.0, off_value=0.0,
axis=-1, name="one_hot_items:0")
print(item_one_hot.name)
解碼後的張量名稱會變成 input_pixels:0。
輸出張量的特殊情況
在多數情況下,服務 SignatureDef 中的輸出值為機率或對數比。
如果模型會歸因於機率,但您想改為解釋對數比值,則必須找出對應對數比值的適當輸出張量名稱。
如果您的服務 SignatureDef 輸出不是機率或對數比對,您應參考訓練圖表中的機率運算。這種情況不太可能發生在 Keras 模型中。如果發生這種情況,您可以使用 TensorBoard (或其他圖表視覺化工具) 來找出正確的輸出張量名稱。
積分梯度的特別注意事項
如果您想使用 Vertex Explainable AI 的整合梯度功能歸因方法,則必須確保輸入內容相對於輸出內容可區分。
解釋中繼資料會在邏輯上將模型的特徵與輸入內容區隔開來。當您使用整合梯度,且輸入張量相對於輸出張量無法區分時,您必須提供該功能的已編碼 (且可區分) 版本。
如果您有無法微分輸入張量,或圖表中含有無法微分運算,請使用下列方法:
- 將不可微分的輸入內容編碼為可微分的輸入內容。
- 將
input_tensor_name設為原始的非可微分輸入張量名稱,並將encoded_tensor_name設為其已編碼的可微分版本名稱。
說明含有編碼的中繼資料檔案
舉例來說,假設模型含有類別特徵,且輸入張量名為 zip_codes:0。由於輸入資料包含郵遞區號字串,因此輸入張量 zip_codes:0 無法區分。如果模型也對這項資料進行預先處理,以便取得郵遞區號的單熱編碼表示法,則預先處理後的輸入張量可進行微分。為了與原始輸入張量的名稱有所區別,您可以將其命名為 zip_codes_embedding:0。
如要在說明要求中使用兩個輸入張量的資料,請在設定用於說明的 Model 時,將 ExplanationMetadata 設為以下值:
- 將輸入功能鍵設為有意義的名稱,例如
zip_codes。 - 將
input_tensor_name設為原始張量的名稱zip_codes:0。 - 將
encoded_tensor_name設為 one-hot 編碼後的張量名稱zip_codes_embedding:0。 - 將
encoding設為COMBINED_EMBEDDING。
{
"inputs": {
"zip_codes": {
"input_tensor_name": "zip_codes:0",
"encoded_tensor_name": "zip_codes_embedding:0",
"encoding": "COMBINED_EMBEDDING"
}
},
"outputs": {
"probabilities": {
"output_tensor_name": "dense/Softmax:0"
}
}
}
或者,您也可以將 input_tensor_name 設為已編碼且可微分的輸入張量名稱,並省略原始的非可微分張量。提供這兩個張量的好處是,您可以為個別郵遞區號值進行歸因,而非使用 one-hot 編碼表示法。在這個範例中,您會排除原始張量 (zip_codes:0),並將 input_tensor_name 設為 zip_codes_embedding:0。我們不建議採用這種做法,因為這會產生難以推論的功能歸因。
編碼
如要為 Model 啟用編碼功能,請指定上述範例所示的編碼設定。
編碼功能可協助您將編碼資料反轉為歸因資料輸入資料,因此不必手動後續處理已傳回的歸因資料。請參閱Vertex Explainable AI 支援的編碼清單。
對於 COMBINED_EMBEDDING 編碼,輸入張量會編碼為 1D 陣列。
例如:
- 輸入:
["This", "is", "a", "test"] - 已編碼的輸入內容:
[0.1, 0.2, 0.3, 0.4]
為 Vertex Explainable AI 匯出 TensorFlow SavedModel
訓練完 TensorFlow 模型後,請將模型匯出為 SavedModel。TensorFlow SavedModel 包含經過訓練的 TensorFlow 模型,以及執行圖形所需的序列化簽名、變數和其他資產。SavedModel 中的每個 SignatureDef 都會標示圖表中的函式,該函式會接受張量輸入內容並產生張量輸出內容。
為確保 SavedModel 與 Vertex Explainable AI 相容,請根據您使用的 TensorFlow 版本 (2 或 1),按照下列任一節的操作說明進行。
TensorFlow 2
如果您使用的是 TensorFlow 2.x,請使用 tf.saved_model.save 儲存模型。您可以在儲存模型時指定輸入簽名。如果您有一個輸入簽名,Vertex Explainable AI 會使用預設的服務函式來處理說明要求。如果您有多個輸入簽章,請在儲存模型時指定服務預設函式的簽章:
tf.saved_model.save(m, model_dir, signatures={
'serving_default': serving_fn,
'xai_model': model_fn # Required for XAI
})
在這種情況下,Vertex Explainable AI 會使用您為說明要求儲存的 xai_model 鍵所對應的模型函式簽章。請使用 xai_model 這個字串做為鍵。
如果您使用預先處理函式,也必須為預先處理函式和模型函式指定簽名。您必須使用字串 xai_preprocess 和 xai_model 做為鍵:
tf.saved_model.save(m, model_dir, signatures={
'serving_default': serving_fn,
'xai_preprocess': preprocess_fn, # Required for XAI
'xai_model': model_fn # Required for XAI
})
在這種情況下,Vertex Explainable AI 會使用預處理函式和模型函式來處理說明要求。請確認預處理函式的輸出內容,符合模型函式預期的輸入內容。
進一步瞭解如何在 TensorFlow 中指定服務簽章。
TensorFlow 1.15
如果您使用的是 TensorFlow 1.15,請不要使用 tf.saved_model.save。Vertex Explainable AI 不支援以這種方式儲存的 TensorFlow 1 模型
如果您在 Keras 中建構及訓練模型,必須將模型轉換為 TensorFlow Estimator,然後匯出至 SavedModel。本節將著重於儲存模型。
建構、編譯、訓練及評估 Keras 模型後,您必須:
- 使用
tf.keras.estimator.model_to_estimator將 Keras 模型轉換為 TensorFlow Estimator - 使用
tf.estimator.export.build_raw_serving_input_receiver_fn提供服務輸入函式 - 使用
tf.estimator.export_saved_model將模型匯出為 SavedModel。
# Build, compile, train, and evaluate your Keras model
model = tf.keras.Sequential(...)
model.compile(...)
model.fit(...)
model.predict(...)
## Convert your Keras model to an Estimator
keras_estimator = tf.keras.estimator.model_to_estimator(keras_model=model, model_dir='export')
## Define a serving input function appropriate for your model
def serving_input_receiver_fn():
...
return tf.estimator.export.ServingInputReceiver(...)
## Export the SavedModel to Cloud Storage, using your serving input function
export_path = keras_estimator.export_saved_model(
'gs://' + 'YOUR_BUCKET_NAME',
serving_input_receiver_fn
).decode('utf-8')
print("Model exported to: ", export_path)
從 SavedModel 的 SignatureDef 取得張量名稱
您可以使用 TensorFlow SavedModel 的 SignatureDef 準備說明中繼資料,前提是該資料必須符合上一節所述「基本方法」的條件。如果您無法存取產生模型的訓練程式碼,這項功能可能會有所幫助。
如要檢查 SavedModel 的 SignatureDef,您可以使用 SavedModel CLI。進一步瞭解如何使用 SavedModel CLI。
請參考以下 SignatureDef 範例:
The given SavedModel SignatureDef contains the following input(s):
inputs['my_numpy_input'] tensor_info:
dtype: DT_FLOAT
shape: (-1, 1)
name: x:0
The given SavedModel SignatureDef contains the following output(s):
outputs['probabilities'] tensor_info:
dtype: DT_FLOAT
shape: (-1, 1)
name: dense/Softmax:0
Method name is: tensorflow/serving/predict
圖表包含名為 x:0 的輸入張量和名為 dense/Softmax:0 的輸出張量。設定 Model 以便說明時,請在 ExplanationMetadata 訊息中使用 x:0 做為輸入張量名稱,並使用 dense/Softmax:0 做為輸出張量名稱。