Module jidenn.model_builders.ModelBuilder

Module for building models from config and compiling them.

Expand source code
"""
Module for building models from config and compiling them.
"""

import tensorflow as tf
from typing import Union, Tuple, List, Literal
from dataclasses import dataclass

from jidenn.config import config
from .optimizer_initialization import get_optimizer
from ..evaluation.evaluation_metrics import EffectiveTaggingEfficiency

from .model_initialization import model_getter_lookup


@dataclass
class ModelBuilder:
    """Class for building models from config.
    Provides a facade between pure model initialization and model building with output layer, optimizer, loss, and metrics, with subsequent compilation.

    Args:
        model_name (str): Name of model to build. Options are 'fc', 'highway', 'pfn', 'efn', 'transformer', 'part', 'depart', 'bdt'
        args_model (config.Models): Model config
        input_size (Union[int, Tuple[None, int], Tuple[Tuple[None, int], Tuple[None, None, int]]]): Input size
        num_labels (int): Number of labels, i.e. size of output layer
        args_optimizer (config.Optimizer): Optimizer config
        preprocess (Union[tf.keras.layers.Layer, None, Tuple[tf.keras.layers.Layer, tf.keras.layers.Layer]], optional): Preprocessing layer(s). Defaults to None.

    """
    model_name: Literal['fc', 'highway', 'pfn', 'efn', 'transformer', 'part', 'depart', 'bdt']
    args_model: config.Models
    input_size: Union[int, Tuple[None, int], Tuple[Tuple[None, int], Tuple[None, None, int]]]
    num_labels: int
    args_optimizer: config.Optimizer
    preprocess: Union[tf.keras.layers.Layer, None, Tuple[tf.keras.layers.Layer, tf.keras.layers.Layer]] = None

    @property
    def model(self) -> tf.keras.Model:
        """Builds model from config."""
        model_getter = model_getter_lookup(self.model_name)
        model = model_getter(input_size=self.input_size,
                             output_layer=self.output_layer,
                             args_model=getattr(self.args_model, self.model_name),
                             preprocess=self.preprocess)
        return model

    @property
    def compiled_model(self) -> tf.keras.Model:
        """Compiled Model."""
        model = self.model

        if self.model_name == 'bdt':
            model.compile(weighted_metrics=self.metrics)
            return model

        model.compile(optimizer=self.optimizer,
                      loss=self.loss,
                      weighted_metrics=self.metrics)
        return model

    @property
    def optimizer(self) -> tf.keras.optimizers.Optimizer:
        """Instantiates optimizer from config."""
        return get_optimizer(self.args_optimizer)

    @property
    def metrics(self) -> List[tf.keras.metrics.Metric]:
        """Metrics used in training."""
        metrics = [tf.keras.metrics.CategoricalAccuracy() if self.num_labels >
                   2 else tf.keras.metrics.BinaryAccuracy(),]
        #    tf.keras.metrics.AUC(),
        #    EffectiveTaggingEfficiency()]
        return metrics

    @property
    def loss(self) -> tf.keras.losses.Loss:
        """Loss function used in training."""""
        if self.num_labels > 2:
            return tf.keras.losses.CategoricalCrossentropy(label_smoothing=self.args_optimizer.label_smoothing)
        else:
            return tf.keras.losses.BinaryCrossentropy(label_smoothing=self.args_optimizer.label_smoothing)

    @property
    def output_layer(self) -> tf.keras.layers.Layer:
        """Output layer for model. It is the same for all models."""
        if self.num_labels > 2:
            return tf.keras.layers.Dense(self.num_labels, activation=tf.nn.softmax)
        else:
            return tf.keras.layers.Dense(1, activation=tf.nn.sigmoid)

Classes

class ModelBuilder (model_name: Literal['fc', 'highway', 'pfn', 'efn', 'transformer', 'part', 'depart', 'bdt'], args_model: Models, input_size: Union[int, Tuple[None, int], Tuple[Tuple[None, int], Tuple[None, None, int]]], num_labels: int, args_optimizer: Optimizer, preprocess: Union[keras.engine.base_layer.Layer, ForwardRef(None), Tuple[keras.engine.base_layer.Layer, keras.engine.base_layer.Layer]] = None)

Class for building models from config. Provides a facade between pure model initialization and model building with output layer, optimizer, loss, and metrics, with subsequent compilation.

Args

