keras input shape for multivariate LSTM - r

I'm trying to fit a LSTM model in keras where I have two inputs
y is the output with shape (100,10)
x is the input with shape (100,20)
library(keras)
x_train_vec <- matrix(rnorm(2000), ncol = 20, nrow = 100)
x_train_arr <- array(data = x_train_vec, dim = c(nrow(x_train_vec), 1, 20))
y_train_vec <- matrix(rnorm(1000), ncol = 10, nrow = 100)
y_train_arr <- array(data = y_train_vec, dim = c(nrow(x_train_vec), 1, 10))
> dim(x_train_arr)
[1] 100 1 20
> dim(y_train_arr)
[1] 100 1 10
Now I want to fit the LSTM model
model <- keras_model_sequential()
model %>%
layer_lstm(units = 50,
input_shape = c(1,10),
batch_size = 1) %>%
layer_dense(units = 1)
model %>%
compile(loss = 'mae', optimizer = 'adam')
model %>% fit(x = x_train_arr,
y = y_train_arr,
batch_size = 1,
epochs = 10,
verbose = 1,
shuffle = FALSE)
But I get this error:
Error in py_call_impl(callable, dots$args, dots$keywords) :
ValueError: Error when checking input: expected lstm_21_input to have
shape (1, 10) but got array with shape (1, 20)
If I change input size to c(1,20), I get:
Error in py_call_impl(callable, dots$args, dots$keywords) :
ValueError: Error when checking target: expected dense_13 to have 2
dimensions, but got array with shape (100, 1, 10)
I also played with different setting but it never works.

IF your Keras version is < 2.0 you need to use model.add(TimeDistributed(Dense(1))).
NOTE that syntax is for python, you need to find the R equivealent.

I figured out how to make it work:
x_train_vec <- matrix(rnorm(2000), ncol = 20, nrow = 100)
x_train_arr <- array(data = x_train_vec, dim = c(nrow(x_train_vec), 20, 1))
y_train_vec <- matrix(rnorm(1000), ncol = 10, nrow = 100)
y_train_arr <- array(data = y_train_vec, dim = c(nrow(x_train_vec), 10))
model <- keras_model_sequential()
model %>%
layer_lstm(units = 50,
input_shape = c(20,1),
batch_size = 1) %>%
layer_dense(units = 10)
model %>%
compile(loss = 'mae', optimizer = 'adam')
model %>% fit(x = x_train_arr,
y = y_train_arr,
batch_size = 1,
epochs = 10,
verbose = 1,
shuffle = FALSE)

Related

Parameter adjustment using kerastuneR packet deep neural network

What is the cause of the following code error?
library(magrittr)
x_data <- matrix(data = runif(500,0,1),nrow = 50,ncol = 5)
y_data <- ifelse(runif(50,0,1) > 0.6, 1L,0L) %>% as.matrix()
x_data2 <- matrix(data = runif(500,0,1),nrow = 50,ncol = 5)
y_data2 <- ifelse(runif(50,0,1) > 0.6, 1L,0L) %>% as.matrix()
library(keras)
library(tensorflow)
library(kerastuneR)
build_model = function(hp) {
model = keras_model_sequential()
model %>% layer_dense(units = hp$Int('units',
min_value = 32,
max_value = 512,
step= 32),input_shape = ncol(x_data),
activation = 'relu') %>%
layer_dense(units = 1, activation = 'softmax') %>%
compile(
optimizer = tf$keras$optimizers$Adam(
hp$Choice('learning_rate',
values=c(1e-2, 1e-3, 1e-4))),
loss = 'binary_crossentropy',
metrics = 'accuracy')
return(model)
}
tuner = RandomSearch(
build_model,
objective = 'val_accuracy',
max_trials = 5,
executions_per_trial = 3,
directory = 'my_dir',
project_name = 'helloworld')
tuner %>% search_summary()
tuner %>% fit_tuner(x_data,y_data,
epochs = 5,
validation_data = list(x_data2,y_data2))
result = kerastuneR::plot_tuner(tuner)
best_5_models = tuner %>% get_best_models(5)
best_5_models[[1]] %>% plot_keras_model()
Error in py_call_impl(callable, dots$args, dots$keywords) :
ValueError: Objective value missing in metrics reported to the Oracle, expected: ['val_accuracy'], found: dict_keys(['loss', 'acc', 'val_loss', 'val_acc'])

