Informazioni su input e output per le spiegazioni

Prima di richiedere spiegazioni, devi inviare un file di metadati delle spiegazioni per configurare la richiesta. Questo file dei metadati deve includere gli input e gli output del modello. Inoltre, include impostazioni facoltative, come le linee di base di input e le impostazioni di visualizzazione per i dati delle immagini.

La specifica degli input e degli output del modello ti consente di selezionare determinate funzionalità per la richiesta di spiegazioni, senza che tu debba modificare il modello. Puoi utilizzare l'SDK Explainable AI per farlo automaticamente quando crei un nuovo modello. Se non utilizzi l'SDK Explainable AI, devi identificare manualmente gli input e gli output.

Questa guida si concentra su come identificare manualmente i tensori di input e di output per aiutarti a preparare il file dei metadati della spiegazione.

Input e output nei metadati della spiegazione

Per preparare i metadati della spiegazione, devi specificare gli input e gli output per il tuo modello in un file denominato explanation_metadata.json:

{
  "inputs": {
    string <input feature key>: {
      "input_tensor_name": string,
  },
  "outputs": {
    string <output value key>:  {
      "output_tensor_name": string
    },
  },
  "framework": "tensorflow"
}

All'interno degli oggetti inputs e outputs del file, devi fornire i nomi dei tensori di input e di output per la richiesta di spiegazioni.

  • Le chiavi per ogni input e output ("chiave della funzionalità di input" e "chiave del valore di output" nell'esempio precedente) ti consentono di assegnare nomi significativi a ciascun tensore. Nell'esempio seguente, la chiave della funzionalità di input è degrees_celsius e la chiave del valore di output è probabilities.
  • Per i valori in ogni metadato input e output, devi fornire il nome effettivo del tensore come input_tensor_name o output_tensor_name. Nell'esempio riportato di seguito, input_tensor_name è x:0 e output_tensor_name è dense/Softmax:0.
{
    "inputs": {
      "degrees_celsius": {
        "input_tensor_name": "x:0",
      }
    },
    "outputs": {
      "probabilities": {
        "output_tensor_name": "dense/Softmax:0"
      }
    },
  "framework": "tensorflow"
}

I nomi effettivi dei tensori sono formattati come name:index.

Trovare i tensori di input e output

Dopo aver addestrato un modello TensorFlow, esportalo come SavedModel. Il file SavedModel di TensorFlow contiene il modello TensorFlow addestrato, oltre a firme, variabili e altri asset serializzati necessari per eseguire il grafico. Ogni SignatureDef identifica una funzione nel grafo che accetta input di tensori e produce output di tensori. Analogamente, il file dei metadati della spiegazione definisce gli input e gli output del grafo per la richiesta di attribuzione delle funzionalità a AI Explanations.

Spesso, i tensori di input e di output specificati nel file di metadati della spiegazione mappano esattamente alle firme che definisci quando salvi il modello. In questo caso, trovare i nomi dei tensori di input e di output è relativamente semplice. Tuttavia, in alcuni casi, gli input o gli output che vuoi spiegare potrebbero essere diversi da quelli che definisci quando salvi il modello.

Gli input e gli output per le spiegazioni sono gli stessi impostati nella pubblicazione SignatureDef se:

  • Gli input non sono in formato serializzato
  • Ogni input a SignatureDef contiene direttamente il valore della funzionalità (possono essere valori numerici o stringhe)
  • Gli output sono valori numerici, trattati come dati numerici. Sono esclusi gli ID del corso, che sono considerati dati categorici.

In questi casi, puoi ottenere i nomi dei tensori di input e di output durante la creazione del modello. In alternativa, puoi ispezionare il SignatureDef del tuo modello salvato con la CLI SavedModel per trovare i nomi dei tensori di input e output.

Per qualsiasi caso che non soddisfi i criteri precedenti, esistono altri approcci che puoi adottare per trovare i tensori di input e output giusti.

Ottenere i nomi dei tensori durante l'addestramento

È più facile accedere ai nomi dei tensori di input e di output durante l'addestramento. Puoi salvare questi valori nel file dei metadati della spiegazione, mentre il programma o l'ambiente ha ancora accesso alle variabili impostate durante la creazione del modello. In questo esempio, il campo name del livello Keras produce il nome del tensore sottostante necessario per i metadati della spiegazione:

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 = keras.Model(inputs=bow_inputs, outputs=predictions)
print('input_tensor_name:', bow_inputs.name)
print('output_tensor_name:', predictions.name)
input_tensor_name: input_1:0
output_tensor_name: dense_1/Sigmoid:0

Per un esempio completo funzionante, consulta i notebook di esempio.

Ottenere i nomi dei tensori dalle definizioni delle firme

Poiché sia i SignatureDef che i metadati di spiegazione identificano gli input e gli output dei tensori, puoi utilizzare SignatureDef per preparare il file di metadati della spiegazione, a condizione che soddisfi i criteri menzionati in precedenza.

Considera l'esempio seguente 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

Il grafo ha un tensore di input denominato x:0 e un tensore di output denominato dense/Softmax:0. Entrambi i tensori hanno anche nomi significativi: my_numpy_input e probabilities rispettivamente. Per richiedere spiegazioni per probabilities rispetto a my_numpy_input, puoi creare un file di metadati delle spiegazioni come segue:

{
    "inputs": {
      "my_numpy_input": {
        "input_tensor_name": "x:0",
      }
    },
    "outputs": {
      "probabilities": {
        "output_tensor_name": "dense/Softmax:0"
      }
    },
  "framework": "tensorflow"
}

Per ispezionare il SignatureDef del tuo SavedModel, puoi utilizzare la CLI di SavedModel. Scopri di più su come utilizzare l'interfaccia a riga di comando SavedModel.

Gestione delle discrepanze di input e output

Esistono alcuni casi comuni in cui i tensori di input e di output nei metadati dell'evidenziazione non devono essere uguali a quelli di pubblicazioneSignatureDef:

  • Hai input serializzati
  • Il grafico include operazioni di preelaborazione
  • Gli output di pubblicazione non sono probabilità, logit o altri tipi di tensori con virgola mobile

In questi casi, devi utilizzare approcci diversi per trovare i tensori di input e di output corretti. L'obiettivo generale è trovare i tensori relativi ai valori delle funzionalità che vuoi spiegare per gli input e i tensori relativi a logit (pre-attivazione), probabilità (post-attivazione) o qualsiasi altra rappresentazione per gli output.

Discrepanze di input

Gli input nei metadati della spiegazione sono diversi da quelli di pubblicazioneSignatureDef se utilizzi un input serializzato per alimentare il modello o se il grafico include operazioni di preelaborazione.

Input serializzati

I SavedModel di TensorFlow possono accettare una serie di input complessi, tra cui:

  • Messaggi tf.Example serializzati
  • Stringhe JSON
  • Stringhe Base64 codificate (per rappresentare i dati immagine)

Se il tuo modello accetta input serializzati come questi, l'utilizzo diretto di questi tensori come input per le spiegazioni non funzionerà o potrebbe produrre risultati non significativi. Devi invece individuare i tensori di input successivi che vengono inseriti nelle colonne di funzionalità all'interno del modello.

Quando esporti il modello, puoi aggiungere un'operazione di analisi al gráfo di TensorFlow chiamando una funzione di analisi nella funzione di input di pubblicazione. Puoi trovare le funzioni di analisi elencate nel modulo tf.io. Queste funzioni di analisi di solito restituiscono tensori come risposta e questi tensori sono selezioni migliori per i metadati della spiegazione.

Ad esempio, puoi utilizzare tf.parse_example() durante l'esportazione del modello. Prende un messaggio tf.Example serializzato e genera un dizionario di tensori da inviare alle colonne delle caratteristiche. Puoi utilizzare il suo output per compilare i metadati della spiegazione. Se alcune di queste uscite sono tf.SparseTensor, ovvero una tupla denominata composta da 3 tensori, allora devi ottenere i nomi degli indici, dei valori e dei tensori dense_shape e compilare i campi corrispondenti nei metadati.

L'esempio seguente mostra come ottenere il nome del tensore di input dopo un'operazione di decodifica:

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)

Input di pre-elaborazione

Se il grafo del modello contiene alcune operazioni di preelaborazione, ti consigliamo di ottenere spiegazioni sui tensori dopo il passaggio di preelaborazione. In questo caso, puoi ottenere i nomi di questi tensori utilizzando la proprietà name di tf.Tensor e inserirli nei metadati della spiegazione:

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)

