Teoría

El paquete caret(Classification And Regression Training) es una herramienta poderosa para la implementación de modelos de Machine Learning.

Instalar paquetes y llamar librerías

#install.packages("caret") #Algoritmos de aprendzaje automático
library(caret)
#install.packages("datasets")
library(datasets)
#install.packages("ggplot2")
library(ggplot2)
#install.packages("DataExplorer") #Analisis Descriptivo
library(DataExplorer) 
#install.packages("lattice")
library(lattice)

Importar la base de datos

df <- data.frame(iris)

Análsis descriptiva

#create_report(df)
plot_missing(df)

plot_histogram(df)

plot_correlation(df)

** NOTA: La variable que queremos predecir tiene que tener formato de FACTOR**

Partir los datos 80-20

set.seed(123)
renglones_entrenamiento <- createDataPartition(df$Species, p=0.8, list = FALSE)
entrenamiento <- iris[renglones_entrenamiento, ]
prueba <- iris [-renglones_entrenamiento, ]

Distintos Tipos de Métodos para Modelar

Los métodos más utilizados para modelar aprendizaje automático son: * SVM: Support Vector Machine Hay varios subtipos: Lineal (svmLinear), Radial (svmRadial), Polinomico (svmPoly), etc. * Arbol de Decisión: rpart * Redes Neuronales: nnet * Random Forest**: rf

La validación cruzada (CV,Cross validation) es una técnica para evaluar el rendimiento de un modelo, divideindo los datos en múltiples subconjuntos, permitiendo medir su capacidad de generalización y evitar sobreajuste (overfitting).

La matriz de confusión (Confusion Matrix) permite analizar que tan bien funciona un modelo y qué tipos de errores comete. Lo que hace es comparar las predicciones del modelo con los valores reales de la variable objetivo.

Si la precisión es muy alta en entrenamiento (95-100%), pero baja en prueba (60-70%), es una señal de sobreajuste (overfitting).

#install.packages("kernlab")
library(kernlab)
## 
## Adjuntando el paquete: 'kernlab'
## The following object is masked from 'package:ggplot2':
## 
##     alpha

Modelo 1. SVM Lineal

modelo1 <-train(Species ~ ., data=entrenamiento,
                method="svmLinear", #Cambiar 
                preProcess=c("scale","center"),
                trControl=trainControl(method="cv",number=10),
                tuneGrid=data.frame(C=1) #Cambiar hiperparámetros
                )

resultado_entrenamiento <- predict(modelo1,entrenamiento)
resultado_prueba1 <- predict(modelo1,prueba)


#Matriz de confusión del  resultado del entrenamiento
mcre1 <-confusionMatrix(resultado_entrenamiento,entrenamiento$Species)
mcre1
## Confusion Matrix and Statistics
## 
##             Reference
## Prediction   setosa versicolor virginica
##   setosa         40          0         0
##   versicolor      0         39         0
##   virginica       0          1        40
## 
## Overall Statistics
##                                           
##                Accuracy : 0.9917          
##                  95% CI : (0.9544, 0.9998)
##     No Information Rate : 0.3333          
##     P-Value [Acc > NIR] : < 2.2e-16       
##                                           
##                   Kappa : 0.9875          
##                                           
##  Mcnemar's Test P-Value : NA              
## 
## Statistics by Class:
## 
##                      Class: setosa Class: versicolor Class: virginica
## Sensitivity                 1.0000            0.9750           1.0000
## Specificity                 1.0000            1.0000           0.9875
## Pos Pred Value              1.0000            1.0000           0.9756
## Neg Pred Value              1.0000            0.9877           1.0000
## Prevalence                  0.3333            0.3333           0.3333
## Detection Rate              0.3333            0.3250           0.3333
## Detection Prevalence        0.3333            0.3250           0.3417
## Balanced Accuracy           1.0000            0.9875           0.9938
#Matriz de confusión del  resultado de la pureba
mcrp1 <-confusionMatrix(resultado_prueba1,prueba$Species)
mcrp1
## Confusion Matrix and Statistics
## 
##             Reference
## Prediction   setosa versicolor virginica
##   setosa         10          0         0
##   versicolor      0         10         1
##   virginica       0          0         9
## 
## Overall Statistics
##                                           
##                Accuracy : 0.9667          
##                  95% CI : (0.8278, 0.9992)
##     No Information Rate : 0.3333          
##     P-Value [Acc > NIR] : 2.963e-13       
##                                           
##                   Kappa : 0.95            
##                                           
##  Mcnemar's Test P-Value : NA              
## 
## Statistics by Class:
## 
##                      Class: setosa Class: versicolor Class: virginica
## Sensitivity                 1.0000            1.0000           0.9000
## Specificity                 1.0000            0.9500           1.0000
## Pos Pred Value              1.0000            0.9091           1.0000
## Neg Pred Value              1.0000            1.0000           0.9524
## Prevalence                  0.3333            0.3333           0.3333
## Detection Rate              0.3333            0.3333           0.3000
## Detection Prevalence        0.3333            0.3667           0.3000
## Balanced Accuracy           1.0000            0.9750           0.9500

Modelo 2. SVM Radial

modelo2 <-train(Species ~ ., data=entrenamiento,
                method="svmRadial", #Cambiar 
                preProcess=c("scale","center"),
                trControl=trainControl(method="cv",number=10),
                tuneGrid=data.frame(sigma=1, C=1) #Cambiar hiperparámetros
                )

resultado_entrenamiento <- predict(modelo1,entrenamiento)
resultado_prueba2 <- predict(modelo2,prueba)