How to implement Bayesian optimization with Keras tuneR

I am hoping to run Bayesian optimization for my neural network via keras tuner.
I have the following code so far:
build_model <- function(hp) {
model <- keras_model_sequential()
model %>% layer_dense(units = hp$Int('units', min_value = 10, max_value = 50, step = 10),
activation = "relu",
input_shape = dim(X_pca_scores_scaled)[[2]]) %>%
layer_dropout(rate = hp$Float('rate', min_value = 0, max_value = 0.5, step = 0.1)) %>%
layer_dense(units = hp$Int('units', min_value = 0, max_value = 50, step = 10),
activation = "relu") %>%
layer_dropout(rate = hp$Float('rate', min_value = 0, max_value = 0.5, step = 0.1)) %>%
layer_dense(units = 1) %>%
compile(
optimizer = "adam",
loss = "mse",
metrics = c("mae"))
return(model)
}
tuner <- kerastuneR::BayesianOptimization(
objective = 'mae',
max_trials = 30)
stop_early <- callback_early_stopping(monitor = "mae",
patience = 5,
min_delta = 0.25,
mode = "min")
tuner %>% fit_tuner(np_array(X_pca_scores_scaled),
np_array(train_targets),
epochs = 30,
callbacks = c(stop_early))
The above code will lead to the following error:
Error in py_get_attr_impl(x, name, silent) :
AttributeError: 'BayesianOptimizationOracle' object has no attribute 'search'
I'm not sure what an oracle is...so I know the problem is somewhere in my implementation regarding that.

How to apply CNN on a dataframe in R?

now I am trying to build a deep learning model as a classifier. My input is a 2D dataframe. I was wondering if it is possible to use CNN layer in the model.
My data looks like this way:
x_train <- data.frame(pain = c(rep(c(0,1), c(4,5))),
gender = c(rep(c(0,1), c(3,6))),
age = c(runif(9,0,1)))
y_train <- data.frame(illness = c(rep(c(0,1), c(2,2)), rep(c(0,1), c(3,2))))
Now I construct a model like this way:
model <- keras_model_sequential() %>%
layer_conv_1d(filters = 1, kernel_size = 2, activation = "elu",
input_shape = c(3,1)) %>%
# layer_max_pooling_2d(pool_size = c(2,2)) %>%
layer_conv_1d(filters = 1, kernel_size = 2, activation = "elu") %>%
layer_max_pooling_1d(pool_size = 2) %>%
layer_dropout(0.5) %>%
layer_dense(
units = 5,
activation = "elu"
) %>%
layer_dropout(0.3) %>%
layer_dense(
units = 3,
activation = "elu"
) %>%
layer_dropout(0.1) %>%
layer_dense(units = 1, activation = "elu")
model %>% compile(
loss = "mean_squared_error",
optimizer = "SGD",
metrics = c('mae', 'acc') # "accuracy"
)
But it doesn't work and tells me it needs a 3 dimensions input
Error in py_call_impl(callable, dots$args, dots$keywords) :
ValueError: Error when checking input: expected conv1d_33_input to have 3 dimensions, but got array with shape (9, 3)
Could anyone give me some advice about that? Thanks a lot for your help : )

R ValueError: Error when checking input: expected simple_rnn_input to have 3 dimensions, but got array with shape (1661, 3)

