Multi-input model with generator function - Keras R - r

I have been trying to build a multi-input model in keras. One input branch would be images and the second one some metaData for the corresponding images.
For the images I need a generator function which would input batches of images. The metaData is in a tabular form.
Now I am wondering how I should pass the data to the model so the right image would be processed with the respective metaData Information. For your Information this will be a regression Task.
The Input Data I have:
Images in dir1/
Data Frame with the path and features.
path feature1 feature2 target
image1.jpg 23.5 100 16
image2.jpg 25.0 88 33
The code I have for now:
generator function for Images:
train_datagen <- image_data_generator(rescale = 1/255)
train_generator <- flow_images_from_dataframe(
dataframe = joined_path_with_metadata,
directory = 'data_dir',
x_col = "path",
y_col = "train",
generator = train_datagen,
target_size = c(150, 150),
batch_size = 20,
color_mode = 'rgb',
class_mode = "sparse"
)
model definition:
vision_model <- keras_model_sequential()
vision_model %>%
layer_conv_2d(filters = 64,
kernel_size = c(3, 3),
activation = 'relu',
padding = 'same',
input_shape = c(150, 150, 3)) %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_flatten()
# Now let's get a tensor with the output of our vision model:
image_input <- layer_input(shape = c(150, 150, 3))
encoded_image <- image_input %>% vision_model
# ANN for tabular data
tabular_input <- layer_input(shape = ncol(dataframe), dtype = 'float32')
mlp_model <- tabular_input %>%
layer_dense(
units = 16,
kernel_initializer = "uniform",
activation = "relu") # Dropout to prevent overfitting
layer_dropout(rate = 0.1) %>%
layer_dense(
units = 32,
kernel_initializer = "uniform",
activation = "relu") %>%
# concatenate the metadata and the image vector then
# train a linear regression on it
output <- layer_concatenate(c(mlp_model, encoded_image)) %>%
layer_dense(units = 1, activation='linear')
# This is the final model:
vqa_model <- keras_model(inputs = c(image_input, tabular_input), outputs = output)
compile:
vqa_model %>% compile(
optimizer = 'adam',
loss = 'mean_squared_error',
metrics = c('mean_squared_error')
)
and the last step would be to fit the model. I am not sure how to do this to make sure that the first row of features will be taken as the metadata of the Images which are read in in batches.

Related

'keras_model_sequential()' runs forever

I am working on a project, where I build an LSTM model for GDP growth forecasting. When I try to build the model using 'keras_model_sequential()' it gets stuck there and runs forever! I am confused, I installed both the Keras and TensorFlow packages but still, it runs forever. R keeps running in the first line of this code sample.
lstm_model <- keras_model_sequential()
lstm_model %>%
# 1st LSTM layer
layer_lstm(units = 20, # size of the layer
batch_input_shape = c(1, 5, 1), # batch size, timesteps, features
return_sequences = TRUE, # reserve the sequence
stateful = TRUE) %>%
# Dropout layer
layer_dropout(rate = 0.3) %>%
# 2nd LSTM layer
layer_lstm(units = 20,
return_sequences = TRUE,
stateful = TRUE) %>%
layer_dropout(rate = 0.3) %>%
# Final dense/output layer
time_distributed(keras::layer_dense(units = 1))
# Use Adam optimizer, Mean absolute error as loss function, and want to see accuracy
lstm_model %>%
compile(loss = 'mae', optimizer = 'adam', metrics = 'accuracy')
#Summary of the model
summary(lstm_model)
# fit the model
lstm_model %>% fit(
x = x_train_arr,
y = y_train_arr,
batch_size = 1,
epochs = 20,
verbose = 0,
shuffle = FALSE
)

How to define lstm, units, lags and batch size in keras package

