Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/es-419/guide/estimator.ipynb
25115 views
Kernel: Python 3
#@title Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.

Estimadores

Advertencia: Los estimadores no se recomiendan para código nuevo. Los estimadores ejecutan el código de estilo v1.Session que es más difícil de escribir correctamente y puede tener un comportamiento inesperado; particularmente, cuando se combina con código TF 2. Los estimadores están incluidos dentro de nuestras garantías de compatibilidad, pero no se les harán correcciones a menos que se trate de vulnerabilidades de seguridad. Para más detalles, consulte la Guía de migración.

En este documento se presenta al tf.estimator, una API de TensorFlow de alto nivel. Los estimadores encapsulan las siguientes acciones:

  • Entrenamiento

  • Evaluación

  • Predicción

  • Exportaciones para servicios

TensorFlow implementa muchos estimadores preconfigurados. Todavía se admiten los estimadores personalizados, pero principalmente como una medida de compatibilidad retrospectiva. Los estimadores no se deberían usar para código nuevo. Las clases de todos los estimadores, los preconfigurados y los personalizados, están basadas en la clase tf.estimator.Estimator.

Para acceder a un ejemplo rápido, consulte los tutoriales sobre estimadores. Para tener una idea general del diseño de la API, consulte la documentación técnica.

Preparación

!pip install -U tensorflow_datasets
import tempfile import os import tensorflow as tf import tensorflow_datasets as tfds

Ventajas

De un modo similar a lo que sucede con tf.keras.Model, un estimator es una abstracción a nivel del modelo. El tf.estimator proporciona algunas capacidades que actualmente aún se encuentran en desarrollo para tf.keras. Estas son:

  • Entrenamiento basado en servidores de parámetros

  • Integración TFX completa

Capacidades de estimadores

Los estimadores aportan los siguientes beneficios:

  • Se pueden ejecutar modelos basados en estimadores en un huésped local o en un entorno de múltiples servidores distribuidos sin cambiar el modelo. Además, los modelos basados en estimadores se pueden ejecutar en más de una CPU, GPU o TPU sin recodificar un modelo.

  • Los estimadores ofrecen un bucle de entrenamiento distribuido seguro que controla cómo y cuándo se hace lo siguiente:

    • Cargar los datos

    • Manejar las excepciones

    • Crear archivos de puntos de verificación y recuperar si se producen fallas

    • Guardar resúmenes para TensorBoard

Al escribir una aplicación con estimadores, hay que hacer una separación entre la canalización de entrada de datos y el modelo. Con esta separación se simplifican los experimentos con distintas bases de datos.

Uso de estimadores preconfigurados

Los estimadores preconfigurados permiten trabajar a un nivel conceptual mucho más alto que las API TensorFlow de base. Ya no hace falta preocuparse por crear el grafo computacional ni las sesiones, ya que los estimadores son los que se ocupan de hacer el "trabajo pesado". Además, los estimadores preconfigurados permiten experimentar con diferentes arquitecturas de modelos con solo hacer unos cambios mínimos en el código. tf.estimator.DNNClassifier, por ejemplo, es una clase de estimador preconfigurado que entrena a los modelos de clasificación basándose en redes neuronales prealimentadas densas.

Un programa TensorFlow que depende de un estimador preconfigurado, normalmente, está compuesto por los siguientes cuatro pasos:

1. Escritura de funciones de entrada

Por ejemplo, se puede crear una función para importar el conjunto de entrenamiento y otra para importar el conjunto de prueba. Los estimadores esperan que sus entradas estén formateadas como pares de objetos:

  • Un diccionario en el que las claves son nombres de características y los valores son Tensores (o SparseTensors) que contienen los datos de características correspondientes.

  • Un Tensor que contiene una o más etiquetas

El input_fn debe devolver una tf.data.Dataset que produzca pares en ese formato.

Por ejemplo, el siguiente código construye una tf.data.Dataset del archivo train.csv del conjunto de datos del Titanic:

def train_input_fn(): titanic_file = tf.keras.utils.get_file("train.csv", "https://storage.googleapis.com/tf-datasets/titanic/train.csv") titanic = tf.data.experimental.make_csv_dataset( titanic_file, batch_size=32, label_name="survived") titanic_batches = ( titanic.cache().repeat().shuffle(500) .prefetch(tf.data.AUTOTUNE)) return titanic_batches

El input_fn se ejecuta en un tf.Graph y también puede devolver directamente un par (features_dics, labels) que contenga tensores de grafos, pero es propenso a errores excepto en casos simples como los de la devolución de constantes.

2. Definición de las columnas de características

Cada tf.feature_column identifica el nombre de una columna, su tipo y cualquier entrada en procesamiento previo.

