在 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 中训练数组数据的内置卷积网络的主要内容,如果未能解决你的问题,请参考以下文章

Keras深度学习实战——卷积神经网络的局限性

R语言实现CNN(卷积神经网络)模型进行回归数据分析

基于CNN卷积神经网络的TensorFlow+Keras深度学习的人脸识别

是否可以使用 Keras 在卷积神经网络的最后一层特征上训练 SVM 或随机森林?

越来越卷,教你使用Python实现卷积神经网络(CNN)

越来越卷,教你使用Python实现卷积神经网络(CNN)