使用自訂訓練的 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
做為輸出張量名稱。