Por ejemplo, el siguiente fragmento crea tres columnas de características.

  • En la primera se usa la característica age directamente como una entrada de punto flotante.

  • En la segunda se usa la característica class como entrada categórica.

  • En la tercera se usa el embark_town como entrada categórica, pero también se usa hashing trick para evitar tener que enumerar las opciones y para establecer la cantidad de opciones.

Para más información, consulte el tutorial sobre columnas de características.

age = tf.feature_column.numeric_column('age') cls = tf.feature_column.categorical_column_with_vocabulary_list('class', ['First', 'Second', 'Third']) embark = tf.feature_column.categorical_column_with_hash_bucket('embark_town', 32)

3. Instanciación del estimador preconfigurado relevante.

Por ejemplo, la siguiente es una muestra de instanciación de un estimador preconfigurado denominado LinearClassifier:

model_dir = tempfile.mkdtemp() model = tf.estimator.LinearClassifier( model_dir=model_dir, feature_columns=[embark, cls, age], n_classes=2 )

Para más información, consulte el tutorial sobre clasificadores lineales.

4. Llamado al entrenamiento, la evaluación o el método de inferencia.

Todos los estimadores ofrecen métodos train, evaluate y predict.

model = model.train(input_fn=train_input_fn, steps=100)
result = model.evaluate(train_input_fn, steps=10) for key, value in result.items(): print(key, ":", value)
for pred in model.predict(train_input_fn): for key, value in pred.items(): print(key, ":", value) break

Beneficios de los estimadores perconfigurados

Los estimadores preconfigurados codifican mejores prácticas, brindando los siguientes beneficios:

  • Mejores prácticas para determinar dónde deberían funcionar las diferentes partes del grafo computacional, mediante la implementación de estrategias en una sola máquina o en un grupo de máquinas (cluster).

  • Mejores prácticas para la escritura de eventos (resumen) y resúmenes universalmente útiles.

Si no usa estimadores preconfigurados, deberá implementar las características anteriores usted mismo.

Estimadores personalizados

El corazón de cada estimador, ya sea preconfigurado o personalizado, es su función modelo, model_fn, que es el método que construye los gráficos para entrenamiento, evaluación y predicción. Cuando se usan estimadores preconfigurados, alguien más ya ha implementado la función modelo. Cuando se depende de un estimador personalizado, a la función modelo debe escribirla usted mismo.

Nota: Una model_fn aún funcionará en el modo de grafo estilo 1.x. Significa que no hay ejecución eager ni dependencias de control automático. Debería planificar entonces la migración fuera del tf.estimator con la model_fn personalizada. Las API alternativas son tf.keras y tf.distribute. Si todavía hace falta un Estimator para alguna parte de su entrenamiento, puede usar el conversor tf.keras.estimator.model_to_estimator para crear un Estimator a partir de un keras.Model.

Creación de un estimador a partir de un modelo Keras

Se pueden convertir modelos Keras existentes en estimadores con tf.keras.estimator.model_to_estimator. Esto resulta útil cuando desea modernizar el código del modelo, pero la canalización de entrenamiento aún requiere estimadores.

Instancie un modelo Keras MobileNet V2 y compile el modelo con el optimizador, la pérdida y las métricas para entrenar con lo siguiente:

keras_mobilenet_v2 = tf.keras.applications.MobileNetV2( input_shape=(160, 160, 3), include_top=False) keras_mobilenet_v2.trainable = False estimator_model = tf.keras.Sequential([ keras_mobilenet_v2, tf.keras.layers.GlobalAveragePooling2D(), tf.keras.layers.Dense(1) ]) # Compile the model estimator_model.compile( optimizer='adam', loss=tf.keras.losses.BinaryCrossentropy(from_logits=True), metrics=['accuracy'])

Cree un Estimator a partir de un modelo Keras compilado. El estado inicial del modelo Keras se preserva en el Estimator creado:

est_mobilenet_v2 = tf.keras.estimator.model_to_estimator(keras_model=estimator_model)

Trate al Estimator derivado del mismo modo que a cualquier otro Estimator.

IMG_SIZE = 160 # All images will be resized to 160x160 def preprocess(image, label): image = tf.cast(image, tf.float32) image = (image/127.5) - 1 image = tf.image.resize(image, (IMG_SIZE, IMG_SIZE)) return image, label
def train_input_fn(batch_size): data = tfds.load('cats_vs_dogs', as_supervised=True) train_data = data['train'] train_data = train_data.map(preprocess).shuffle(500).batch(batch_size) return train_data

Para entrenar, llame a la función entrenamiento del estimador:

est_mobilenet_v2.train(input_fn=lambda: train_input_fn(32), steps=50)

Del mismo modo, para evaluar, llame a la función evaluar del estimador:

est_mobilenet_v2.evaluate(input_fn=lambda: train_input_fn(32), steps=10)

