---
title: "Let's build Image classifiers-I"
author: 'Philippe Fullsack+others'
output:
  html_document:
    toc: yes
  pdf_document: null
  pdf_presentation: null
  slidy_presentation:
    css: slidy.css
    widescreen: yes
  word_document: null
---

# Theme of activity

   + (a) Image classification problems in R

   + (b) Review and compare models

   + (c) MNIST digit prediction
   
   + (d) Suggested variants  


# MNIST digit prediction

Why is the MNIST digit prediction problem popular? 

Answer: because of the simplicity and importance of this task, and of the role it played in the emergence of deep learning models.


<b>Lecun 1989 (7000 citations)</b>: goal: decipher (handwritten)  ZIP codes

<img src="../images/lecun-1989.png">

<img src="https://d3i71xaburhd42.cloudfront.net/a4bfe622ab32e6c645eb4be2079734355b22d304/2-Figure1-1.png">

<b>Fundamental idea: CONSTRAIN THE LEARNING NETWORK to tune its complexity </b>

Deep learning rests on the recognition of the role of symmetries in data (my opinion anyway).

We are NOT going to use neural networks here. Instead we will use (unconstrained) classical prediction
methods (including Random Forest), and this will serve as a basis for a comparison between the methods learned in this course and more advanced methods (deep networks) that you will see or use in the future.


Our goal is to learn how to load the data, and fit and compare various models of prediction in R.


## The data

Images (original 28x28, here downsampled to 16x16) of handwritten digits (0-9)

Load the data:

```{r}
set.seed(1)
train <- read.csv("../Data/mnist_train.psv", sep="|", as.is=TRUE, header=FALSE)
test <- read.csv("../Data/mnist_test.psv", sep="|", as.is=TRUE, header=FALSE)
```

257 columns: 

column 1: digit class (response)

column i+1 : pixel intensity  in (-1,1) of pixel number i

```{r}
dim(train)
train[1:10,1:10]
```

Use  *rasterImage* to plot images


```{r}
y <- matrix(as.matrix(train[3400,-1]),16,16,byrow=TRUE)
y <- 1 - (y + 1)*0.5

plot(0,0)
rasterImage(y,-1,-1,1,1)
```

Plot a grid of 48 observations.


```{r, fig.width=7, fig.height=6}

ngr=6
ngc=8
iset <- sample(1:nrow(train),ngr*ngc)
               #5*7)
par(mar=c(0,0,0,0))
par(mfrow=c(ngr,ngc))
for (j in iset) {
  y <- matrix(as.matrix(train[j,-1]),16,16,byrow=TRUE)
  y <- 1 - (y + 1)*0.5

  plot(0,0,xlab="",ylab="",axes=FALSE)
  rasterImage(y,-1,-1,1,1)
  box()
  text(-0.8,-0.7, train[j,1], cex=3, col="red")
}
```

Separate the predictors from the response:

```{r}
Xtrain <- as.matrix(train[,-1])
Xtest <- as.matrix(test[,-1])
ytrain <- train[,1]
ytest <- test[,1]
```

We are ready to build prediction models.


# Prediction by Random forest

We can also run a random forest model. It will run significantly
faster if I restrict the maximum number of nodes somewhat.

```{r}
library(randomForest)
outRf1 <- randomForest(Xtrain,  factor(ytrain), maxnodes=10)
predRf1 <- predict(outRf1, Xtest)
```


Let us calculation the misclassification rate on the test set:


```{r}
mean(predRf1 != ytest)
```

Is this good or is this bad? Maybe we can do better by making a more appropriate choice of the hyperparameters. Here I will only play with 'maxnodes'


```{r}
outRf2 <- randomForest(Xtrain,  factor(ytrain), maxnodes=20)
predRf2 <- predict(outRf2, Xtest)
```



```{r}
outRf3 <- randomForest(Xtrain,  factor(ytrain), maxnodes=30)
predRf3 <- predict(outRf3, Xtest)
```


How well did we do?
10: 0.26,
20: 0.14,
30: 0.128


The accuracy seems to saturate. Assuming that this model is the one we want to keep, the question remains: can we do better?

We need to run another model to answer this question.

Let us try a simple alternative: the k-nearest neighbors (K-nn) model


### fit a K-nearest neighbors model (alternative model 1)

As a simple model, we can use k-nearest neighbors. I set k equal to three,
which in a multi-class model says to use the closest point unless the
next two closest points agree on the class label.

$k=3$ means that we select the class of the closest point as the predicted response except when
the next two closest points give the same class label. In the latter case, we vote for the common label, not for the label of the closest point

```{r}
library(FNN)
predKnn <- knn(Xtrain,Xtest,ytrain,k=3)
```

Let's calculation the misclassification rate of K-nn on the test set (same set as before!)

```{r}
mean(predKnn != ytest)
```

Oh boy!

Lesson learned? 

+ Random forest will not necessarily to the best job? 

+ To consolidate the comparison between the two models, we should of course to a more extensive validation check. I let you do this, e.g. by repeating this exercises on other test-train random splits.


# Summary

+ We have learned how to load, plot and classify images in R

+ Can you do the same with handwritten letters (search for the Emnist dataset)




