tensorflow - 如何使用 tfa.layers.PoincareNormalize 实现 Poincaré 嵌入?
问题描述
我正在尝试实现 Poincaré 嵌入,如 Facebook(链接)在我的分层数据的一篇论文中所讨论的那样。您可以在此处找到有关 Poincaré 嵌入的更易于理解的解释。
根据这篇论文,我在这里和这里找到了 Tensorflow 的一些实现,以及Tensorflow Addons 中的 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 替换嵌入层是行不通的。我假设它可以放置在嵌入层之后的某个位置,以便对于反向传播步骤,“值”在每次迭代时都被投影到双曲空间中,但到目前为止也没有运气。
解决方案
庞加莱嵌入
然而,虽然复杂的符号数据集通常表现出潜在的层次结构,但最先进的方法通常在欧几里得向量空间中学习嵌入,而这并没有考虑到这个属性。为此,我们引入了一种新方法,通过将符号数据嵌入到双曲空间(或更准确地说,嵌入到 n 维庞加莱球中)来学习符号数据的层次表示。
Poincaré 嵌入允许您在非欧几里得空间中创建分层嵌入。与中心的向量相比,庞加莱球外侧的向量层次结构较低。
将欧几里得度量张量映射到黎曼度量张量的转换是一个开放的 d 维单位球。
此非欧式空间中 2 个向量之间的距离计算为
Poincaré 嵌入的研究论文写得非常好,你也会在流行的库中找到一些非常棒的实现。不用说,他们被低估了。
您可以使用的两个实现位于 -
tensorflow_addons.PoincareNormalize
gensim.models.poincare
TensorFlow 插件实现
根据文档,对于一维张量,tfa.layers.PoincareNormalize
沿轴 = 0 计算以下输出。
(x * (1 - epsilon)) / ||x|| if ||x|| > 1 - epsilon
output =
x otherwise
对于更高维度的张量,它沿维度轴独立地对每个一维切片进行归一化。
这种转换可以简单地应用于 n-dims 的嵌入。让我们为时间序列的每个元素创建一个 5 暗淡的嵌入。在这种情况下,维度轴=-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 实现
另一个实现 Poincare 嵌入可以在 Gensim 中找到。它与使用 Gensim 的 Word2Vec 时使用的非常相似。
该过程将是 -
- 训练 Gensim 嵌入(word2vec 或 poincare)
- 使用嵌入初始化 Keras 中的嵌入层
- 将嵌入层设置为不可训练
- 为下游任务训练模型
from gensim.models.poincare import PoincareModel
relations = [('kangaroo', 'marsupial'), ('kangaroo', 'mammal'), ('gib', 'cat'), ('cow', 'mammal'), ('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 嵌入的更多详细信息。
推荐阅读
- wordpress - 在 WordPress 网站中添加新页面时,它会重定向到主页
- javascript - 是否有可能知道用户何时通过勇敢的奖励进行了 BAT 捐赠?
- sql - 在 ms 访问中获取错误的计数结果
- javascript - 如何使用 Javascript 查询父记录
- url - 将验证添加到 DocuSign 的 Salesforce URL 按钮
- spring - 异常:Spring Boot 中的 multipart/form-data 请求失败
- php - 如何在 Elementor 中编写自定义帖子查询,以获取由多个动态分类过滤的自定义帖子类型的帖子?
- django - 在 react-redux 中从字符串转换为 uniqueidentifier 时转换失败
- javascript - 赛普拉斯测试输入字段值是否有多行
- docker - Gss 失败 - Docker 中的 Dotnet 5 和 Windows Auth