在Keras(RStudio接口)中实现自定义层

在Keras(RStudio接口)中实现自定义层,r,tensorflow,keras,R,Tensorflow,Keras,我在使用R的Keras接口实现单词嵌入模型中的自定义层时遇到了一些问题。下面是我的代码的玩具版本,它将重现错误: rm(list = ls()) library(keras) library(tensorflow) # ================================ # inputs # ================================ input_target <- layer_input(shape = 1) input_context <-

我在使用R的Keras接口实现单词嵌入模型中的自定义层时遇到了一些问题。下面是我的代码的玩具版本,它将重现错误:

rm(list = ls())
library(keras)
library(tensorflow)

# ================================
# inputs
# ================================

input_target <- layer_input(shape = 1)
input_context <- layer_input(shape = 1)

# embedding matrix for mean vectors
embedding_mu <- layer_embedding(
  input_dim = 1000, 
  output_dim = 50, 
  embeddings_initializer = initializer_random_uniform(),
  input_length = 1, 
  name = "embedding_mu"
)

# embedding matrix for sigma vectors
embedding_sigma <- layer_embedding(
  input_dim = 1000, 
  output_dim = 50, 
  embeddings_initializer = initializer_random_uniform(),
  input_length = 1, 
  name = "embedding_sigma"
)

# select target mu from the mu embedding matrix
target_vector_mu <- input_target %>%
  embedding_mu() %>% 
  layer_flatten()

# select context mu from the mu embedding matrix
context_vector_mu <- input_context %>%
  embedding_mu() %>%
  layer_flatten()

# select target sigma from the sigma embedding matrix
target_vector_sigma <- input_target %>%
  embedding_sigma() %>% 
  layer_flatten()

# select context sigma from the sigma embedding matrix
context_vector_sigma <- input_context %>%
  embedding_sigma() %>%
  layer_flatten()

# ================================
# custom layer
# ================================
KLenergy <- function(args){ # args <- list(mu_w, mu_c, sigma_w, sigma_c)
  comp1 <- tf$reduce_sum(tf$div(args[[4]], args[[3]]), axis = integer(1))
  comp2 <- tf$reduce_sum(tf$div(tf$square(tf$subtract(args[[1]], args[[2]])), args[[3]]), axis = integer(1))
  comp3 <- tf$subtract(tf$log(tf$reduce_prod(args[[4]], axis = integer(1))), tf$log(tf$reduce_prod(args[[3]], axis = integer(1))))
  energy <- 0.5*(comp1 + comp2 - comp3)
  return(energy)
}

kl_energy <- layer_lambda(list(target_vector_mu, 
                                 context_vector_mu, 
                                 target_vector_sigma, 
                                 context_vector_sigma),
                            KLenergy)


output <- layer_dense(kl_energy, units = 1, activation = "relu")

# ================================
# model compile
# ================================
model <- keras_model(list(input_target, input_context), output)
model %>% compile(
  loss = "binary_crossentropy", 
  optimizer = "Adagrad")

summary(model)
我希望kl_能量层没有形状,但是我没有

kl_energy
Tensor("lambda_5/Mul:0", shape=(?,), dtype=float32)
在定义自定义层时是否缺少参数?我尝试设置keepdims=TRUE:

KLenergy <- function(args){ # args <- list(mu_w, mu_c, sigma_w, sigma_c)
  comp1 <- tf$reduce_sum(tf$div(args[[4]], args[[3]]), axis = as.integer(1), keepdims = TRUE)
  comp2 <- tf$reduce_sum(tf$div(tf$square(tf$subtract(args[[1]], args[[2]])), args[[3]]), axis = as.integer(1), keepdims = TRUE)
  comp3 <- tf$subtract(tf$log(tf$reduce_prod(args[[4]], axis = as.integer(1), keepdims = TRUE)), tf$log(tf$reduce_prod(args[[3]], axis = as.integer(1), keepdims = TRUE)))
  energy <- 0.5*(comp1 + comp2 - comp3)
  return(energy)
}
任何指导都将不胜感激

丹尼尔的工作代码学分如下:

# ================================
# inputs
# ================================

input_target <- layer_input(shape = 1)
input_context <- layer_input(shape = 1)

# embedding matrix for mean vectors
embedding_mu <- layer_embedding(
  input_dim = 1000, 
  output_dim = 50, 
  embeddings_initializer = initializer_random_uniform(),
  input_length = 1, 
  name = "embedding_mu"
)

# embedding matrix for sigma vectors
embedding_sigma <- layer_embedding(
  input_dim = 1000, 
  output_dim = 50, 
  embeddings_initializer = initializer_random_uniform(),
  input_length = 1, 
  name = "embedding_sigma"
)

# select target mu from the mu embedding matrix
target_vector_mu <- input_target %>%
  embedding_mu() %>% 
  layer_flatten()

# select context mu from the mu embedding matrix
context_vector_mu <- input_context %>%
  embedding_mu() %>%
  layer_flatten()

# select target sigma from the sigma embedding matrix
target_vector_sigma <- input_target %>%
  embedding_sigma() %>% 
  layer_flatten()

