rstudio / keras3

R Interface to Keras
https://keras3.posit.co/
Other
831 stars 282 forks source link

Memory leak when writing custom callback #1054

Open mr-francois opened 4 years ago

mr-francois commented 4 years ago

The code in this example allocates an increasing amount of memory after every epoch.

library(magrittr)
library(keras)
model <- keras::keras_model_sequential()
model %>% 
  layer_dense(units = 4, activation = 'relu', input_shape = c(5)) %>% 
  layer_dense(units = 3, activation = 'softmax')

model %>% compile(
  loss = 'categorical_crossentropy',
  optimizer = keras::optimizer_rmsprop(),
  metrics = c('accuracy')
)

dummy_generator <- function(batch_size){
  function(){
    x <- sample(0:4, batch_size ,replace = TRUE)
    x <- keras::to_categorical(x, num_classes = 5)
    y <- sample(0:2, batch_size ,replace = TRUE)
    y <- keras::to_categorical(y, num_classes = 3)
    list(x,y)
  }
}

gen <- dummy_generator(batch_size=7)  
gen_val <- dummy_generator(batch_size=7)  

cb <- R6::R6Class("cb",
                  inherit = keras::KerasCallback,

                  public = list(

                    on_epoch_end = function(epoch, logs) {

                      input <- array(1:5, dim = c(1,5))
                      for (i in 1:50){
                        pred <- self$model$predict(input)
                      }

                    }
                  ))

custom_cb <- cb$new()

model %>% keras::fit_generator(
  generator = gen,
  validation_data = gen_val,
  validation_steps = 2,
  steps_per_epoch = 15,
  epochs = 150,
  callbacks = list(custom_cb)
)
turgut090 commented 4 years ago

Does the problem persist if you use reticulate::PyClass() instead of R6?

mr-francois commented 4 years ago

Using reticulate::PyClass() does not seem to change anything

library(magrittr)
library(keras)
model <- keras::keras_model_sequential()
model %>% 
  layer_dense(units = 4, activation = 'relu', input_shape = c(5)) %>% 
  layer_dense(units = 3, activation = 'softmax')

model %>% compile(
  loss = 'categorical_crossentropy',
  optimizer = keras::optimizer_rmsprop(),
  metrics = c('accuracy')
)

dummy_generator <- function(batch_size){
  function(){
    x <- sample(0:4, batch_size ,replace = TRUE)
    x <- keras::to_categorical(x, num_classes = 5)
    y <- sample(0:2, batch_size ,replace = TRUE)
    y <- keras::to_categorical(y, num_classes = 3)
    list(x,y)
  }
}

gen <- dummy_generator(batch_size=7)  
gen_val <- dummy_generator(batch_size=7)  

cb <- reticulate::PyClass("cb",
                          #inherit = keras::KerasCallback,
                          inherit = tensorflow::tf$keras$callbacks$Callback,

                          list(
                            on_epoch_end = function(self, epoch, logs) {

                              input <- array(1:5, dim = c(1,5))
                              for (i in 1:50){
                                pred <- self$model$predict(input)
                              }

                            }
                          ))

custom_cb <- cb()

model %>% keras::fit_generator(
  generator = gen,
  validation_data = gen_val,
  validation_steps = 2,
  steps_per_epoch = 15,
  epochs = 150,
  callbacks = list(custom_cb)
)