Teoría

el paquete Caret (classification and regression training) es un paquete integral con una amplia variedad de algoritmos para el aprendizaje automático.

Instalar paquetes y llamar librerías

ˆ

#install.packages("ggplot2")
library("ggplot2")
#install.packages("lattice") # crear gráficos 
library("lattice")
#install.packages("caret") #algoritmos de aprendizaje automatico
library("caret")
#install.packages("datasets") #Usar bd en, en este caso iris
library("datasets")
#install.packages("DataExplorer") #analisis exploratorio
library("DataExplorer")
library(nnet)

Crear la base de datos

df<- data.frame(iris)

Entender la bd

summary(df)
##   Sepal.Length    Sepal.Width     Petal.Length    Petal.Width   
##  Min.   :4.300   Min.   :2.000   Min.   :1.000   Min.   :0.100  
##  1st Qu.:5.100   1st Qu.:2.800   1st Qu.:1.600   1st Qu.:0.300  
##  Median :5.800   Median :3.000   Median :4.350   Median :1.300  
##  Mean   :5.843   Mean   :3.057   Mean   :3.758   Mean   :1.199  
##  3rd Qu.:6.400   3rd Qu.:3.300   3rd Qu.:5.100   3rd Qu.:1.800  
##  Max.   :7.900   Max.   :4.400   Max.   :6.900   Max.   :2.500  
##        Species  
##  setosa    :50  
##  versicolor:50  
##  virginica :50  
##                 
##                 
## 
str(df)
## '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 ...
#create_report(df)
plot_missing(df)

plot_histogram(df)

plot_correlation(df)

Nota: la variabole que queremos predecir debe tener formato de FACTOR

Partir la base de datos

#Normalmente 80-20
set.seed(123) #num aleatorios son los mismos
renglones_entrenamiento<-createDataPartition(df$Species,p=.8,list=FALSE)
entrenamiento<-iris[renglones_entrenamiento,]
prueba<-iris[-renglones_entrenamiento,]

Distintos tipos de metodos para modelar

Loa métodos más utilizados oara modelar aprendizajes automatico son: * SV: Support vector machine o máquina de vectores de soporte. Hay varios subtipos: Lineal(svmLinear), Radial (svmRadial), Polinomico (svmPoly), etc.

  • Árbol de Decisión: rpart
  • Redes Neuronales: nnet
  • Random Forest o Bosques Aleatorios: rf

Modelo 1. SVM Lineal

modelo1<- train(Species ~ ., data=entrenamiento,
                method = "svmLinear", #cambiar
                preProcess= c("scale","center"),
                trControl=trainControl(method = "cv", number = 10),
                tuneGride=data.frame(c=1))#cambiar
resultado_entrenamiento1<- predict(modelo1,entrenamiento)
resultado_prueba<-predict(modelo1,prueba)
#matriz de confusión 
#es una tabla de evaluación que desgloda el rendimiento del modelo de clasificacion
#matriz de confusion 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
mcrp1<- confusionMatrix(resultado_prueba, 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 Lineal

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

resultado_entrenamiento2<- predict(modelo1,entrenamiento)
resultado_prueba2<-predict(modelo2,prueba)
#matriz de confusión 
#es una tabla de evaluación que desgloda el rendimiento del modelo de clasificacion
#matriz de confusion 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
mcrp2<- confusionMatrix(resultado_prueba, prueba$Species)
mcrp2
## 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 3. SVM Lineal

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

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

# Matriz de Confusión
# Es una tabla de evaluación que desglosa el rendimiento del modelo de clasificación.

# 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         40         4
##   virginica       0          0        36
## 
## 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            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
# 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         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 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
                  )

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

# Matriz de Confusión
# Es una tabla de evaluación que desglosa el rendimiento del modelo de clasificación.

# 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",
  preProcess = c("center", "scale"),
  trControl = trainControl(method = "cv", number = 10),
  tuneLength = 5,        # o usa tuneGrid si quieres controlar size/decay
  trace = FALSE,
  MaxNWts = 5000         # por si hay muchas variables/pesos
)

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

# Matriz de Confusión
# Es una tabla de evaluación que desglosa el rendimiento del modelo de clasificación.

# 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
)
## 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
# Es una tabla de evaluación que desglosa el rendimiento del modelo de clasificación.

