【问题标题】:Using a custom R generator function with fit_generator (Keras, R)使用带有 fit_generator (Keras, R) 的自定义 R 生成器函数
【发布时间】:2019-04-20 19:48:23
【问题描述】:

我想训练一个卷积网络来解决图像数据上的多类、多标签问题。由于数据的性质,并且出于我会饶恕你的原因,最好我可以使用自定义 R 生成器函数来提供给 fit_generator 命令,而不是其内置的 image_data_generator 和 @ 987654324@ 命令(我成功地能够开始工作,只是不是针对这个特定问题)。

在这里 (https://www.rdocumentation.org/packages/keras/versions/2.2.0/topics/fit_generator) 它说我可以做到这一点,但没有给出任何示例。所以我尝试了以下方法。这是我正在尝试做的一个非常精简的示例(此代码完全是自包含的):

library(keras)
library(reticulate)      #for py_iterator function

play.network = keras_model_sequential() %>%
  layer_dense(units = 10, activation = "relu", input_shape = c(10)) %>%
  layer_dense(units = 1, activation = "relu")

play.network %>% compile(
  optimizer = "rmsprop",
  loss = "mse"
)

mikes.custom.generator.function = function()     #generates a 2-list of a random 1 x 10 array, and a scalar
{
  new.func = function()
  {
    arr = array(dim = c(1,10))
    arr[,] = sample(1:10, 10, replace = TRUE)/10
    return(list(arr,runif(1)))
  }
}

mikes.custom.iterator = py_iterator(mikes.custom.generator.function())          #creates a python iterator object

generator_next(mikes.custom.iterator)                 #correctly returns a 2-member list consisting of a 1 x 10 array, and a scalar
generator_next(mikes.custom.iterator)[[1]]            #a 1 x 10 array
generator_next(mikes.custom.iterator)[[2]]            #a scalar

#try to fit with "fit_generator":

play.network %>% fit_generator(                       #FREEZES.
  mikes.custom.iterator,
  steps_per_epoch = 1,
  epochs = 1
)

事情在训练时冻结,没有给我错误消息或任何东西。我还针对我的原始问题使用自定义图像数据生成器进行了尝试,结果相同。

请注意,如果我只使用fit 并手动输入训练数据,这个网络训练得很好:

play.network %>% fit(generator_next(mikes.custom.iterator)[[1]],generator_next(mikes.custom.iterator)[[2]], epochs = 1, batch_size = 1)      

#trains just fine

我想我知道问题所在,但我不知道解决方案。如果您向它询问我的自定义迭代器的类,它会给出

class(mikes.custom.iterator)

[1] "python.builtin.iterator"  "rpytools.generator.RGenerator"  "python.builtin.object" 

而如果我使用内置的 image_data_generator 和 flow_images_from_directory 命令构建一个迭代器,它会给出

train_datagen <- image_data_generator(rescale = 1/255)

class(train_datagen)

[1] "keras.preprocessing.image.ImageDataGenerator" "keras_preprocessing.image.ImageDataGenerator" "python.builtin.object"

train_generator <- flow_images_from_directory(
  train_dir,
  train_datagen,
  ....
)

class(train_generator)

[1] "python.builtin.iterator" "keras_preprocessing.image.DirectoryIterator" "keras_preprocessing.image.Iterator"        "tensorflow.python.keras.utils.data_utils.Sequence" "python.builtin.object"

所以我的猜测是train_datagen 和/或train_generator 具有mikes.custom.iterator 没有的属性,并且fit_generator 试图使用基本generator_next 以外的函数调用mikes.custom.iterator(即理论上它应该真正需要的一切)。但是我不知道它们可能是什么,也不知道如何正确构建mikes.custom.iterator,即使在网上搜索了两个小时。

帮助任何人?

【问题讨论】:

    标签: r image keras generator


    【解决方案1】:
    sampling_generator <- function(X_data, Y_data, batch_size) {
      function() {
        rows <- sample(1:nrow(X_data), batch_size, replace = TRUE)
        list(X_data[rows,], Y_data[rows,])
      }
    }
    
    model %>% 
      fit_generator(sampling_generator(X_train, Y_train, batch_size = 128), 
                steps_per_epoch = nrow(X_train) / 128, epochs = 10)
    

    我在 R keras 常见问题解答中找到了这个答案,似乎可行

    https://keras.rstudio.com/articles/faq.html#how-can-i-use-keras-with-datasets-that-dont-fit-in-memory

    【讨论】:

    • 对不起,我直到现在才看到这个答案戴夫,我已经离线一段时间了。非常感谢!
    【解决方案2】:

    在 R 中,您可以使用 &lt;&lt;- 运算符构建迭代器。这对于构建自定义生成器功能非常有帮助;并且兼容 Keras 的fit_generator() 功能。

    一些最小的例子:

    # example data
    data <- data.frame(
      x = runif(80),
      y = runif(80),
      z = runif(80)
    )
    
    # example generator
    data_generator <- function(data, x, y, batch_size) {
    
      # start iterator
      i <- 1
    
      # return an iterator function
      function() {
    
        # reset iterator if already seen all data
        if ((i + batch_size - 1) > nrow(data)) i <<- 1
    
        # iterate current batch's rows
        rows <- c(i:min(i + batch_size - 1, nrow(data)))
    
        # update to next iteration
        i <<- i + batch_size
    
        # create container arrays
        x_array <- array(0, dim = c(length(rows), length(x)))
        y_array <- array(0, dim = c(length(rows), length(y)))
    
        # fill the container
        x_array[1:length(rows), ] <- data[rows, x]
        y_array[1:length(rows), ] <- data[rows, y]
    
        # return the batch
        list(x_array, y_array)
    
      }
    
    }
    
    # set-up a generator
    gen <- data_generator(
      data = data.matrix(data),
      x = 1:2, # it is flexible, you can use the column numbers,
      y = c("y", "z"), # or the column name
      batch_size = 32
    )
    

    从上面的函数中,您可以通过调用生成器来简单地检查结果数组:

    gen()
    

    或者您也可以使用简单的 Keras 模型测试生成器:

    # import keras
    library(keras)
    
    # set up a simple keras model
    model <- keras_model_sequential() %>% 
      layer_dense(32, input_shape = c(2)) %>% 
      layer_dense(2)
    
    model %>% compile(
      optimizer = "rmsprop",
      loss = "mse"
    )
    
    # fit using generator
    model %>% fit_generator(
      generator = gen,
      steps_per_epoch = 100, # will auto-reset after see all sample
      epochs = 10
    )
    

    我不得不承认这个过程有点复杂,需要大量的编程。您应该查看François Chollet 本人的这篇精选博文,或者我个人开发的kerasgenerator 软件包。

    【讨论】:

    • 很好的答案,帮助了我很多!谢谢!
    • 确实是优秀的答案!谢谢你。您知道是否可以使用这种方法在每个 epoch 开始时对数据集进行洗牌?
    猜你喜欢
    • 2018-10-23
    • 2018-12-21
    • 2018-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-12
    • 2019-09-28
    • 1970-01-01
    相关资源
    最近更新 更多