library(dplyr)
library(readr)
library(caret)
library(doMC)

Prepare de data

Read datasets

features_data<-list()
for (capture in list.files("data/labeled/",pattern = "capture2011081[012345689](-[123])?.binetflow.labels",full.names = T)){
  capture_df <- readr::read_csv(capture)
  features_data<-rbind(features_data,capture_df)
}

Create two classes, botnet and normal

features_data <-features_data %>% mutate(label=ifelse(label=="infected","botnet","normal"))
features_data$label <- features_data$label %>% as.factor()
features_data

Run k-means with 25 centroids

Filter observation inside begnin cluster

features_data_reduced<-features_cluster %>% filter(cluster != begnin_cluster) 
readr::write_csv(file="/home/harpo/Dropbox/graph-reatures-reduced.csv", features_data_reduced)

Train a classiffier

Split in train and test

train_index<-caret::createDataPartition(features_data_reduced$label,p=0.8,list = F)
trainset <- features_data_reduced[train_index,]
testset  <- features_data_reduced[-train_index,]
trainset %>% group_by(label) %>% count()
testset %>% group_by(label) %>% count()

Prepare stuff for caret

We are going to use a 10-folds cross validation.

registerDoMC(cores = 8)
ctrl_fast <- trainControl(
  method = "cv",
  number = 10,
  returnResamp = 'final',
  savePredictions = 'final',
  verboseIter = F,
  classProbs = TRUE,
  summaryFunction = twoClassSummary,
  allowParallel = T,
  sampling = "up" # UPSAMPLING
)

tgrid <- expand.grid(
  mtry = 6,
  splitrule = "gini",
  min.node.size = 10)

Train a Random forests (Ranger package)

bot_formula<-formula(label ~ ID+OD+IDW+ODW+BC+LCC+AC) # features used for training

rfFit <- caret::train(bot_formula,
  data = trainset,
  method = "ranger",
  #tuneGrid = tgrid,
  #metric = 'Kappa',
  metric = "Sens",
  tuneLength  = 10, 
  verbose = 2,
  trControl = ctrl_fast,
  num.trees = 100,
  max.depth = 6,
  #class.weights = c(746.75,1),
)
note: only 6 unique complexity parameters in default grid. Truncating the grid to 6 .
rfFit
Random Forest 

14955 samples
    7 predictor
    2 classes: 'botnet', 'normal' 

No pre-processing
Resampling: Cross-Validated (10 fold) 
Summary of sample sizes: 13459, 13460, 13460, 13459, 13459, 13460, ... 
Addtional sampling using up-sampling

Resampling results across tuning parameters:

  mtry  splitrule   ROC        Sens  Spec     
  2     gini        0.9755126  0.55  0.9758952
  2     extratrees  0.9746867  0.70  0.9794430
  3     gini        0.9748760  0.60  0.9716770
  3     extratrees  0.9814846  0.75  0.9797122
  4     gini        0.9514487  0.65  0.9696682
  4     extratrees  0.9768130  0.70  0.9809175
  5     gini        0.9047122  0.65  0.9691327
  5     extratrees  0.9797253  0.80  0.9800472
  6     gini        0.9312846  0.65  0.9685299
  6     extratrees  0.9761082  0.80  0.9793760
  7     gini        0.8846495  0.65  0.9686638
  7     extratrees  0.9808463  0.70  0.9841308

Tuning parameter 'min.node.size' was held constant at a value of 1
Sens was used to select the optimal model using the largest value.
The final values used for the model were mtry = 5, splitrule = extratrees and min.node.size = 1.

Balanced Accuracy during Cross validation

rfFit$pred %>% group_by(Resample) %>% 
    yardstick::bal_accuracy(obs,pred) %>% 
    summarise(bal_acc=mean(.estimate),bal_acc_sd=sd(.estimate))

Prediction on independet test.

preds<-predict(rfFit,testset)
confusionMatrix(reference=testset$label,
                data=preds %>% as.factor(),mode = 'everything') 
Confusion Matrix and Statistics

          Reference