# 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

Tabla de Resultados

resultados <- data.frame(
  "svmLinear" = c(mcre1$overall["Accuracy"], mcrp1$overall["Accuracy"]),
  "svmRadial" = c(mcre2$overall["Accuracy"], mcrp2$overall["Accuracy"]),
  "svmPoly"   = c(mcre3$overall["Accuracy"], mcrp3$overall["Accuracy"]),
  "rpart"     = c(mcre4$overall["Accuracy"], mcrp4$overall["Accuracy"]),
  "nnet"      = c(mcre5$overall["Accuracy"], mcrp5$overall["Accuracy"]),
  "rf"        = c(mcre6$overall["Accuracy"], mcrp6$overall["Accuracy"])
)

# Add a third row: difference
diff_row <- resultados[1, ] - resultados[2, ]
resultados <- rbind(resultados, diff_row)

rownames(resultados) <-  c("Precisión de entrenamiento", "Precisión de prueba", "Diferencia")
resultados
##                            svmLinear svmRadial    svmPoly      rpart      nnet
## Precisión de entrenamiento 0.9916667 0.9916667 0.96666667 0.96666667 0.9666667
## Precisión de prueba        0.9666667 0.9666667 0.93333333 0.93333333 0.9666667
## Diferencia                 0.0250000 0.0250000 0.03333333 0.03333333 0.0000000
##                                    rf
## Precisión de entrenamiento 1.00000000
## Precisión de prueba        0.93333333
## Diferencia                 0.06666667

Conclusiones

Acorde a la tabla de resultados, observamos que ningún método presenta sobreajuste. Podemos seleccionar el de svmLinear por su desempeño.