#Matriz de confusión del  resultado del entrenamiento
mcre2 <-confusionMatrix(resultado_entrenamiento,entrenamiento$Species)
mcre2
## Confusion Matrix and Statistics
## 
##             Reference
## Prediction   setosa versicolor virginica
##   setosa         40          0         0
##   versicolor      0         39         0
##   virginica       0          1        40
## 
## Overall Statistics
##                                           
##                Accuracy : 0.9917          
##                  95% CI : (0.9544, 0.9998)
##     No Information Rate : 0.3333          
##     P-Value [Acc > NIR] : < 2.2e-16       
##                                           
##                   Kappa : 0.9875          
##                                           
##  Mcnemar's Test P-Value : NA              
## 
## Statistics by Class:
## 
##                      Class: setosa Class: versicolor Class: virginica
## Sensitivity                 1.0000            0.9750           1.0000
## Specificity                 1.0000            1.0000           0.9875
## Pos Pred Value              1.0000            1.0000           0.9756
## Neg Pred Value              1.0000            0.9877           1.0000
## Prevalence                  0.3333            0.3333           0.3333
## Detection Rate              0.3333            0.3250           0.3333
## Detection Prevalence        0.3333            0.3250           0.3417
## Balanced Accuracy           1.0000            0.9875           0.9938
#Matriz de confusión del  resultado de la pureba
mcrp2 <-confusionMatrix(resultado_prueba2,prueba$Species)
mcrp2
## Confusion Matrix and Statistics
## 
##             Reference
## Prediction   setosa versicolor virginica
##   setosa         10          0         0
##   versicolor      0         10         2
##   virginica       0          0         8
## 
## Overall Statistics
##                                           
##                Accuracy : 0.9333          
##                  95% CI : (0.7793, 0.9918)
##     No Information Rate : 0.3333          
##     P-Value [Acc > NIR] : 8.747e-12       
##                                           
##                   Kappa : 0.9             
##                                           
##  Mcnemar's Test P-Value : NA              
## 
## Statistics by Class:
## 
##                      Class: setosa Class: versicolor Class: virginica
## Sensitivity                 1.0000            1.0000           0.8000
## Specificity                 1.0000            0.9000           1.0000
## Pos Pred Value              1.0000            0.8333           1.0000
## Neg Pred Value              1.0000            1.0000           0.9091
## Prevalence                  0.3333            0.3333           0.3333
## Detection Rate              0.3333            0.3333           0.2667
## Detection Prevalence        0.3333            0.4000           0.2667
## Balanced Accuracy           1.0000            0.9500           0.9000

Modelo 3. Polinómico

modelo3 <-train(Species ~ ., data=entrenamiento,
                method="svmPoly", #Cambiar 
                preProcess=c("scale","center"),
                trControl=trainControl(method="cv",number=10),
                tuneGrid=data.frame(degree=1, scale=1,C=1) #Cambiar hiperparámetros
                )

resultado_entrenamiento <- predict(modelo3,entrenamiento)
resultado_prueba3 <- predict(modelo3,prueba)


#Matriz de confusión del  resultado del entrenamiento
mcre3 <-confusionMatrix(resultado_entrenamiento,entrenamiento$Species)
mcre3
## Confusion Matrix and Statistics
## 
##             Reference
## Prediction   setosa versicolor virginica
##   setosa         40          0         0
##   versicolor      0         39         0
##   virginica       0          1        40
## 
## Overall Statistics
##                                           
##                Accuracy : 0.9917          
##                  95% CI : (0.9544, 0.9998)
##     No Information Rate : 0.3333          
##     P-Value [Acc > NIR] : < 2.2e-16       
##                                           
##                   Kappa : 0.9875          
##                                           
##  Mcnemar's Test P-Value : NA              
## 
## Statistics by Class:
## 
##                      Class: setosa Class: versicolor Class: virginica
## Sensitivity                 1.0000            0.9750           1.0000
## Specificity                 1.0000            1.0000           0.9875
## Pos Pred Value              1.0000            1.0000           0.9756
## Neg Pred Value              1.0000            0.9877           1.0000
## Prevalence                  0.3333            0.3333           0.3333
## Detection Rate              0.3333            0.3250           0.3333
## Detection Prevalence        0.3333            0.3250           0.3417
## Balanced Accuracy           1.0000            0.9875           0.9938
#Matriz de confusión del  resultado de la pureba
mcrp3 <-confusionMatrix(resultado_prueba3,prueba$Species)
mcrp3
## Confusion Matrix and Statistics
## 
##             Reference
## Prediction   setosa versicolor virginica
##   setosa         10          0         0
##   versicolor      0         10         1
##   virginica       0          0         9
## 
## Overall Statistics
##                                           
##                Accuracy : 0.9667          
##                  95% CI : (0.8278, 0.9992)
##     No Information Rate : 0.3333          
##     P-Value [Acc > NIR] : 2.963e-13       
##                                           
##                   Kappa : 0.95            
##                                           
##  Mcnemar's Test P-Value : NA              
## 
## Statistics by Class:
## 
##                      Class: setosa Class: versicolor Class: virginica
## Sensitivity                 1.0000            1.0000           0.9000
## Specificity                 1.0000            0.9500           1.0000
## Pos Pred Value              1.0000            0.9091           1.0000
## Neg Pred Value              1.0000            1.0000           0.9524
## Prevalence                  0.3333            0.3333           0.3333
## Detection Rate              0.3333            0.3333           0.3000
## Detection Prevalence        0.3333            0.3667           0.3000
## Balanced Accuracy           1.0000            0.9750           0.9500

Modelo 4. Árbol de Decisión

modelo4 <-train(Species ~ ., data=entrenamiento,
                method="rpart", #Cambiar 
                preProcess=c("scale","center"),
                trControl=trainControl(method="cv",number=10),
                tuneLength=10 #Cambiar hiperparámetros
                )

resultado_entrenamiento <- predict(modelo4,entrenamiento)
resultado_prueba4 <- predict(modelo4,prueba)


