我正在尝试编写一个在R中带有可训练权重的自定义Keras层,该层:
- 接收输入向量x,并返回值
exp(A * X*A)
,其中$A$是可训练的对角矩阵。
其中exp是矩阵指数映射。
回答:
请注意,理解您的批次大小所在的位置非常重要,并且一层不能具有基于批次大小的权重大小(除非您使用batch_shape
或batch_input_shape
而不是shape
来定义您的输入——这将迫使您在模型中使用固定的批次大小)。由于批次大小通常用于“个体”和“独立”的样本,因此在操作中使用批次大小和混合样本是不健康的!
尽管如此,我假设这里的X
形状为(batch, dim, dim)
,因此A
的形状将为(dim, dim)
。
为此,您可以构建一个自定义层,如下所示:https://tensorflow.rstudio.com/guide/keras/custom_layers/
其中build
将具有形状为(1, dim, 1)
的kernel
(即A
):
build = function(input_shape) { self$kernel <- self$add_weight( name = 'kernel', shape = list(1,input_shape[[2]], 1), initializer = initializer_random_normal(), #您可以选择不同的初始化器 trainable = TRUE ) },
而call
将使用数学技巧来模拟对角线。
请注意,如果A
是对角矩阵,那么A x X x A
的结果将是B*X
(逐元素),其中B
是:
#假设A在对角线上有元素[a, b, c, ...],B是:[ [aa, ab, ac, ...], [ab, bb, bc, ...], [ac, bc, cc, ...], ...]
因此,我们不会使用对角线,而是使用广播技巧进行逐元素乘法:
call = function(x, mask = NULL) { kernelTransposed <- tf$reshape(self$kernel, shape(1L, 1L, -1L)) #(1, 1, dim) B <- self$kernel * kernelTransposed #(1, dim, dim) tf$math$exp(x * B) },
输出形状保持不变:
compute_output_shape = function(input_shape) { input_shape }