在 R keras 中训练数组数据的内置卷积网络
Posted
技术标签:
【中文标题】在 R keras 中训练数组数据的内置卷积网络【英文标题】:Training built-in convnets on array data in R keras 【发布时间】:2021-12-06 10:10:51 【问题描述】:我正在尝试在 R keras 中根据我自己的数据训练一个内置的 convnet 架构。我的数据存储在 R 中的一个数组中,而不是存储在单个图像文件中,这似乎是标准的。
我认为我的主要问题是我不知道如何正确预处理我的特征数据。
这是一个简单的数据和模型定义示例(有效):
#simulate data resembling images, but in array format:
p <- 32 # note: minium height/width for resnet
toy_x <- array(runif(p*p*100*3), c(100, p, p, 3))
toy_y <- runif(100)
#define and compile model
input <- layer_input(shape = c(p, p, 3))
N1 <- application_resnet50(weights = NULL,
input_tensor = input,
include_top = FALSE)
output_layer_instance <- layer_dense(units = 1, activation = 'sigmoid')
output <- input %>% N1() %>% output_layer_instance()
model <- keras_model(input, output)
model %>% compile(loss = "binary_crossentropy", optimizer = "adam")
但是当我尝试使用以下代码拟合模型时,出现错误:
model %>% fit(toy_x, toy_y, epochs = 1)
我不确定该错误是否提供了很多信息,但这里是:
Error in py_call_impl(callable, dots$args, dots$keywords) :
ValueError: in user code:
/root/.local/share/r-miniconda/envs/r-reticulate/lib/python3.6/site-packages/tensorflow/python/keras/engine/training.py:571 train_function *
outputs = self.distribute_strategy.run(
/root/.local/share/r-miniconda/envs/r-reticulate/lib/python3.6/site-packages/tensorflow/python/distribute/distribute_lib.py:951 run **
return self._extended.call_for_each_replica(fn, args=args, kwargs=kwargs)
/root/.local/share/r-miniconda/envs/r-reticulate/lib/python3.6/site-packages/tensorflow/python/distribute/distribute_lib.py:2290 call_for_each_replica
return self._call_for_each_replica(fn, args, kwargs)
/root/.local/share/r-miniconda/envs/r-reticulate/lib/python3.6/site-packages/tensorflow/python/distribute/distribute_lib.py:2649 _call_for_each_replica
return fn(*args, **kwargs)
/root/.local/share/r-miniconda/envs/r-reticulate/lib/python3.6/site-packages/tensorflow/python/keras/engine/training.py:533 train_step
我尝试了一些替代解决方案。如上所述,我认为这个问题可能是由于缺乏对特征数据的预处理。我曾尝试使用内置的预处理功能,但没有运气 - 运行以下命令时出现与上述相同的错误:
toy_x_preproc <- imagenet_preprocess_input(toy_x)
model %>% fit(toy_x_preproc, toy_y, epochs = 1)
我还测试了代码在不使用内置示例 resnet 的情况下运行,方法是将其替换为简单的 convnet(仍然使用功能 API):
#define & compile model
model2_input <- layer_input(shape = c(p, p, 3))
model2_output <- model2_input %>%
layer_conv_2d(filters = 25, kernel_size = c(2,2), activation = "relu",
input_shape = c(p,p,1)) %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_flatten() %>%
layer_dense(units = 1, activation = 'sigmoid')
model2 <- keras_model(model2_input, model2_output)
model2 %>% compile(
loss = "binary_crossentropy",
optimizer = "adam")
#train on "raw" toy_x -- works
model2 %>% fit(toy_x, toy_y, epochs = 1)
这运行没有错误。如果我重新运行整个块但适合toy_x_preproc
,它也可以工作。
感谢您的阅读 - 如果有任何帮助,我将不胜感激。
【问题讨论】:
【参考方案1】:您的模型输出形状为shape(NULL,1,1,1)
,您的训练标签形状为shape(NULL)
。如果您正在执行自定义顶部,您可能希望在模型中包含降维层,例如 layer_flatten()
、layer_global_max_pooling_3d()
或其他降低输出排名的东西。您可能还想调用 k_expand_dims()
或在训练数据标签中手动包含一个值为 1 的维度,以将其从 shape(batch_size)
获取到 shape(batch_size, 1)
。
旁注:如果调用堆栈很大,默认打印的错误会被截断。如果您致电reticulate::py_last_error()
,您仍然可以获得完整的错误消息,这通常会提供必要的线索。例如,在遇到fit
调用中的错误后,如果您立即运行purrr::walk(reticulate::py_last_error(), cat)
,您会看到一个很长的打印输出,其中包括最后一行:
ValueError: `logits` and `labels` must have the same shape, received ((None, 1, 1, 1) vs (None, 1)).
【讨论】:
谢谢!你是完全正确的,问题是我标签的尺寸。还要感谢有关错误消息的提示 - 很长一段时间以来,我一直对无信息错误感到沮丧,所以这也非常有用!以上是关于在 R keras 中训练数组数据的内置卷积网络的主要内容,如果未能解决你的问题,请参考以下文章
基于CNN卷积神经网络的TensorFlow+Keras深度学习的人脸识别