t-kalinowski / deep-learning-with-R-2nd-edition-code

Code from the book "Deep Learning with R, 2nd Edition"
https://blogs.rstudio.com/ai/posts/2022-05-31-deep-learning-with-r-2e/
41 stars 18 forks source link

Error in py_call_impl(callable, call_args$unnamed, call_args$named) #19

Closed yuriy-babenko closed 1 month ago

yuriy-babenko commented 1 month ago

Looking at newswire example https://github.com/t-kalinowski/deep-learning-with-R-2nd-edition-code/blame/5d666f93d52446511a8a8e4eb739eba1c0ffd199/ch04.R#L221

Running code:

install.packages("remotes")
remotes::install_github("rstudio/tensorflow")
reticulate::install_python()
install.packages("keras3") 
keras3::install_keras(envname = "r-reticulate")
library(keras3)

reuters <- dataset_reuters(num_words = 10000)
c(c(train_data, train_labels), c(test_data, test_labels)) %<-% reuters

# vectorize data 
vectorize_sequences <- function(sequences, dimension = 10000) {
  results <- matrix(0, nrow = length(sequences), ncol = dimension)
  for (i in seq_along(sequences))
       results[i, sequences[[i]]] <- 1
  results
}

x_train <- vectorize_sequences(train_data)
x_test <- vectorize_sequences(test_data)

# vectorize labels 
to_one_hot <- function(labels, dimension = 46) {
  results <- matrix(0, nrow = length(labels), ncol = dimension)
  labels <- labels + 1
  for(i in seq_along(labels)) {
    j <- labels[[i]]
    results[i, j] <- 1
  }
  results
}
y_train <- to_one_hot(train_labels)
y_test <- to_one_hot(test_labels)

#model 
model <- keras_model_sequential() %>% 
  layer_dense(units = 64, activation = "relu") %>% 
  layer_dense(units = 64, activation = "relu") %>% 
  layer_dense(units = 46, activation = "softmax") 

model %>% compile(optimizer = "rmsprop",
                  loss = "categorical_crossentropy",
                  metrics = "accuracy") 

# validation 
val_indices <- 1:1000
x_val <- x_train[val_indices, ]
partial_x_train <- x_train[-val_indices, ]

y_val <- y_train[val_indices, ]
partial_y_train <- y_train[-val_indices, ]

#train model 
history <- model %>% fit(
  partial_x_train,
  partial_y_train,
  epochs = 20, 
  batch_size = 512, 
  validation_data = list(x_val, y_val)
)

Specifically, at training the model step, hitting:

> Error in py_call_impl(callable, call_args$unnamed, call_args$named) : 
  ValueError: Data cardinality is ambiguous. Make sure all arrays contain the same number of samples.'x' sizes: 1246
'y' sizes: 7982

Which sounds like an issue here https://github.com/rstudio/keras3/issues/1063, yet in their code their used: val_indices <- 1:10000 instead of 1000.

t-kalinowski commented 1 month ago

The above code executed without any errors for me. Can you tell me more about your system (OS, package versions, python version, etc.)

That said, I have seen similar errors before. At some point tensorflow became more strict about the shape of training data. In older versions, in fit() it used to implicitly promote 1d arrays with shape(n) to 2d arrays of shape(n, 1). But then stopped doing that in favor of requiring users to be more explicit.

You can likely fix the error by adding a 1 dim to the input y: dim(y) <- c(dim(y), 1)

yuriy-babenko commented 1 month ago

> reticulate::py_config() version: 3.11.9 (main, Aug 7 2024, 13:09:04) [Clang 15.0.0 (clang-1500.3.9.4)]

> sessionInfo() R version 4.4.1 (2024-06-14) Platform: aarch64-apple-darwin20 Running under: macOS Sonoma 14.5

> tensorflow::tf_config() TensorFlow v2.17.0 (~/.virtualenvs/r-keras/lib/python3.11/site-packages/keras) Python v3.11 (~/.virtualenvs/r-keras/bin/python)

yuriy-babenko commented 1 month ago

y: dim(y) <- c(dim(y), 1)

with that you mean partial_y_train or which y?

t-kalinowski commented 1 month ago

Yes, I mean partial_y_train passed to fit() must be a 2d array with shape (n, 1).

But, still, I can't reproduce the error locally with the same OS, Python version, and latest packages.

yuriy-babenko commented 1 month ago

1) tried changing the dimensions of _partial_ytrain but hitting Error in py_call_impl(callable, call_args$unnamed, call_args$named) :ValueError: Cannot take the length of shape with unknown rank.

dim(partial_y_train) <- c(dim(partial_y_train), 1)

2) I re-ran the notebook from scratch today and do not observe the error any longer either. I did not have to change anything in the code. This is a bit weird but maybe some local dependency on my machine? I am not sure ...

t-kalinowski commented 1 month ago

You were likely working interactively and had accumulated state. My best guess is that at some point you converted partial_y_train from an R array to a tensor, and then dim<- doesn't work on that.

Also, it's probably a bad habit to use dim<-, array_reshape(), is better/safer when working with an R array that will be passed to NumPy/TensorFlow/Jax/PyTorch, or op_reshape() when you already have a tensor.

(If you have a GPU, be careful not to convert large datasets to TF tensors prematurely, because they will be allocated on the GPU and then there won't be enough memory for the model. It's best to pass an R array, NumPy array, or tfdataset to fit().

yuriy-babenko commented 1 month ago

Thank you @t-kalinowski. Appreciate your detailed advise and kind help. Many great insights (in addition to the brilliant book).