Il nome del tensore decodificato diventa input_pixels:0.

Discrepanze di output

Nella maggior parte dei casi, gli output nella pubblicazione SignatureDef sono probabilità o logit.

Se il tuo modello attribuisce probabilità, ma vuoi spiegare i valori di logit, devi trovare i nomi dei tensori di output appropriati che corrispondono ai logit.

Se la pubblicazione SignatureDef ha output che non sono probabilità o logit, devi fare riferimento all'operazione di probabilità nel grafico di addestramento. Questo scenario è improbabile per i modelli Keras. In questo caso, puoi utilizzare TensorBoard (o altri strumenti di visualizzazione dei grafici) per individuare i nomi dei tensori di output corretti.

Considerazioni aggiuntive per i gradienti integrati

AI Explanations forniscono due metodi di attribuzione delle funzionalità: valori di Shapley campionati e gradienti integrati. L'utilizzo del metodo dei gradienti integrati richiede di assicurarti che gli input siano differenziabili rispetto all'output, quindi devi tenerlo presente quando prepari i metadati della spiegazione. Non è necessario assicurarsi che gli input siano differenziabili se utilizzi il metodo di attribuzione delle funzionalità di Shapley campionate. Scopri di più sui metodi di attribuzione delle funzionalità supportati in AI Explanations.