#Matriz de confusión del  resultado del entrenamiento
mcre4 <-confusionMatrix(resultado_entrenamiento,entrenamiento$Species)
mcre4
## Confusion Matrix and Statistics
## 
##             Reference
## Prediction   setosa versicolor virginica
##   setosa         40          0         0
##   versicolor      0         39         3
##   virginica       0          1        37
## 
## Overall Statistics
##                                           
##                Accuracy : 0.9667          
##                  95% CI : (0.9169, 0.9908)
##     No Information Rate : 0.3333          
##     P-Value [Acc > NIR] : < 2.2e-16       
##                                           
##                   Kappa : 0.95            
##                                           
##  Mcnemar's Test P-Value : NA              
## 
## Statistics by Class:
## 
##                      Class: setosa Class: versicolor Class: virginica
## Sensitivity                 1.0000            0.9750           0.9250
## Specificity                 1.0000            0.9625           0.9875
## Pos Pred Value              1.0000            0.9286           0.9737
## Neg Pred Value              1.0000            0.9872           0.9634
## Prevalence                  0.3333            0.3333           0.3333
## Detection Rate              0.3333            0.3250           0.3083
## Detection Prevalence        0.3333            0.3500           0.3167
## Balanced Accuracy           1.0000            0.9688           0.9563
#Matriz de confusión del  resultado de la pureba
mcrp4 <-confusionMatrix(resultado_prueba4,prueba$Species)
mcrp4
## Confusion Matrix and Statistics
## 
##             Reference
## Prediction   setosa versicolor virginica
##   setosa         10          0         0
##   versicolor      0         10         2
##   virginica       0          0         8
## 
## Overall Statistics
##                                           
##                Accuracy : 0.9333          
##                  95% CI : (0.7793, 0.9918)
##     No Information Rate : 0.3333          
##     P-Value [Acc > NIR] : 8.747e-12       
##                                           
##                   Kappa : 0.9             
##                                           
##  Mcnemar's Test P-Value : NA              
## 
## Statistics by Class:
## 
##                      Class: setosa Class: versicolor Class: virginica
## Sensitivity                 1.0000            1.0000           0.8000
## Specificity                 1.0000            0.9000           1.0000
## Pos Pred Value              1.0000            0.8333           1.0000
## Neg Pred Value              1.0000            1.0000           0.9091
## Prevalence                  0.3333            0.3333           0.3333
## Detection Rate              0.3333            0.3333           0.2667
## Detection Prevalence        0.3333            0.4000           0.2667
## Balanced Accuracy           1.0000            0.9500           0.9000

Modelo 5. Redes Neuronales

modelo5 <-train(Species ~ ., data=entrenamiento,
                method="nnet", #Cambiar 
                preProcess=c("scale","center"),
                trControl=trainControl(method="cv",number=10),
                trace=FALSE #Para ocultar el resultado
                )

resultado_entrenamiento <- predict(modelo5,entrenamiento)
resultado_prueba5 <- predict(modelo5,prueba)


#Matriz de confusión del  resultado del entrenamiento
mcre5 <-confusionMatrix(resultado_entrenamiento,entrenamiento$Species)
mcre5
## Confusion Matrix and Statistics
## 
##             Reference
## Prediction   setosa versicolor virginica
##   setosa         40          0         0
##   versicolor      0         36         0
##   virginica       0          4        40
## 
## Overall Statistics
##                                           
##                Accuracy : 0.9667          
##                  95% CI : (0.9169, 0.9908)
##     No Information Rate : 0.3333          
##     P-Value [Acc > NIR] : < 2.2e-16       
##                                           
##                   Kappa : 0.95            
##                                           
##  Mcnemar's Test P-Value : NA              
## 
## Statistics by Class:
## 
##                      Class: setosa Class: versicolor Class: virginica
## Sensitivity                 1.0000            0.9000           1.0000
## Specificity                 1.0000            1.0000           0.9500
## Pos Pred Value              1.0000            1.0000           0.9091
## Neg Pred Value              1.0000            0.9524           1.0000
## Prevalence                  0.3333            0.3333           0.3333
## Detection Rate              0.3333            0.3000           0.3333
## Detection Prevalence        0.3333            0.3000           0.3667
## Balanced Accuracy           1.0000            0.9500           0.9750
#Matriz de confusión del  resultado de la pureba
mcrp5 <-confusionMatrix(resultado_prueba5,prueba$Species)
mcrp5
## Confusion Matrix and Statistics
## 
##             Reference
## Prediction   setosa versicolor virginica
##   setosa         10          0         0
##   versicolor      0          9         0
##   virginica       0          1        10
## 
## Overall Statistics
##                                           
##                Accuracy : 0.9667          
##                  95% CI : (0.8278, 0.9992)
##     No Information Rate : 0.3333          
##     P-Value [Acc > NIR] : 2.963e-13       
##                                           
##                   Kappa : 0.95            
##                                           
##  Mcnemar's Test P-Value : NA              
## 
## Statistics by Class:
## 
##                      Class: setosa Class: versicolor Class: virginica
## Sensitivity                 1.0000            0.9000           1.0000
## Specificity                 1.0000            1.0000           0.9500
## Pos Pred Value              1.0000            1.0000           0.9091
## Neg Pred Value              1.0000            0.9524           1.0000
## Prevalence                  0.3333            0.3333           0.3333
## Detection Rate              0.3333            0.3000           0.3333
## Detection Prevalence        0.3333            0.3000           0.3667
## Balanced Accuracy           1.0000            0.9500           0.9750

Modelo 6. Bosques Aleatorios

#install.packages("randomForest")
library(randomForest)
## randomForest 4.7-1.2
## Type rfNews() to see new features/changes/bug fixes.
## 
## Adjuntando el paquete: 'randomForest'
## The following object is masked from 'package:ggplot2':
## 
##     margin
modelo6 <-train(Species ~ ., data=entrenamiento,
                method="rf", #Cambiar 
                preProcess=c("scale","center"),
                trControl=trainControl(method="cv",number=10),
                tuneGrid= expand.grid(mtry= c(2,4,6)) #Para ocultar el resultado
                )
