Teoría

El paqueTe caret(Classification and Regression Training) es una herramienta poderosa para la implementación de modelos de Mchine Learning.

Instalar paquetes y llamar librerías

#install.packages("caret") #Algoritmos de aprendizaje automático
library(caret)
## Loading required package: ggplot2
## Loading required package: lattice
#install.packages("datasets") #Para usar la base de datos "Iris"
library(datasets)
#install.packages("lattice") #Crear gráficos
library(lattice)
#install.packages("DataExplorer") #Análisis Descriptivo"
library(DataExplorer)
#install.packages("kernlab")
library(kernlab)
## 
## Attaching package: 'kernlab'
## The following object is masked from 'package:ggplot2':
## 
##     alpha

Importar la base de datos

df <- data.frame(iris)

Análisis Descriptivo

#create_report(df)
plot_missing(df)

plot_histogram(df)

plot_correlation(df)

** NOTA: La variable que queremos predecir debe 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 uyilizados para modelar aprendizaje autompatico son: * SVM: Support Vector Machine o Máquina de vectores de soporte. Hay varios subtipos: Lineal(symLinear), Radial (symRadial), Polinómico, (svmPoly), etc. * Árbol de decisión: rpart * Redes neuronales: nnet Random Forest** o Bosques Aleatorios: rf #La validación cruzada (cross validation, CV) es una técnica para evaluar el rendimiento de un modelo, divdiendo los datos en múltplies subconguntos, permitiendo medir su capacidadd de generalización y evitar sobreajustes (overfitting). La matriz de confussión (Confusion Matrix*) permite analizar qué tan bien funciona un modelo y qué tipos de errores comete. Lo que hace es comprar las preicciones del modelo con los valores reales de la variable objetivo.

Si la precisión es muy alta en entrenamientoo (95-100%), pero baja en prueba 60, 30) es muy alta de sobreajuste (overfitting)

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) #Cambia hiperparámetros
                )

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

#Matriz de Confusión del Resultado del Entrenamiento
mcre1 <- confusionMatrix(resultado_entrenamiento1, 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 Prueba
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) #Cambia hiperparámetros
                )

resultado_entrenamiento2 <- predict(modelo2, entrenamiento)
resultado_prueba2 <- predict(modelo2, prueba)

#Matriz de Confusión del Resultado del Entrenamiento
mcre2 <- confusionMatrix(resultado_entrenamiento2, 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 Prueba
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 Poly

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) #Cambia hiperparámetros
                )

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

#Matriz de Confusión del Resultado del Entrenamiento
mcre3 <- confusionMatrix(resultado_entrenamiento3, 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 Prueba
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 #Cambia hiperparámetros
                )

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

#Matriz de Confusión del Resultado del Entrenamiento
mcre4 <- confusionMatrix(resultado_entrenamiento4, 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 Prueba
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
                )

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

#Matriz de Confusión del Resultado del Entrenamiento
mcre5 <- confusionMatrix(resultado_entrenamiento5, 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 Prueba
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

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)) #Cambiar hiperparámetros
                )
## 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_entrenamiento6 <- predict(modelo6, entrenamiento)
resultado_prueba6 <- predict(modelo6, prueba)