I metadati della spiegazione separano logicamente le caratteristiche di un modello dai relativi input. Quando utilizzi i gradienti integrati con un tensore di input non differenziabile rispetto al tensore di output, devi fornire anche la versione codificata (e differenziabile) della funzionalità.

Utilizza il seguente approccio se hai tensori di input non differenziabili o se hai operazioni non differenziabili nel grafico:

  • Codifica gli input non differenziabili come input differenziabili.
  • Imposta input_tensor_name sul nome del tensore di input originale non differenziabile e imposta encoded_tensor_name sul nome della relativa versione codificata e differenziabile.

File di metadati della spiegazione con codifica

Ad esempio, considera un modello che ha una caratteristica categorica con un tensore di input denominato zip_codes:0. Poiché i dati di input includono i codici postali come stringhe, il tensore di input zip_codes:0 non è differenziabile. Se il modello pre-elabora anche questi dati per ottenere una rappresentazione con codifica one-hot dei codici postali, il tensore di input dopo la pre-elaborazione è differenziabile. Per distinguerlo dal tensore di input originale, puoi chiamarlo zip_codes_embedding:0.

Per utilizzare i dati di entrambi i tensori di input nella richiesta di spiegazioni, imposta i metadati inputs come segue:

  • Imposta la chiave della funzionalità di input su un nome significativo, ad esempio zip_codes.
  • Imposta input_tensor_name sul nome del tensore originale, zip_codes:0.
  • Imposta encoded_tensor_name sul nome del tensore dopo la codifica one-hot, zip_codes_embedding:0.
  • Imposta encoding su 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"
      }
    },
  "framework": "tensorflow"
}

In alternativa, puoi impostare input_tensor_name sul nome del tensore di input differenziabile codificato e omettere il tensore originale non differenziabile. Il vantaggio di fornire entrambi i tensori è che gli attributi possono essere assegnati ai singoli valori del codice postale anziché alla sua rappresentazione di codifica one-hot. In questo esempio, dovresti escludere il tensore originale (zip_codes:0) e impostare input_tensor_name su zip_codes_embedding:0. Questo approccio non è consigliato, perché gli attribuiti delle funzionalità risultanti sarebbero difficili da valutare.

Codifica

Per attivare la codifica nella richiesta di spiegazioni, specifica le impostazioni di codifica come mostrato nell'esempio precedente.

La funzionalità di codifica consente di invertire il processo dai dati codificati ai dati di input per le attribuzioni, eliminando la necessità di eseguire il post-trattamento manualmente delle attribuzioni restituite. Al momento, le spiegazioni basate sull'IA supportano combined_embedding, dove una funzionalità di lunghezza variabile viene combinata in un embedding. Un'operazione di esempio che corrisponde a questo combined_embedding è tf.nn.embedding_lookup_sparse.

Per combined_embedding:

Il tensore di input viene codificato in un array 1D. Ad esempio:

  • Input: ["This", "is", "a", "test"]
  • Codificata: [0.1, 0.2, 0.3, 0.4]

Passaggi successivi