Source code for trieste.models.utils

# Copyright 2021 The Trieste Contributors
#
# 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
#
#     http://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.

"""
This module contains auxiliary objects and functions that are used by multiple model types.
"""

from __future__ import annotations

from typing import Any, Optional

import gpflow
import tensorflow as tf
from gpflow.utilities.traversal import _merge_leaf_components, leaf_components

from .. import logging
from ..data import Dataset
from ..utils.misc import get_variables
from .interfaces import ProbabilisticModel, TrainableProbabilisticModel


[docs] def write_summary_data_based_metrics( dataset: Dataset, model: ProbabilisticModel, prefix: str = "", ) -> None: """ Logging utility for writing TensorBoard summary of various metrics for model diagnostics. :param dataset: The dataset to use for computing the metrics. All available data in the dataset will be used. :param model: The model to produce metrics for. :param prefix: The prefix to add to "accuracy" category of model summaries. """ name = prefix + "accuracy" predict = model.predict(dataset.query_points) # basics logging.histogram(f"{name}/predict_mean", predict[0]) logging.scalar(f"{name}/predict_mean__mean", tf.reduce_mean(predict[0])) logging.histogram(f"{name}/predict_variance", predict[1]) logging.scalar(f"{name}/predict_variance__mean", tf.reduce_mean(predict[1])) logging.histogram(f"{name}/observations", dataset.observations) logging.scalar(f"{name}/observations_mean", tf.reduce_mean(dataset.observations)) logging.scalar(f"{name}/observations_variance", tf.math.reduce_variance(dataset.observations)) # accuracy metrics diffs = tf.cast(dataset.observations, predict[0].dtype) - predict[0] z_residuals = diffs / tf.math.sqrt(predict[1]) logging.histogram(f"{name}/absolute_error", tf.math.abs(diffs)) logging.histogram(f"{name}/z_residuals", z_residuals) logging.scalar(f"{name}/root_mean_square_error", tf.math.sqrt(tf.reduce_mean(diffs**2))) logging.scalar(f"{name}/mean_absolute_error", tf.reduce_mean(tf.math.abs(diffs))) logging.scalar(f"{name}/z_residuals_std", tf.math.reduce_std(z_residuals)) # variance metrics variance_error = predict[1] - diffs**2 logging.histogram(f"{name}/variance_error", variance_error) logging.scalar( f"{name}/root_mean_variance_error", tf.math.sqrt(tf.reduce_mean(variance_error**2)), )
[docs] def write_summary_kernel_parameters(kernel: gpflow.kernels.Kernel, prefix: str = "") -> None: """ Logging utility for writing TensorBoard summary of kernel parameters. Provides useful diagnostics for models with a GPflow kernel. Only trainable parameters are logged. :param kernel: The kernel to use for computing the metrics. :param prefix: The prefix to add to "kernel" category of model summaries. """ components = _merge_leaf_components(leaf_components(kernel)) for k, v in components.items(): if v.trainable: if tf.rank(v) == 0: logging.scalar(f"{prefix}kernel.{k}", v) elif tf.rank(v) == 1: for i, vi in enumerate(v): logging.scalar(f"{prefix}kernel.{k}[{i}]", vi)
[docs] def write_summary_likelihood_parameters( likelihood: gpflow.likelihoods.Likelihood, prefix: str = "" ) -> None: """ Logging utility for writing TensorBoard summary of likelihood parameters. Provides useful diagnostics for models with a GPflow likelihood. Only trainable parameters are logged. :param likelihood: The likelihood to use for computing the metrics. :param prefix: The prefix to add to "likelihood" category of model summaries. """ likelihood_components = _merge_leaf_components(leaf_components(likelihood)) for k, v in likelihood_components.items(): if v.trainable: logging.scalar(f"{prefix}likelihood.{k}", v)
[docs] def get_module_with_variables(model: ProbabilisticModel, *dependencies: Any) -> tf.Module: """ Return a fresh module with a model's variables attached, which can then be extended with methods and saved using tf.saved_model. :param model: Model to extract variables from. :param dependencies: Dependent objects whose variables should also be included. """ module = tf.Module() module.saved_variables = get_variables(model) for dependency in dependencies: module.saved_variables += get_variables(dependency) return module
[docs] def optimize_model_and_save_result(model: TrainableProbabilisticModel, dataset: Dataset) -> None: """ Optimize the model objective and save the (optimizer-specific) optimization result in the model object. To access it, use ``get_last_optimization_result``. :param dataset: The data with which to train the model. """ setattr(model, "_last_optimization_result", model.optimize(dataset))
[docs] def get_last_optimization_result(model: TrainableProbabilisticModel) -> Optional[Any]: """ The last saved (optimizer-specific) optimization result. """ return getattr(model, "_last_optimization_result")