Noções básicas sobre entradas e saídas para explicação

Antes de solicitar explicações, você precisa enviar um arquivo de metadados de explicação para configurar a solicitação de explicações. Esse arquivo de metadados precisa incluir as entradas e saídas do modelo. Além disso, ele inclui configurações opcionais, como valores de referência de entrada e configurações de visualização de dados de imagem.

Especificar as entradas e saídas do modelo permite que você selecione atributos específicos para solicitação de explicação, sem a necessidade de alterar o modelo. É possível usar o SDK do Explainable AI para fazer isso automaticamente ao criar um novo modelo. Se você não estiver usando o SDK do Explainable AI, precisará identificar as entradas e saídas manualmente.

Neste guia, explicamos como identificar manualmente os tensores de entrada e saída para ajudar a preparar o arquivo de metadados de explicação.

Entradas e saídas em metadados de explicação

Para preparar seus metadados de explicação, especifique as entradas e saídas para seu modelo em um arquivo chamado explanation_metadata.json:

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

Dentro dos objetos inputs e outputs do arquivo, forneça os nomes dos tensores de entrada e saída para sua solicitação de explicações.

  • As chaves para cada entrada e saída ("chave de recurso de entrada" e "chave do valor de saída" no exemplo anterior) permitem que você forneça nomes significativos para cada tensor. Na amostra abaixo, a tecla de recurso de entrada é degrees_celsius e a chave do valor de saída é probabilities.
  • Para os valores em cada input e output de metadados, forneça o nome real do tensor como input_tensor_name ou output_tensor_name. No exemplo abaixo, 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"
}

Os nomes do tensor real são formatados como name:index.

Como encontrar tensores de entrada e saída

Depois de treinar um modelo do TensorFlow, exporte-o como um SavedModel. O SavedModel do TensorFlow contém o modelo do TensorFlow que você treinou, junto às assinaturas serializadas, variáveis e outros recursos necessários para executar o gráfico. Cada SignatureDef identifica uma função no gráfico que aceita entradas de tensor e produz saídas dele. Da mesma forma, seu arquivo de metadados de explicação define as entradas e saídas do gráfico para a solicitação de atribuição de recurso à AI Explanations.

Geralmente, os tensores de entrada e saída especificados no arquivo de metadados de explicação são mapeados exatamente para as assinaturas definidas quando você salva o modelo. Nesse caso, encontrar os nomes dos tensores de entrada e saída é relativamente simples. No entanto, algumas vezes, as entradas ou saídas que você quer explicar podem ser diferentes das que você define ao salvar o modelo.

Suas entradas e saídas para explicações são as mesmas que você definiu em SignatureDef de exibição se:

  • suas entradas não estão em formato serializado;
  • cada entrada para SignatureDef contém o valor do elemento diretamente (pode ser valores numéricos ou strings);
  • as saídas são valores numéricos, tratados como dados numéricos. Isso exclui os IDs de classe, que são considerados dados categorizados.

Nesses casos, é possível ter os nomes dos tensores de entrada e saída ao criar o modelo. Como alternativa, é possível inspecionar SignatureDef do SavedModel com o CLI SavedModel para encontrar os nomes dos tensores de entrada e saída.

Para qualquer caso que não se encaixe nos critérios anteriores, há outras abordagens que podem ser seguidas para encontrar os tensores de entrada e saída corretos.

Como conseguir os nomes de tensores durante o treinamento

É mais fácil acessar os nomes dos tensores de entrada e saída durante o treinamento. Salve esses valores no seu arquivo de metadados de explicação enquanto o programa ou ambiente ainda tiver acesso às variáveis definidas durante a criação do modelo. Neste exemplo, o campo name da camada Keras produz o nome do tensor subjacente que você precisa para os metadados de explicação:

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

Para um exemplo completo de trabalho, consulte os notebooks de exemplo.

Como conseguir os nomes de tensores por meio de definições de assinatura

Dado que SignatureDefs e os metadados de explicação identificam entradas e saídas do tensor, é possível usar SignatureDef para preparar seu arquivo de metadados de explicação, desde que ele atenda aos critérios mencionados anteriormente.

Veja o exemplo a seguir 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

O gráfico tem um tensor de entrada denominado x:0 e um tensor de saída denominado dense/Softmax:0. Ambos os tensores também têm nomes significativos: my_numpy_input e probabilities, respectivamente. Para solicitar explicações para probabilities em relação a my_numpy_input, crie um arquivo de metadados de explicação da seguinte maneira:

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

Para inspecionar o SignatureDef do SavedModel, use a CLI SavedModel. Saiba mais sobre como usar a CLI SavedModel.

Como lidar com discrepâncias de entrada e saída

Há alguns casos comuns em que os tensores de entrada e saída nos metadados de explicação não podem ser os mesmos de SignatureDef de exibição, como, por exemplo, se:

  • você inseriu entradas em série;
  • seu gráfico inclui operações de pré-processamento;
  • suas saídas de exibição não são probabilidades, logits ou outros tipos de tensores de ponto flutuante.

Nesses casos, use abordagens diferentes para encontrar os tensores de entrada e saída corretos. A meta geral é encontrar os tensores pertencentes aos valores de atributos que você quer explicar para entradas e tensores relativos a logits (pré-ativação), probabilidades (pós-ativação) ou qualquer outra representação para saídas.

Discrepâncias de entrada

As entradas nos seus metadados de explicação diferem daquelas na sua exibição SignatureDef se você usar uma entrada serializada para alimentar o modelo ou se o gráfico incluir operações de pré-processamento.

Entradas serializadas

