r - 在 Keras 中实现自定义层(RStudio 界面)
问题描述
我在使用 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)
执行“输出”层后出现以下错误:
Error in py_call_impl(callable, dots$args, dots$keywords) :
ValueError: Input 0 is incompatible with layer dense_2: expected min_ndim=2, found ndim=1
Detailed traceback:
File "/anaconda3/envs/r-tensorflow/lib/python3.6/site-packages/keras/engine/base_layer.py", line 414, in __call__
self.assert_input_compatibility(inputs)
File "/anaconda3/envs/r-tensorflow/lib/python3.6/site-packages/keras/engine/base_layer.py", line 327, in assert_input_compatibility
str(K.ndim(x)))
我希望 kl_energy 层具有形状(无,1),但我得到(无,)。
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)
}
但这给了我一个形状为 (1, None) 的 kl_energy 层,这不是我想要的。最终,该层的输出应该与原始 word2vec 模型(使用 layer_dot -请参见此处)中的形状相同,但使用此自定义层:
kl_energy
Tensor("lambda_7/Mul:0", shape=(1, ?), dtype=float32)
任何指导将不胜感激。
工作代码(以下归功于 Daniel):
# ================================
# 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
to return (None,1)
。
如前所述,您应该使用as.integer(1)
, 或1L
R 表示法。
推荐阅读
- google-cloud-platform - 使用 Ansible 使用客户管理的加密密钥启动 Google Compute 实例
- django - 如何在选择的 Django 表单中呈现选项?
- java - Java 8 Optional 不能应用于接口
- spring - 如何在spring webflux中使用webclient在rest api中下载pdf文件
- java - JavaFX 应用程序使用多线程滞后
- machine-learning - Logistic 回归的搜索/预测时间复杂度是多少?
- c++ - 这不应该给出越界警告吗?
- android - FastAdapter 和 ConstraintLayout 的滚动问题:跳过 211 帧
- java - 编程语言(尤其是飞镖)中的死代码是什么意思?
- java - 线程“主”java.lang.RuntimeException 中的异常:无法启动 Selenium 会话:未找到