Skip to Content
Course content

114: Keras and TensorFlow Interfaces in R

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I've been staring at this air quality dataset for a while, and while a linear regression would probably do the trick, I want to see if I can get a simple neural network to pick up on some of the non-linear patterns in ozone levels. The tricky part isn't the math—it's the plumbing. Since Keras and TensorFlow are native to Python, we're essentially using R as a remote control via the reticulate package. Let's see where things break.

The Reticulate Bridge

First thing I do is call library(keras). Now, if you've never done this before, you'll probably get an error saying the backend isn't installed. I remember the first time I ran this; I thought I had everything set up because I had Python on my machine, but Keras in R needs a very specific environment.

library(keras)
# This usually fails the first time
model <- keras_model_sequential() 
# Error: Python environment not found.

Right. I forgot that R doesn't just "find" TensorFlow. I have to explicitly tell it to set up the environment. I'll run install_keras(). This is where the magic happens: R reaches out, creates a virtual environment (usually via Conda or venv), and installs the actual Python libraries. It's a bit of a black box, but once it's done, the bridge is built.

install_keras() 
# I'll wait a few minutes for the binaries to download...

Fighting with Tensor Dimensions

Now that the engine is running, I'll try to feed in my data. I'm using the airquality dataset. I want to predict Ozone using Solar.R and Wind. I'll keep it simple and just scale the data first, since neural networks hate it when one feature is 0-1 and another is 0-1000.

data(airquality)
df <- na.omit(airquality[, c("Ozone", "Solar.R", "Wind")])
x_train <- scale(df[, 2:3])
y_train <- scale(df[, 1])

model <- keras_model_sequential() %>%
  layer_dense(units = 64, activation = "relu", input_shape = c(2)) %>%
  layer_dense(units = 1)

model %>% compile(optimizer = "adam", loss = "mse")

# Let's try to fit the model
model %>% fit(x_train, y_train, epochs = 10, batch_size = 32)

Wait, I just noticed something. If I had passed df[, 2:3] as a data frame instead of using scale() (which returns a matrix), Keras would have thrown a fit. R data frames are lists under the hood, but TensorFlow expects contiguous blocks of memory—tensors. I've spent way too many hours debugging "input must be a numeric matrix" errors. Always ensure your data is converted to a matrix or an array before it hits the fit function.

Tuning the Architecture

The model ran, but the loss is hovering around a point that feels too high. I suspect my model is too simple, or maybe the learning rate is off. Let's try adding another hidden layer and changing the activation. I'll go with a "bottleneck" approach to see if the network can compress the information.

model <- keras_model_sequential() %>%
  layer_dense(units = 32, activation = "relu", input_shape = c(2)) %>%
  layer_dense(units = 16, activation = "relu") %>%
  layer_dense(units = 1)

model %>% compile(
  optimizer = optimizer_adam(learning_rate = 0.01), 
  loss = "mse"
)

history <- model %>% fit(
  x_train, y_train, 
  epochs = 100, 
  batch_size = 16, 
  validation_split = 0.2
)

I increased the learning rate to 0.01 because the default was too sluggish for this tiny dataset. I also added a validation_split. This is a key part of the Keras interface in R; it handles the splitting internally, so I don't have to manually slice my matrices. Looking at the output, the validation loss is tracking with the training loss, which means I'm not overfitting... yet.

Evaluating the R-to-Python Handshake

The final step is getting predictions back into a format that makes sense in R. When I call predict(), Keras returns a matrix. To make it useful, I need to un-scale those values to get back to actual Ozone concentrations.

preds <- model %>% predict(x_train)
# The predictions are scaled. Let's bring them back to the original scale.
# Since y_train was scaled using (x - mean)/sd:
original_scale_preds <- preds * attr(y_train, "scaled:scale") + attr(y_train, "scaled:center")

plot(df$Ozone, original_scale_preds, main="Actual vs Predicted Ozone")
abline(0, 1, col="red")

It's not perfect, but it's working. The most important takeaway here is that you aren't really "writing" TensorFlow in R; you're using a very polished R wrapper that translates your commands into Python. When you see an error, ask yourself: "Is this an R error, or is this a Python error being passed back to me?" Usually, it's the latter, and the fix usually involves checking the dimensions of your matrices.




📋 Practical Task

Building a Nonlinear Regression Model for Housing Prices

Using the Boston dataset (available in the MASS library), build a Keras model to predict the median value of homes (medv). Your goal is to implement a model that improves upon a basic linear baseline.

  • Data Prep: Load the Boston dataset, remove any missing values, and scale both your features and your target variable.
  • Architecture: Create a sequential model with at least two hidden layers. Use the relu activation function for the hidden layers and a linear activation for the output layer.
  • Training: Compile the model using the adam optimizer and mse (Mean Squared Error) as the loss function. Train the model for 100 epochs with a batch size of 32, reserving 20% of the data for validation.
  • Verification: Predict the values for the training set and plot the "Actual vs. Predicted" values. Ensure you un-scale the predictions back to the original dollar amounts before plotting.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.