Конкретная функция Tensorflow 2.0 structd_input_signature возвращаемое значение - PullRequest
2 голосов
/ 08 января 2020

Мне трудно понять типы возврата structured_input_signature при проверке tf.ConcreteFunction.

В документах Google https://www.tensorflow.org/guide/concrete_function#using_a_concrete_function возвращается кортеж. Например,

@tf.function
def power(a,b):
  print('Tracing "power"\n')
  return a**b

float_power = power.get_concrete_function(
  a = tf.TensorSpec(shape=[], dtype=tf.float32),
  b = tf.TensorSpec(shape=[], dtype=tf.float32))

print(float_power.structured_input_signature)
print(float_power.structured_outputs)

печатает

Tracing "power"

((TensorSpec(shape=(), dtype=tf.float32, name='a'), TensorSpec(shape=(), dtype=tf.float32, name='b')), {})
Tensor("Identity:0", shape=(), dtype=float32)

Однако, когда модуль сохранен и загружен, вывод немного отличается:

float_power_mod = tf.Module()
float_power_mod.float_power = float_power
tf.saved_model.save(float_power_mod, './float_power_mod')

mod_4 = tf.saved_model.load('./float_power_mod')
float_power_func = mod_4.signatures['serving_default']
print(float_power_func.structured_input_signature)

печатает

((),
 {'a': TensorSpec(shape=(), dtype=tf.float32, name='a'),
  'b': TensorSpec(shape=(), dtype=tf.float32, name='b')})

Что такое логика c, стоящая за заполнением кортежа против диктата в возвращаемом кортеже structd_input_signature?

1 Ответ

1 голос
/ 26 февраля 2020

Короткий ответ

dict позволяет нам передавать аргументы с ключевым словом в функцию, чтобы мы могли пометить вещественные входные тензоры соответствующими заполнителями, принятыми TF.

result = float_power_func(a=tf.constant(2.), b=tf.constant(3.))

Длинный ответ

Чтобы сохранить модель TF, сначала нам нужно сериализовать тензоры. В экспортированном каталоге вы можете найти файл .pb, который является протобуфом, используемым для сериализации всей вашей модели. Под моделью я подразумеваю коллекцию тензоров и отношения этих тензоров, все они записаны в protobuf. Хотя TF предоставляет функции для сериализации и получения вашего кода, например,

from tensorflow.python.saved_model import nested_structure_coder

coder = nested_structure_coder.StructureCoder()
signature_proto = coder.encode_structure(float_power.structured_input_signature)
print(signature_proto)

печатает

tuple_value {
  values {
    tuple_value {
      values {
        tensor_spec_value {
          name: "a"
          shape {
          }
          dtype: DT_FLOAT
        }
      }
      values {
        tensor_spec_value {
          name: "b"
          shape {
          }
          dtype: DT_FLOAT
        }
      }
    }
  }
  values {
    dict_value {
    }
  }
}

Однако вышеприведенная сериализованная структура не удовлетворяет потребностям. Мы не можем назначить вход для ключа, потому что возвращаемое значение является кортежем.

((TensorSpec(shape=(), dtype=tf.float32, name='a'), TensorSpec(shape=(), dtype=tf.float32, name='b')), {})

Как вы, возможно, поняли, реальный процесс сериализации модели намного сложнее, который включает добавление новых тегов и подписей для обслуживания. , в реплике и кросс-реплика контекста для распространения стратегии, среди многих других. Несмотря на всю сложность, ядро ​​одинаковое, получите подписи и сериализуйте их, код получен здесь

signatures = signature_serialization.canonicalize_signatures(signatures)

signatures перепаковывается и входные тензоры перемещаются внутри dict_value в виде пар ключ-значение

value {
    canonicalized_input_signature {
      tuple_value {
        values {
          tuple_value {
          }
        }
        values {
          dict_value {
            fields {
              key: "a"
              value {
                tensor_spec_value {
                  name: "a"
                  shape {
                  }
                  dtype: DT_FLOAT
                }
              }
            }
            fields {
              key: "b"
              value {
                tensor_spec_value {
                  name: "b"
                  shape {
                  }
                  dtype: DT_FLOAT
                }
              }
            }
          }
        }
      }
    }

и расшифровав его, вы получите

((),
 {'a': TensorSpec(shape=(), dtype=tf.float32, name='a'),
  'b': TensorSpec(shape=(), dtype=tf.float32, name='b')})
...