This is a binary image classification Nerual Net made with the Keras API. There are a bunch of ways to do this like with the Generator functions but this what felt most natural to me at the time of writing this.

I pulled 10 photos of cats and humans from google and saved them as .jpg. Although this is a super small data set, the goal is to use 16 photos as a training set to predict the outcome of the 4 photos in the test set.

Load in Packages

library(reticulate)
library(tidyverse)
## -- Attaching packages -------------------------------------------------- tidyverse 1.3.0 --
## v ggplot2 3.3.2     v purrr   0.3.4
## v tibble  3.0.3     v dplyr   1.0.1
## v tidyr   1.1.1     v stringr 1.4.0
## v readr   1.3.1     v forcats 0.5.0
## -- Conflicts ----------------------------------------------------- tidyverse_conflicts() --
## x dplyr::filter() masks stats::filter()
## x dplyr::lag()    masks stats::lag()
library(tensorflow)
library(keras)
library(magick)
## Linking to ImageMagick 6.9.9.14
## Enabled features: cairo, freetype, fftw, ghostscript, lcms, pango, rsvg, webp
## Disabled features: fontconfig, x11
use_condaenv("r-reticulate", required = TRUE)

If we want to check out the cats and human pictures

cat = image_read("C:\\Users\\spenc\\Desktop\\nn_pics2\\training\\01.jpg")
human = image_read("C:\\Users\\spenc\\Desktop\\nn_pics2\\training\\09.jpg")
plot(cat)

plot(human)

Import Training and Test data

Training

trainpics = list.files("C:\\Users\\spenc\\Desktop\\nn_pics2\\training", 
                       full.names = TRUE) 

#Instead of using loops, the apply functions work great here 
loadpics = function(filenames) {
  a = lapply(filenames, image_load, grayscale = TRUE) #grayscale the image
  b = lapply(a, image_to_array) #turns it into an array
  c = lapply(b,image_array_resize, height = 100, width = 100) #resize
  d = normalize(c, axis = 1) #normalize to make small numbers 
  return(d)}

trainx =loadpics(trainpics) #loads training files

Testing

testpics = list.files("C:\\Users\\spenc\\Desktop\\nn_pics2\\test", 
                      full.names = TRUE) 

testx = loadpics(testpics) # load test files

Make the labels for the training data

0 is feral beast and 1 is human

trainy = c(0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1)
testy  = c(0,0,1,1)
trainlabel = to_categorical(trainy)
testlabel = to_categorical(testy)

Time to use Keras

Define

model1 = keras_model_sequential()
model1 %>%
  layer_flatten() %>%
  layer_dense(units = 128, activation = 'relu') %>%
  layer_dense(units = 128, activation = 'relu')%>%
  layer_dense(units = 2, activation = 'softmax')
# For the last layer, you could also try a sigmoid activation with 1 unit.

Compile

model1 %>%
  compile (optimizer = 'adam',loss = 'binary_crossentropy', 
           metrics = c('accuracy'))
#If you had more than 2 categories, then you would want to use categorical_crossentropy for the loss function

Fit

fit1 = model1 %>%
  fit(x = trainx, y = trainlabel, epochs = 15, batch_size=32 ,
      validation_split = .1, callbacks = callback_tensorboard("logs/run_a")) 
#the callback just lets me view the model in tensorboard
#an epoch is how many times the model trains 

plot(fit1)
## `geom_smooth()` using formula 'y ~ x'

Evaluate

# Evaluate Training Data
model1 %>%
  evaluate(trainx,trainlabel)
##      loss  accuracy 
## 0.1146009 1.0000000
# Evaluate Test Data
model1 %>%
  evaluate(testx,testlabel)
##      loss  accuracy 
## 0.9901535 0.7500000

Predict

predictedclasses1 = model1 %>%
  predict_classes(testx)
table(Prediction = predictedclasses1, Actual = testy)
##           Actual
## Prediction 0 1
##          0 1 0
##          1 1 2
#tensorboard("logs/run_a") - If you want to check your runs in Tensorboard

#save_model_tf(model1, "model1") - save the model

Of the 4 pictures in our test set, we guessed whether the photo had a human or cat in it 3 times. 75% isn’t too bad though for such a small data set. The next step to this problem would be to do an image classification problem with multiple classes and a much larger data set.