Applicazioni pratiche di machine learning/Riconoscimento della scrittura a mano

Caricamento librerie

modifica
 library(caret)

Parte 1 : Dati

modifica

I seguenti files di dati train.csv e test.csv contengono immagini in scala di grigio di numeri disegnati a mano, da zero a nove.

Ogni immagine ha 28 pixel di altezza e 28 pixel di larghezza, per un totale di 784 pixel . Ogni pixel ha un singolo numero associato ad esso, che indica la luminosità o l'oscurità di quel pixel, dove i numeri più alti indicano colori più scuri. Questo numero intero è compreso tra 0 e 255 incluso.

Il training set di dati (train.csv) ha 785 colonne. La prima colonna, chiamata "label", è il numero disegnato dall'utente. Il resto delle colonne contiene i numeri di pixel dell'immagine associata.

Ogni colonna di pixel nel training set ha come nome “pixelx”, dove x è un numero intero compreso tra 0 e 783, incluso. Ad esempio, pixel31 indica il pixel che si trova nella quarta colonna da sinistra e la seconda riga dall'alto.

Il testing set , (test.csv), è uguale al training set , tranne per il fatto che non contiene la colonna "label", che dovrà essere prevista costruendo un modello di classificazione tramite un algoritmo di machine learning.


Caricamento dei dati:

 training <- read.csv("train.csv")
 testing <- read.csv("test.csv")

Parte 2: Domanda di ricerca

modifica

Si vuole predire quale numero da 0 a 9 corrisponde a ciascuna delle 28.000 righe del testing set, ognuna delle quali contiene 784 pixels rappresentati da 784 numeri compresi tra 0 e 255 incluso, relativi al numero scritto a mano dall'utente.

Parte 3: Modellizzazione

modifica

Invece di riconoscere il numero tramite 784 pixels, si calcolano i "principal components" riducendo il numero di predictors da 784 a 20 . Con 20 principal components la varianza ottenuta è pari a circa il 60% come si vede dal seguente grafico :

 #Calcolo principal components
 pca <- prcomp(training[,-1])
 # Calcolo varianza dei singoli principal components
 v <- pca$sdev^2
 #Varianza dei singoli principal componenents diviso la varianza totale
 p <- v/sum(v)
 #Varianza dei primi 20 principal components
 plot(cumsum(p[1:20]) )
 

Divido il training set in un 70% su cui costruisco il modello previsionale utilizzando l'algoritmo di machine learning Random Forest e in un rimanente 30% che chiamo validation set su cui testo il modello. Calcolo poi la confusion matrix sia sul training set. che sul validation set che mi danno rispettivamente un' Accuracy quasi del 100% sul training set, e un'Accuracy del 91% sul validation set . Tutto ciò soltanto con 20 principal components invece di 784 predictors.

 inTrain <- createDataPartition(y=training$label,p=0.7,list = FALSE)
 train_p <- training[inTrain,]
 test_p <- training[-inTrain,]

 pca <- prcomp(train_p[,-1], rank. = 20)
 Z <- as.data.frame(pca$x)
 train_data <- cbind(Z,label=as.factor(train_p$label))
 model <- train(label ~ .,   data=train_data, method="rf", ntree=10)
 pred <- predict(model, newdata=train_data)
 print("Confusion Matrix on training data with Accuracy about 100%")
 confusionMatrix(pred,train_data$label)
 
 test.data <- predict(pca, newdata=test_p)
 test.data <- as.data.frame(test.data)
 rf.pred <- predict(model,test.data) 
 print("Confusion Matrix on testing data with Accuracy about 91%")
 confusionMatrix(rf.pred,as.factor(test_p$label))
Confusion Matrix and Statistics
         Reference
Prediction    0    1    2    3    4    5    6    7    8    9
         0 2871    0    1    1    0    2    2    0    1    2
         1    0 3286    1    0    0    1    0    0    1    0
         2    0    0 2931    2    0    1    0    2    1    0
         3    0    0    0 3019    0    4    0    0    4    3
         4    0    0    1    0 2863    1    0    2    2    5
         5    0    0    0    1    0 2690    0    0    4    0
         6    0    0    2    1    1    0 2864    0    0    0
         7    0    0    0    0    1    0    0 3063    0    1
         8    0    0    2    0    1    0    0    0 2834    1
         9    0    1    0    0    7    0    0    2    0 2917
Overall Statistics
                                         
              Accuracy : 0.9978          
                95% CI : (0.9972, 0.9983)
   No Information Rate : 0.1118          
   P-Value [Acc > NIR] : < 2.2e-16       
                                         
                 Kappa : 0.9975          
                                         
Mcnemar's Test P-Value : NA              
Statistics by Class:
                    Class: 0 Class: 1 Class: 2 Class: 3 Class: 4 Class: 5