Para más detalles, consulte la documentación sobre tf.keras.estimator.model_to_estimator.

Estimadores para guardar puntos de verificación (checkpoints) basados en objetos

Por defecto, los estimadores guardan puntos de verificación con nombres variables más que con el grafo de objetos descripto en la Guía de puntos de verificación. tf.train.Checkpoint leerá puntos de verificación basados en nombres, pero los nombres variables pueden cambiar cuando se muevan partes de un modelo fuera del model_fn del estimador. Para guardar compatibilidad hacia adelante, los puntos de verificación basados en objetos facilitan el entrenamiento de un modelo dentro de un estimador y después lo usan fuera.

import tensorflow.compat.v1 as tf_compat
def toy_dataset(): inputs = tf.range(10.)[:, None] labels = inputs * 5. + tf.range(5.)[None, :] return tf.data.Dataset.from_tensor_slices( dict(x=inputs, y=labels)).repeat().batch(2)
class Net(tf.keras.Model): """A simple linear model.""" def __init__(self): super(Net, self).__init__() self.l1 = tf.keras.layers.Dense(5) def call(self, x): return self.l1(x)
def model_fn(features, labels, mode): net = Net() opt = tf.keras.optimizers.Adam(0.1) ckpt = tf.train.Checkpoint(step=tf_compat.train.get_global_step(), optimizer=opt, net=net) with tf.GradientTape() as tape: output = net(features['x']) loss = tf.reduce_mean(tf.abs(output - features['y'])) variables = net.trainable_variables gradients = tape.gradient(loss, variables) return tf.estimator.EstimatorSpec( mode, loss=loss, train_op=tf.group(opt.apply_gradients(zip(gradients, variables)), ckpt.step.assign_add(1)), # Tell the Estimator to save "ckpt" in an object-based format. scaffold=tf_compat.train.Scaffold(saver=ckpt)) tf.keras.backend.clear_session() est = tf.estimator.Estimator(model_fn, './tf_estimator_example/') est.train(toy_dataset, steps=10)

tf.train.Checkpoint, entonces, puede cargar los puntos de verificación del estimador desde su model_dir.

opt = tf.keras.optimizers.Adam(0.1) net = Net() ckpt = tf.train.Checkpoint( step=tf.Variable(1, dtype=tf.int64), optimizer=opt, net=net) ckpt.restore(tf.train.latest_checkpoint('./tf_estimator_example/')) ckpt.step.numpy() # From est.train(..., steps=10)

SavedModels de estimadores

Los estimadores exportan SavedModels con tf.Estimator.export_saved_model.

input_column = tf.feature_column.numeric_column("x") estimator = tf.estimator.LinearClassifier(feature_columns=[input_column]) def input_fn(): return tf.data.Dataset.from_tensor_slices( ({"x": [1., 2., 3., 4.]}, [1, 1, 0, 0])).repeat(200).shuffle(64).batch(16) estimator.train(input_fn)

Para guardar un Estimator debe crear un serving_input_receiver. Esta función construye una parte de un tf.Graph que analiza los datos crudos recibidos por el SavedModel.

El módulo tf.estimator.export contiene funciones para ayudar a construir estos receivers.

El siguiente código construye un receptor, basado en las feature_columns, que acepta búferes de protocolo tf.Example serializados, y que, por lo general, se usan con tf-serving.

tmpdir = tempfile.mkdtemp() serving_input_fn = tf.estimator.export.build_parsing_serving_input_receiver_fn( tf.feature_column.make_parse_example_spec([input_column])) estimator_base_path = os.path.join(tmpdir, 'from_estimator') estimator_path = estimator.export_saved_model(estimator_base_path, serving_input_fn)

También puede cargar y ejecutar ese modelo desde Python:

imported = tf.saved_model.load(estimator_path) def predict(x): example = tf.train.Example() example.features.feature["x"].float_list.value.extend([x]) return imported.signatures["predict"]( examples=tf.constant([example.SerializeToString()]))
print(predict(1.5)) print(predict(3.5))

tf.estimator.export.build_raw_serving_input_receiver_fn le permite crear funciones de entrada que toman tensores en bruto más que tf.train.Example.

Uso de tf.distribute.Strategy con estimador (compatibilidad limitada)

tf.estimator es una API de TensorFlow de entrenamiento distribuido que originalmente era compatible con el método de servidores con parámetros asincrónicos. Ahora, tf.estimator admite tf.distribute.Strategy. Si usted usa tf.estimator, puede cambiar a entrenamiento distribuido haciendo unas pocas modificaciones en el código. De este modo, los usuarios de estimadores, ahora pueden hacer entrenamientos distribuidos sincrónicos en múltiples GPU con múltiples nodos trabajador, así como también, pueden usar TPU. No obstante, esta compatibilidad en estimadores es limitada. Para más detalles, consulte la sección Qué es compatible ahora que se encuentra más adelante.

Si usa tf.distribute.Strategy con estimador, será levemente diferente al caso de Keras. En vez de usar strategy.scope, ahora pase el objeto estrategia al RunConfig para el estimador.

Para más información, puede consultar la guía sobre entrenamiento distribuido.

A continuación, un fragmento de código en el que se muestra esto con un estimador preconfigurado, LinearRegressor y MirroredStrategy:

mirrored_strategy = tf.distribute.MirroredStrategy() config = tf.estimator.RunConfig( train_distribute=mirrored_strategy, eval_distribute=mirrored_strategy) regressor = tf.estimator.LinearRegressor( feature_columns=[tf.feature_column.numeric_column('feats')], optimizer='SGD', config=config)

En este caso se usa un estimador preconfigurado, pero el mismo código también funciona con un estimador personalizado.train_distribute determina cómo se distribuirá el entrenamiento y eval_distribute determina cómo se distribuirá la evaluación. Esta es otra diferencia de Keras, donde se usa la misma estrategia tanto para el entrenamiento como para la evaluación.

Ahora puede entrenar y evaluar este estimador con una función de entrada:

def input_fn(): dataset = tf.data.Dataset.from_tensors(({"feats":[1.]}, [1.])) return dataset.repeat(1000).batch(10) regressor.train(input_fn=input_fn, steps=10) regressor.evaluate(input_fn=input_fn, steps=10)

Otra diferencia para destacar en este caso entre el modelo estimador y Keras es el manejo de la entrada. En Keras, cada lote de conjunto de datos se divide automáticamente en múltiples réplicas. En Estimator, sin embargo, no se realiza una división automática de lotes, ni un particionamiento horizontal automático de los datos a través de diferentes nodos trabajador (workers). Usted tiene el control total de cómo desea que los datos se distribuyan entre los nodos trabajador y dispositivos, debe proporcionar una input_fn para especificar cómo se distribuirán sus datos.

A su input_fn se la llama una vez por cada nodo trabajador, dando, por tanto, un conjunto de datos por nodo. Entonces, con un lote de ese conjunto de datos se alimenta a una réplica en ese nodo trabajador, de modo tal que se consumen N lotes para N réplicas en 1 nodo. En otras palabras, el conjunto de datos devuelto por la input_fn deberá proporcionar lotes de tamaño PER_REPLICA_BATCH_SIZE. Y el tamaño del lote global para un paso se puede obtener como PER_REPLICA_BATCH_SIZE * strategy.num_replicas_in_sync.

Cuando realice un entrenamiento con múltiples nodos trabajador, deberá o bien separar los datos en los nodos trabajador o aleatorizar con semilla aleatoria en cada uno. Puede consultar un ejemplo de cómo hacerlo en el tutorial Entrenamiento multitrabajador con estimador.

De un modo similar, también se pueden usar las estrategias multitrabajador y servidor parámetro. El código se mantiene igual, pero hay que usar tf.estimator.train_and_evaluate y establecer variables de entorno TF_CONFIG para cada binario que se esté ejecutando en su grupo (cluster).

Qué es compatible ahora

Hay una compatibilidad limitada para el entrenamiento con Estimador usando todas las estrategias excepto TPUStrategy. El entrenamiento y la evaluación básicos deberían funcionar, pero hay unas cuantas características avanzadas como v1.train.Scaffold que no funcionan. También puede haber errores (bugs) en esta integración y no hay planes para mejorar activamente esta compatibilidad (el foco está puesto en la compatibilidad con el ciclo de entrenamiento personalizado y con Keras). En caso de ser posible, sin embargo, sería preferible usar tf.distribute con esas API.

API de entrenamientoMirroredStrategyTPUStrategyMultiWorkerMirroredStrategyCentralStorageStrategyParameterServerStrategy
API de estimadorCompatibilidad limitadaNo compatibleCompatibilidad limitadaCompatibilidad limitadaCompatibilidad limitada

Ejemplos y tutoriales

A continuación, compartimos algunos ejemplos completos en los que se muestra cómo usar las diferentes estrategias con estimadores:

  1. En el tutorial Entrenamiento multitrabajador con estimador se muestra cómo se puede realizar el entrenamiento con múltiples nodos trabajador usando MultiWorkerMirroredStrategy en el conjunto de datos MNIST.

  2. Un ejemplo, de principio a fin, del funcionamiento de entrenamiento multitrabajador con estrategias de distribuición en tensorflow/ecosystem con plantillas Kubernetes. Este ejemplo comienza con un modelo Keras y lo convierte en un estimador con la API tf.keras.estimator.model_to_estimator.

  3. El modelo ResNet50 oficial, que se puede entrenar ya sea con MirroredStrategy o con MultiWorkerMirroredStrategy.