Here is my code:
used_time_period = "2009-01-01::2017-04-01"
data_used = data_input[used_time_period,]
split_coefficient = 0.8
train_set_rate = round(nrow(data_used) * split_coefficient)
data_train = data_used[1:train_set_rate,]
data_test = data_used[(train_set_rate + 1):nrow(data_used),]
model = keras_model_sequential() %>%
layer_simple_rnn(units = 75, input_shape = dim(data_train[,1:3]), activation = "relu", return_sequences = TRUE) %>%
layer_dense(units = 2, activation = "relu")
model %>% compile(optimizer = "adam", loss = "binary_crossentropy", metrics = "binary_accuracy")
history = model %>% fit(x = data_train[,1:3], y = data_train[,4:5], epochs = 40, batch_size = 20)
the error i'm getting is this:
ValueError: Error when checking input: expected simple_rnn_input to
have 3 dimensions, but got array with shape (1661, 3)
dim(data_train[,1:3]) = (1661, 3)
dim(data_train[,4:5]) = (1661, 2)
What am I doing wrong?
As the error message says, layer_simple_rnn requires a 3D array but you are using a data.frame, which is a 2D array (a table with rows and columns).
According to the Keras documentation, the recurrent layer needs an array with shape (batch_size, timesteps, input_dim). Assuming each column corresponds to a different date (correct me if I'm wrong), this should probably work:
dim(data_train[, 1:3]) # [1] 10 3
X <- as.matrix(data_train[, 1:3]) # Convert to an array
dim(X) # [1] 10 3
dim(X) <- c(dim(X), 1)
dim(X) # [1] 10 3 1
# The same for Y
Y <- as.matrix(data_train[, 4:5])
dim(Y) <- c(dim(Y), 1)
Now X and Y have 3 dimensions and you can feed them to your model:
history = model %>% fit(x = X, y = Y, epochs = 40, batch_size = 20)

How to make sure inputs can be diveded by batch size in stateful LSTM?

I'm having some issues training a network using stateful LSTMs.
Given the code below, I'm getting the following error message:
Error in py_call_impl(callable, dots$args, dots$keywords) :
ValueError: In a stateful network, you should only pass inputs with a number of samples that can be divided by the batch size. Found: 9384 samples
Input is sent from an external application, so I cannot control the exact number of inputs sent. What would be the best way to ensure that the input can always be divided nu the batch size?
neural.train = function(model,XY)
{
XY <- as.matrix(XY)
X <- XY[,-ncol(XY)]
Y <- XY[,ncol(XY)]
Y <<- ifelse(Y > 0,1,0)
dropout <- 0.3
batchSize <- 64
newModel <- keras_model_sequential()
newModel %>%
layer_lstm(batch_input_shape = c(batchSize, 30, 19), units = 72, return_sequences = TRUE, stateful = TRUE, dropout = dropout, recurrent_dropout = dropout) %>%
#layer_dense(units = 20) %>%
#layer_lstm(units = 50, return_sequences = TRUE, stateful = TRUE, dropout = dropout, recurrent_dropout = dropout) %>%
layer_lstm(units = 16, dropout = dropout, recurrent_dropout = dropout, return_sequences = FALSE, stateful = TRUE) %>%
layer_dense(units = 8) %>%
layer_batch_normalization() %>%
layer_dense(units = 1, activation = 'relu')
newModel %>% compile(
optimizer = optimizer_rmsprop(lr = 0.001),
loss = 'binary_crossentropy',
metrics = c('accuracy')
)
#X_conv <- matrix(c(X[1,1:10],X[1,11:20]),ncol=10,nrow=2)
ar <- array(X,c(dim(X)[1],30,19))
#newModel %>% fit(X, Y, epochs=20, batch_size=100, validation_split = 0.2, shuffle=TRUE, callbacks=reduce_lr)
newModel %>% fit(ar, Y, epochs=100, batch_size=batchSize, validation_split = 0.2, shuffle=FALSE)
Models[[model]] <<- serialize_model(newModel, include_optimizer = TRUE)
}

Resources