如何使用tfa.layers.PoincareNormalize实现Poincaré嵌入? 庞加莱嵌入Tensorflow 插件实现Gensim 实现

问题描述

我正在尝试为我的分层数据实现Facebook(Link)发表的论文中所述的Poincaré嵌入。您可能会发现Poincaré嵌入here的更易理解的解释。

基于该论文,我在Tensorflow插件中找到了Tensorflow herehere以及tfa.layers.PoincareNormalize的一些实现。后者甚至与上述论文有联系,这使我相信这对我来说可能是一个很好的起点。但是,到目前为止,我没有实现tfa.layers.Poincarenormalize的运气,除了我链接的API页面上的一些常规信息外,也找不到任何文档。

有人知道该层应该如何实现以提供本文讨论的双曲空间中的嵌入吗?我的起点是采用标准嵌入层的实现,如下所示(它实际上是类别变量的实体嵌入)?

input = Input(shape=(1,))
model = Embedding(input_dim=my_input_dim,output_dim=embed_dim,name="my_feature")(input)
model = Reshape(target_shape=(embed_dim,))(model)
model = Dense(1)(model)
model = Activation('sigmoid')(model)

仅用tfa.layers.Poincarenormalize替换Embedding层,因为输入不同。我假设可以将其放置在嵌入层之后的某个位置,以便在反向传播步骤中,每次迭代将“值”投影到双曲空间中,但到目前为止也没有运气。

解决方法

庞加莱嵌入

然而,虽然复杂的符号数据集通常表现出潜在的层次结构,但最先进的方法通常会在欧几里得向量空间中学习嵌入,而这并没有考虑到这一特性。为此,我们引入了一种新方法,通过将符号数据嵌入双曲线空间(或更准确地说是 n 维庞加莱球)来学习符号数据的分层表示。

庞加莱嵌入允许您在非欧几里得空间中创建分层嵌入。庞加莱球外侧的向量与中心的向量相比,层次结构较低。

enter image description here

将欧几里得度量张量映射到黎曼度量张量的变换是一个开放的 d 维单位球。

enter image description here

这个非欧空间中两个向量之间的距离计算为

enter image description here

research paper for Poincaré embeddings 写得非常棒,您也会在流行的库中找到一些非常棒的实现。不用说,他们被低估了。

您可以使用的两个实现位于 -

  • tensorflow_addons.PoincareNormalize
  • gensim.models.poincare

Tensorflow 插件实现

根据文档,对于一维张量,tfa.layers.PoincareNormalize 沿轴 = 0 计算以下输出。

          (x * (1 - epsilon)) / ||x||     if ||x|| > 1 - epsilon
output =
           x                              otherwise

对于更高维的张量,它沿维度轴独立地对每个一维切片进行归一化。

这种转换可以简单地应用于 n-dims 的嵌入。让我们为时间序列的每个元素创建一个 5dim 的嵌入。本例中的维度axis=-1,即从欧氏空间映射到非欧氏空间。

from tensorflow.keras import layers,Model,utils
import tensorflow_addons as tfa

X = np.random.random((100,10))
y = np.random.random((100,))


inp = layers.Input((10,))
x = layers.Embedding(500,5)(inp)
x = tfa.layers.PoincareNormalize(axis=-1)(x)  #<-------
x = layers.Flatten()(x)
out = layers.Dense(1)(x)

model = Model(inp,out)
model.compile(optimizer='adam',loss='binary_crossentropy')
utils.plot_model(model,show_shapes=True,show_layer_names=False)

model.fit(X,y,epochs=3)
Epoch 1/3
4/4 [==============================] - 0s 2ms/step - loss: 7.9455
Epoch 2/3
4/4 [==============================] - 0s 2ms/step - loss: 7.5753
Epoch 3/3
4/4 [==============================] - 0s 2ms/step - loss: 7.2429
<tensorflow.python.keras.callbacks.History at 0x7fbb14595310>

Gensim 实现

可以在 Gensim 中找到另一个实现 Poincare 嵌入。它与您在使用 Gensim 的 Word2Vec 时使用的非常相似。

过程将是 -

  1. 训练 Gensim 嵌入(word2vec 或 poincare)
  2. 使用嵌入在 Keras 中初始化嵌入层
  3. 将嵌入层设置为不可训练
  4. 为下游任务训练模型
from gensim.models.poincare import PoincareModel

relations = [('kangaroo','marsupial'),('kangaroo','mammal'),('gib','cat'),('cow',('cat','pet')]

model = PoincareModel(relations,size = 2,negative = 2)  #Change size for higher dims
model.train(epochs=10)

print('kangroo vs marsupial:',model.kv.similarity('kangaroo','marsupial'))
print('gib vs mammal:',model.kv.similarity('gib','mammal'))

print('Embedding for Cat: ',model.kv['cat'])
kangroo vs marsupial: 0.9481239343527523
gib vs mammal: 0.5325816385250299

Embedding for Cat:  [0.22193988 0.0776986 ]

有关训练和保存 Poincare 嵌入的更多详细信息,请参见 here