I have data of almost 4700 entries. I have to predict power output. I am unable to understand the algorithm of the LSTM like what is units? how to select units for my data and what are data lags? The code I am using for this work is available here https://www.r-bloggers.com/2018/11/lstm-with-keras-tensorflow/ as I have interest in lstm so I am only using that part of this code.
library(keras)
model <- keras_model_sequential()
model %>%
layer_lstm(units = 100,
input_shape = c(datalags, 2),
batch_size = batch.size,
return_sequences = TRUE,
stateful = TRUE) %>%
layer_dropout(rate = 0.5) %>%
layer_lstm(units = 50,
return_sequences = FALSE,
stateful = TRUE) %>%
layer_dropout(rate = 0.5) %>%
layer_dense(units = 1)
model %>%
compile(loss = 'mae', optimizer = 'adam')
So in this code I am unable to understand
what is meant by units here?
What are datalags,
The code uses datalags value as 10, how do I define it for my data? and how to manually select them for my data?

Output order in Keras predict_generator

I have followed online tutorial about image recognition using Keras in R ending up with the following code:
library(keras)
view_list <- c("Inside", "Outside")
output_n <- length(view_list)
# image size to scale down to (original images are 100 x 100 px)
img_width <- 20
img_height <- 20
target_size <- c(img_width, img_height)
# RGB = 3 channels
channels <- 3
train_image_files_path <- "C:/Users/Tomek/Desktop/Photos"
valid_image_files_path <- "C:/Users/Tomek/Desktop/Photos valid"
test_image_files_path <- "C:/Users/Tomek/Desktop/Photos test"
# optional data augmentation
train_data_gen = image_data_generator(rescale = 1/255 )
# Validation data shouldn't be augmented! But it should also be scaled.
valid_data_gen <- image_data_generator(rescale = 1/255)
test_data_gen <- image_data_generator(rescale = 1/255)
# training images
train_image_array_gen <- flow_images_from_directory(train_image_files_path,
train_data_gen,
target_size = target_size,
class_mode = "categorical",
classes = view_list,
seed = 42)
# validation images
valid_image_array_gen <- flow_images_from_directory(valid_image_files_path,
valid_data_gen,
target_size = target_size,
class_mode = "categorical",
classes = view_list,
seed = 42)
# test images
test_image_array_gen <- flow_images_from_directory(test_image_files_path,
test_data_gen,
target_size = target_size,
class_mode = "categorical",
classes = view_list,
seed = 42)
cat("Number of images per class:")
table(factor(train_image_array_gen$classes))
train_image_array_gen$class_indices
views_classes_indices <- train_image_array_gen$class_indices
save(views_classes_indices, file = "C:/Users/Tomek/Desktop/views_classes_indices.RData")
# number of training samples
train_samples <- train_image_array_gen$n
# number of validation samples
valid_samples <- valid_image_array_gen$n
# number of test samples
test_samples <- test_image_array_gen$n
# define batch size and number of epochs
batch_size <- 1
epochs <- 10
# initialise model
model <- keras_model_sequential()
# add layers
model %>%
layer_conv_2d(filter = 32, kernel_size = c(3,3), padding = "same", input_shape = c(img_width, img_height, channels)) %>%
layer_activation("relu") %>%
# Second hidden layer
layer_conv_2d(filter = 16, kernel_size = c(3,3), padding = "same") %>%
layer_activation_leaky_relu(0.5) %>%
layer_batch_normalization() %>%
# Use max pooling
layer_max_pooling_2d(pool_size = c(2,2)) %>%
layer_dropout(0.25) %>%
# Flatten max filtered output into feature vector
# and feed into dense layer
layer_flatten() %>%
layer_dense(100) %>%
layer_activation("relu") %>%
layer_dropout(0.5) %>%
# Outputs from dense layer are projected onto output layer
layer_dense(output_n) %>%
layer_activation("softmax")
# compile
model %>% compile(
loss = "categorical_crossentropy",
optimizer = optimizer_rmsprop(lr = 0.0001, decay = 1e-6),
metrics = "accuracy"
)
summary(model)
# fit
hist <- model %>% fit_generator(
# training data
train_image_array_gen,
# epochs
steps_per_epoch = as.integer(train_samples / batch_size),
epochs = epochs,
# validation data
validation_data = valid_image_array_gen,
validation_steps = as.integer(valid_samples / batch_size),
# print progress
verbose = 2,
callbacks = list(
# save best model after every epoch
callback_model_checkpoint("C:/Users/Tomek/Desktop/views_checkpoints.h5", save_best_only = TRUE),
# only needed for visualising with TensorBoard
callback_tensorboard(log_dir = "C:/Users/Tomek/Desktop/keras/logs")
)
)
plot(hist)
#prediction
a <- model %>% predict_generator(test_image_array_gen, steps = 5, verbose = 1, workers = 1)
a <- round(a, digits = 4)
The classification model (with two output classes) seems to work quite nicely. The accuracy on the train and the validation sets is equal to ~99% and ~95% respectively. However, I am not sure about the results of predictions on the test set. It looks like the predictions for observations are shuffled and I am not able to find a way to check which prediction refers to which image(observation). I have seen some threads on that issue: github medium 1 medium 2.
Nevertheless, I am really new to Keras and Python and I have hard time applying the suggested solutions in R. What is the easiest way to track which prediction refers to which image from the test set in predict_generator output?
I figured it out and the answer is simple. The shuffling is caused by argument shuffle which by default is set to true. After changing it, predictions correspond to the order of test_image_array_gen$filenames However, bear in mind that the order of predictions (and filenames) is different than the one on Windows which may be a bit confusing.
Order in Windows: Photo 1 Photo 2 ... Photo 10 Photo 11
Order in R: Photo 1 Photo 10 Photo 11 ... Photo 2
# test images
test_image_array_gen <- flow_images_from_directory(test_image_files_path,
test_data_gen,
target_size = target_size,
class_mode = "categorical",
classes = view_list,
seed = 42,
shuffle = FALSE)
#prediction
a <- model %>% predict_generator(test_image_array_gen, steps = ceiling(test_samples/32), verbose = 1, workers = 1)
#bind predictions with photos names
b <- cbind.data.frame(a, test_image_array_gen$filenames)

