Classification Example with Keras One-dimensional Layer Model in R

   Convolutional layers are one of the main components of deep learning models. Basically, they are useful when we work with multi-dimensional data like images. However, it is possible to implement the convolutional layers to the classification data like the Iris dataset. All we have to do is to adjust feature data into the one-dimensional vector and feed them into the one-dimensional convolutional layer. This tutorial explains how to implement the method to classify the Iris dataset by applying the layer_conv_1d in R.
   A while back, we also learned how to use a one-dimensional convolutional layer to classify data with Python. If you are interested, please refer to the post.
   The tutorial covers:
  1. Preparing the data
  2. Defining and fitting the model
  3. Predicting and accuracy check
  4. Source code listing
We'll start by loading the required packages in R. Here, we need the Keras R interface package.

library(keras)
library(caret)

Preparing the data

We'll load the Iris dataset and check the content and dimensions of datasets to get the idea about it.

data(iris)
 
str(iris)
'data.frame': 150 obs. of  5 variables:
 $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
 $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
 $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
 $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
 $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
 
dim(iris)
[1] 150   5

First, we'll convert the 'Species' character type into the numeric value. 

unique(iris$Species)
[1] setosa     versicolor virginica 
Levels: setosa versicolor virginica

iris$Species=as.numeric(iris$Species)-1
unique(iris$Species)
[1] 0 1 2

Here, we've converted 'setosa' to 0, 'versicolor' to 1, and 'virginica' to 2. 

Next, we'll split data into the train and test parts and separate x feature and y label data.

indexes = createDataPartition(iris$Species, p = .85, list = F)
train = iris[indexes, ]
test = iris[-indexes, ]
 
xtrain = as.matrix(train[, -5])
ytrain = as.matrix(train[, 5])
xtest = as.matrix(test[, -5])
ytest = as.matrix(test[, 5]) 

Next, we'll reshape the x data into the one-dimensional array type. The label y data becomes a one-hot categorical type.

dim(xtrain)
[1] 128   4
 
dim(ytrain)
[1] 128   1
 
xtrain = array(xtrain, dim = c(nrow(xtrain), 4, 1))
xtest = array(xtest, dim = c(nrow(xtest), 4, 1))
ytrain = to_categorical(ytrain)
 
dim(xtrain)
[1] 128   4   1
 
dim(ytrain)
[1] 128   3


Defining and fitting the model

We'll define the Keras sequential model. In the input layer, we'll use a one-dimensional convolutional layer layer_conv_1d and its input shape becomes as it is confirmed above (4,1). We'll add max-pooling and flatten layers into the model. For the output layer, we use the Dense layer containing the number of output classes and 'softmax' activation.

model = keras_model_sequential() %>%
  layer_conv_1d(filters=64, kernel_size=2, input_shape=c(4,1), activation="relu") %>%
  layer_max_pooling_1d() %>%
  layer_flatten() %>%
  layer_dense(units = 3, activation = "softmax")
 
model %>% compile(loss = 'categorical_crossentropy',
                  optimizer = 'adam',
                  metrics = 'accuracy')
 
model %>% summary()
______________________________________________________________________
Layer (type)                   Output Shape                Param #    
======================================================================
conv1d_2 (Conv1D)              (None, 3, 64)               192        
______________________________________________________________________
max_pooling1d_2 (MaxPooling1D) (None, 1, 64)               0          
______________________________________________________________________
flatten_2 (Flatten)            (None, 64)                  0          
______________________________________________________________________
dense_2 (Dense)                (None, 3)                   195        
======================================================================
Total params: 387
Trainable params: 387
Non-trainable params: 0
______________________________________________________________________


Predicting and accuracy check

We'll fit the model with train data then will check the training accuracy.

model %>% fit(xtrain, ytrain, epochs=100, verbose=0)
 
scores = model %>% evaluate(xtrain, ytrain, verbose = 0)
print(scores)
$loss
[1] 0.3239077

$acc
[1] 0.9609375

Now we can predict the test data. The prediction result shows the probability of each class. We'll extract the class with the highest prediction value as the predicted result.

ypred = model %>% predict(xtest)
head(ypred)
          [,1]       [,2]        [,3]
[1,] 0.9482948 0.04799704 0.003708256
[2,] 0.9239359 0.07060570 0.005458369
[3,] 0.9251963 0.06861981 0.006183801
[4,] 0.9153184 0.07734418 0.007337495
[5,] 0.9487829 0.04729233 0.003924868
[6,] 0.9337994 0.05986732 0.006333135

yhat = data.frame("ypred" = ifelse(max.col(ypred[ ,1:3])==1, "0",
                   ifelse(max.col(ypred[ ,1:3])==2, "1", "2")))

Finally, we'll check the accuracy rate with confusion matrics.

confusionMatrix(as.factor(ytest), yhat$ypred)
Confusion Matrix and Statistics

          Reference
Prediction 0 1 2
         0 8 0 0
         1 0 7 0
         2 0 0 7

Overall Statistics
                                     
               Accuracy : 1          
                 95% CI : (0.8456, 1)
    No Information Rate : 0.3636     
    P-Value [Acc > NIR] : 2.161e-10  
                                     
                  Kappa : 1          
 Mcnemar's Test P-Value : NA         

Statistics by Class:

                     Class: 0 Class: 1 Class: 2
Sensitivity            1.0000   1.0000   1.0000
Specificity            1.0000   1.0000   1.0000
Pos Pred Value         1.0000   1.0000   1.0000
Neg Pred Value         1.0000   1.0000   1.0000
Prevalence             0.3636   0.3182   0.3182
Detection Rate         0.3636   0.3182   0.3182
Detection Prevalence   0.3636   0.3182   0.3182
Balanced Accuracy      1.0000   1.0000   1.0000


   In this tutorial, we've briefly learned how to classify the Iris dataset with Keras one-dimensional convolutional layer in R. The full source code is listed below.


Source code listing

library(keras)
library(caret)
 
data(iris)
str(iris)
dim(iris) 
 
unique(iris$Species)
 
iris$Species=as.numeric(iris$Species)-1
unique(iris$Species) 
 
indexes = createDataPartition(iris$Species, p = .85, list = F)
train = iris[indexes, ]
test = iris[-indexes, ]
 
xtrain = as.matrix(train[, -5])
ytrain = as.matrix(train[, 5])
xtest = as.matrix(test[, -5])
ytest = as.matrix(test[, 5])  
dim(xtrain)
dim(ytrain)
 
xtrain = array(xtrain, dim = c(nrow(xtrain), 4, 1))
xtest = array(xtest, dim = c(nrow(xtest), 4, 1))
ytrain = to_categorical(ytrain)
 
dim(xtrain)
dim(ytrain)
 
model = keras_model_sequential() %>%
  layer_conv_1d(filters=64, kernel_size=2, input_shape=c(4,1), activation="relu") %>%
  layer_max_pooling_1d() %>%
  layer_flatten() %>%
  layer_dense(units = 3, activation = "softmax")
 
model %>% compile(loss = 'categorical_crossentropy',
                  optimizer = 'adam',
                  metrics = 'accuracy')
 
model %>% summary()
   
model %>% fit(xtrain, ytrain, epochs=100, verbose=0)
 
scores = model %>% evaluate(xtrain, ytrain, verbose = 0)
print(scores)
 
ypred = model %>% predict(xtest)
head(ypred) 
 
confusionMatrix(as.factor(ytest), yhat$ypred) 

No comments:

Post a Comment