Source code for graphdot.microkernel.kronecker_delta

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import numpy as np
from graphdot.codegen.cpptool import cpptype
from graphdot.util.pretty_tuple import pretty_tuple
from ._base import MicroKernel


[docs]def KroneckerDelta(h, h_bounds=(1e-3, 1)): r"""Creates a Kronecker delta microkernel that returns either 1 or h depending on whether two features compare equal, i.e. :math:`k_\delta(i, j) = \begin{cases} 1, i = j \\ h, otherwise \end{cases}`. Parameters ---------- h: float in (0, 1) The value of the microkernel when two features do not compare equal. h_bounds: tuple or "fixed" If tuple, contains the lower and upper bounds that `h` is allowed to vary during hyperparameter optimization. If "fixed", the hyperparameter will not be optimized during training. """ @cpptype(h=np.float32) class KroneckerDeltaKernel(MicroKernel): @property def name(self): return 'KroneckerDelta' def __init__(self, h, h_bounds): self.h = float(h) self.h_bounds = h_bounds self._assert_bounds('h', h_bounds) def __call__(self, i, j, jac=False): if jac is True: return ( 1.0 if i == j else self.h, np.array([0.0 if i == j else 1.0]) ) else: return 1.0 if i == j else self.h def __repr__(self): return f'{self.name}({self.h})' def gen_expr(self, x, y, theta_scope=''): f = f'({x} == {y} ? 1.0f : {theta_scope}h)' j = [f'({x} == {y} ? 0.0f : 1.0f)'] return f, j @property def theta(self): return pretty_tuple( self.name, ['h'] )(self.h) @theta.setter def theta(self, seq): self.h = seq[0] @property def bounds(self): return (self.h_bounds,) @property def minmax(self): return (self.h, 1) return KroneckerDeltaKernel(h, h_bounds)