Learn R Programming

ddalpha (version 1.3.16)

Custom Methods: Using Custom Depth Functions and Classifiers

Description

To use a custom depth function or classifier one has to implement three functions: parameters validator, learning and calculating functions.

Arguments

Details

To define a depth function:

.<NAME>_validate

validates parameters passed to ddalpha.train and passes them to the ddalpha object.

IN:ddalpha
the ddalpha object, containing the data and settings (mandatory)<custom parameters>
parameters that are passed to the user-defined method...
other parameters (mandatory) OUT:
list()list of output parameters, after the validation is finished, these parameters are stored in the ddalpha object

.<NAME>_learn

trains the depth

IN:ddalpha
the ddalpha object, containing the data and settings MODIFIES:
ddalphastore the calculated statistics in the ddalpha object
depthscalculate the depths of each pattern, e.g.
for (i in 1:ddalpha$numPatterns) ddalpha$patterns[[i]]$depths = .<NAME>_depths(ddalpha, ddalpha$patterns[[i]]$points)
OUT:ddalpha

.<NAME>_depths

calculates the depths

IN:ddalpha
the ddalpha object, containing the data and settingsobjects
the objects for which the depths are calculated
OUT:depths

Usage: ddalpha.train(data, depth = "<NAME>", <custom parameters>, ...)

#### Custom depths ####.MyDepth_validate <- function(ddalpha, mydepth.parameter = "value", ...){ print("MyDepth validating") # validate the parameters if (!is.valid(mydepth.parameter)){ warning("Argument \"mydepth.parameter\" not specified correctly. Default value is used") mydepth.parameter = "value" # or stop("Argument \"mydepth.parameter\" not specified correctly.") } # the values from the return list will be stored in the ddalpha object return (list(mydepthpar = mydepth.parameter)) }.MyDepth_learn <- function(ddalpha){ print("MyDepth learning") #1. Calculate any statistics based on data that .MyDepth_depths needs # and store them to the ddalpha object: ddalpha$mydepth.statistic = "some value" #2. Calculate depths for each pattern for (i in 1:ddalpha$numPatterns){ ddalpha$patterns[[i]]$depths = .MyDepth_depths(ddalpha, ddalpha$patterns[[i]]$points) } return(ddalpha) }.MyDepth_depths <- function(ddalpha, objects){ print("MyDepth calculating") depths <- NULL # The depth parameters are accessible in the ddalpha object: mydepth.parameter = ddalpha$mydepth.parameter mydepth.statistic = ddalpha$mydepth.statistic #calculate the depths of the objects w.r.t. each pattern for (i in 1:ddalpha$numPatterns){ depth_wrt_i = #calculate depths of the objects, as vector depths <- cbind(depths, depth_wrt_i) } return (depths) }ddalpha.train(data, depth = "MyDepth", ...)

To define a classifier:

.<NAME>_validate

validates parameters passed to ddalpha.train and passes them to the ddalpha object

IN:ddalpha
the ddalpha object, containing the data and settings (mandatory)<custom parameters>
parameters that are passed to the user-defined method...
other parameters (mandatory)OUT:
list()list of output parameters, after the validation is finished, these parameters are stored in the ddalpha object. In case of a multiclass classifier the validator must return methodSeparatorBinary = F and/or pass aggregation.method = "none" to ddalpha.train

.<NAME>_learn

trains the classifier. Is different for binnary and mylticlass classifiers.

IN:ddalpha
the ddalpha object, containing the data and settingsindex1
(only for binary) index of the first classindex2
(only for binary) index of the second classdepths1
(only for binary) depths of the first class w.r.t. all classesdepths2
(only for binary) depths of the second class w.r.t. all classes
depths w.r.t. only given classes are received by depths1[,c(index1, index2)]
for the multiclass classifiers the depths are accessible via ddalpha$patterns[[i]]$depthsOUT:
classifierthe trained classifier object

.<NAME>_classify

classifies the objects

IN:ddalpha
the ddalpha object, containing the data and global settingsclassifier
the previously trained classifierobjects
the objects (depths) that are classified
OUT:result
a vector with classification results
(binary) the objects from class "classifier$index1" get positive values

Usage: ddalpha.train(data, separator = "<NAME>", ...)