Prediction botnet normal
    botnet      4     93
    normal      1   3640
                                          
               Accuracy : 0.9749          
                 95% CI : (0.9693, 0.9796)
    No Information Rate : 0.9987          
    P-Value [Acc > NIR] : 1               
                                          
                  Kappa : 0.0761          
                                          
 Mcnemar's Test P-Value : <2e-16          
                                          
            Sensitivity : 0.800000        
            Specificity : 0.975087        
         Pos Pred Value : 0.041237        
         Neg Pred Value : 0.999725        
              Precision : 0.041237        
                 Recall : 0.800000        
                     F1 : 0.078431        
             Prevalence : 0.001338        
         Detection Rate : 0.001070        
   Detection Prevalence : 0.025950        
      Balanced Accuracy : 0.887544        
                                          
       'Positive' Class : botnet          
                                          
LS0tCnRpdGxlOiAiQm90bmV0IENsYXNzaWZpY2F0aW9uIHVzaW5nIEdyYXBoIGZlYXR1cmVzIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoZHBseXIpCmxpYnJhcnkocmVhZHIpCmxpYnJhcnkoY2FyZXQpCmxpYnJhcnkoZG9NQykKbGlicmFyeShyYW5nZXIpCmBgYAoKIyBQcmVwYXJlIGRlIGRhdGEKIyMgUmVhZCBkYXRhc2V0cwpgYGB7cn0KZmVhdHVyZXNfZGF0YTwtbGlzdCgpCmZvciAoY2FwdHVyZSBpbiBsaXN0LmZpbGVzKCJkYXRhL2xhYmVsZWQvIixwYXR0ZXJuID0gImNhcHR1cmUyMDExMDgxWzAxMjM0NTY4OV0oLVsxMjNdKT8uYmluZXRmbG93LmxhYmVscyIsZnVsbC5uYW1lcyA9IFQpKXsKICBjYXB0dXJlX2RmIDwtIHJlYWRyOjpyZWFkX2NzdihjYXB0dXJlKQogIGZlYXR1cmVzX2RhdGE8LXJiaW5kKGZlYXR1cmVzX2RhdGEsY2FwdHVyZV9kZikKfQpgYGAKCiMjIENyZWF0ZSB0d28gY2xhc3NlcywgYm90bmV0IGFuZCBub3JtYWwKYGBge3J9CmZlYXR1cmVzX2RhdGEgPC1mZWF0dXJlc19kYXRhICU+JSBtdXRhdGUobGFiZWw9aWZlbHNlKGxhYmVsPT0iaW5mZWN0ZWQiLCJib3RuZXQiLCJub3JtYWwiKSkKZmVhdHVyZXNfZGF0YSRsYWJlbCA8LSBmZWF0dXJlc19kYXRhJGxhYmVsICU+JSBhcy5mYWN0b3IoKQpmZWF0dXJlc19kYXRhCmBgYAoKIyMgUnVuIGstbWVhbnMgd2l0aCAyNSBjZW50cm9pZHMKYGBge3J9CnNvdXJjZSgiY29kZS9SL2Z1bmN0aW9ucy9jYWxjdWxhdGVfY2x1c3RlcmluZy5SIikKbGFiZWxzX2RhdGEgPC0gZmVhdHVyZXNfZGF0YSAlPiUgc2VsZWN0KGxhYmVsKQpub2Rlc19kYXRhIDwtIGZlYXR1cmVzX2RhdGEgJT4lIHNlbGVjdChub2RlKQpmZWF0dXJlc19kYXRhPC1mZWF0dXJlc19kYXRhICU+JSBzZWxlY3QoLWxhYmVsLC1ub2RlKQoKY2x1c3Rlcl9kYXRhIDwtIGttZWFucyhmZWF0dXJlc19kYXRhLCBjZW50ZXJzID0gMjUsbnN0YXJ0ID0gMTAsIGl0ZXIubWF4ID0gMTAwMDApCmZlYXR1cmVzX2NsdXN0ZXI8LWRhdGEuZnJhbWUobm9kZT1ub2Rlc19kYXRhLGZlYXR1cmVzX2RhdGEsbGFiZWw9bGFiZWxzX2RhdGEsY2x1c3Rlcj1jbHVzdGVyX2RhdGEkY2x1c3RlcikKCmNsdXN0ZXJzX3NpemUgPC0gZmVhdHVyZXNfY2x1c3RlciAlPiUgZ3JvdXBfYnkoY2x1c3RlcikgJT4lIGNvdW50KCkKICBiZWduaW5fY2x1c3RlcjwtY2x1c3RlcnNfc2l6ZSAgJT4lIGFycmFuZ2UoZGVzYyhuKSkgJT4lIGhlYWQoMSkgJT4lIHNlbGVjdChjbHVzdGVyKSAlPiUgdW5saXN0KCkgJT4lIHVubmFtZSgpCiAgdG90X2JvdDwtZmVhdHVyZXNfY2x1c3RlciAlPiUgZmlsdGVyKGxhYmVsPT0gImJvdG5ldCIpICU+JSBucm93KCkKICB0b3RfaG9zdDwtZmVhdHVyZXNfY2x1c3RlciAlPiUgZmlsdGVyKGxhYmVsIT0gImJvdG5ldCIpICU+JSBucm93CiAgY2x1c3RfYm90PC1mZWF0dXJlc19jbHVzdGVyICU+JSBmaWx0ZXIoY2x1c3RlciA9PSBiZWduaW5fY2x1c3RlcikgJT4lIGZpbHRlcihsYWJlbD09ImJvdG5ldCIpICU+JSBucm93KCkKICBjbHVzdF9ob3N0PC1mZWF0dXJlc19jbHVzdGVyICU+JSBmaWx0ZXIoY2x1c3RlciA9PSBiZWduaW5fY2x1c3RlcikgJT4lIGZpbHRlcihsYWJlbCE9ImJvdG5ldCIpICU+JSBucm93KCkKICBib2IgPC0gdG90X2JvdCAtIGNsdXN0X2JvdAogIGhvYiA8LSB0b3RfaG9zdCAtIGNsdXN0X2hvc3QKCnJiaW5kKGhvYixib2IpICU+JSBhcy5kYXRhLmZyYW1lKCkKYGBgCgojIyBGaWx0ZXIgb2JzZXJ2YXRpb24gaW5zaWRlIGJlZ25pbiBjbHVzdGVyCmBgYHtyfQpmZWF0dXJlc19kYXRhX3JlZHVjZWQ8LWZlYXR1cmVzX2NsdXN0ZXIgJT4lIGZpbHRlcihjbHVzdGVyICE9IGJlZ25pbl9jbHVzdGVyKSAKcmVhZHI6OndyaXRlX2NzdihmaWxlPSIvaG9tZS9oYXJwby9Ecm9wYm94L2dyYXBoLXJlYXR1cmVzLXJlZHVjZWQuY3N2IiwgZmVhdHVyZXNfZGF0YV9yZWR1Y2VkKQpgYGAKCgojIFRyYWluIGEgY2xhc3NpZmZpZXIKCiMjIFNwbGl0IGluIHRyYWluIGFuZCB0ZXN0CmBgYHtyfQp0cmFpbl9pbmRleDwtY2FyZXQ6OmNyZWF0ZURhdGFQYXJ0aXRpb24oZmVhdHVyZXNfZGF0YV9yZWR1Y2VkJGxhYmVsLHA9MC44LGxpc3QgPSBGKQp0cmFpbnNldCA8LSBmZWF0dXJlc19kYXRhX3JlZHVjZWRbdHJhaW5faW5kZXgsXQp0ZXN0c2V0ICA8LSBmZWF0dXJlc19kYXRhX3JlZHVjZWRbLXRyYWluX2luZGV4LF0KdHJhaW5zZXQgJT4lIGdyb3VwX2J5KGxhYmVsKSAlPiUgY291bnQoKQp0ZXN0c2V0ICU+JSBncm91cF9ieShsYWJlbCkgJT4lIGNvdW50KCkKYGBgCgojIyBQcmVwYXJlIHN0dWZmIGZvciBjYXJldAoKV2UgYXJlIGdvaW5nIHRvIHVzZSBhIDEwLWZvbGRzIGNyb3NzIHZhbGlkYXRpb24uCmBgYHtyfQpyZWdpc3RlckRvTUMoY29yZXMgPSA4KQpjdHJsX2Zhc3QgPC0gdHJhaW5Db250cm9sKAogIG1ldGhvZCA9ICJjdiIsCiAgbnVtYmVyID0gMTAsCiAgcmV0dXJuUmVzYW1wID0gJ2ZpbmFsJywKICBzYXZlUHJlZGljdGlvbnMgPSAnZmluYWwnLAogIHZlcmJvc2VJdGVyID0gRiwKICBjbGFzc1Byb2JzID0gVFJVRSwKICBzdW1tYXJ5RnVuY3Rpb24gPSB0d29DbGFzc1N1bW1hcnksCiAgYWxsb3dQYXJhbGxlbCA9IFQsCiAgc2FtcGxpbmcgPSAidXAiICMgVVBTQU1QTElORwopCgp0Z3JpZCA8LSBleHBhbmQuZ3JpZCgKICBtdHJ5ID0gNiwKICBzcGxpdHJ1bGUgPSAiZ2luaSIsCiAgbWluLm5vZGUuc2l6ZSA9IDEwKQpgYGAKCiMjIFRyYWluIGEgUmFuZG9tIGZvcmVzdHMgKFJhbmdlciBwYWNrYWdlKQpgYGB7cn0KYm90X2Zvcm11bGE8LWZvcm11bGEobGFiZWwgfiBJRCtPRCtJRFcrT0RXK0JDK0xDQytBQykgIyBmZWF0dXJlcyB1c2VkIGZvciB0cmFpbmluZwoKcmZGaXQgPC0gY2FyZXQ6OnRyYWluKGJvdF9mb3JtdWxhLAogIGRhdGEgPSB0cmFpbnNldCwKICBtZXRob2QgPSAicmFuZ2VyIiwKICAjdHVuZUdyaWQgPSB0Z3JpZCwKICAjbWV0cmljID0gJ0thcHBhJywKICBtZXRyaWMgPSAiU2VucyIsCiAgdHVuZUxlbmd0aCAgPSAxMCwgCiAgdmVyYm9zZSA9IDIsCiAgdHJDb250cm9sID0gY3RybF9mYXN0LAogIG51bS50cmVlcyA9IDEwMCwKICBtYXguZGVwdGggPSA2LAogICNjbGFzcy53ZWlnaHRzID0gYyg3NDYuNzUsMSksCikKcmZGaXQKYGBgCgoKCiMjIyBCYWxhbmNlZCBBY2N1cmFjeSBkdXJpbmcgQ3Jvc3MgdmFsaWRhdGlvbgpgYGB7cn0KcmZGaXQkcHJlZCAlPiUgZ3JvdXBfYnkoUmVzYW1wbGUpICU+JSAKICAgIHlhcmRzdGljazo6YmFsX2FjY3VyYWN5KG9icyxwcmVkKSAlPiUgCiAgICBzdW1tYXJpc2UoYmFsX2FjYz1tZWFuKC5lc3RpbWF0ZSksYmFsX2FjY19zZD1zZCguZXN0aW1hdGUpKQpgYGAKCiMjIyBQcmVkaWN0aW9uIG9uIGluZGVwZW5kZXQgdGVzdC4KCmBgYHtyfQpwcmVkczwtcHJlZGljdChyZkZpdCx0ZXN0c2V0KQpjb25mdXNpb25NYXRyaXgocmVmZXJlbmNlPXRlc3RzZXQkbGFiZWwsCiAgICAgICAgICAgICAgICBkYXRhPXByZWRzICU+JSBhcy5mYWN0b3IoKSxtb2RlID0gJ2V2ZXJ5dGhpbmcnKSAKYGBgCgpgYGB7ciBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQpyZiA8LSByYW5nZXIoYm90X2Zvcm11bGEsIAogICAgICAgICAgICAgICBmZWF0dXJlc19kYXRhX3JlZHVjZWQsCiAgICAgICAgICAgICAgIG51bS50cmVlcyA9IDEwMDAsIAogICAgICAgICAgICAgICBrZWVwLmluYmFnID0gVFJVRSwKICAgICAgICAgICAgICAgY2xhc3Mud2VpZ2h0cyA9IGMoMC4wMDAwMDEsMC45OSksCiAgICAgICAgICAgICAgIHByb2JhYmlsaXR5ID0gVFJVRSkKYGBgCgpgYGB7ciBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQpwcmVkczwtcHJlZGljdChyZixmZWF0dXJlc19kYXRhX3JlZHVjZWQpCnByZWRzPC1hcHBseShwcmVkcyRwcmVkaWN0aW9ucywgMSwKICAgICAgZnVuY3Rpb24oeCkgewogICAgICAgIG5hbWVzKHgpW3doaWNoLm1heCh4KV0KICAgICAgfSkKCmNvbmZ1c2lvbk1hdHJpeChyZWZlcmVuY2U9ZmVhdHVyZXNfZGF0YV9yZWR1Y2VkJGxhYmVsLAogICAgICAgICAgICAgICAgZGF0YT0gcHJlZHMlPiUgYXMuZmFjdG9yKCkpCmBgYAoK