Keras中层的斜对称矩阵重构

Keras中层的斜对称矩阵重构,r,keras,deep-learning,R,Keras,Deep Learning,假设我有一个keras模型(例如) 输出的形状正确,但不是对称的。我怎样才能做到这一点呢?我认为有两种方法可以做到这一点。更简单的方法是完全按照您最初的方法操作-在某个点上为每个示例(d,d)引入一个具有二维方形输出的层,该层是不对称的,然后将其添加到其自身的转置版本中,使其对称。它可能如下所示: layers_NE<-keras_model_sequential() layers_NE %>% layer_dense(units=Height,

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


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

我认为有两种方法可以做到这一点。更简单的方法是完全按照您最初的方法操作-在某个点上为每个示例(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
                           })
层密度百分比层密度(单位=高度,
激活=“relu”,
可训练的,
输入_shape=4,
偏差\初始值设定项=“随机\正常”)
%>%层密度(单位=(d^2),
激活=“线性”,
可训练的,
偏差\初始值设定项=“随机\正常”)
%>%图层形状(输入形状=(d^2),
目标形状=c(d,d)
)
%>%层λ(f=函数(x){
(x+k_排列_维数(x,模式=c(1,3,2))*0.5
})
在添加带有自己的转置版本的模型后,结果将是对称的(我想这里不需要平均)。这个解决方案中有一点冗余,因为您必须实际训练d^2个单元,而不是d(d+1)/2。除此之外应该没问题


第二个更简单的解决方案是实际创建d(d+1)/2个单元,并以非对角元素“复制”的方式将它们放入(d,d)形状中。我相信您需要的是使用
k_gather
功能创建一个lambda层。但唯一的省钱办法是你在其中一层上训练更少的神经元。

更节俭的版本,它应该在没有额外神经元的情况下做你想做的事情。还必须引入两个换位,以便将
k_-gather
应用于正确的轴,因为
k_-gather
是如何暴露于R的(在python中,您可以将
axis=1
作为参数传递给
tf.gather
):


对称矩阵是什么意思?方形矩阵是对称的,取决于它的值,因此它取决于密集层的输出。我猜你不能控制你的网络是对称的。如果你正在研究的问题的目标是找到一个对称矩阵,你可以定义你的损失函数来惩罚非对称输出。基本上我想用这些条目在R^(d(d-1)/2中映射一个向量,一个矩阵的上三角部分和下三角部分。是的,我对第二种方法非常感兴趣。你知道怎么做吗?我会非常满意的。这东西对你有用吗?对于聚集,您需要达到一种状态,其中有一个维度的三维整数张量(批次,D,D),它只是第一维度上(1,D,D)张量批次时间的重复,第二维度和第三维度中的值,例如[1,2],[2,3]]表示D=2,或[1,2,3],[2,4,5],[3,5]]表示D=3等(使用R的1索引表示法).我可能会坚持转置-我真的没有看到任何问题,除了性能方面的问题(并且只有当该层对您来说是最大的)。Keras+tensorflow让构建这样简单的东西变得太痛苦了。而且R也不能让它变得更简单。我想转置可以完成这项工作,但因为我想建立非常深入的网络,所以节俭的方法基本上就是我一直在考虑的。既然我对R不是很熟练,你能使用python公式吗?我很乐意在这个案例中介绍我的观点:)用python版本更新,尽管我不能100%确定我正确理解了您的请求。
layers_NE %>%layer_reshape(input_shape = (d^2),
                           target_shape = c(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
                           })
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))
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)),
])