# Construcción de modelos para TF2 [TOC] El proceso de entrenamiento de un modelo de ML utilizando la librería Keras provista por Tensorflow está basado en las clases: - **TFKerasModel** - **TFKerasTrainerConfig** - **TFKerasTrainer** El ejemplo completo de implementación puede encontrarse en [News example](LINK). ## Model **Define la arquitectura del modelo a ser construido.** Todo modelo a ser administrado dentro del API CONABIO ML debe cumplir los siguientes lineamientos: 1. Deben ser subclase de [TFKerasModel](LINK). Lo que implica la obligatoria implementación de la función `create_model` y opcionalmente (si se desea un manejo interno especial) de `create` teniendo cuidado de enlazar a su clase padre. ```python class ModelName(TFKerasModel): @classmethod def create(cls: TFKerasModel.ModelType, model_config: { }, **kwargs) -> TFKerasModel.ModelType: [ OPTIONAL HANDLING ] return cls(model=model_name, model_config=model_config) @classmethod def create_model(cls, model_config): MANDATORY [ . . . ] ``` 2. El modelo puede utilizar libremente todos tipos definidos en [tf.keras](https://www.tensorflow.org/api_docs/python/tf/keras), inclusive los módulos en [TFHub](https://www.tensorflow.org/hub). Sin embargo, la funcion `create_model` debe regresar este modelo. ```python @classmethod def create_model(cls, model_config): [ model building ] return model ``` 3. Para un manejo modular y un reporte adecuado del modelo se aconseja que TODAS las opciones de configuración sean definidas en el parámetro model_config al momento de su creación. ```python model = ModelName({ "model_name": { "layer":{ "embedding_layer": {[ url, type, ... ]}, "dense_layer":{[units, activation, ... ]} } } }) ``` ### Pipeline Para defininir un modelo del tipo TFKerasModel en un pipeline se debe agregar un proceso apuntando a la función de clase `create` del modelo a construir y definir la configuración del modelo. Como se muestra: ```python [ . . . ] .add_process(name="create_NNLM_Classifier", action=NNLM_Classifier.create, args={ "model_config": { [ . . . ] } }) [ . . . ] ``` ### Implementación La implementación completa necesaria para construir un modelo en TFKeras y administrarlo por medio del pipeline se muestra a continuación: **Pipeline** ```python pipeline = Pipeline()\ [. . . ] .add_process(name="create_NNLM_Classifier", action=NNLM_Classifier.create, args={ "model_config": { "NNLM_Classifier": { "layers": { "embedding_layer": { "url": "https://tfhub.dev/google/nnlm-en-dim128-with-normalization/2" }, "dense_layer_0":{ "activation": "relu", "units": 50 }, "dense_layer_1":{ "activation": "sigmoid", "units": 20 }, } } } }) ``` **Model definition** ```python class NNLM_Classifier(TFKerasModel): @classmethod def create_model(cls, model_config): hub_layer = tf_hub.KerasLayer(model_config["embedding_layer"]["url"], input_shape=model_config["input_shape"], dtype=tf.string) model = tf.keras.Sequential() model.add(hub_layer) model.add(tf.keras.layers.Dense( model_config["dense_layer_0"]["units"], activation=model_config["dense_layer_0"]["activation"])) model.add(tf.keras.layers.Dense( model_config["dense_layer_0"]["units"], activation=activation=model_config["dense_layer_0"]["activation"])) return model ``` ## Trainerconfig **Define el ambiente de ejecución, así como las variables de control para el entrenamiento del modelo.** Para crear un ambiente de ejecución se debe utilizar la clase [TFTrainerConfig](LINK) por medio del método `create`, cuya firma es: ```python class TFKerasTrainerConfig(CBTrainerConfig): @classmethod def create(cls: CBTrainerConfig.TrainerConfigType, config: dict = { [ . . . ] }) -> CBTrainerConfig.TrainerConfigType: [ . . . ] ``` Como se muestra: ```python trainer_config = TFKerasTrainerConfig.create(config={ 'callbacks':{}, 'strategy':{} }) ``` Existen 2 variables de control a aplicarse en un modelo a ser entrenado: los reportes de evolución del modelo y la estrategia en la que el modelo se entrenará. ### Reportes de evolución (Callbacks) Las variables de reporte están basadas en los [callbacks de ejecución de tf.Keras](https://www.tensorflow.org/api_docs/python/tf/keras/callbacks). Se definen en el parámetro `callbacks` en el diccionario de configuración `config`. Se deben deben configurar las variables de interés de cada reporte a realizarse. Se muestran los valores por defecto de los callbacks definidos: `checkpoint` Basado en [ModelCheckpoint](https://www.tensorflow.org/api_docs/python/tf/keras/callbacks/ModelCheckpoint). Guarda el modelo de acuerdo a criterios establecidos. ```python CHECKPOINT_CALLBACK: { 'filepath': { 'type': str, 'optional': False }, 'monitor': { 'type': str, 'default': 'val_loss' }, 'verbose': { 'type': int, 'default': 1 }, 'save_best_only': { 'type': bool, 'default': True }, 'save_weights_only': { 'type': bool, 'default': False }, 'mode': { 'type': str, 'default': 'auto' }, 'save_freq': { 'type': str, 'default': "epoch" } } ``` `tensorboard` Basado en [Tersorboard](https://www.tensorflow.org/api_docs/python/tf/keras/callbacks/TensorBoard). Reporta a Tensorboard el estado del modelo. ```python TENSORBOARD_CALLBACK: { 'log_dir': { 'type': str, 'optional': False }, 'histogram_freq': { 'type': int, 'default': 0 }, 'profile_batch': { 'type': int, 'default': 2 }, 'write_graph': { 'type': bool, 'default': True }, 'write_images': { 'type': bool, 'default': False }, 'embeddings_freq': { 'type': int, 'default': 0 }, 'update_freq': { 'type': str, 'default': 'epoch' } } ``` `learningrate_scheduler` Basado en [LearningRateScheduler](https://www.tensorflow.org/api_docs/python/tf/keras/callbacks/LearningRateScheduler). Define la función de control de learning rate. ```python LR_CALLBACK: { 'verbose': { 'type': int, 'default': 1 }, 'scheduler':{ 'type': Callable, 'optional': False } } ``` ### Estrategia de entrenamiento. Administra la manera en la que el entrenamiento se realizará, está basada en las [estrategias de entrenamiento](https://www.tensorflow.org/guide/distributed_training) de TF. Se definen en el parámetro `strategy` en el diccionario de configuración `config`. `mirrored_strategy` La estategia [mirroredstrategy](https://www.tensorflow.org/guide/distributed_training#mirroredstrategy) esta disponible y se debendefinir los dispositivos a utilizar en la estrategia, en caso de `None` todos los dispositivos disponibles serán utilizados. ```python MIRROREDSTRATEGY: { 'devices': { 'type': list, 'default': None } } ``` ### Pipeline Para administrar un modelo en el ambiente de ejecución TFKerasTrainerConfig por medio del pipeline solo es necesario configurar el proceso relacionado apuntando a la función de clase `create`. Como se muestra a continuación: ```python .add_process(name="tfkeras_trainer_cfg", action=TFKerasTrainerConfig.create, args={ "config": { "callbacks": { CHECKPOINT_CALLBACK: { "filepath": os.path.join(results_path, "checkpoints"), "save_best_only": True }, TENSORBOARD_CALLBACK: { "log_dir": os.path.join(results_path, "tb_logs") } }, 'strategy':{ MIRROREDSTRATEGY: { "devices": ["GPU:0"] } } } }) ``` ## Trainer **Utilizando un ambiente de ejecución (TFTrainerConfig) se entrena un modelo (TFKerasModel) con un dataset del tipo [Dataset](LINK).** Para entrenar un modelo del API CONABIO-ML se debe utilizar un entrenador *(trainer)*. Para modelos basados en `tf.keras` que sean subclase de `TFKerasModel` se utiliza la clase [TFKerasTrainer](LINK) que hereda de la clase [Trainer](LINK) por medio de su método de clase `train`, que a continuación se describe: ```python class TFKerasTrainer(Trainer): @classmethod def train(cls, dataset: Dataset.DatasetType, model: TFKerasModel.ModelType, execution_config: TrainerConfig.TrainerConfigType, train_config: dict = {}) -> Model.ModelType: [ . . . ] ``` ### Recursos necesarios Para entrenar un modelo los siguientes recursos son necesarios: 1. **dataset.** Debe ser del tipo [Dataset](LINK) y tener definidos por lo menos los fields `item` y `label`. El entrenamiento se realiza sobre las particiones `train` y se utiliza la particion `validation` (opcionalmente), para control de evolución. Si el dataset *no está particionado** se utiliza completamente como partición `train`. 2. **model.** Debe ser del tipo [TFKerasModel](LINK) con el método `create_model` definido. Véase [TFKerasModel](https://hackmd.io/h9FjIdt-Sz6dW54pWd6T0w#Model). 3. **execution_config**. Debe ser del tipo [TFTrainerConfig](LINK). Véase [TFTrainerConfig](https://hackmd.io/h9FjIdt-Sz6dW54pWd6T0w#Trainerconfig). ### Configuración de entrenamiento Adicionalmente, se tiene que indicar la configuración del experimento a realizar. Esto se realiza por medio del diccionario de configuración `train_config`. ```python 'train_config': { [model_name]: { 'optimizer': { [optimizer_name]: { 'learning_rate': { 'constant': { [learning_rate_config] } } } }, 'loss': { [loss_name]: { [loss_config] } }, 'epochs': int, "metrics": [metrics], 'batch_size': int }, 'dataset_handling': { "item_type": tf.DType, "label_type": tf.DType, "labels_as_categorical": { "labelset": [labels] } } } ``` **model_name**: Indica la configuración del modelo. El nombre debe coincidir con el modelo definido (Véase [definición de modelo](https://hackmd.io/h9FjIdt-Sz6dW54pWd6T0w#Model)). Los parámetros a definir son: 1. **optimizer**: Optimizador a utilizarse. Véase [Optimizadores disponibles](LINK) - **learning_rate**: Learning rate aplicado al optimizador. Véase [Configuración de learning rate](LINK) 2. **loss**: Función de pérdida. Véase [Funciones de pérdida disponibles](LINK) 3. **epochs**. Épocas de entrenamiento. 4. **metrics**: Métricas a calcular. Véase [Métricas disponibles](LINK) 5. **batch_size**. Tamaño de batch de entrenamiento. **dataset_handling**: Indica los parámetros de manejo del dataset a la hora de ser manejado por el entrenador. 1. **item_type**: Tipo de dato esperado para el campo `item` del dataset. 2. **label_type**: Tipo de dato esperado para el campo `label` del dataset. 3. **labels_as_categorical**: Si el campo `label` no es un entero, se debe indicar su tratamiento como tal. - **labelset**: (Opcional) Lista de clases disponibles en el campo `label`. Si se indica `None`, se intentarán deducir los valores posibles de la partición `train`. Se presenta un ejemplo de la implementación de un entrenado TFKerasTrainer: ```python dataset = Dataset.from_[TYPE] model = ModelName({"model_name": { [model_config] } }) trainer_config = TFKerasTrainerConfig.create(config={ [trainer_config] }) train_config = { [ train_config ] } model_trained = TFKerasTrainer.train(dataset, model, trainer_config, train_config) ``` ### Pipeline Para entrenar un modelo utilizando el entrenador TFKerasTrainer por medio del pipeline se debe utilizar el método de clase `train` utilizando los recursos descritos. Como se muestra a continuación: ```python [ . . . ] .add_process(name="tfkeras_trainer_cfg", action=TFKerasTrainerConfig.create, [ . . . ] ) .add_process(name="from_folder_news", action=Dataset.from_folder, [ . . . ] ) .add_process(name="create_NNLM_Classifier", action=NNLM_Classifier.create, [ . . . ] ) .add_process(name="train_NNLM_CLassifier", action=TFKerasTrainer.train, inputs_from_processes=["from_folder_news", "create_NNLM_Classifier", "tfkeras_trainer_cfg"], reportable=True, args={ 'train_config': { 'NNLM_Classifier': { 'optimizer': { 'adam': { 'learning_rate': { 'constant': { 'learning_rate': 0.001, } } } }, 'loss': { 'categorical_crossentropy': {} }, 'epochs': 2, "metrics": ["accuracy"], 'batch_size': 64 }, 'dataset_handling': { "item_type": tf.string, "label_type": tf.int64, "labels_as_categorical": { "labelset": ['talk.politics.mideast', [ . . . ] ] } } } }) [ . . . ] ``` ## Diagrama Esquemáticamente el funcionamiento de este proceso se muestra en la figura siguiente: ![](https://i.imgur.com/iV7kz9D.png)