## Warning in randomForest.default(x, y, mtry = param$mtry, ...): invalid mtry:
## reset to within valid range
## Warning in randomForest.default(x, y, mtry = param$mtry, ...): invalid mtry:
## reset to within valid range
## Warning in randomForest.default(x, y, mtry = param$mtry, ...): invalid mtry:
## reset to within valid range
## Warning in randomForest.default(x, y, mtry = param$mtry, ...): invalid mtry:
## reset to within valid range
## Warning in randomForest.default(x, y, mtry = param$mtry, ...): invalid mtry:
## reset to within valid range
## Warning in randomForest.default(x, y, mtry = param$mtry, ...): invalid mtry:
## reset to within valid range
## Warning in randomForest.default(x, y, mtry = param$mtry, ...): invalid mtry:
## reset to within valid range
## Warning in randomForest.default(x, y, mtry = param$mtry, ...): invalid mtry:
## reset to within valid range
## Warning in randomForest.default(x, y, mtry = param$mtry, ...): invalid mtry:
## reset to within valid range
## Warning in randomForest.default(x, y, mtry = param$mtry, ...): invalid mtry:
## reset to within valid range
resultado_entrenamiento <- predict(modelo6,entrenamiento)
resultado_prueba6 <- predict(modelo6,prueba)


#Matriz de confusión del  resultado del entrenamiento
mcre6 <-confusionMatrix(resultado_entrenamiento,entrenamiento$Species)
mcre6
## Confusion Matrix and Statistics
## 
##             Reference
## Prediction   setosa versicolor virginica
##   setosa         40          0         0
##   versicolor      0         40         0
##   virginica       0          0        40
## 
## Overall Statistics
##                                      
##                Accuracy : 1          
##                  95% CI : (0.9697, 1)
##     No Information Rate : 0.3333     
##     P-Value [Acc > NIR] : < 2.2e-16  
##                                      
##                   Kappa : 1          
##                                      
##  Mcnemar's Test P-Value : NA         
## 
## Statistics by Class:
## 
##                      Class: setosa Class: versicolor Class: virginica
## 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.3333            0.3333           0.3333
## Detection Rate              0.3333            0.3333           0.3333
## Detection Prevalence        0.3333            0.3333           0.3333
## Balanced Accuracy           1.0000            1.0000           1.0000
#Matriz de confusión del  resultado de la pureba
mcrp6 <-confusionMatrix(resultado_prueba6,prueba$Species)
mcrp6
## Confusion Matrix and Statistics
## 
##             Reference
## Prediction   setosa versicolor virginica
##   setosa         10          0         0
##   versicolor      0         10         2
##   virginica       0          0         8
## 
## Overall Statistics
##                                           
##                Accuracy : 0.9333          
##                  95% CI : (0.7793, 0.9918)
##     No Information Rate : 0.3333          
##     P-Value [Acc > NIR] : 8.747e-12       
##                                           
##                   Kappa : 0.9             
##                                           
##  Mcnemar's Test P-Value : NA              
## 
## Statistics by Class:
## 
##                      Class: setosa Class: versicolor Class: virginica
## Sensitivity                 1.0000            1.0000           0.8000
## Specificity                 1.0000            0.9000           1.0000
## Pos Pred Value              1.0000            0.8333           1.0000
## Neg Pred Value              1.0000            1.0000           0.9091
## Prevalence                  0.3333            0.3333           0.3333
## Detection Rate              0.3333            0.3333           0.2667
## Detection Prevalence        0.3333            0.4000           0.2667
## Balanced Accuracy           1.0000            0.9500           0.9000
print(mcre1$overall["Accuracy"])
##  Accuracy 
## 0.9916667
print(mcrp1$overall["Accuracy"])
##  Accuracy 
## 0.9666667

Resumen de los Resultados

