facebookresearch / poincare-embeddings

PyTorch implementation of the NIPS-17 paper "Poincaré Embeddings for Learning Hierarchical Representations"
Other
1.68k stars 231 forks source link

Entailment cones compute the wrong angle? #79

Open FremyCompany opened 3 years ago

FremyCompany commented 3 years ago

Hi,

I could be wrong, but I have the impression the entailment cones energy function is wrong, and optimizes the inverted order relationship between concepts.

If I understood correctly...:

However, after training, I observe the reverse to be true:

I'm either doing something very wrong, or have incorrect assumptions, or the energy function is reversed compared to what it should be according to the entailment cones article, no?

FremyCompany commented 3 years ago

I should specify that I am using the poincare manifold.

ericaltendorf commented 1 year ago

Same question. I haven't fully understood the source code yet, but training with the included mammals data, with

       -model entailment_cones \
       -manifold poincare \

produces embeddings where the norms of more specific mammal entries seem smaller than the norms of more general.

What did you end up doing with this?

marlin-codes commented 1 year ago

I also found a similar problem. And from the understanding of the Cone formula, the angel_at_u should be

    def angle_at_u(self, u, v):
        eps = 1e-6
        norm_u = u.norm(2, dim=-1)
        norm_v = v.norm(2, dim=-1)
        dot_prod = (u * v).sum(dim=-1)
        edist = (u - v).norm(2, dim=-1)  # euclidean distance
        num = (dot_prod * (1 + norm_u ** 2) - norm_u ** 2 * (1 + norm_v ** 2))
        denom = (norm_u * edist * ((1 + norm_v**2 * norm_u**2 - 2 * dot_prod).clamp(min=eps).sqrt())) + eps
        return (num / denom).clamp_(min=-1 + eps, max=1 - eps).acos()

In the author's code, angle_at_u is given by the following and it actually computes the angle_at_v. Please let me know if I am wrong, thanks.

    def angle_at_u(self, u, v):
        norm_u = u.norm(2, dim=-1)
        norm_v = v.norm(2, dim=-1)
        dot_prod = (u * v).sum(dim=-1)
        edist = (u - v).norm(2, dim=-1)  # euclidean distance
        num = (dot_prod * (1 + norm_v ** 2) - norm_v ** 2 * (1 + norm_u ** 2))
        denom = (norm_v * edist * (1 + norm_v**2 * norm_u**2 - 2 * dot_prod).sqrt())
        return (num / denom).clamp_(min=-1 + self.eps, max=1 - self.eps).acos()