Generator function in keras for mixed data input (image, csv) - R

I want to build a generator function to input Image Data together with the corresponding metadata. There are more than 20 k Images and that is why I can't just read them into memory. I have tried also to use flow_from_dataframe but in the multi-input case it's getting complicated.
The generator function looks like this:
data_files_generator_train <- function(dir) {
files <- list.files(dir ,pattern = "jpg$")
next_file <- 0
function() {
next_file <<- next_file + 1
if (next_file > length(files))
{next_file <<- 1}
# determine the file name
file <- files[[next_file]]
image <- image_load(file, target_size = c(150,150)) %>%
image_to_array() %>%
array_reshape(dim = c(150, 150, 3)) %>%
imagenet_preprocess_input()
x_image <- image/ 255
x_attr <- paintings_attributes_train %>% filter(path == file) %>% select(-c(target, path))
y <- paintings_attributes_train %>% filter(path == file) %>% select(target)
x_attr <- matrix(x_attr, ncol = 16)
y <- matrix(y)
return(list(list(x_image, x_attr), y))
}}
I get the following error:
Error in py_call_impl(callable, dots$args, dots$keywords) :
ValueError: Error when checking model input: the list of Numpy arrays that you are passing to your model is not the size the model expected. Expected to see 2 array(s), but instead got the following list of 1 arrays: [array([[0.00769116, 0.17699115, 0.1436
the model definition looks as follows:
vision_model <- keras_model_sequential()
vision_model %>%
layer_conv_2d(filters = 64,
kernel_size = c(3, 3),
activation = 'relu',
padding = 'same',
input_shape = c(150, 150, 3)) %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_flatten()
# tensor with the output of our vision model:
image_input <- layer_input(shape = c(150, 150, 3))
encoded_image <- image_input %>% vision_model
tabular_input <- layer_input(shape = 16, dtype = 'float32')
mlp_model <- tabular_input %>%
layer_dense(
units = 16,
kernel_initializer = "uniform",
activation = "relu")
# concatenate the metadata vector and the image vector then
# train a linear regression on it
output <- layer_concatenate(c(mlp_model, encoded_image)) %>%
layer_dense(units = 1, activation='linear')
# This is our final model:
vqa_model <- keras_model(inputs = c(tabular_input, image_input), outputs = output)
The Question is related to Create a mixed data generator (images,csv) in keras.
Thanks for any help!

Layer conv2d_1 was called with an input that isn't a symbolic tensor / Keras / Cloudml / R

I am using the R interface to Keras version 2.14, and version 1.5 for Tensorflow.
When I run the following code at my local machine, it runs without any issues. When I run it on cloudml, I get the error message given below.
I have checked the forums, but with my limited knowledge of python, unable to translate the solutions given so far to R.
Thank you for your help.
Error message:
"Error: ValueError: Layer conv2d_1 was called with an input that isn't a symbolic tensor. Received type: . Full input: []. All inputs to the layer should be tensors. Detailed traceback: File "/usr/local/lib/python2.7/dist-packages/keras/engine/base_layer.py", line 414, in call self.assert_input_compatibility(inputs) File "/usr/local/lib/python2.7/dist-packages/keras/engine/base_layer.py", line 285, in assert_input_compatibility str(inputs) + '. All inputs to the layer"
Here is the complete code:
original_dataset_dir <- "./train"
base_dir <- "./cats_and_dogs_small"
train_dir <- file.path(base_dir, "train")
validation_dir <- file.path(base_dir, "validation")
test_dir <- file.path(base_dir, "test")
train_cats_dir <- file.path(train_dir, "cats")
train_dogs_dir <- file.path(train_dir, "dogs")
validation_cats_dir <- file.path(validation_dir, "cats")
validation_dogs_dir <- file.path(validation_dir, "dogs")
test_cats_dir <- file.path(test_dir, "cats")
test_dogs_dir <- file.path(test_dir, "dogs")
cat("total training cat images:", length(list.files(train_cats_dir)), "\n")
cat("total training dog images:", length(list.files(train_dogs_dir)), "\n")
cat("total validation cat images:", length(list.files(validation_cats_dir)), "\n")
cat("total validation dog images:", length(list.files(validation_dogs_dir)), "\n")
cat("total test cat images:", length(list.files(test_cats_dir)), "\n")
cat("total test dog images:", length(list.files(test_dogs_dir)), "\n")
list.files(test_dogs_dir)
# now create the model
library(keras)
model <- keras_model_sequential() %>%
layer_conv_2d(filters = 32, kernel_size = c(3, 3), activation = "relu",
input_shape = c(150, 150, 3)) %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_conv_2d(filters = 64, kernel_size = c(3, 3), activation = "relu") %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_conv_2d(filters = 128, kernel_size = c(3, 3), activation = "relu") %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_conv_2d(filters = 128, kernel_size = c(3, 3), activation = "relu") %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_flatten() %>%
layer_dense(units = 512, activation = "relu") %>%
layer_dense(units = 1, activation = "sigmoid")
# look at the model
summary(model)
model %>% compile(
loss = "binary_crossentropy",
optimizer = optimizer_rmsprop(lr = 1e-4),
metrics = c("acc")
)
# All images will be rescaled by 1/255
train_datagen <- image_data_generator(rescale = 1/255)
validation_datagen <- image_data_generator(rescale = 1/255)
train_generator <- flow_images_from_directory(
# This is the target directory
train_dir,
# This is the data generator
train_datagen,
# All images will be resized to 150x150
target_size = c(150, 150),
batch_size = 20,
# Since we use binary_crossentropy loss, we need binary labels
class_mode = "binary"
)
validation_generator <- flow_images_from_directory(
validation_dir,
validation_datagen,
target_size = c(150, 150),
batch_size = 20,
class_mode = "binary"
)
batch <- generator_next(train_generator)
str(batch)
history <- model %>% fit_generator(
train_generator,
steps_per_epoch = 100,
epochs = 5,
validation_data = validation_generator,
validation_steps = 50
)
model %>% save_model_hdf5("cats_and_dogs_small_1.h5")
plot(history)
cml1.R
library(cloudml)
#gcloud_init()
cloudml_train("cats-and-dogs.R")

Resources