# select context sigma from the sigma embedding matrix
context_vector_sigma <- input_context %>%
  embedding_sigma() %>%
  layer_flatten()

# ================================
# custom layer
# ================================
KLenergy <- function(args){ # args <- list(mu_w, mu_c, sigma_w, sigma_c)
  comp1 <- tf$reduce_sum(tf$div(args[[4]], args[[3]]), axis = as.integer(1), keepdims = TRUE)
  comp2 <- tf$reduce_sum(tf$div(tf$square(tf$subtract(args[[1]], args[[2]])), args[[3]]), axis = as.integer(1), keepdims = TRUE)
  comp3 <- tf$subtract(tf$log(tf$reduce_prod(args[[4]], axis = as.integer(1), keepdims = TRUE)), tf$log(tf$reduce_prod(args[[3]], axis = as.integer(1), keepdims = TRUE)))
  energy <- 0.5*(comp1 + comp2 - comp3)
  return(energy)
}

kl_energy <- layer_lambda(list(target_vector_mu, 
                               context_vector_mu, 
                               target_vector_sigma, 
                               context_vector_sigma),
                          KLenergy)


output <- layer_dense(kl_energy, units = 1, activation = "relu")

# ================================
# model compile
# ================================
model <- keras_model(list(input_target, input_context), output)
model %>% compile(
   loss = "binary_crossentropy", 
  optimizer = "Adagrad")

summary(model)
不要忘记使用keepdims=TRUE返回None,1


如前所述,您应该使用as.integer1或R表示法中的1L。

integer1有什么特殊功能吗?你能试一下轴=1吗?-那么,R中的轴是用first=0还是first=1计算的?根据你的代码,似乎1是第一个轴?如果您尝试axis=2或axis=integer2,它会带来错误吗?如果不指定integer,您会得到一个类型错误,这是特定于通过RStudio使用Keras的错误。它将轴=1中的1读取为浮点,但它需要和整数。至于使用axis=integer2,我仍然得到一个形状为None的kl_能量层,真的吗?但是整数1不是在创建一个带零的向量吗?你在其他地方使用的都是数字,为什么那个地方会出错?如果这是一个数组,那么你应该创建一个包含1的数组。你完全正确,愚蠢的错误,它应该是as.integer1。我仍然得到相同的错误,虽然形状仍然没有,并且执行的输出给出了相同的错误消息。就是这样!谢谢你捕捉到丹尼尔,只需要一双额外的眼睛。请注意,你可以将as.integer1写成1L
kl_energy
Tensor("lambda_7/Mul:0", shape=(1, ?), dtype=float32)
# ================================
# inputs
# ================================

input_target <- layer_input(shape = 1)
input_context <- layer_input(shape = 1)

# embedding matrix for mean vectors
embedding_mu <- layer_embedding(
  input_dim = 1000, 
  output_dim = 50, 
  embeddings_initializer = initializer_random_uniform(),
  input_length = 1, 
  name = "embedding_mu"
)

# embedding matrix for sigma vectors
embedding_sigma <- layer_embedding(
  input_dim = 1000, 
  output_dim = 50, 
  embeddings_initializer = initializer_random_uniform(),
  input_length = 1, 
  name = "embedding_sigma"
)

# select target mu from the mu embedding matrix
target_vector_mu <- input_target %>%
  embedding_mu() %>% 
  layer_flatten()

# select context mu from the mu embedding matrix
context_vector_mu <- input_context %>%
  embedding_mu() %>%
  layer_flatten()

# select target sigma from the sigma embedding matrix
target_vector_sigma <- input_target %>%
  embedding_sigma() %>% 
  layer_flatten()

# select context sigma from the sigma embedding matrix
context_vector_sigma <- input_context %>%
  embedding_sigma() %>%
  layer_flatten()

# ================================
# custom layer
# ================================
KLenergy <- function(args){ # args <- list(mu_w, mu_c, sigma_w, sigma_c)
  comp1 <- tf$reduce_sum(tf$div(args[[4]], args[[3]]), axis = as.integer(1), keepdims = TRUE)
  comp2 <- tf$reduce_sum(tf$div(tf$square(tf$subtract(args[[1]], args[[2]])), args[[3]]), axis = as.integer(1), keepdims = TRUE)
  comp3 <- tf$subtract(tf$log(tf$reduce_prod(args[[4]], axis = as.integer(1), keepdims = TRUE)), tf$log(tf$reduce_prod(args[[3]], axis = as.integer(1), keepdims = TRUE)))
  energy <- 0.5*(comp1 + comp2 - comp3)
  return(energy)
}

kl_energy <- layer_lambda(list(target_vector_mu, 
                               context_vector_mu, 
                               target_vector_sigma, 
                               context_vector_sigma),
                          KLenergy)


output <- layer_dense(kl_energy, units = 1, activation = "relu")

# ================================
# model compile
# ================================
model <- keras_model(list(input_target, input_context), output)
model %>% compile(
   loss = "binary_crossentropy", 
  optimizer = "Adagrad")

summary(model)