Обратите внимание, что очень важно, чтобы вы понимали, где находится ваш размер пакета, и что слой НЕ МОЖЕТ иметь веса с размерами, основанными на размере пакета (если вы не определите свои входные данные с помощью batch_shape
или batch_input_shape
вместо shape
- это заставит вас использовать фиксированный размер партии в модели). Поскольку размер партии обычно для «отдельных» и «независимых» выборок, нецелесообразно использовать размер партии в операциях и смешивании образцов!
Тем не менее, я предполагаю, что X
здесь имеет форму (batch, dim, dim)
, и что A
будет иметь форму (dim, dim)
, следовательно.
Для этого вы создаете пользовательский слой, например здесь: https://tensorflow.rstudio.com/guide/keras/custom_layers/
Где build
будет иметь kernel
(A
) с формой (1, dim, 1)
-
build = function(input_shape) {
self$kernel <- self$add_weight(
name = 'kernel',
shape = list(1,input_shape[[2]], 1),
initializer = initializer_random_normal(), #you may choose different initializers
trainable = TRUE
)
},
И call будет использовать математический трюк для имитации диагонали.
Обратите внимание, что если диагональ A
, то результат A x X x A
будет B*X
(поэлементно), где B
:
#supposing A has the elements [a, b, c, ...] in the diagonals,
B is:
[ [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
}