使用自訂訓練的 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 不可微分。如果模型也會預先處理這項資料,以取得郵遞區號的 one-hot 編碼表示法,那麼預先處理後的輸入張量就是可微分的。為與原始輸入張量區別,您可以將其命名為 zip_codes_embedding:0。
如要在說明要求中使用兩個輸入張量的資料,請在為說明Model設定 ExplanationMetadata 時,將 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 可解釋 AI 支援的編碼清單。
如果是 COMBINED_EMBEDDING 編碼,輸入張量會編碼為 1D 陣列。
例如:
- 輸入:
["This", "is", "a", "test"] - 編碼輸入內容:
[0.1, 0.2, 0.3, 0.4]
匯出 TensorFlow SavedModel,供 Vertex Explainable AI 使用
訓練完 TensorFlow 模型後,請將模型匯出為 SavedModel。TensorFlow SavedModel 包含經過訓練的 TensorFlow 模型,以及執行圖形所需的序列化簽章、變數和其他資產。SavedModel 中的每個 SignatureDef 都會識別圖表中的函式,該函式會接受張量輸入內容並產生張量輸出內容。
如要確保 SavedModel 與 Vertex Explainable AI 相容,請按照下列其中一個章節的說明操作,具體取決於您使用的是 TensorFlow 2 還是 TensorFlow 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 做為輸出張量名稱。