#### Custom classifiers ####.MyClassifier_validate <- function(ddalpha, my.parameter = "value", ...){ print("MyClassifier validating") # validate the parameters ... # always include methodSeparatorBinary. # TRUE for the binary classifier, FALSE otherwise return(list(methodSeparatorBinary = T, my.parameter = my.parameter )) }# a binary classifier # the package takes care of the voting procedures. Just train it as if there are only two classes .MyClassifier_learn <- function(ddalpha, index1, index2, depths1, depths2){ print("MyClassifier (binary) learning") # The parameters are accessible in the ddalpha object: my.parameter = ddalpha$my.parameter #depths w.r.t. only given classes are received by depths1[,c(index1, index2)] depths2[,c(index1, index2)] # train the classifier classifier <- ... #return the needed values in a list, e.g. return(list( coefficients = classifier$coefficients, ... )) }# a multiclass classifier .MyClassifier_learn <- function(ddalpha){ print("MyClassifier (multiclass) learning") # access the data through the ddalpha object, e.g. for (i in 1:ddalpha$numPatterns){ depth <- ddalpha$patterns[[i]]$depths number <- ddalpha$patterns[[i]]$cardinality ... } # train the classifier classifier <- ... # return the classifier return(classifier) }# the interface of the classify function is equal for binary and multiclass classifiers .MyClassifier_classify <- function(ddalpha, classifier, depths){ print("MyClassifier classifying") # The global parameters are accessible in the ddalpha object: my.parameter = ddalpha$my.parameter # The parameters generated by .MyClassifier_learn are accessible in the classifier object: classifier$coefficients # here are the depths w.r.t. the first class depths[,classifier$index1] # here are the depths w.r.t. the second class depths[,classifier$index2] # fill results in a vector, so that: # (binary) the objects from class "classifier$index1" get positive values # (multiclass) the objects get the numbers of patterns in ddalpha result <- ... return(result) }ddalpha.train(data, separator = "MyClassifier", ...)

See Also

ddalpha.train

Examples

Run this code

if (FALSE) {

#### example:  Euclidean depth ####

#.Euclidean_validate is basically not needed

.Euclidean_learn <- function(ddalpha){
  print("Euclidean depth learning")
  
  #1. Calculate any statistics based on data that .MyDepth_depths needs
  #   and store them to the ddalpha object: 
  for (i in 1:ddalpha$numPatterns){
    ddalpha$patterns[[i]]$center <- colMeans(ddalpha$patterns[[i]]$points)
  }
  
  #2. Calculate depths for each pattern
  for (i in 1:ddalpha$numPatterns){
    ddalpha$patterns[[i]]$depths = .Euclidian_depths(ddalpha, ddalpha$patterns[[i]]$points)
  }
  
  return(ddalpha)
}

.Euclidean_depths <- function(ddalpha, objects){
  print("Euclidean depth calculating")
  depths <- NULL
  
  #calculate the depths of the objects w.r.t. each pattern
  for (i in 1:ddalpha$numPatterns){
    # The depth parameters are accessible in the ddalpha object:
    center = ddalpha$patterns[[i]]$center
    
    depth_wrt_i <- 1/(1 + colSums((t(objects) - center)^2))
    depths <- cbind(depths, depth_wrt_i)
  }
  
  return (depths)
}

#### example:  binary decision tree ####

library(rpart)

.tree_validate  <- function(ddalpha, ...){
  print("tree validating")
  return(list(methodSeparatorBinary = T))
}

# a binary classifier 
# the package takes care of the voting procedures. Just train it as if there are only two classes
.tree_learn <- function(ddalpha, index1, index2, depths1, depths2){
  print("tree learning")
  
  # prepare the data
  data = as.data.frame(cbind( (rbind(depths1, depths2)), 
                              c(rep(1, times = nrow(depths1)), rep(-1, times = nrow(depths1)))))
  names(data) <- paste0("V",seq_len(ncol(data)))
  names(data)[ncol(data)] <- "O"
  # train the classifier
  classifier <- rpart(O~., data = data)
  
  #return the needed values in a list, e.g.
  return(classifier)
}

# the interface of the classify function is equal for binary and multiclass classifiers
.tree_classify <- function(ddalpha, classifier, depths){
  print("tree classifying")
  
  # fill results in a vector, so that the objects from class "classifier$index1" get positive values
  data = as.data.frame(depths)
  names(data) <- paste0("V",seq_len(ncol(data)))
  result <- predict(classifier, as.data.frame(depths), type = "vector")
  
  return(result)
}




#### checking ####

library(ddalpha)
data = getdata("hemophilia")

ddalpha = ddalpha.train(data = data, depth = "Euclidean", separator = "tree")
c = ddalpha.classify(ddalpha, data[,1:2])
errors = sum(unlist(c) != data[,3])/nrow(data)
print(paste("Error rate: ",errors))

# building the depth contours using the custom depth
depth.contours.ddalpha(ddalpha, asp = T, levels = seq(0.5, 1, length.out = 10))

}

Run the code above in your browser using DataLab