Sensitivity           1.00000   0.9997  0.99762   0.9983  0.99652  0.99667
Specificity           0.99966   0.9999  0.99977   0.9996  0.99959  0.99981
Pos Pred Value        0.99687   0.9991  0.99796   0.9964  0.99617  0.99814
Neg Pred Value        1.00000   1.0000  0.99974   0.9998  0.99962  0.99966
Prevalence            0.09764   0.1118  0.09992   0.1028  0.09771  0.09179
Detection Rate        0.09764   0.1118  0.09968   0.1027  0.09737  0.09149
Detection Prevalence  0.09795   0.1119  0.09989   0.1031  0.09775  0.09166
Balanced Accuracy     0.99983   0.9998  0.99870   0.9990  0.99805  0.99824
                     Class: 6 Class: 7 Class: 8 Class: 9
Sensitivity           0.99930   0.9980  0.99543  0.99590
Specificity           0.99985   0.9999  0.99985  0.99962
Pos Pred Value        0.99861   0.9993  0.99859  0.99658
Neg Pred Value        0.99992   0.9998  0.99951  0.99955
Prevalence            0.09747   0.1044  0.09683  0.09962
Detection Rate        0.09741   0.1042  0.09638  0.09921
Detection Prevalence  0.09754   0.1042  0.09652  0.09955
Balanced Accuracy     0.99958   0.9990  0.99764  0.99776

Confusion Matrix and Statistics
         Reference
Prediction    0    1    2    3    4    5    6    7    8    9
         0 1212    0    8    5    1   18   12    2    4    4
         1    0 1366    3    2    6    4    1    9    8    2
         2    7    3 1145   26   10    4   12   24   17    4
         3    2    7   11 1179    2   36    4    6   44   28
         4    2    3   11    3 1071    9    5   14    9   85
         5    9    3    7   44    5  971   12   15   48   12
         6   16    1    9    4   16   10 1220    0    9    3
         7    4    3   22   15   10    5    0 1234   10   52
         8    6    5   20   36   10   24    5    6 1047   15
         9    3    6    3   13   68   15    0   22   20 1054
Overall Statistics
                                         
              Accuracy : 0.9128          
                95% CI : (0.9078, 0.9177)
   No Information Rate : 0.1109          
   P-Value [Acc > NIR] : < 2.2e-16       
                                         
                 Kappa : 0.9031          
                                         
Mcnemar's Test P-Value : NA              
Statistics by Class:
                    Class: 0 Class: 1 Class: 2 Class: 3 Class: 4 Class: 5
Sensitivity           0.96114   0.9778  0.92413  0.88847  0.89324  0.88595
Specificity           0.99524   0.9969  0.99058  0.98758  0.98763  0.98652
Pos Pred Value        0.95735   0.9750  0.91454  0.89386  0.88366  0.86234
Neg Pred Value        0.99568   0.9972  0.99171  0.98688  0.98876  0.98910
Prevalence            0.10010   0.1109  0.09836  0.10534  0.09518  0.08700
Detection Rate        0.09621   0.1084  0.09089  0.09359  0.08502  0.07708
Detection Prevalence  0.10050   0.1112  0.09939  0.10471  0.09621  0.08939
Balanced Accuracy     0.97819   0.9873  0.95736  0.93802  0.94044  0.93624
                     Class: 6 Class: 7 Class: 8 Class: 9
Sensitivity           0.95987  0.92643  0.86102  0.83717
Specificity           0.99400  0.98926  0.98884  0.98677
Pos Pred Value        0.94720  0.91070  0.89182  0.87542
Neg Pred Value        0.99549  0.99128  0.98521  0.98201
Prevalence            0.10090  0.10574  0.09653  0.09994
Detection Rate        0.09685  0.09796  0.08312  0.08367
Detection Prevalence  0.10225  0.10757  0.09320  0.09558
Balanced Accuracy     0.97694  0.95784  0.92493  0.91197

Parte 4: Previsione

modifica

Utilizzo infine il modello precedentemente creato per riconoscere i numeri scritti a mano sul testing set:

 test.data <- predict(pca, newdata = testing)
 test.data <- as.data.frame(test.data)

 rf.pred <- predict(model,test.data) 
 df <- data.frame(ImageId=1:nrow(testing),Label=rf.pred)
 df
 write.csv(df, file="digit_recognizer.csv", row.names = FALSE)
   ImageId Label
1         1     2
2         2     0
3         3     9
4         4     9
5         5     3
6         6     7
7         7     0
8         8     3
9         9     0
10       10     3
11       11     5
12       12     7
13       13     4
14       14     0
15       15     4
16       16     3
17       17     3
18       18     1
19       19     9
20       20     0
21       21     9
22       22     1
23       23     1
24       24     5
25       25     7
26       26     4
27       27     2
28       28     7
29       29     9
30       30     7
31       31     7
32       32     5
33       33     4
34       34     2
35       35     6
36       36     2
37       37     5
38       38     5
39       39     1
40       40     6
...