#Matriz de Confusión del Resultado del Entrenamiento
mcre6 <- confusionMatrix(resultado_entrenamiento6, 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 Prueba
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

Resumen de 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"]),
  "Árbol 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
##                            Árbol.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
LS0tDQp0aXRsZTogIkNBUkVUIg0KYXV0aG9yOiAiTmFuY3kgTWFycm9xdcOtbiAtIEEwMTE5ODU1MyINCmRhdGU6ICIyMDI1LTAyLTIwIg0Kb3V0cHV0OiANCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0b2M6IFRSVUUNCiAgICB0b2NfZmxvYXQ6IFRSVUUNCiAgICBjb2RlX2Rvd25sb2FkOiBUUlVFDQogICAgdGhlbTogInVuaXRlZCINCiAgICBoaWdsaWdodDogImVzcHJlc3NvIg0KLS0tDQoNCiFbXSgiQzpcXFVzZXJzXFxsZW5vdm9cXERvd25sb2Fkc1xcSXJpcy5qcGciKQ0KDQojIDxzcGFuIHN0eWxlPSAiY29sb3I6cHVycGxlOyI+VGVvcsOtYTwvc3Bhbj4NCkVsIHBhcXVlVGUgY2FyZXQoKkNsYXNzaWZpY2F0aW9uIGFuZCBSZWdyZXNzaW9uIFRyYWluaW5nKikgZXMgdW5hIGhlcnJhbWllbnRhIHBvZGVyb3NhIHBhcmEgbGEgaW1wbGVtZW50YWNpw7NuIGRlIG1vZGVsb3MgZGUgKipNY2hpbmUgTGVhcm5pbmcqKi4gIA0KDQoNCiMjIDxzcGFuIHN0eWxlPSAiY29sb3I6cHVycGxlOyI+SW5zdGFsYXIgcGFxdWV0ZXMgeSBsbGFtYXIgbGlicmVyw61hczwvc3Bhbj4NCmBgYHtyIG1lc3NhZ2U9VFJVRSwgd2FybmluZz1UUlVFfQ0KI2luc3RhbGwucGFja2FnZXMoImNhcmV0IikgI0FsZ29yaXRtb3MgZGUgYXByZW5kaXphamUgYXV0b23DoXRpY28NCmxpYnJhcnkoY2FyZXQpDQojaW5zdGFsbC5wYWNrYWdlcygiZGF0YXNldHMiKSAjUGFyYSB1c2FyIGxhIGJhc2UgZGUgZGF0b3MgIklyaXMiDQpsaWJyYXJ5KGRhdGFzZXRzKQ0KI2luc3RhbGwucGFja2FnZXMoImxhdHRpY2UiKSAjQ3JlYXIgZ3LDoWZpY29zDQpsaWJyYXJ5KGxhdHRpY2UpDQojaW5zdGFsbC5wYWNrYWdlcygiRGF0YUV4cGxvcmVyIikgI0Fuw6FsaXNpcyBEZXNjcmlwdGl2byINCmxpYnJhcnkoRGF0YUV4cGxvcmVyKQ0KI2luc3RhbGwucGFja2FnZXMoImtlcm5sYWIiKQ0KbGlicmFyeShrZXJubGFiKQ0KYGBgDQoNCiMjIDxzcGFuIHN0eWxlPSAiY29sb3I6cHVycGxlOyI+SW1wb3J0YXIgbGEgYmFzZSBkZSBkYXRvczwvc3Bhbj4NCmBgYHtyfQ0KZGYgPC0gZGF0YS5mcmFtZShpcmlzKQ0KYGBgDQoNCiMjIDxzcGFuIHN0eWxlPSAiY29sb3I6cHVycGxlOyI+QW7DoWxpc2lzIERlc2NyaXB0aXZvPC9zcGFuPg0KDQpgYGB7cn0NCiNjcmVhdGVfcmVwb3J0KGRmKQ0KcGxvdF9taXNzaW5nKGRmKQ0KcGxvdF9oaXN0b2dyYW0oZGYpDQpwbG90X2NvcnJlbGF0aW9uKGRmKQ0KYGBgDQoqKiBOT1RBOiBMYSB2YXJpYWJsZSBxdWUgcXVlcmVtb3MgcHJlZGVjaXIgZGViZSB0ZW5lciBmb3JtYXRvIGRlIEZBQ1RPUi4gKioNCg0KIyMgPHNwYW4gc3R5bGU9ICJjb2xvcjpwdXJwbGU7Ij5QYXJ0aXIgbG9zIGRhdG9zIDgwLTIwPC9zcGFuPg0KYGBge3J9DQpzZXQuc2VlZCgxMjMpDQpyZW5nbG9uZXNfZW50cmVuYW1pZW50byA8LSBjcmVhdGVEYXRhUGFydGl0aW9uKGRmJFNwZWNpZXMsIHA9MC44LCBsaXN0PUZBTFNFKQ0KZW50cmVuYW1pZW50byA8LSBpcmlzW3Jlbmdsb25lc19lbnRyZW5hbWllbnRvLCBdDQpwcnVlYmEgPC0gaXJpc1stcmVuZ2xvbmVzX2VudHJlbmFtaWVudG8sIF0NCmBgYA0KDQojIyA8c3BhbiBzdHlsZT0gImNvbG9yOnB1cnBsZTsiPkRpc3RpbnRvcyB0aXBvcyBkZSBtw6l0b2RvcyBwYXJhIE1vZGVsYXI8L3NwYW4+DQpMb3MgbcOpdG9kb3MgbcOhcyB1eWlsaXphZG9zIHBhcmEgbW9kZWxhciBhcHJlbmRpemFqZSBhdXRvbXBhdGljbyBzb246DQoqICoqU1ZNOiAqU3VwcG9ydCBWZWN0b3IgTWFjaGluZSogbyBNw6FxdWluYSBkZSB2ZWN0b3JlcyBkZSBzb3BvcnRlLiBIYXkgdmFyaW9zIHN1YnRpcG9zOiBMaW5lYWwoc3ltTGluZWFyKSwgUmFkaWFsIChzeW1SYWRpYWwpLCBQb2xpbsOzbWljbywgKHN2bVBvbHkpLCBldGMuDQoqICoqw4FyYm9sIGRlIGRlY2lzacOzbioqOiBycGFydA0KKiAqKlJlZGVzIG5ldXJvbmFsZXMqKjogbm5ldA0KKipSYW5kb20gRm9yZXN0KiogbyBCb3NxdWVzIEFsZWF0b3Jpb3M6IHJmDQojTGEgKnZhbGlkYWNpw7NuKiogY3J1emFkKiphICgqKmNyb3NzIHZhbGlkYXRpb24qKiwgQ1YpIGVzIHVuYSB0w6ljbmljYSBwYXJhIGV2YWx1YXIgZWwgcmVuZGltaWVudG8gZGUgdW4gbW9kZWxvLCBkaXZkaWVuZG8gbG9zIGRhdG9zIGVuIG3Dumx0cGxpZXMgc3ViY29uZ3VudG9zLCBwZXJtaXRpZW5kbyBtZWRpciBzdSBjYXBhY2lkYWRkIGRlIGdlbmVyYWxpemFjacOzbiB5IGV2aXRhciBzb2JyZWFqdXN0ZXMgKCpvdmVyZml0dGluZyopLg0KTGEgKiptYXRyaXogZGUgY29uZnVzc2nDs24qKiAoKkNvbmZ1c2lvbiBNYXRyaXgqKSBwZXJtaXRlIGFuYWxpemFyIHF1w6kgdGFuIGJpZW4gZnVuY2lvbmEgdW4gbW9kZWxvIHkgcXXDqSB0aXBvcyBkZSBlcnJvcmVzIGNvbWV0ZS4gTG8gcXVlIGhhY2UgZXMgY29tcHJhciBsYXMgcHJlaWNjaW9uZXMgZGVsIG1vZGVsbyBjb24gbG9zIHZhbG9yZXMgcmVhbGVzIGRlIGxhIHZhcmlhYmxlIG9iamV0aXZvLg0KDQpTaSBsYSBwcmVjaXNpw7NuIGVzIG11eSBhbHRhIGVuIGVudHJlbmFtaWVudG9vICg5NS0xMDAlKSwgcGVybyBiYWphIGVuIHBydWViYSA2MCwgMzApIGVzIG11eSBhbHRhIGRlIHNvYnJlYWp1c3RlICgqb3ZlcmZpdHRpbmcqKQ0KDQojIDxzcGFuIHN0eWxlPSAiY29sb3I6cHVycGxlOyI+TW9kZWxvIDEgU1ZNIExpbmVhbDwvc3Bhbj4NCg0KYGBge3J9DQptb2RlbG8xIDwtIHRyYWluKFNwZWNpZXMgfiAuLCBkYXRhPWVudHJlbmFtaWVudG8sIA0KICAgICAgICAgICAgICAgIG1ldGhvZCA9InN2bUxpbmVhciIsICNDYW1iaWFyDQogICAgICAgICAgICAgICAgcHJlUHJvY2Vzcz1jKCJzY2FsZSIsICJjZW50ZXIiKSwNCiAgICAgICAgICAgICAgICB0ckNvbnRyb2wgPSB0cmFpbkNvbnRyb2wobWV0aG9kPSJjdiIsIG51bWJlcj0xMCksDQogICAgICAgICAgICAgICAgdHVuZUdyaWQgPSBkYXRhLmZyYW1lKEM9MSkgI0NhbWJpYSBoaXBlcnBhcsOhbWV0cm9zDQogICAgICAgICAgICAgICAgKQ0KDQpyZXN1bHRhZG9fZW50cmVuYW1pZW50bzEgPC0gcHJlZGljdChtb2RlbG8xLCBlbnRyZW5hbWllbnRvKQ0KcmVzdWx0YWRvX3BydWViYTEgPC0gcHJlZGljdChtb2RlbG8xLCBwcnVlYmEpDQoNCiNNYXRyaXogZGUgQ29uZnVzacOzbiBkZWwgUmVzdWx0YWRvIGRlbCBFbnRyZW5hbWllbnRvDQptY3JlMSA8LSBjb25mdXNpb25NYXRyaXgocmVzdWx0YWRvX2VudHJlbmFtaWVudG8xLCBlbnRyZW5hbWllbnRvJFNwZWNpZXMpDQptY3JlMQ0KDQojTWF0cml6IGRlIENvbmZ1c2nDs24gZGVsIFJlc3VsdGFkbyBkZSBsYSBQcnVlYmENCm1jcnAxIDwtIGNvbmZ1c2lvbk1hdHJpeChyZXN1bHRhZG9fcHJ1ZWJhMSwgcHJ1ZWJhJFNwZWNpZXMpDQptY3JwMQ0KYGBgDQojIDxzcGFuIHN0eWxlPSAiY29sb3I6cHVycGxlOyI+TW9kZWxvIDIgU1ZNIFJhZGlhbDwvc3Bhbj4NCg0KYGBge3J9DQptb2RlbG8yIDwtIHRyYWluKFNwZWNpZXMgfiAuLCBkYXRhPWVudHJlbmFtaWVudG8sIA0KICAgICAgICAgICAgICAgIG1ldGhvZCA9InN2bVJhZGlhbCIsICNDYW1iaWFyDQogICAgICAgICAgICAgICAgcHJlUHJvY2Vzcz1jKCJzY2FsZSIsICJjZW50ZXIiKSwNCiAgICAgICAgICAgICAgICB0ckNvbnRyb2wgPSB0cmFpbkNvbnRyb2wobWV0aG9kPSJjdiIsIG51bWJlcj0xMCksDQogICAgICAgICAgICAgICAgdHVuZUdyaWQgPSBkYXRhLmZyYW1lKHNpZ21hPTEsIEM9MSkgI0NhbWJpYSBoaXBlcnBhcsOhbWV0cm9zDQogICAgICAgICAgICAgICAgKQ0KDQpyZXN1bHRhZG9fZW50cmVuYW1pZW50bzIgPC0gcHJlZGljdChtb2RlbG8yLCBlbnRyZW5hbWllbnRvKQ0KcmVzdWx0YWRvX3BydWViYTIgPC0gcHJlZGljdChtb2RlbG8yLCBwcnVlYmEpDQoNCiNNYXRyaXogZGUgQ29uZnVzacOzbiBkZWwgUmVzdWx0YWRvIGRlbCBFbnRyZW5hbWllbnRvDQptY3JlMiA8LSBjb25mdXNpb25NYXRyaXgocmVzdWx0YWRvX2VudHJlbmFtaWVudG8yLCBlbnRyZW5hbWllbnRvJFNwZWNpZXMpDQptY3JlMg0KDQojTWF0cml6IGRlIENvbmZ1c2nDs24gZGVsIFJlc3VsdGFkbyBkZSBsYSBQcnVlYmENCm1jcnAyIDwtIGNvbmZ1c2lvbk1hdHJpeChyZXN1bHRhZG9fcHJ1ZWJhMiwgcHJ1ZWJhJFNwZWNpZXMpDQptY3JwMg0KYGBgDQoNCiMgPHNwYW4gc3R5bGU9ICJjb2xvcjpwdXJwbGU7Ij5Nb2RlbG8gMyBQb2x5PC9zcGFuPg0KDQpgYGB7cn0NCm1vZGVsbzMgPC0gdHJhaW4oU3BlY2llcyB+IC4sIGRhdGE9ZW50cmVuYW1pZW50bywgDQogICAgICAgICAgICAgICAgbWV0aG9kID0ic3ZtUG9seSIsICNDYW1iaWFyDQogICAgICAgICAgICAgICAgcHJlUHJvY2Vzcz1jKCJzY2FsZSIsICJjZW50ZXIiKSwNCiAgICAgICAgICAgICAgICB0ckNvbnRyb2wgPSB0cmFpbkNvbnRyb2wobWV0aG9kPSJjdiIsIG51bWJlcj0xMCksDQogICAgICAgICAgICAgICAgdHVuZUdyaWQgPSBkYXRhLmZyYW1lKGRlZ3JlZT0xLCBzY2FsZT0xLCBDPTEpICNDYW1iaWEgaGlwZXJwYXLDoW1ldHJvcw0KICAgICAgICAgICAgICAgICkNCg0KcmVzdWx0YWRvX2VudHJlbmFtaWVudG8zIDwtIHByZWRpY3QobW9kZWxvMywgZW50cmVuYW1pZW50bykNCnJlc3VsdGFkb19wcnVlYmEzIDwtIHByZWRpY3QobW9kZWxvMywgcHJ1ZWJhKQ0KDQojTWF0cml6IGRlIENvbmZ1c2nDs24gZGVsIFJlc3VsdGFkbyBkZWwgRW50cmVuYW1pZW50bw0KbWNyZTMgPC0gY29uZnVzaW9uTWF0cml4KHJlc3VsdGFkb19lbnRyZW5hbWllbnRvMywgZW50cmVuYW1pZW50byRTcGVjaWVzKQ0KbWNyZTMNCg0KI01hdHJpeiBkZSBDb25mdXNpw7NuIGRlbCBSZXN1bHRhZG8gZGUgbGEgUHJ1ZWJhDQptY3JwMyA8LSBjb25mdXNpb25NYXRyaXgocmVzdWx0YWRvX3BydWViYTMsIHBydWViYSRTcGVjaWVzKQ0KbWNycDMNCmBgYA0KIyA8c3BhbiBzdHlsZT0gImNvbG9yOnB1cnBsZTsiPk1vZGVsbyA0IMOBcmJvbCBkZSBEZWNpc2nDs248L3NwYW4+DQoNCg0KYGBge3J9DQptb2RlbG80IDwtIHRyYWluKFNwZWNpZXMgfiAuLCBkYXRhPWVudHJlbmFtaWVudG8sIA0KICAgICAgICAgICAgICAgIG1ldGhvZCA9InJwYXJ0IiwgI0NhbWJpYXINCiAgICAgICAgICAgICAgICBwcmVQcm9jZXNzPWMoInNjYWxlIiwgImNlbnRlciIpLA0KICAgICAgICAgICAgICAgIHRyQ29udHJvbCA9IHRyYWluQ29udHJvbChtZXRob2Q9ImN2IiwgbnVtYmVyPTEwKSwNCiAgICAgICAgICAgICAgICB0dW5lTGVuZ3RoID0gMTAgI0NhbWJpYSBoaXBlcnBhcsOhbWV0cm9zDQogICAgICAgICAgICAgICAgKQ0KDQpyZXN1bHRhZG9fZW50cmVuYW1pZW50bzQgPC0gcHJlZGljdChtb2RlbG80LCBlbnRyZW5hbWllbnRvKQ0KcmVzdWx0YWRvX3BydWViYTQgPC0gcHJlZGljdChtb2RlbG80LCBwcnVlYmEpDQoNCiNNYXRyaXogZGUgQ29uZnVzacOzbiBkZWwgUmVzdWx0YWRvIGRlbCBFbnRyZW5hbWllbnRvDQptY3JlNCA8LSBjb25mdXNpb25NYXRyaXgocmVzdWx0YWRvX2VudHJlbmFtaWVudG80LCBlbnRyZW5hbWllbnRvJFNwZWNpZXMpDQptY3JlNA0KDQojTWF0cml6IGRlIENvbmZ1c2nDs24gZGVsIFJlc3VsdGFkbyBkZSBsYSBQcnVlYmENCm1jcnA0IDwtIGNvbmZ1c2lvbk1hdHJpeChyZXN1bHRhZG9fcHJ1ZWJhNCwgcHJ1ZWJhJFNwZWNpZXMpDQptY3JwNA0KYGBgDQoNCiMgPHNwYW4gc3R5bGU9ICJjb2xvcjpwdXJwbGU7Ij5Nb2RlbG8gNSBSZWRlcyBOZXVyb25hbGVzPC9zcGFuPg0KDQoNCmBgYHtyfQ0KbW9kZWxvNSA8LSB0cmFpbihTcGVjaWVzIH4gLiwgZGF0YT1lbnRyZW5hbWllbnRvLCANCiAgICAgICAgICAgICAgICBtZXRob2QgPSJubmV0IiwgI0NhbWJpYXINCiAgICAgICAgICAgICAgICBwcmVQcm9jZXNzPWMoInNjYWxlIiwgImNlbnRlciIpLA0KICAgICAgICAgICAgICAgIHRyQ29udHJvbCA9IHRyYWluQ29udHJvbChtZXRob2Q9ImN2IiwgbnVtYmVyPTEwKSwNCiAgICAgICAgICAgICAgICB0cmFjZT1GQUxTRQ0KICAgICAgICAgICAgICAgICkNCg0KcmVzdWx0YWRvX2VudHJlbmFtaWVudG81IDwtIHByZWRpY3QobW9kZWxvNSwgZW50cmVuYW1pZW50bykNCnJlc3VsdGFkb19wcnVlYmE1IDwtIHByZWRpY3QobW9kZWxvNSwgcHJ1ZWJhKQ0KDQojTWF0cml6IGRlIENvbmZ1c2nDs24gZGVsIFJlc3VsdGFkbyBkZWwgRW50cmVuYW1pZW50bw0KbWNyZTUgPC0gY29uZnVzaW9uTWF0cml4KHJlc3VsdGFkb19lbnRyZW5hbWllbnRvNSwgZW50cmVuYW1pZW50byRTcGVjaWVzKQ0KbWNyZTUNCg0KI01hdHJpeiBkZSBDb25mdXNpw7NuIGRlbCBSZXN1bHRhZG8gZGUgbGEgUHJ1ZWJhDQptY3JwNSA8LSBjb25mdXNpb25NYXRyaXgocmVzdWx0YWRvX3BydWViYTUsIHBydWViYSRTcGVjaWVzKQ0KbWNycDUNCmBgYA0KIyA8c3BhbiBzdHlsZT0gImNvbG9yOnB1cnBsZTsiPk1vZGVsbyA2IEJvc3F1ZXMgQWxlYXRvcmlvczwvc3Bhbj4NCg0KDQpgYGB7cn0NCm1vZGVsbzYgPC0gdHJhaW4oU3BlY2llcyB+IC4sIGRhdGE9ZW50cmVuYW1pZW50bywgDQogICAgICAgICAgICAgICAgbWV0aG9kID0icmYiLCAjQ2FtYmlhcg0KICAgICAgICAgICAgICAgIHByZVByb2Nlc3M9Yygic2NhbGUiLCAiY2VudGVyIiksDQogICAgICAgICAgICAgICAgdHJDb250cm9sID0gdHJhaW5Db250cm9sKG1ldGhvZD0iY3YiLCBudW1iZXI9MTApLA0KICAgICAgICAgICAgICAgIHR1bmVHcmlkID0gZXhwYW5kLmdyaWQobXRyeSA9IGMoMiw0LDYpKSAjQ2FtYmlhciBoaXBlcnBhcsOhbWV0cm9zDQogICAgICAgICAgICAgICAgKQ0KDQpyZXN1bHRhZG9fZW50cmVuYW1pZW50bzYgPC0gcHJlZGljdChtb2RlbG82LCBlbnRyZW5hbWllbnRvKQ0KcmVzdWx0YWRvX3BydWViYTYgPC0gcHJlZGljdChtb2RlbG82LCBwcnVlYmEpDQoNCiNNYXRyaXogZGUgQ29uZnVzacOzbiBkZWwgUmVzdWx0YWRvIGRlbCBFbnRyZW5hbWllbnRvDQptY3JlNiA8LSBjb25mdXNpb25NYXRyaXgocmVzdWx0YWRvX2VudHJlbmFtaWVudG82LCBlbnRyZW5hbWllbnRvJFNwZWNpZXMpDQptY3JlNg0KDQojTWF0cml6IGRlIENvbmZ1c2nDs24gZGVsIFJlc3VsdGFkbyBkZSBsYSBQcnVlYmENCm1jcnA2IDwtIGNvbmZ1c2lvbk1hdHJpeChyZXN1bHRhZG9fcHJ1ZWJhNiwgcHJ1ZWJhJFNwZWNpZXMpDQptY3JwNg0KYGBgDQoNCiMgPHNwYW4gc3R5bGU9ICJjb2xvcjpwdXJwbGU7Ij5SZXN1bWVuIGRlIFJlc3VsdGFkb3M8L3NwYW4+DQoNCmBgYHtyfQ0KcmVzdWx0YWRvcyA8LSBkYXRhLmZyYW1lKA0KICAiU1ZNIExpbmVhbCIgPSBjKG1jcmUxJG92ZXJhbGxbIkFjY3VyYWN5Il0sIG1jcnAxJG92ZXJhbGxbIkFjY3VyYWN5Il0pLA0KICAiU1ZNIFJhZGlhbCIgPSBjKG1jcmUyJG92ZXJhbGxbIkFjY3VyYWN5Il0sIG1jcnAyJG92ZXJhbGxbIkFjY3VyYWN5Il0pLA0KICAiU1ZNIFBvbGluw7NtaWNvIiA9IGMobWNyZTMkb3ZlcmFsbFsiQWNjdXJhY3kiXSwgbWNycDMkb3ZlcmFsbFsiQWNjdXJhY3kiXSksDQogICLDgXJib2wgZGUgRGVjaXNpw7NuIiA9IGMobWNyZTQkb3ZlcmFsbFsiQWNjdXJhY3kiXSwgbWNycDQkb3ZlcmFsbFsiQWNjdXJhY3kiXSksDQogICJSZWRlcyBOZXVyb25hbGVzIiA9IGMobWNyZTUkb3ZlcmFsbFsiQWNjdXJhY3kiXSwgbWNycDUkb3ZlcmFsbFsiQWNjdXJhY3kiXSksDQogICJCb3NxdWVzIEFsZWF0b3Jpb3MiID0gYyhtY3JlNiRvdmVyYWxsWyJBY2N1cmFjeSJdLCBtY3JwNiRvdmVyYWxsWyJBY2N1cmFjeSJdKQ0KKQ0Kcm93bmFtZXMocmVzdWx0YWRvcykgPC0gYygiUHJlY2lzacOzbiBkZSBFbnRyZW5hbWllbnRvIiwgIlByZWNpc2nDs24gZGUgUHJ1ZWJhIikNCnJlc3VsdGFkb3MNCmBgYA0KDQo=