【问题标题】:Reshaping Layer into Skew-Symmetric Matrix in Keras在 Keras 中将层重塑为斜对称矩阵
【发布时间】:2020-03-11 09:53:12
【问题描述】:

假设我有一个 keras 模型(例如)

layers_NE<-keras_model_sequential()
layers_NE %>% layer_dense(units=Height,
                           activation = "relu",
                           trainable=TRUE,
                           input_shape = 4,
                           bias_initializer = "random_normal") 
          %>% layer_dense(units = (d^2),
                           activation = "linear",
                           trainable = TRUE,
                           bias_initializer = "random_normal")

我想将最后一层重塑为 斜对称矩阵 输出,例如像这样c(a,b,c)-&gt; c(c(a,b),c(b,c)) (这里 c(a,b,c) 是输出的符号我的网络)

到目前为止,我已经尝试过:

layers_NE %>%layer_reshape(input_shape = (d^2),
                           target_shape = c(d,d)
                           )

输出的形状正确,但不对称。我怎样才能做到这一点?

【问题讨论】:

  • 对称矩阵是什么意思?方阵根据其值是对称的,因此它取决于密集层的输出。我猜你无法控制你的网络是对称的。如果您正在处理的问题的目标是找到一个对称矩阵,您可以定义您的损失函数来惩罚非对称输出。
  • 基本上我想使用这些条目在 R^(d(d-1)/2) 矩阵的上三角部分和下三角部分映射一个向量。

标签: r keras deep-learning


【解决方案1】:

更节俭的版本应该完全按照您的意愿行事,而无需额外的神经元。由于k_gather 暴露给 R 的方式,还必须引入两个转置以将k_gather 应用于正确的轴(在 python 中,您可以将axis=1 作为参数传递给tf.gather):

Height <- 10
d <- 7
layers_NE<-keras_model_sequential()
layers_NE %>% layer_dense(units=Height,
                          activation = "relu",
                          trainable=TRUE,
                          input_shape = 4,
                          bias_initializer = "random_normal") 
%>% layer_dense(units = (d * (d+1) / 2),
                activation = "linear",
                trainable = TRUE,
                bias_initializer = "random_normal")
%>% layer_lambda(f=function(x) {
    selector <- array(0, dim=c(d^2))
    ind <- 0 # zero-based indicies needed here
    for (i in 1:d) {
        for (j in i:d) {
            selector[(i-1) * d + j] <- ind
            selector[(j-1) * d + i] <- ind
            ind <- ind + 1
        }
    }
    t_ind <- k_constant(selector, dtype='int32')
    k_permute_dimensions(k_gather(k_permute_dimensions(x, pattern=c(2,1)), t_ind), pattern=c(2,1))
})
%>% layer_reshape(input_shape = (d^2),
                  target_shape = c(d,d))

更新。这是类似的部分,但在 Python 中 - 唯一重要的区别是 tf.gather 可以用 axis=1 调用:

def select_symmetric(x, d):
    selector = np.zeros(d*d, dtype=np.int32)
    ind = 0
    for i in range(d):
        for j in range(i, d):
            selector[i * d + j] = ind
            selector[j * d + i] = ind
            ind += 1
    t_ind = tf.constant(selector, dtype=tf.int32)
    return tf.gather(x, t_ind, axis=1)

Height = 10
d = 7
model = tf.keras.models.Sequential([
    tf.keras.layers.Dense(Height, 'relu', input_shape=(4,)),
    tf.keras.layers.Dense(d * (d + 1) // 2, 'linear'),
    tf.keras.layers.Lambda(select_symmetric, arguments={'d': d}),
    tf.keras.layers.Reshape(target_shape=(d, d)),
])

【讨论】:

  • 由于我对 R 不是很流利,您是否可以使用 python 公式?我很乐意在这种情况下传递要点:)
  • 已更新为 python 版本,但不能 100% 确定我正确理解了您的要求。
【解决方案2】:

我看到了两种方法来实现这一点。更简单的方法是完全按照您最初的做法 - 在某个时候引入一个具有每个示例 (d,d) 的二维平方输出的层,该层不是对称的,然后通过将其添加到自己的转置版本来使其对称。它可能如下所示:

layers_NE<-keras_model_sequential()
layers_NE %>% layer_dense(units=Height,
                           activation = "relu",
                           trainable=TRUE,
                           input_shape = 4,
                           bias_initializer = "random_normal") 
          %>% layer_dense(units = (d^2),
                           activation = "linear",
                           trainable = TRUE,
                           bias_initializer = "random_normal")
          %>%layer_reshape(input_shape = (d^2),
                           target_shape = c(d,d)
                           )
          %>% layer_lambda(f=function(x) {
                             (x + k_permute_dimensions(x, pattern=c(1,3,2))) * 0.5
                           })

添加具有自己转置版本的模型后,结果将是对称的(我猜这里不需要平均)。这个解决方案有一点冗余,因为你必须实际训练 d^2 个单位而不是 d(d+1)/2。除此之外应该没问题。

第二个 - 更节俭的解决方案是实际创建 d(d+1)/2 个单位并将它们放入 (d,d) 形状中,以“复制”非对角元素。我相信您正在寻找的是创建例如使用k_gather 函数的 lambda 层。但唯一的节省是您在其中一层上训练的神经元更少。

【讨论】:

  • 是的,我对第二种方式完全感兴趣。你知道怎么做吗?我会非常满意。
  • 转置对你有用吗?对于收集,您需要达到一个状态,其中您有一个维度的 3d 整数张量 (Batch, D, D),这只是 (1, D, D) 张量在第一维上的批处理时间和第二、第三维中的值的重复尺寸例如[[1, 2], [2, 3]] 用于 d=2,或 [[1,2,3],[2,4,5],[3,5,6]] 用于 d=3 等.(使用 R 的 1 索引符号)。
  • 我可能会坚持转置——除了性能方面,我真的没有看到任何问题(并且只有当该层对你来说是最大的时候)。 Keras + tensorflow 让构建这样简单的东西变得太痛苦了。而 R 也没有让它变得更容易。
  • 我想转置可以完成这项工作,但由于我想制作非常深的网络,所以我一直在考虑节俭的方法
猜你喜欢
  • 1970-01-01
  • 2011-01-16
  • 1970-01-01
  • 2018-09-12
  • 1970-01-01
  • 2019-12-28
  • 2013-05-17
  • 2023-01-25
  • 1970-01-01
相关资源
最近更新 更多