首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >双曲坐标(Poincaré嵌入)作为神经网络的输出

双曲坐标(Poincaré嵌入)作为神经网络的输出
EN

Data Science用户
提问于 2019-08-03 12:05:21
回答 1查看 239关注 0票数 3

我正在尝试构建一个深度学习预测器,它以一组单词向量(在欧几里德空间中)作为输入,并输出Poincaré嵌入。到目前为止,我没有多少运气,因为模型预测了n维实空间中的任意点,而不是双曲空间。这导致距离,因此损失函数是未定义的。因此,我需要在某种程度上限制模型的输出。我试过几件事。

首先是定义使双曲线距离最小化的损失函数(在Poincaré超盘上):

代码语言:javascript
运行
复制
def distance_loss(u, v):
    max_norm = 1 - K.epsilon()

    sq_u_norm = K.clip(K.sum(K.pow(u, 2), axis=-1), 0, max_norm)
    sq_v_norm = K.clip(K.sum(K.pow(v, 2), axis=-1), 0, max_norm)

    sq_dist = K.sum(K.pow(u - v, 2), axis=-1)
    poincare_dist = tf.acosh(1 + (sq_dist / ((1 - sq_u_norm) * (1 - sq_v_norm))) * 2)
    neg_exp_dist = K.exp(-poincare_dist)
    return -K.log(neg_exp_dist)

这是我从这里这里那里略带沉默地提起的。

然而,这似乎不能很好地发挥作用。下一步是将优化器更改为我从笔记本中获得的关于这个主题的内容,以及一些幻灯片(PDF)。请注意,我在Tensorflow中使用Keras2.1.6,所以我不得不做一些更改。

代码语言:javascript
运行
复制
def get_normalization(p):
    p_norm = K.sum(K.square(p), -1, keepdims=True)
    mp = K.square(1 - p_norm)/4.0
    return mp, K.sqrt(p_norm)


def project(p, p_norm):
    p_norm_clip = K.maximum(p_norm, 1.0)
    p_norm_cond = K.cast(p_norm > 1.0, dtype='float') * K.epsilon()
    return p/p_norm_clip - p_norm_cond

class AdamPoincare(Adam):
    @interfaces.legacy_get_updates_support
    def get_updates(self,loss,params):
        grads = self.get_gradients(loss, params)
        self.updates = [K.update_add(self.iterations, 1)]

        lr = self.lr
        if self.initial_decay > 0:
            lr = lr * (1. / (1. + self.decay * K.cast(self.iterations,
                                                      K.dtype(self.decay))))

        t = K.cast(self.iterations, K.floatx()) + 1
        lr_t = lr * (K.sqrt(1. - K.pow(self.beta_2, t)) /
                     (1. - K.pow(self.beta_1, t)))

        ms = [K.zeros(K.int_shape(p), dtype=K.dtype(p)) for p in params]
        vs = [K.zeros(K.int_shape(p), dtype=K.dtype(p)) for p in params]

        self.weights = [self.iterations] + ms + vs

        for p, g, m, v in zip(params, grads, ms, vs):

            normalization, p_norm = get_normalization(p)
            g = normalization * g

            m_t = (self.beta_1 * m) + (1. - self.beta_1) * g
            v_t = (self.beta_2 * v) + (1. - self.beta_2) * K.square(g)
            p_t = p - lr_t * m_t / (K.sqrt(v_t) + self.epsilon)

            self.updates.append(K.update(m, m_t))
            self.updates.append(K.update(v, v_t))

            new_p = project(p_t, p_norm)

            # Apply constraints.
            if getattr(p, 'constraint', None) is not None:
                new_p = p.constraint(new_p)

            self.updates.append(K.update(p, new_p))
        return self.updates

这也没有做我想做的事情,所以最后我尝试添加一个lambda层,在前传上投射出点(虽然我不知道这是否合适)。目标输出已经是双曲空间中的坐标(因此,在向后通过时,这应该是不操作的)。

代码语言:javascript
运行
复制
def poincare_project(x, axis=-1):
    square_sum = K.tf.reduce_sum(
        K.tf.square(x), axis, keepdims=True)
    x_inv_norm = K.tf.rsqrt(square_sum)
    x_inv_norm = K.tf.minimum((1. - K.epsilon()) * x_inv_norm, 1.)
    outputs = K.tf.multiply(x, x_inv_norm)
    return outputs


x_dense = Dense(int(params["semantic_dense"]))(x_activation)
x_activation = activation(x_dense)
x_output = Dense(params["semantic_dim"], activation="tanh")(x_activation)
x_project = Lambda(poincare_project)(x_output)

但是它仍然会产生垃圾结果(不会最小化距离,或者在后续的评估中导致NaN/Inf )。现在,这些实现中的任何一个都可能存在缺陷,或者整个想法都是无效的。我现在还不能说。具体目标是一种有监督的实体链接形式,其中输入是上下文中的目标词(使用预先训练的快速文本向量,甚至是BERT嵌入),输出是Poincare嵌入中的一个点,表示结构化本体(使用gensim实现进行预训练)。

我确实找到了一个(pdf格式),它试图通过重新参数化模型来做到这一点,但我无法从他们的描述中判断如何实现这一点。不过,它确实清晰地描述了这个问题。

EN

回答 1

Data Science用户

发布于 2022-01-27 21:36:16

在TensorFlow中HyperLib封装实现了Poincaré模型。

这个包定义了点之间的双曲距离:

代码语言:javascript
运行
复制
def dist(self, x, y):
    """ Hyperbolic distance between points 
    Args:
        x, y: Tensors of size B x dim of points in the Poincare ball
    """
    norm = tf.norm(self.mobius_add(-x,y) + self.eps[x.dtype], 
                    axis=1, 
                    keepdims=True
                    )
    return 2./self._sqrt_c * atanh_( self._sqrt_c * norm)

def mobius_add(self, x, y):
    """Element-wise Mobius addition.
  Args:
    x: Tensor of size B x dimension representing hyperbolic points.
    y: Tensor of size B x dimension representing hyperbolic points.
    c: Tensor of size 1 representing the absolute hyperbolic curvature.
  Returns:
    Tensor of shape B x dimension representing the element-wise Mobius addition
    of x and y.
  """
    cx2 = self._c * tf.reduce_sum(x * x, axis=-1, keepdims=True)
    cy2 = self._c * tf.reduce_sum(y * y, axis=-1, keepdims=True)
    cxy = self._c * tf.reduce_sum(x * y, axis=-1, keepdims=True)
    num = (1 + 2 * cxy + cy2) * x + (1 - cx2) * y
    denom = 1 + 2 * cxy + cx2 * cy2
    return self.proj(num / tf.maximum(denom, self.min_norm)) 
```
代码语言:javascript
运行
复制
票数 1
EN
页面原文内容由Data Science提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://datascience.stackexchange.com/questions/56889

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档