resultados <- data.frame(
  "SVM Lineal" = c(mcre1$overall["Accuracy"],mcrp1$overall["Accuracy"]),
  "SVM Radial" = c(mcre2$overall["Accuracy"],mcrp2$overall["Accuracy"]),
  "SVM Polinómico" = c(mcre3$overall["Accuracy"],mcrp3$overall["Accuracy"]),
  "Árboles de decisión" = c(mcre4$overall["Accuracy"],mcrp4$overall["Accuracy"]),
  "Redes Neuronales" = c(mcre5$overall["Accuracy"],mcrp5$overall["Accuracy"]),
  "Bosques aleatorios" = c(mcre6$overall["Accuracy"],mcrp6$overall["Accuracy"])
)
rownames(resultados) <-c("Precisión de entrenamiento","Precisión de prueba")
resultados
##                            SVM.Lineal SVM.Radial SVM.Polinómico
## Precisión de entrenamiento  0.9916667  0.9916667      0.9916667
## Precisión de prueba         0.9666667  0.9333333      0.9666667
##                            Árboles.de.decisión Redes.Neuronales
## Precisión de entrenamiento           0.9666667        0.9666667
## Precisión de prueba                  0.9333333        0.9666667
##                            Bosques.aleatorios
## Precisión de entrenamiento          1.0000000
## Precisión de prueba                 0.9333333
LS0tDQp0aXRsZTogIkNBUkVUIg0KYXV0aG9yOiAiUm9tZXJ5IEx1bmEgQTAxNzQ5ODM3Ig0KZGF0ZTogIjIwMjUtMDItMjAiDQpvdXRwdXQ6IA0KICBodG1sX2RvY3VtZW50Og0KICAgICAgdG9jOiBUUlVFDQogICAgICB0b2NfZmxvYXQ6IFRSVUUNCiAgICAgIGNvZGVfZG93bmxvYWQ6IFRSVUUNCiAgICAgIHRoZW1lOiAic3BhY2VsYWIiDQogICAgICBoaWdobGlnaHQ6ICJrYXRlIg0KLS0tDQoNCiFbXShDOlxcVXNlcnNcXHJ5bHVuXFxPbmVEcml2ZVxcSW3DoWdlbmVzXFxpcmlzLnBuZykgDQoNCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiBwdXJwbGU7Ij5UZW9yw61hPC9zcGFuPg0KDQpFbCBwYXF1ZXRlIGNhcmV0KCpDbGFzc2lmaWNhdGlvbiBBbmQgUmVncmVzc2lvbiBUcmFpbmluZyopIGVzIHVuYSBoZXJyYW1pZW50YSBwb2Rlcm9zYSBwYXJhIGxhIGltcGxlbWVudGFjacOzbiBkZSBtb2RlbG9zIGRlICoqTWFjaGluZSBMZWFybmluZyoqLg0KDQojIyA8c3BhbiBzdHlsZT0iY29sb3I6IHB1cnBsZTsiPkluc3RhbGFyIHBhcXVldGVzIHkgbGxhbWFyIGxpYnJlcsOtYXM8L3NwYW4+DQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KI2luc3RhbGwucGFja2FnZXMoImNhcmV0IikgI0FsZ29yaXRtb3MgZGUgYXByZW5kemFqZSBhdXRvbcOhdGljbw0KbGlicmFyeShjYXJldCkNCiNpbnN0YWxsLnBhY2thZ2VzKCJkYXRhc2V0cyIpDQpsaWJyYXJ5KGRhdGFzZXRzKQ0KI2luc3RhbGwucGFja2FnZXMoImdncGxvdDIiKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KI2luc3RhbGwucGFja2FnZXMoIkRhdGFFeHBsb3JlciIpICNBbmFsaXNpcyBEZXNjcmlwdGl2bw0KbGlicmFyeShEYXRhRXhwbG9yZXIpIA0KI2luc3RhbGwucGFja2FnZXMoImxhdHRpY2UiKQ0KbGlicmFyeShsYXR0aWNlKQ0KYGBgDQoNCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogcHVycGxlOyI+SW1wb3J0YXIgbGEgYmFzZSBkZSBkYXRvczwvc3Bhbj4NCmBgYHtyfQ0KZGYgPC0gZGF0YS5mcmFtZShpcmlzKQ0KYGBgDQoNCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogcHVycGxlOyI+QW7DoWxzaXMgZGVzY3JpcHRpdmE8L3NwYW4+DQpgYGB7cn0NCiNjcmVhdGVfcmVwb3J0KGRmKQ0KcGxvdF9taXNzaW5nKGRmKQ0KYGBgDQpgYGB7cn0NCnBsb3RfaGlzdG9ncmFtKGRmKQ0KYGBgDQpgYGB7cn0NCnBsb3RfY29ycmVsYXRpb24oZGYpDQpgYGANCg0KDQoqKiBOT1RBOiBMYSB2YXJpYWJsZSBxdWUgcXVlcmVtb3MgcHJlZGVjaXIgdGllbmUgcXVlIHRlbmVyIGZvcm1hdG8gZGUgRkFDVE9SKioNCg0KIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBwdXJwbGU7Ij5QYXJ0aXIgbG9zIGRhdG9zIDgwLTIwPC9zcGFuPg0KYGBge3J9DQpzZXQuc2VlZCgxMjMpDQpyZW5nbG9uZXNfZW50cmVuYW1pZW50byA8LSBjcmVhdGVEYXRhUGFydGl0aW9uKGRmJFNwZWNpZXMsIHA9MC44LCBsaXN0ID0gRkFMU0UpDQplbnRyZW5hbWllbnRvIDwtIGlyaXNbcmVuZ2xvbmVzX2VudHJlbmFtaWVudG8sIF0NCnBydWViYSA8LSBpcmlzIFstcmVuZ2xvbmVzX2VudHJlbmFtaWVudG8sIF0NCmBgYA0KDQojIyA8c3BhbiBzdHlsZT0iY29sb3I6IHB1cnBsZTsiPkRpc3RpbnRvcyBUaXBvcyBkZSBNw6l0b2RvcyBwYXJhIE1vZGVsYXI8L3NwYW4+DQpMb3MgbcOpdG9kb3MgbcOhcyB1dGlsaXphZG9zIHBhcmEgbW9kZWxhciBhcHJlbmRpemFqZSBhdXRvbcOhdGljbyBzb246DQoqICoqU1ZNOiAqU3VwcG9ydCBWZWN0b3IgTWFjaGluZSogSGF5IHZhcmlvcyBzdWJ0aXBvczogTGluZWFsIChzdm1MaW5lYXIpLCBSYWRpYWwgKHN2bVJhZGlhbCksIFBvbGlub21pY28gKHN2bVBvbHkpLCBldGMuDQoqICoqQXJib2wgZGUgRGVjaXNpw7NuKio6IHJwYXJ0DQoqICoqUmVkZXMgTmV1cm9uYWxlcyoqOiBubmV0DQoqICoqUmFuZG9tIEZvcmVzdCoqOiByZg0KDQpMYSB2YWxpZGFjacOzbiBjcnV6YWRhIChDVixDcm9zcyB2YWxpZGF0aW9uKSBlcyB1bmEgdMOpY25pY2EgcGFyYSBldmFsdWFyIGVsIHJlbmRpbWllbnRvIGRlIHVuIG1vZGVsbywgZGl2aWRlaW5kbyBsb3MgZGF0b3MgZW4gbcO6bHRpcGxlcyBzdWJjb25qdW50b3MsIHBlcm1pdGllbmRvIG1lZGlyIHN1IGNhcGFjaWRhZCBkZSBnZW5lcmFsaXphY2nDs24geSBldml0YXIgc29icmVhanVzdGUgKG92ZXJmaXR0aW5nKS4NCg0KTGEgKiptYXRyaXogZGUgY29uZnVzacOzbiAoQ29uZnVzaW9uIE1hdHJpeCkqKiBwZXJtaXRlIGFuYWxpemFyIHF1ZSB0YW4gYmllbiBmdW5jaW9uYSB1biBtb2RlbG8geSBxdcOpIHRpcG9zIGRlIGVycm9yZXMgY29tZXRlLiBMbyBxdWUgaGFjZSBlcyBjb21wYXJhciBsYXMgcHJlZGljY2lvbmVzIGRlbCBtb2RlbG8gY29uIGxvcyB2YWxvcmVzIHJlYWxlcyBkZSBsYSB2YXJpYWJsZSBvYmpldGl2by4NCg0KU2kgbGEgcHJlY2lzacOzbiBlcyBtdXkgYWx0YSBlbiBlbnRyZW5hbWllbnRvICg5NS0xMDAlKSwgcGVybyBiYWphIGVuIHBydWViYSAoNjAtNzAlKSwgZXMgdW5hIHNlw7FhbCBkZSAqKnNvYnJlYWp1c3RlKiogKG92ZXJmaXR0aW5nKS4NCg0KYGBge3J9DQojaW5zdGFsbC5wYWNrYWdlcygia2VybmxhYiIpDQpsaWJyYXJ5KGtlcm5sYWIpDQpgYGANCg0KIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBwdXJwbGU7Ij5Nb2RlbG8gMS4gU1ZNIExpbmVhbDwvc3Bhbj4NCmBgYHtyfQ0KbW9kZWxvMSA8LXRyYWluKFNwZWNpZXMgfiAuLCBkYXRhPWVudHJlbmFtaWVudG8sDQogICAgICAgICAgICAgICAgbWV0aG9kPSJzdm1MaW5lYXIiLCAjQ2FtYmlhciANCiAgICAgICAgICAgICAgICBwcmVQcm9jZXNzPWMoInNjYWxlIiwiY2VudGVyIiksDQogICAgICAgICAgICAgICAgdHJDb250cm9sPXRyYWluQ29udHJvbChtZXRob2Q9ImN2IixudW1iZXI9MTApLA0KICAgICAgICAgICAgICAgIHR1bmVHcmlkPWRhdGEuZnJhbWUoQz0xKSAjQ2FtYmlhciBoaXBlcnBhcsOhbWV0cm9zDQogICAgICAgICAgICAgICAgKQ0KDQpyZXN1bHRhZG9fZW50cmVuYW1pZW50byA8LSBwcmVkaWN0KG1vZGVsbzEsZW50cmVuYW1pZW50bykNCnJlc3VsdGFkb19wcnVlYmExIDwtIHByZWRpY3QobW9kZWxvMSxwcnVlYmEpDQoNCg0KI01hdHJpeiBkZSBjb25mdXNpw7NuIGRlbCAgcmVzdWx0YWRvIGRlbCBlbnRyZW5hbWllbnRvDQptY3JlMSA8LWNvbmZ1c2lvbk1hdHJpeChyZXN1bHRhZG9fZW50cmVuYW1pZW50byxlbnRyZW5hbWllbnRvJFNwZWNpZXMpDQptY3JlMQ0KDQojTWF0cml6IGRlIGNvbmZ1c2nDs24gZGVsICByZXN1bHRhZG8gZGUgbGEgcHVyZWJhDQptY3JwMSA8LWNvbmZ1c2lvbk1hdHJpeChyZXN1bHRhZG9fcHJ1ZWJhMSxwcnVlYmEkU3BlY2llcykNCm1jcnAxDQpgYGANCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogcHVycGxlOyI+TW9kZWxvIDIuIFNWTSBSYWRpYWw8L3NwYW4+DQpgYGB7cn0NCm1vZGVsbzIgPC10cmFpbihTcGVjaWVzIH4gLiwgZGF0YT1lbnRyZW5hbWllbnRvLA0KICAgICAgICAgICAgICAgIG1ldGhvZD0ic3ZtUmFkaWFsIiwgI0NhbWJpYXIgDQogICAgICAgICAgICAgICAgcHJlUHJvY2Vzcz1jKCJzY2FsZSIsImNlbnRlciIpLA0KICAgICAgICAgICAgICAgIHRyQ29udHJvbD10cmFpbkNvbnRyb2wobWV0aG9kPSJjdiIsbnVtYmVyPTEwKSwNCiAgICAgICAgICAgICAgICB0dW5lR3JpZD1kYXRhLmZyYW1lKHNpZ21hPTEsIEM9MSkgI0NhbWJpYXIgaGlwZXJwYXLDoW1ldHJvcw0KICAgICAgICAgICAgICAgICkNCg0KcmVzdWx0YWRvX2VudHJlbmFtaWVudG8gPC0gcHJlZGljdChtb2RlbG8xLGVudHJlbmFtaWVudG8pDQpyZXN1bHRhZG9fcHJ1ZWJhMiA8LSBwcmVkaWN0KG1vZGVsbzIscHJ1ZWJhKQ0KDQoNCiNNYXRyaXogZGUgY29uZnVzacOzbiBkZWwgIHJlc3VsdGFkbyBkZWwgZW50cmVuYW1pZW50bw0KbWNyZTIgPC1jb25mdXNpb25NYXRyaXgocmVzdWx0YWRvX2VudHJlbmFtaWVudG8sZW50cmVuYW1pZW50byRTcGVjaWVzKQ0KbWNyZTINCg0KI01hdHJpeiBkZSBjb25mdXNpw7NuIGRlbCAgcmVzdWx0YWRvIGRlIGxhIHB1cmViYQ0KbWNycDIgPC1jb25mdXNpb25NYXRyaXgocmVzdWx0YWRvX3BydWViYTIscHJ1ZWJhJFNwZWNpZXMpDQptY3JwMg0KYGBgDQojIyA8c3BhbiBzdHlsZT0iY29sb3I6IHB1cnBsZTsiPk1vZGVsbyAzLiBQb2xpbsOzbWljbzwvc3Bhbj4NCmBgYHtyfQ0KbW9kZWxvMyA8LXRyYWluKFNwZWNpZXMgfiAuLCBkYXRhPWVudHJlbmFtaWVudG8sDQogICAgICAgICAgICAgICAgbWV0aG9kPSJzdm1Qb2x5IiwgI0NhbWJpYXIgDQogICAgICAgICAgICAgICAgcHJlUHJvY2Vzcz1jKCJzY2FsZSIsImNlbnRlciIpLA0KICAgICAgICAgICAgICAgIHRyQ29udHJvbD10cmFpbkNvbnRyb2wobWV0aG9kPSJjdiIsbnVtYmVyPTEwKSwNCiAgICAgICAgICAgICAgICB0dW5lR3JpZD1kYXRhLmZyYW1lKGRlZ3JlZT0xLCBzY2FsZT0xLEM9MSkgI0NhbWJpYXIgaGlwZXJwYXLDoW1ldHJvcw0KICAgICAgICAgICAgICAgICkNCg0KcmVzdWx0YWRvX2VudHJlbmFtaWVudG8gPC0gcHJlZGljdChtb2RlbG8zLGVudHJlbmFtaWVudG8pDQpyZXN1bHRhZG9fcHJ1ZWJhMyA8LSBwcmVkaWN0KG1vZGVsbzMscHJ1ZWJhKQ0KDQoNCiNNYXRyaXogZGUgY29uZnVzacOzbiBkZWwgIHJlc3VsdGFkbyBkZWwgZW50cmVuYW1pZW50bw0KbWNyZTMgPC1jb25mdXNpb25NYXRyaXgocmVzdWx0YWRvX2VudHJlbmFtaWVudG8sZW50cmVuYW1pZW50byRTcGVjaWVzKQ0KbWNyZTMNCg0KI01hdHJpeiBkZSBjb25mdXNpw7NuIGRlbCAgcmVzdWx0YWRvIGRlIGxhIHB1cmViYQ0KbWNycDMgPC1jb25mdXNpb25NYXRyaXgocmVzdWx0YWRvX3BydWViYTMscHJ1ZWJhJFNwZWNpZXMpDQptY3JwMw0KYGBgDQojIyA8c3BhbiBzdHlsZT0iY29sb3I6IHB1cnBsZTsiPk1vZGVsbyA0LiDDgXJib2wgZGUgRGVjaXNpw7NuPC9zcGFuPg0KDQpgYGB7cn0NCm1vZGVsbzQgPC10cmFpbihTcGVjaWVzIH4gLiwgZGF0YT1lbnRyZW5hbWllbnRvLA0KICAgICAgICAgICAgICAgIG1ldGhvZD0icnBhcnQiLCAjQ2FtYmlhciANCiAgICAgICAgICAgICAgICBwcmVQcm9jZXNzPWMoInNjYWxlIiwiY2VudGVyIiksDQogICAgICAgICAgICAgICAgdHJDb250cm9sPXRyYWluQ29udHJvbChtZXRob2Q9ImN2IixudW1iZXI9MTApLA0KICAgICAgICAgICAgICAgIHR1bmVMZW5ndGg9MTAgI0NhbWJpYXIgaGlwZXJwYXLDoW1ldHJvcw0KICAgICAgICAgICAgICAgICkNCg0KcmVzdWx0YWRvX2VudHJlbmFtaWVudG8gPC0gcHJlZGljdChtb2RlbG80LGVudHJlbmFtaWVudG8pDQpyZXN1bHRhZG9fcHJ1ZWJhNCA8LSBwcmVkaWN0KG1vZGVsbzQscHJ1ZWJhKQ0KDQoNCiNNYXRyaXogZGUgY29uZnVzacOzbiBkZWwgIHJlc3VsdGFkbyBkZWwgZW50cmVuYW1pZW50bw0KbWNyZTQgPC1jb25mdXNpb25NYXRyaXgocmVzdWx0YWRvX2VudHJlbmFtaWVudG8sZW50cmVuYW1pZW50byRTcGVjaWVzKQ0KbWNyZTQNCg0KI01hdHJpeiBkZSBjb25mdXNpw7NuIGRlbCAgcmVzdWx0YWRvIGRlIGxhIHB1cmViYQ0KbWNycDQgPC1jb25mdXNpb25NYXRyaXgocmVzdWx0YWRvX3BydWViYTQscHJ1ZWJhJFNwZWNpZXMpDQptY3JwNA0KYGBgDQojIyA8c3BhbiBzdHlsZT0iY29sb3I6IHB1cnBsZTsiPk1vZGVsbyA1LiBSZWRlcyBOZXVyb25hbGVzPC9zcGFuPg0KDQpgYGB7cn0NCm1vZGVsbzUgPC10cmFpbihTcGVjaWVzIH4gLiwgZGF0YT1lbnRyZW5hbWllbnRvLA0KICAgICAgICAgICAgICAgIG1ldGhvZD0ibm5ldCIsICNDYW1iaWFyIA0KICAgICAgICAgICAgICAgIHByZVByb2Nlc3M9Yygic2NhbGUiLCJjZW50ZXIiKSwNCiAgICAgICAgICAgICAgICB0ckNvbnRyb2w9dHJhaW5Db250cm9sKG1ldGhvZD0iY3YiLG51bWJlcj0xMCksDQogICAgICAgICAgICAgICAgdHJhY2U9RkFMU0UgI1BhcmEgb2N1bHRhciBlbCByZXN1bHRhZG8NCiAgICAgICAgICAgICAgICApDQoNCnJlc3VsdGFkb19lbnRyZW5hbWllbnRvIDwtIHByZWRpY3QobW9kZWxvNSxlbnRyZW5hbWllbnRvKQ0KcmVzdWx0YWRvX3BydWViYTUgPC0gcHJlZGljdChtb2RlbG81LHBydWViYSkNCg0KDQojTWF0cml6IGRlIGNvbmZ1c2nDs24gZGVsICByZXN1bHRhZG8gZGVsIGVudHJlbmFtaWVudG8NCm1jcmU1IDwtY29uZnVzaW9uTWF0cml4KHJlc3VsdGFkb19lbnRyZW5hbWllbnRvLGVudHJlbmFtaWVudG8kU3BlY2llcykNCm1jcmU1DQoNCiNNYXRyaXogZGUgY29uZnVzacOzbiBkZWwgIHJlc3VsdGFkbyBkZSBsYSBwdXJlYmENCm1jcnA1IDwtY29uZnVzaW9uTWF0cml4KHJlc3VsdGFkb19wcnVlYmE1LHBydWViYSRTcGVjaWVzKQ0KbWNycDUNCmBgYA0KIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBwdXJwbGU7Ij5Nb2RlbG8gNi4gQm9zcXVlcyBBbGVhdG9yaW9zPC9zcGFuPg0KDQoNCg0KYGBge3J9DQojaW5zdGFsbC5wYWNrYWdlcygicmFuZG9tRm9yZXN0IikNCmxpYnJhcnkocmFuZG9tRm9yZXN0KQ0KDQptb2RlbG82IDwtdHJhaW4oU3BlY2llcyB+IC4sIGRhdGE9ZW50cmVuYW1pZW50bywNCiAgICAgICAgICAgICAgICBtZXRob2Q9InJmIiwgI0NhbWJpYXIgDQogICAgICAgICAgICAgICAgcHJlUHJvY2Vzcz1jKCJzY2FsZSIsImNlbnRlciIpLA0KICAgICAgICAgICAgICAgIHRyQ29udHJvbD10cmFpbkNvbnRyb2wobWV0aG9kPSJjdiIsbnVtYmVyPTEwKSwNCiAgICAgICAgICAgICAgICB0dW5lR3JpZD0gZXhwYW5kLmdyaWQobXRyeT0gYygyLDQsNikpICNQYXJhIG9jdWx0YXIgZWwgcmVzdWx0YWRvDQogICAgICAgICAgICAgICAgKQ0KDQpyZXN1bHRhZG9fZW50cmVuYW1pZW50byA8LSBwcmVkaWN0KG1vZGVsbzYsZW50cmVuYW1pZW50bykNCnJlc3VsdGFkb19wcnVlYmE2IDwtIHByZWRpY3QobW9kZWxvNixwcnVlYmEpDQoNCg0KI01hdHJpeiBkZSBjb25mdXNpw7NuIGRlbCAgcmVzdWx0YWRvIGRlbCBlbnRyZW5hbWllbnRvDQptY3JlNiA8LWNvbmZ1c2lvbk1hdHJpeChyZXN1bHRhZG9fZW50cmVuYW1pZW50byxlbnRyZW5hbWllbnRvJFNwZWNpZXMpDQptY3JlNg0KDQojTWF0cml6IGRlIGNvbmZ1c2nDs24gZGVsICByZXN1bHRhZG8gZGUgbGEgcHVyZWJhDQptY3JwNiA8LWNvbmZ1c2lvbk1hdHJpeChyZXN1bHRhZG9fcHJ1ZWJhNixwcnVlYmEkU3BlY2llcykNCm1jcnA2DQpgYGANCg0KDQoNCg0KYGBge3J9DQpwcmludChtY3JlMSRvdmVyYWxsWyJBY2N1cmFjeSJdKQ0KcHJpbnQobWNycDEkb3ZlcmFsbFsiQWNjdXJhY3kiXSkNCmBgYA0KIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBwdXJwbGU7Ij5SZXN1bWVuIGRlIGxvcyBSZXN1bHRhZG9zPC9zcGFuPg0KDQpgYGB7cn0NCnJlc3VsdGFkb3MgPC0gZGF0YS5mcmFtZSgNCiAgIlNWTSBMaW5lYWwiID0gYyhtY3JlMSRvdmVyYWxsWyJBY2N1cmFjeSJdLG1jcnAxJG92ZXJhbGxbIkFjY3VyYWN5Il0pLA0KICAiU1ZNIFJhZGlhbCIgPSBjKG1jcmUyJG92ZXJhbGxbIkFjY3VyYWN5Il0sbWNycDIkb3ZlcmFsbFsiQWNjdXJhY3kiXSksDQogICJTVk0gUG9saW7Ds21pY28iID0gYyhtY3JlMyRvdmVyYWxsWyJBY2N1cmFjeSJdLG1jcnAzJG92ZXJhbGxbIkFjY3VyYWN5Il0pLA0KICAiw4FyYm9sZXMgZGUgZGVjaXNpw7NuIiA9IGMobWNyZTQkb3ZlcmFsbFsiQWNjdXJhY3kiXSxtY3JwNCRvdmVyYWxsWyJBY2N1cmFjeSJdKSwNCiAgIlJlZGVzIE5ldXJvbmFsZXMiID0gYyhtY3JlNSRvdmVyYWxsWyJBY2N1cmFjeSJdLG1jcnA1JG92ZXJhbGxbIkFjY3VyYWN5Il0pLA0KICAiQm9zcXVlcyBhbGVhdG9yaW9zIiA9IGMobWNyZTYkb3ZlcmFsbFsiQWNjdXJhY3kiXSxtY3JwNiRvdmVyYWxsWyJBY2N1cmFjeSJdKQ0KKQ0Kcm93bmFtZXMocmVzdWx0YWRvcykgPC1jKCJQcmVjaXNpw7NuIGRlIGVudHJlbmFtaWVudG8iLCJQcmVjaXNpw7NuIGRlIHBydWViYSIpDQpyZXN1bHRhZG9zDQpgYGANCg0K