model_name : str
Name of model to build. Options are 'fc', 'highway', 'pfn', 'efn', 'transformer', 'part', 'depart', 'bdt'
args_model : config.Models
Model config
input_size : Union[int, Tuple[None, int], Tuple[Tuple[None, int], Tuple[None, None, int]]]
Input size
num_labels : int
Number of labels, i.e. size of output layer
args_optimizer : config.Optimizer
Optimizer config
preprocess : Union[tf.keras.layers.Layer, None, Tuple[tf.keras.layers.Layer, tf.keras.layers.Layer]], optional
Preprocessing layer(s). Defaults to None.
Expand source code
@dataclass
class ModelBuilder:
    """Class for building models from config.
    Provides a facade between pure model initialization and model building with output layer, optimizer, loss, and metrics, with subsequent compilation.

    Args:
        model_name (str): Name of model to build. Options are 'fc', 'highway', 'pfn', 'efn', 'transformer', 'part', 'depart', 'bdt'
        args_model (config.Models): Model config
        input_size (Union[int, Tuple[None, int], Tuple[Tuple[None, int], Tuple[None, None, int]]]): Input size
        num_labels (int): Number of labels, i.e. size of output layer
        args_optimizer (config.Optimizer): Optimizer config
        preprocess (Union[tf.keras.layers.Layer, None, Tuple[tf.keras.layers.Layer, tf.keras.layers.Layer]], optional): Preprocessing layer(s). Defaults to None.

    """
    model_name: Literal['fc', 'highway', 'pfn', 'efn', 'transformer', 'part', 'depart', 'bdt']
    args_model: config.Models
    input_size: Union[int, Tuple[None, int], Tuple[Tuple[None, int], Tuple[None, None, int]]]
    num_labels: int
    args_optimizer: config.Optimizer
    preprocess: Union[tf.keras.layers.Layer, None, Tuple[tf.keras.layers.Layer, tf.keras.layers.Layer]] = None

    @property
    def model(self) -> tf.keras.Model:
        """Builds model from config."""
        model_getter = model_getter_lookup(self.model_name)
        model = model_getter(input_size=self.input_size,
                             output_layer=self.output_layer,
                             args_model=getattr(self.args_model, self.model_name),
                             preprocess=self.preprocess)
        return model

    @property
    def compiled_model(self) -> tf.keras.Model:
        """Compiled Model."""
        model = self.model

        if self.model_name == 'bdt':
            model.compile(weighted_metrics=self.metrics)
            return model

        model.compile(optimizer=self.optimizer,
                      loss=self.loss,
                      weighted_metrics=self.metrics)
        return model

    @property
    def optimizer(self) -> tf.keras.optimizers.Optimizer:
        """Instantiates optimizer from config."""
        return get_optimizer(self.args_optimizer)

    @property
    def metrics(self) -> List[tf.keras.metrics.Metric]:
        """Metrics used in training."""
        metrics = [tf.keras.metrics.CategoricalAccuracy() if self.num_labels >
                   2 else tf.keras.metrics.BinaryAccuracy(),]
        #    tf.keras.metrics.AUC(),
        #    EffectiveTaggingEfficiency()]
        return metrics

    @property
    def loss(self) -> tf.keras.losses.Loss:
        """Loss function used in training."""""
        if self.num_labels > 2:
            return tf.keras.losses.CategoricalCrossentropy(label_smoothing=self.args_optimizer.label_smoothing)
        else:
            return tf.keras.losses.BinaryCrossentropy(label_smoothing=self.args_optimizer.label_smoothing)

    @property
    def output_layer(self) -> tf.keras.layers.Layer:
        """Output layer for model. It is the same for all models."""
        if self.num_labels > 2:
            return tf.keras.layers.Dense(self.num_labels, activation=tf.nn.softmax)
        else:
            return tf.keras.layers.Dense(1, activation=tf.nn.sigmoid)

Class variables

var args_modelModels
var args_optimizerOptimizer
var input_size : Union[int, Tuple[None, int], Tuple[Tuple[None, int], Tuple[None, None, int]]]
var model_name : Literal['fc', 'highway', 'pfn', 'efn', 'transformer', 'part', 'depart', 'bdt']
var num_labels : int
var preprocess : Union[keras.engine.base_layer.Layer, ForwardRef(None), Tuple[keras.engine.base_layer.Layer, keras.engine.base_layer.Layer]]

Instance variables

var compiled_model : keras.engine.training.Model

Compiled Model.

Expand source code
@property
def compiled_model(self) -> tf.keras.Model:
    """Compiled Model."""
    model = self.model

    if self.model_name == 'bdt':
        model.compile(weighted_metrics=self.metrics)
        return model

    model.compile(optimizer=self.optimizer,
                  loss=self.loss,
                  weighted_metrics=self.metrics)
    return model
var loss : keras.losses.Loss

Loss function used in training.

Expand source code
@property
def loss(self) -> tf.keras.losses.Loss:
    """Loss function used in training."""""
    if self.num_labels > 2:
        return tf.keras.losses.CategoricalCrossentropy(label_smoothing=self.args_optimizer.label_smoothing)
    else:
        return tf.keras.losses.BinaryCrossentropy(label_smoothing=self.args_optimizer.label_smoothing)
var metrics : List[keras.metrics.base_metric.Metric]

Metrics used in training.

Expand source code
@property
def metrics(self) -> List[tf.keras.metrics.Metric]:
    """Metrics used in training."""
    metrics = [tf.keras.metrics.CategoricalAccuracy() if self.num_labels >
               2 else tf.keras.metrics.BinaryAccuracy(),]
    #    tf.keras.metrics.AUC(),
    #    EffectiveTaggingEfficiency()]
    return metrics
var model : keras.engine.training.Model

Builds model from config.

Expand source code
@property
def model(self) -> tf.keras.Model:
    """Builds model from config."""
    model_getter = model_getter_lookup(self.model_name)
    model = model_getter(input_size=self.input_size,
                         output_layer=self.output_layer,
                         args_model=getattr(self.args_model, self.model_name),
                         preprocess=self.preprocess)
    return model
var optimizer : keras.optimizers.optimizer_experimental.optimizer.Optimizer

Instantiates optimizer from config.

Expand source code
@property
def optimizer(self) -> tf.keras.optimizers.Optimizer:
    """Instantiates optimizer from config."""
    return get_optimizer(self.args_optimizer)
var output_layer : keras.engine.base_layer.Layer

Output layer for model. It is the same for all models.

Expand source code
@property
def output_layer(self) -> tf.keras.layers.Layer:
    """Output layer for model. It is the same for all models."""
    if self.num_labels > 2:
        return tf.keras.layers.Dense(self.num_labels, activation=tf.nn.softmax)
    else:
        return tf.keras.layers.Dense(1, activation=tf.nn.sigmoid)