Source code for pykeen.models.unimodal.trans_h

"""An implementation of TransH."""

import itertools
from collections.abc import Mapping
from typing import Any, ClassVar

from class_resolver import HintOrType, OptionalKwargs
from torch.nn import functional, init

from ..nbase import ERModel
from ...constants import DEFAULT_EMBEDDING_HPO_EMBEDDING_DIM_RANGE
from ...nn import TransHInteraction
from ...regularizers import NormLimitRegularizer, OrthogonalityRegularizer, Regularizer
from ...typing import FloatTensor, Hint, Initializer

__all__ = [
    "TransH",
]


[docs] class TransH(ERModel[FloatTensor, tuple[FloatTensor, FloatTensor], FloatTensor]): r"""An implementation of TransH [wang2014]_. This model represents entities as $d$-dimensional vectors, and relations as pair of a normal vector and translation inside the hyperplane. They are stored in an :class:`~pykeen.nn.representation.Embedding`. The representations are then passed to the :class:`~pykeen.nn.modules.TransHInteraction` function to obtain scores. .. seealso:: - OpenKE `implementation of TransH <https://github.com/thunlp/OpenKE/blob/master/models/TransH.py>`_ --- citation: author: Wang year: 2014 link: https://aaai.org/papers/8870-knowledge-graph-embedding-by-translating-on-hyperplanes/ """ #: The default strategy for optimizing the model's hyper-parameters hpo_default: ClassVar[Mapping[str, Any]] = { "embedding_dim": DEFAULT_EMBEDDING_HPO_EMBEDDING_DIM_RANGE, "scoring_fct_norm": {"type": int, "low": 1, "high": 2}, } #: The custom regularizer used by [wang2014]_ for TransH regularizer_default: ClassVar[type[Regularizer]] = NormLimitRegularizer #: The settings used by [wang2014]_ for TransH # The regularization in TransH enforces the defined soft constraints that should computed only for every batch. # Therefore, apply_only_once is always set to True. regularizer_default_kwargs: ClassVar[Mapping[str, Any]] = { "weight": 0.05, "apply_only_once": True, "dim": -1, "p": 2, "power_norm": True, "max_norm": 1.0, } #: The custom regularizer used by [wang2014]_ for TransH relation_regularizer_default: ClassVar[type[Regularizer]] = OrthogonalityRegularizer #: The settings used by [wang2014]_ for TransH relation_regularizer_default_kwargs: ClassVar[Mapping[str, Any]] = { "weight": 0.05, "apply_only_once": True, "epsilon": 1e-5, } def __init__( self, *, embedding_dim: int = 50, scoring_fct_norm: int = 2, power_norm: bool = False, entity_initializer: Hint[Initializer] = init.xavier_normal_, # note: this parameter is not named "entity_regularizer" for compatability with the # regularizer-specific HPO code regularizer: HintOrType[Regularizer] = None, regularizer_kwargs: OptionalKwargs = None, relation_initializer: Hint[Initializer] = init.xavier_normal_, relation_regularizer: HintOrType[Regularizer] = None, relation_regularizer_kwargs: OptionalKwargs = None, **kwargs, ) -> None: r"""Initialize TransH. :param embedding_dim: the entity embedding dimension $d$. Is usually $d \in [50, 300]$. :param scoring_fct_norm: The norm used with :func:`torch.linalg.vector_norm`. Typically is 1 or 2. :param power_norm: Whether to use the p-th power of the $L_p$ norm. It has the advantage of being differentiable around 0, and numerically more stable. :param entity_initializer: The entity initializer function. Defaults to :func:`pykeen.nn.init.xavier_normal_`. :param regularizer: The entity regularizer. Defaults to :attr:`pykeen.models.TransH.regularizer_default`. :param regularizer_kwargs: Keyword-based parameters for the entity regularizer. If `entity_regularizer` is None, the default from :attr:`pykeen.models.TransH.regularizer_default_kwargs` will be used instead :param relation_initializer: The relation initializer function. Defaults to :func:`pykeen.nn.init.xavier_normal_`. :param relation_regularizer: The relation regularizer. Defaults to :attr:`pykeen.models.TransH.relation_regularizer_default`. :param relation_regularizer_kwargs: Keyword-based parameters for the relation regularizer. If `relation_regularizer` is None, the default from :attr:`pykeen.models.TransH.relation_regularizer_default_kwargs` will be used instead :param kwargs: Remaining keyword arguments are passed to :class:`~pykeen.models.ERModel` """ super().__init__( interaction=TransHInteraction, interaction_kwargs={"p": scoring_fct_norm, "power_norm": power_norm}, entity_representations_kwargs={ "shape": embedding_dim, "initializer": entity_initializer, }, relation_representations_kwargs=[ # translation vector in hyperplane { "shape": embedding_dim, "initializer": relation_initializer, }, # normal vector of hyperplane { "shape": embedding_dim, "initializer": relation_initializer, # normalise the normal vectors to unit l2 length "constrainer": functional.normalize, }, ], **kwargs, ) # As described in [wang2014], all entities and relations are used to compute the regularization term # which enforces the defined soft constraints. # thus, we need to use a weight regularizer instead of having an Embedding regularizer, # which only regularizes the weights used in a batch self.append_weight_regularizer( parameter=self.entity_representations[0].parameters(), regularizer=regularizer, regularizer_kwargs=regularizer_kwargs, # note: the following is already the default # default_regularizer=self.regularizer_default, # default_regularizer_kwargs=self.regularizer_default_kwargs, ) self.append_weight_regularizer( parameter=itertools.chain.from_iterable(r.parameters() for r in self.relation_representations), regularizer=relation_regularizer, regularizer_kwargs=relation_regularizer_kwargs, default_regularizer=self.relation_regularizer_default, default_regularizer_kwargs=self.relation_regularizer_default_kwargs, )