Os SavedModels do TensorFlow podem aceitar uma variedade de entradas complexas, incluindo:

  • Mensagens serializadas tf.Example
  • Strings JSON
  • Strings Base64 codificadas (para representar dados de imagem)

Se o modelo aceitar entradas serializadas como essas, usar esses tensores diretamente como entrada para suas explicações não funcionará ou poderá produzir resultados sem sentido. Em vez disso, localize os tensores de entrada subsequentes que estão alimentando as colunas de recurso no seu modelo.

Ao exportar o modelo, é possível adicionar uma operação de análise ao gráfico do TensorFlow chamando uma função de análise na função de entrada de exibição. Encontre funções de análise listadas no módulo tf.io (em inglês). Essas funções de análise geralmente retornam tensores como uma resposta, e eles são as melhores opções para os metadados de explicação.

Por exemplo, é possível usar tf.parse_example() (em inglês) ao exportar seu modelo. Ele recebe uma mensagem serializada tf.Example e gera um dicionário de alimentadores de tensores para apresentar colunas. Use a saída para preencher os metadados de explicação. Se algumas dessas saídas forem tf.SparseTensor (uma tupla nomeada que consiste em três tensores), você precisa dos nomes de índices, valores e tensores dense_shape. Também é preciso preencher os campos correspondentes nos metadados.

O exemplo a seguir mostra como conseguir o nome do tensor de entrada após uma operação de decodificação:

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)

Entradas de pré-processamento

Se o gráfico de modelo contiver algumas operações de pré-processamento, convém conseguir explicações sobre os tensores após a etapa de pré-processamento. Nesse caso, é possível conseguir os nomes desses tensores usando a propriedade name de tf.Tensor e colocando-os nos metadados de explicação:

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)

O nome do tensor decodificado torna-se input_pixels:0.

Discrepâncias de saída

Na maioria dos casos, os resultados em SignatureDef de exibição são probabilidades ou logits.

Se o modelo estiver atribuindo probabilidades, mas você quiser explicar os valores de logit, será preciso encontrar os nomes de tensores de saída apropriados que correspondem aos logits.

Se SignatureDef de exibição tiver saídas que não sejam probabilidades ou logits, consulte a operação de probabilidades no gráfico de treinamento. Este cenário é improvável para os modelos Keras. Se isso acontecer, use o TensorBoard (em inglês), ou outras ferramentas de visualização de gráfico, para ajudar a localizar os nomes de tensores de saída corretos.

Outras considerações para gradientes integrados

O AI Explanations fornece dois métodos de atribuição de recurso: amostra de Shapley e gradientes integrados. Usar o método de gradientes integrados requer que você tenha certeza de que suas entradas são diferenciáveis em relação à saída, portanto, tenha isso em mente ao preparar seus metadados de explicação. Você não precisa garantir isso se usar o método de atribuição de amostra de recurso Shapley. Saiba mais sobre os métodos de atribuição de recursos aceitos no AI Explanations.

Os metadados de explicação separam logicamente os recursos de um modelo de suas entradas. Ao usar gradientes integrados com um tensor de entrada que não é diferenciável em relação ao tensor de saída, você precisa fornecer a versão codificada (e diferenciável) desse recurso também.

Use a abordagem a seguir se você tiver tensores de entrada não diferenciáveis ou se tiver operações não diferenciáveis em seu gráfico:

  • Codifique as entradas não diferenciáveis como entradas diferenciáveis.
  • Defina input_tensor_name ao nome do tensor de entrada não-diferenciável original e defina encoded_tensor_name ao nome de versão codificada e diferenciável.

Explicação do arquivo de metadados com codificação

Por exemplo, considere um modelo que tenha um recurso categórico com um tensor de entrada denominado zip_codes:0. Como os dados de entrada incluem códigos postais como strings, o tensor de entrada zip_codes:0 não é diferenciável. Se o modelo também pré-processar esses dados para conseguir uma representação de codificação one-hot dos códigos postais, o tensor de entrada após o pré-processamento é diferenciável. Para diferenciá-lo do tensor de entrada original, seria possível nomeá-lo zip_codes_embedding:0.

Para usar os dados de ambos os tensores de entrada na sua solicitação de explicações, defina os metadados inputs da seguinte maneira:

  • Defina a chave de recurso de entrada para um nome significativo, como zip_codes.
  • Defina input_tensor_name como o nome do tensor original, zip_codes:0.
  • Defina encoded_tensor_name como o nome do tensor após a codificação, zip_codes_embedding:0.
  • Defina encoding como 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"
}

Como alternativa, defina input_tensor_name ao nome do tensor de entrada codificado e diferenciável e omita o tensor não diferenciável original. A vantagem de fornecer ambos os tensores é que as atribuições podem ser feitas para valores de CEP individuais, em vez da representação de codificação one-hot. Neste exemplo, exclua o tensor original (zip_codes:0) e defina input_tensor_name para zip_codes_embedding:0. Essa abordagem não é recomendada, porque as atribuições de recursos resultantes seriam difíceis de considerar.

Codificação

Para ativar a codificação na sua solicitação de explicações, especifique as configurações de codificação como mostrado no exemplo anterior.

O recurso de codificação ajuda a reverter o processo de dados codificados para dados de entrada para atribuições, o que elimina a necessidade de pós-processamento manual das atribuições retornadas. Atualmente, o AI Explanations é compatível com combined_embedding, em que um recurso de tamanho variável é combinado em uma incorporação. Um exemplo de operação que corresponde a combined_embedding é tf.nn.embedding_lookup_sparse (em inglês).

Para combined_embedding:

O tensor de entrada é codificado em uma matriz 1D. Exemplo:

  • Entrada: ["This", "is", "a", "test"]
  • Codificado: [0.1, 0.2, 0.3, 0.4]

A seguir