LS0tCnRpdGxlOiAiQ2FyZXQiCmF1dGhvcjogIkthcmxhIE1pcmV5YSBWZWxkZXJyYWluIEEwMDIyNzQxMSIKZGF0ZTogIjIwMjUtMDgtMjIiCm91dHB1dDogCiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICB0aGVtZTogc2ltcGxleAotLS0KCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiMxODc0Q0QiPiBUZW9yw61hIDwvc3Bhbj4KZWwgcGFxdWV0ZSAqKkNhcmV0IChjbGFzc2lmaWNhdGlvbiBhbmQgcmVncmVzc2lvbiB0cmFpbmluZykqKiBlcyB1biBwYXF1ZXRlIGludGVncmFsIGNvbiB1bmEgYW1wbGlhIHZhcmllZGFkIGRlIGFsZ29yaXRtb3MgcGFyYSBlbCBhcHJlbmRpemFqZSBhdXRvbcOhdGljby4KCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiMxODc0Q0QiPiBJbnN0YWxhciBwYXF1ZXRlcyB5IGxsYW1hciBsaWJyZXLDrWFzIDwvc3Bhbj4Ky4YKYGBge3J9CiNpbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIikKbGlicmFyeSgiZ2dwbG90MiIpCiNpbnN0YWxsLnBhY2thZ2VzKCJsYXR0aWNlIikgIyBjcmVhciBncsOhZmljb3MgCmxpYnJhcnkoImxhdHRpY2UiKQojaW5zdGFsbC5wYWNrYWdlcygiY2FyZXQiKSAjYWxnb3JpdG1vcyBkZSBhcHJlbmRpemFqZSBhdXRvbWF0aWNvCmxpYnJhcnkoImNhcmV0IikKI2luc3RhbGwucGFja2FnZXMoImRhdGFzZXRzIikgI1VzYXIgYmQgZW4sIGVuIGVzdGUgY2FzbyBpcmlzCmxpYnJhcnkoImRhdGFzZXRzIikKI2luc3RhbGwucGFja2FnZXMoIkRhdGFFeHBsb3JlciIpICNhbmFsaXNpcyBleHBsb3JhdG9yaW8KbGlicmFyeSgiRGF0YUV4cGxvcmVyIikKbGlicmFyeShubmV0KQpgYGAKCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiMxODc0Q0QiPiBDcmVhciBsYSBiYXNlIGRlIGRhdG9zIDwvc3Bhbj4KCmBgYHtyfQpkZjwtIGRhdGEuZnJhbWUoaXJpcykKYGBgCgojIDxzcGFuIHN0eWxlPSJjb2xvcjojMTg3NENEIj4gRW50ZW5kZXIgbGEgYmQgPC9zcGFuPgoKYGBge3J9CnN1bW1hcnkoZGYpCnN0cihkZikKI2NyZWF0ZV9yZXBvcnQoZGYpCnBsb3RfbWlzc2luZyhkZikKcGxvdF9oaXN0b2dyYW0oZGYpCnBsb3RfY29ycmVsYXRpb24oZGYpCmBgYAoqKk5vdGE6IGxhIHZhcmlhYm9sZSBxdWUgcXVlcmVtb3MgcHJlZGVjaXIgZGViZSB0ZW5lciBmb3JtYXRvIGRlIEZBQ1RPUioqCgojIDxzcGFuIHN0eWxlPSJjb2xvcjojMTg3NENEIj4gUGFydGlyIGxhIGJhc2UgZGUgZGF0b3MgPC9zcGFuPgpgYGB7cn0KI05vcm1hbG1lbnRlIDgwLTIwCnNldC5zZWVkKDEyMykgI251bSBhbGVhdG9yaW9zIHNvbiBsb3MgbWlzbW9zCnJlbmdsb25lc19lbnRyZW5hbWllbnRvPC1jcmVhdGVEYXRhUGFydGl0aW9uKGRmJFNwZWNpZXMscD0uOCxsaXN0PUZBTFNFKQplbnRyZW5hbWllbnRvPC1pcmlzW3Jlbmdsb25lc19lbnRyZW5hbWllbnRvLF0KcHJ1ZWJhPC1pcmlzWy1yZW5nbG9uZXNfZW50cmVuYW1pZW50byxdCmBgYAoKIyA8c3BhbiBzdHlsZT0iY29sb3I6IzE4NzRDRCI+IERpc3RpbnRvcyB0aXBvcyBkZSBtZXRvZG9zIHBhcmEgbW9kZWxhciA8L3NwYW4+CkxvYSBtw6l0b2RvcyAgbcOhcyAgdXRpbGl6YWRvcyBvYXJhIG1vZGVsYXIgYXByZW5kaXphamVzIGF1dG9tYXRpY28gc29uOgoqICoqU1YqKjogKlN1cHBvcnQgdmVjdG9yIG1hY2hpbmUqIG8gbcOhcXVpbmEgZGUgdmVjdG9yZXMgZGUgc29wb3J0ZS4gSGF5IHZhcmlvcyBzdWJ0aXBvczogTGluZWFsKHN2bUxpbmVhciksIFJhZGlhbCAoc3ZtUmFkaWFsKSwgUG9saW5vbWljbyAoc3ZtUG9seSksIGV0Yy4KCiogKirDgXJib2wgZGUgRGVjaXNpw7NuKio6IHJwYXJ0CiogKipSZWRlcyBOZXVyb25hbGVzKio6IG5uZXQKKiAqKlJhbmRvbSBGb3Jlc3QqKiBvIEJvc3F1ZXMgQWxlYXRvcmlvczogcmYKCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiMxODc0Q0QiPiBNb2RlbG8gMS4gU1ZNIExpbmVhbCAgPC9zcGFuPgpgYGB7cn0KbW9kZWxvMTwtIHRyYWluKFNwZWNpZXMgfiAuLCBkYXRhPWVudHJlbmFtaWVudG8sCiAgICAgICAgICAgICAgICBtZXRob2QgPSAic3ZtTGluZWFyIiwgI2NhbWJpYXIKICAgICAgICAgICAgICAgIHByZVByb2Nlc3M9IGMoInNjYWxlIiwiY2VudGVyIiksCiAgICAgICAgICAgICAgICB0ckNvbnRyb2w9dHJhaW5Db250cm9sKG1ldGhvZCA9ICJjdiIsIG51bWJlciA9IDEwKSwKICAgICAgICAgICAgICAgIHR1bmVHcmlkZT1kYXRhLmZyYW1lKGM9MSkpI2NhbWJpYXIKcmVzdWx0YWRvX2VudHJlbmFtaWVudG8xPC0gcHJlZGljdChtb2RlbG8xLGVudHJlbmFtaWVudG8pCnJlc3VsdGFkb19wcnVlYmE8LXByZWRpY3QobW9kZWxvMSxwcnVlYmEpCiNtYXRyaXogZGUgY29uZnVzacOzbiAKI2VzIHVuYSB0YWJsYSBkZSBldmFsdWFjacOzbiBxdWUgZGVzZ2xvZGEgZWwgcmVuZGltaWVudG8gZGVsIG1vZGVsbyBkZSBjbGFzaWZpY2FjaW9uCiNtYXRyaXogZGUgY29uZnVzaW9uIGRlbCByZXN1bHRhZG8gZGVsIGVudHJlbmFtaWVudG8KbWNyZTE8LSBjb25mdXNpb25NYXRyaXgocmVzdWx0YWRvX2VudHJlbmFtaWVudG8xLGVudHJlbmFtaWVudG8kU3BlY2llcykKbWNyZTEKCm1jcnAxPC0gY29uZnVzaW9uTWF0cml4KHJlc3VsdGFkb19wcnVlYmEsIHBydWViYSRTcGVjaWVzKQptY3JwMQoKYGBgCgojIDxzcGFuIHN0eWxlPSJjb2xvcjojMTg3NENEIj4gTW9kZWxvIDIuIFNWTSBMaW5lYWwgIDwvc3Bhbj4KCmBgYHtyfQptb2RlbG8yPC0gdHJhaW4oU3BlY2llcyB+IC4sIGRhdGE9ZW50cmVuYW1pZW50bywKICAgICAgICAgICAgICAgIG1ldGhvZCA9ICJzdm1SYWRpYWwiLCAjY2FtYmlhcgogICAgICAgICAgICAgICAgcHJlUHJvY2Vzcz0gYygic2NhbGUiLCJjZW50ZXIiKSwKICAgICAgICAgICAgICAgIHRyQ29udHJvbD10cmFpbkNvbnRyb2wobWV0aG9kID0gImN2IiwgbnVtYmVyID0gMTApLAogICAgICAgICAgICAgICAgdHVuZUdyaWRlPWRhdGEuZnJhbWUoc2lnbWE9MSxDPTEpCiAgICAgICAgICAgICAgICApICNjYW1iaWFyCgpyZXN1bHRhZG9fZW50cmVuYW1pZW50bzI8LSBwcmVkaWN0KG1vZGVsbzEsZW50cmVuYW1pZW50bykKcmVzdWx0YWRvX3BydWViYTI8LXByZWRpY3QobW9kZWxvMixwcnVlYmEpCiNtYXRyaXogZGUgY29uZnVzacOzbiAKI2VzIHVuYSB0YWJsYSBkZSBldmFsdWFjacOzbiBxdWUgZGVzZ2xvZGEgZWwgcmVuZGltaWVudG8gZGVsIG1vZGVsbyBkZSBjbGFzaWZpY2FjaW9uCiNtYXRyaXogZGUgY29uZnVzaW9uIGRlbCByZXN1bHRhZG8gZGVsIGVudHJlbmFtaWVudG8KbWNyZTI8LSBjb25mdXNpb25NYXRyaXgocmVzdWx0YWRvX2VudHJlbmFtaWVudG8yLGVudHJlbmFtaWVudG8kU3BlY2llcykKbWNyZTIKCm1jcnAyPC0gY29uZnVzaW9uTWF0cml4KHJlc3VsdGFkb19wcnVlYmEsIHBydWViYSRTcGVjaWVzKQptY3JwMgpgYGAKCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiMxODc0Q0QiPiBNb2RlbG8gMy4gU1ZNIExpbmVhbCAgPC9zcGFuPgoKYGBge3J9Cm1vZGVsbzMgPC0gdHJhaW4oU3BlY2llcyB+IC4sIGRhdGE9ZW50cmVuYW1pZW50bywKICAgICAgICAgICAgICAgICAgbWV0aG9kID0gInN2bVBvbHkiLCAjQ2FtYmlhcgogICAgICAgICAgICAgICAgICBwcmVQcm9jZXNzPWMoInNjYWxlIiwgImNlbnRlciIpLAogICAgICAgICAgICAgICAgICB0ckNvbnRyb2wgPSB0cmFpbkNvbnRyb2wobWV0aG9kPSJjdiIsIG51bWJlcj0xMCksCiAgICAgICAgICAgICAgICAgIHR1bmVHcmlkZSA9IGRhdGEuZnJhbWUoZGVncmVlPTEsIHNjYWxlPTEsIEM9MSkgI2NhbWJpYXIKICAgICAgICAgICAgICAgICAgKQoKcmVzdWx0YWRvX2VudHJlbmFtaWVudG8zIDwtICBwcmVkaWN0KG1vZGVsbzMsIGVudHJlbmFtaWVudG8pCnJlc3VsdGFkb19wcnVlYmEzIDwtICBwcmVkaWN0KG1vZGVsbzMsIHBydWViYSkKCiMgTWF0cml6IGRlIENvbmZ1c2nDs24KIyBFcyB1bmEgdGFibGEgZGUgZXZhbHVhY2nDs24gcXVlIGRlc2dsb3NhIGVsIHJlbmRpbWllbnRvIGRlbCBtb2RlbG8gZGUgY2xhc2lmaWNhY2nDs24uCgojIE1hdHJpeiBkZSBDb25mdXNpw7NuIGRlbCBSZXN1bHRhZG8gZGVsIEVudHJlbmFtaWVudG8KbWNyZTMgPC0gY29uZnVzaW9uTWF0cml4KHJlc3VsdGFkb19lbnRyZW5hbWllbnRvMywgZW50cmVuYW1pZW50byRTcGVjaWVzKQptY3JlMwoKIyBNYXRyaXogZGUgQ29uZnVzacOzbiBkZWwgUmVzdWx0YWRvIGRlIGxhIFBydWViYQptY3JwMyA8LSBjb25mdXNpb25NYXRyaXgocmVzdWx0YWRvX3BydWViYTMsIHBydWViYSRTcGVjaWVzKQptY3JwMwpgYGAKCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiAjMTg3NENEIj4gTW9kZWxvIDQuIMOBcmJvbCBkZSBEZWNpc2nDs24gPC9zcGFuPgoKYGBge3J9Cm1vZGVsbzQgPC0gdHJhaW4oU3BlY2llcyB+IC4sIGRhdGE9ZW50cmVuYW1pZW50bywKICAgICAgICAgICAgICAgICAgbWV0aG9kID0gInJwYXJ0IiwgI0NhbWJpYXIKICAgICAgICAgICAgICAgICAgcHJlUHJvY2Vzcz1jKCJzY2FsZSIsICJjZW50ZXIiKSwKICAgICAgICAgICAgICAgICAgdHJDb250cm9sID0gdHJhaW5Db250cm9sKG1ldGhvZD0iY3YiLCBudW1iZXI9MTApLAogICAgICAgICAgICAgICAgICB0dW5lTGVuZ3RoID0gMTAgIyBjYW1iaWFyCiAgICAgICAgICAgICAgICAgICkKCnJlc3VsdGFkb19lbnRyZW5hbWllbnRvNCA8LSAgcHJlZGljdChtb2RlbG80LCBlbnRyZW5hbWllbnRvKQpyZXN1bHRhZG9fcHJ1ZWJhNCA8LSAgcHJlZGljdChtb2RlbG80LCBwcnVlYmEpCgojIE1hdHJpeiBkZSBDb25mdXNpw7NuCiMgRXMgdW5hIHRhYmxhIGRlIGV2YWx1YWNpw7NuIHF1ZSBkZXNnbG9zYSBlbCByZW5kaW1pZW50byBkZWwgbW9kZWxvIGRlIGNsYXNpZmljYWNpw7NuLgoKIyBNYXRyaXogZGUgQ29uZnVzacOzbiBkZWwgUmVzdWx0YWRvIGRlbCBFbnRyZW5hbWllbnRvCm1jcmU0IDwtIGNvbmZ1c2lvbk1hdHJpeChyZXN1bHRhZG9fZW50cmVuYW1pZW50bzQsIGVudHJlbmFtaWVudG8kU3BlY2llcykKbWNyZTQKCiMgTWF0cml6IGRlIENvbmZ1c2nDs24gZGVsIFJlc3VsdGFkbyBkZSBsYSBQcnVlYmEKbWNycDQgPC0gY29uZnVzaW9uTWF0cml4KHJlc3VsdGFkb19wcnVlYmE0LCBwcnVlYmEkU3BlY2llcykKbWNycDQKYGBgCgojIDxzcGFuIHN0eWxlPSJjb2xvcjogIzE4NzRDRCI+IE1vZGVsbyA1LiBSZWRlcyBOZXVyb25hbGVzIDwvc3Bhbj4KCmBgYHtyfQptb2RlbG81IDwtIHRyYWluKAogIFNwZWNpZXMgfiAuLAogIGRhdGEgPSBlbnRyZW5hbWllbnRvLAogIG1ldGhvZCA9ICJubmV0IiwKICBwcmVQcm9jZXNzID0gYygiY2VudGVyIiwgInNjYWxlIiksCiAgdHJDb250cm9sID0gdHJhaW5Db250cm9sKG1ldGhvZCA9ICJjdiIsIG51bWJlciA9IDEwKSwKICB0dW5lTGVuZ3RoID0gNSwgICAgICAgICMgbyB1c2EgdHVuZUdyaWQgc2kgcXVpZXJlcyBjb250cm9sYXIgc2l6ZS9kZWNheQogIHRyYWNlID0gRkFMU0UsCiAgTWF4Tld0cyA9IDUwMDAgICAgICAgICAjIHBvciBzaSBoYXkgbXVjaGFzIHZhcmlhYmxlcy9wZXNvcwopCgpyZXN1bHRhZG9fZW50cmVuYW1pZW50bzUgPC0gIHByZWRpY3QobW9kZWxvNSwgZW50cmVuYW1pZW50bykKcmVzdWx0YWRvX3BydWViYTUgPC0gIHByZWRpY3QobW9kZWxvNSwgcHJ1ZWJhKQoKIyBNYXRyaXogZGUgQ29uZnVzacOzbgojIEVzIHVuYSB0YWJsYSBkZSBldmFsdWFjacOzbiBxdWUgZGVzZ2xvc2EgZWwgcmVuZGltaWVudG8gZGVsIG1vZGVsbyBkZSBjbGFzaWZpY2FjacOzbi4KCiMgTWF0cml6IGRlIENvbmZ1c2nDs24gZGVsIFJlc3VsdGFkbyBkZWwgRW50cmVuYW1pZW50bwptY3JlNSA8LSBjb25mdXNpb25NYXRyaXgocmVzdWx0YWRvX2VudHJlbmFtaWVudG81LCBlbnRyZW5hbWllbnRvJFNwZWNpZXMpCm1jcmU1CgojIE1hdHJpeiBkZSBDb25mdXNpw7NuIGRlbCBSZXN1bHRhZG8gZGUgbGEgUHJ1ZWJhCm1jcnA1IDwtIGNvbmZ1c2lvbk1hdHJpeChyZXN1bHRhZG9fcHJ1ZWJhNSwgcHJ1ZWJhJFNwZWNpZXMpCm1jcnA1CmBgYAoKIyA8c3BhbiBzdHlsZT0iY29sb3I6ICMxODc0Q0QiPiBNb2RlbG8gNi4gQm9zcXVlcyBBbGVhdG9yaW9zIDwvc3Bhbj4KCmBgYHtyfQptb2RlbG82IDwtIHRyYWluKFNwZWNpZXMgfiAuLCBkYXRhID0gZW50cmVuYW1pZW50bywKICAgICAgICAgICAgICAgICBtZXRob2QgPSAicmYiLCAjQ2FtYmlhcgogICAgICAgICAgICAgICAgIHByZVByb2Nlc3MgPSBjKCJzY2FsZSIsICJjZW50ZXIiKSwKICAgICAgICAgICAgICAgICB0ckNvbnRyb2wgPSB0cmFpbkNvbnRyb2wobWV0aG9kID0gImN2IiwgbnVtYmVyID0gMTApLAogICAgICAgICAgICAgICAgIHR1bmVHcmlkID0gZXhwYW5kLmdyaWQobXRyeSA9IGMoMiw0LDYpKSAjQ2FtYmlhcgopCnJlc3VsdGFkb19lbnRyZW5hbWllbnRvNiA8LSBwcmVkaWN0KG1vZGVsbzYsIGVudHJlbmFtaWVudG8pCnJlc3VsdGFkb19wcnVlYmE2IDwtIHByZWRpY3QobW9kZWxvNiwgcHJ1ZWJhKQoKIyBNYXRyaXogZGUgQ29uZnVzacOzbgojIEVzIHVuYSB0YWJsYSBkZSBldmFsdWFjacOzbiBxdWUgZGVzZ2xvc2EgZWwgcmVuZGltaWVudG8gZGVsIG1vZGVsbyBkZSBjbGFzaWZpY2FjacOzbi4KCiMgTWF0cml6IGRlIENvbmZ1c2nDs24gZGVsIFJlc3VsdGFkbyBkZWwgRW50cmVuYW1pZW50bwptY3JlNiA8LSBjb25mdXNpb25NYXRyaXgocmVzdWx0YWRvX2VudHJlbmFtaWVudG82LCBlbnRyZW5hbWllbnRvJFNwZWNpZXMpCm1jcmU2CgojIE1hdHJpeiBkZSBDb25mdXNpw7NuIGRlbCBSZXN1bHRhZG8gZGUgbGEgUHJ1ZWJhCm1jcnA2IDwtIGNvbmZ1c2lvbk1hdHJpeChyZXN1bHRhZG9fcHJ1ZWJhNiwgcHJ1ZWJhJFNwZWNpZXMpCm1jcnA2CmBgYAoKIyA8c3BhbiBzdHlsZT0iY29sb3I6ICMxODc0Q0QiPiBUYWJsYSBkZSBSZXN1bHRhZG9zIDwvc3Bhbj4KCmBgYHtyfQpyZXN1bHRhZG9zIDwtIGRhdGEuZnJhbWUoCiAgInN2bUxpbmVhciIgPSBjKG1jcmUxJG92ZXJhbGxbIkFjY3VyYWN5Il0sIG1jcnAxJG92ZXJhbGxbIkFjY3VyYWN5Il0pLAogICJzdm1SYWRpYWwiID0gYyhtY3JlMiRvdmVyYWxsWyJBY2N1cmFjeSJdLCBtY3JwMiRvdmVyYWxsWyJBY2N1cmFjeSJdKSwKICAic3ZtUG9seSIgICA9IGMobWNyZTMkb3ZlcmFsbFsiQWNjdXJhY3kiXSwgbWNycDMkb3ZlcmFsbFsiQWNjdXJhY3kiXSksCiAgInJwYXJ0IiAgICAgPSBjKG1jcmU0JG92ZXJhbGxbIkFjY3VyYWN5Il0sIG1jcnA0JG92ZXJhbGxbIkFjY3VyYWN5Il0pLAogICJubmV0IiAgICAgID0gYyhtY3JlNSRvdmVyYWxsWyJBY2N1cmFjeSJdLCBtY3JwNSRvdmVyYWxsWyJBY2N1cmFjeSJdKSwKICAicmYiICAgICAgICA9IGMobWNyZTYkb3ZlcmFsbFsiQWNjdXJhY3kiXSwgbWNycDYkb3ZlcmFsbFsiQWNjdXJhY3kiXSkKKQoKIyBBZGQgYSB0aGlyZCByb3c6IGRpZmZlcmVuY2UKZGlmZl9yb3cgPC0gcmVzdWx0YWRvc1sxLCBdIC0gcmVzdWx0YWRvc1syLCBdCnJlc3VsdGFkb3MgPC0gcmJpbmQocmVzdWx0YWRvcywgZGlmZl9yb3cpCgpyb3duYW1lcyhyZXN1bHRhZG9zKSA8LSAgYygiUHJlY2lzacOzbiBkZSBlbnRyZW5hbWllbnRvIiwgIlByZWNpc2nDs24gZGUgcHJ1ZWJhIiwgIkRpZmVyZW5jaWEiKQpyZXN1bHRhZG9zCmBgYAoKIyA8c3BhbiBzdHlsZT0iY29sb3I6ICMxODc0Q0QiPiBDb25jbHVzaW9uZXMgPC9zcGFuPgpBY29yZGUgYSBsYSB0YWJsYSBkZSByZXN1bHRhZG9zLCBvYnNlcnZhbW9zIHF1ZSBuaW5nw7puIG3DqXRvZG8gcHJlc2VudGEgc29icmVhanVzdGUuIFBvZGVtb3Mgc2VsZWNjaW9uYXIgZWwgZGUgKipzdm1MaW5lYXIqKiBwb3Igc3UgZGVzZW1wZcOxby4KCgoK