A função tf.feature_column.input_layer() no TensorFlow reordena automaticamante as colunas de recursos fornecidas, com base em seus atributos name, em vez de respeitar a ordem na lista de entrada. Essa ordenação interna pode resultar em tensores de saída com disposição inesperada das características.
Exemplo de código demonstrando o comportamento:
import tensorflow as tf
# Definição das colunas categóricas
coluna_x = tf.feature_column.categorical_column_with_vocabulary_list(
key='recurso_x', vocabulary_list=['val1', 'val2', 'val3'])
coluna_y = tf.feature_column.categorical_column_with_vocabulary_list(
key='recurso_y', vocabulary_list=['tipo_a', 'tipo_b', 'tipo_c'])
coluna_z = tf.feature_column.categorical_column_with_vocabulary_list(
key='recurso_z', vocabulary_list=['estado_1', 'estado_0', 'estado_2'])
coluna_x_y = tf.feature_column.crossed_column(
keys=[coluna_x, coluna_y], hash_bucket_size=5)
# Criação das colunas de indicador
indicador_x = tf.feature_column.indicator_column(coluna_x)
indicador_y = tf.feature_column.indicator_column(coluna_y)
indicador_z = tf.feature_column.indicator_column(coluna_z)
indicador_x_y = tf.feature_column.indicator_column(coluna_x_y)
# Dados de exemplo (tensor de recursos fictício)
dados_features = {'recurso_x': tf.constant(['val1', 'val2']),
'recurso_y': tf.constant(['tipo_c', 'tipo_a']),
'recurso_z': tf.constant(['estado_0', 'estado_2'])}
# Saída individual para cada coluna
print(tf.feature_column.input_layer(dados_features, [indicador_x]))
print(tf.feature_column.input_layer(dados_features, [indicador_y]))
print(tf.feature_column.input_layer(dados_features, [indicador_z]))
print(tf.feature_column.input_layer(dados_features, [indicador_x_y]))
# Saída combinada - a ordem pode não ser a esperada
saida_combinada = tf.feature_column.input_layer(
dados_features, [indicador_x, indicador_y, indicador_z, indicador_x_y])
print(saida_combinada)
Ao combinar múltiplas colunas, o tensor resultante não segue a sequência indicador_x, indicador_y, indicador_z, indicador_x_y. Em vez disso, as colunas são organizadas alfabeticamente com base em seus nomes gerados, como 'recurso_x_indicator', 'recurso_x_X_recurso_y_indicator', 'recurso_y_indicator', 'recurso_z_indicator'. Essa ordenação é realizada internamente na função _internal_input_layer do TensorFlow.
Trecho relevante do código-fonte onde ocorre a ordenação:
# No método _get_logits dentro de _internal_input_layer
builder = _LazyBuilder(features)
output_tensors = []
ordered_columns = []
for column in sorted(feature_columns, key=lambda x: x.name):
ordered_columns.append(column)
# ... processamento adicional para cada coluna
Para verificar a ordenação resultante, podemos inspecionar os nomes das colunas após a classificação:
lista_colunas = [indicador_x, indicador_y, indicador_z, indicador_x_y]
colunas_ordenadas = sorted(lista_colunas, key=lambda c: c.name)
nomes_ordenados = [c.name for c in colunas_ordenadas]
print(nomes_ordenados)
# Saída típica: ['recurso_x_indicator', 'recurso_x_X_recurso_y_indicator', 'recurso_y_indicator', 'recurso_z_indicator']
Portanto, o tensor concatenado na saída de input_layer corresponderá à ordem dos nomes classificados, não à ordem original da lista fornecida. Isso pode ser relevante para fluxos de trabalho que dependem de uma estrutura específica de características no modelo.