#Code to reproduce https://mbq.me/blog/relevance-and-redundancy setNames( do.call(expand.grid,rep(list(c(T,F)),5)), c("A","B","N1","N2","N3") )->X cbind(X,AoB=with(X,A|B),AnB=with(X,A&B),nA=!X$A)->X factor(with(X,A!=B))->Y data.frame(lapply(X,factor))->X greedySVM<-function(X=X,Y=Y,sel=names(X),err=Inf){ #Empty selection is not interesting if(length(sel)==0) return(NULL) #Try proposed selection cerr<-try(kernlab::ksvm(Y~.,X[,sel,drop=FALSE],cross=5)@cross) #Cross-validation may fail if(inherits(cerr,"try-error")) return(NULL) #Error increase, not good if(cerr>err) return(NULL) #It is not worse, but maybe can be even better? for(remove in seq(along=sel)) if(!is.null(ans<-greedySVM(X,Y,sel[-remove],cerr))) return(ans) #Current solution is an optimum return(paste(sort(sel),collapse="+")) } permuteGreedySVM<-function(X=X,Y=Y,tries=100){ unlist(parallel::mclapply(1:tries, function(.) greedySVM(X[,sample(ncol(X))],Y), mc.cores=parallel::detectCores() ))->sels sort(table(sels)/length(sels),dec=TRUE) }