Changeset 10741:7fc0b0c7309a in orange


Ignore:
Timestamp:
04/04/12 12:12:35 (2 years ago)
Author:
Miran@…
Branch:
default
Children:
10744:dbaf14551a4e, 10745:5aa0dea24e1a
Message:

Added support for multi-target tree learners to random forests,
added scoring documentation for the new mt scoring functions.

Files:
2 edited

Legend:

Unmodified
Added
Removed
  • Orange/ensemble/forest.py

    r10587 r10741  
    161161 
    162162        return RandomForestClassifier(classifiers = classifiers, name=self.name,\ 
    163                     domain=instances.domain, class_var=instances.domain.class_var) 
     163                    domain=instances.domain, class_var=instances.domain.class_var, \ 
     164                    class_vars=instances.domain.class_vars) 
     165 
     166             
    164167RandomForestLearner = Orange.utils.deprecated_members({"examples":"instances"})(RandomForestLearner) 
    165168 
     
    186189    :type class_var: :class:`Orange.feature.Descriptor` 
    187190 
    188     """ 
    189     def __init__(self, classifiers, name, domain, class_var, **kwds): 
     191    :param class_vars: the multi-target class features. 
     192    :type class_vars: list of :class:`Orange.feature.Descriptor` 
     193 
     194    """ 
     195    def __init__(self, classifiers, name, domain, class_var, class_vars, **kwds): 
    190196        self.classifiers = classifiers 
    191197        self.name = name 
    192198        self.domain = domain 
    193199        self.class_var = class_var 
     200        self.class_vars = class_vars 
    194201        self.__dict__.update(kwds) 
     202        self.single_class = True if not class_vars else False 
    195203 
    196204    def __call__(self, instance, result_type = orange.GetValue): 
     
    208216        from operator import add 
    209217         
    210         # handle discreete class 
    211          
    212         if self.class_var.var_type == Orange.feature.Discrete.Discrete: 
    213          
    214             # voting for class probabilities 
    215             if result_type == orange.GetProbabilities or result_type == orange.GetBoth: 
    216                 prob = [0.] * len(self.domain.class_var.values) 
    217                 for c in self.classifiers: 
    218                     a = [x for x in c(instance, orange.GetProbabilities)] 
    219                     prob = map(add, prob, a) 
    220                 norm = sum(prob) 
    221                 cprob = Orange.statistics.distribution.Discrete(self.class_var) 
    222                 for i in range(len(prob)): 
    223                     cprob[i] = prob[i]/norm 
     218        # get results to avoid multiple calls 
     219        res_both = [c(instance, orange.GetBoth) for c in self.classifiers] 
     220 
     221        # transform single class instance to match multi-target instances 
     222        if self.single_class: 
     223            self.class_vars = [self.class_var] 
     224            res_both = [([(r[0])],[(r[1])]) for r in res_both] 
     225 
     226        mt_prob = [] 
     227        mt_value = [] 
     228 
     229        for varn in xrange(len(self.class_vars)): 
     230 
     231            self.class_var = self.class_vars[varn] 
     232             
     233            # handle discreete class 
     234         
     235            if self.class_var.var_type == Orange.feature.Discrete.Discrete: 
     236         
     237                # voting for class probabilities 
     238                if result_type == orange.GetProbabilities or result_type == orange.GetBoth: 
     239                    prob = [0.] * len(self.class_var.values) 
     240                    for r in res_both: 
     241                        a = [x for x in r[1][varn]] 
     242                        prob = map(add, prob, a) 
     243                    norm = sum(prob) 
     244                    cprob = Orange.statistics.distribution.Discrete(self.class_var) 
     245                    for i in range(len(prob)): 
     246                        cprob[i] = prob[i]/norm 
    224247                 
    225             # voting for crisp class membership, notice that 
    226             # this may not be the same class as one obtaining the 
    227             # highest probability through probability voting 
    228             if result_type == orange.GetValue or result_type == orange.GetBoth: 
    229                 cfreq = [0] * len(self.domain.class_var.values) 
    230                 for c in self.classifiers: 
    231                     cfreq[int(c(instance))] += 1 
    232                 index = cfreq.index(max(cfreq)) 
    233                 cvalue = Orange.data.Value(self.domain.class_var, index) 
    234      
    235             if result_type == orange.GetValue: return cvalue 
    236             elif result_type == orange.GetProbabilities: return cprob 
    237             else: return (cvalue, cprob) 
    238          
    239         else: 
    240             # Handle continuous class 
    241          
    242             # voting for class probabilities 
    243             if result_type == orange.GetProbabilities or result_type == orange.GetBoth: 
    244                 probs = [c(instance, orange.GetBoth) for c in self.classifiers] 
    245                 cprob = dict() 
    246                 for val,prob in probs: 
    247                     if prob != None: #no probability output 
    248                         a = dict(prob.items()) 
    249                     else: 
    250                         a = { val.value : 1. } 
    251                     cprob = dict( (n, a.get(n, 0)+cprob.get(n, 0)) for n in set(a)|set(cprob) ) 
    252                 cprob = Orange.statistics.distribution.Continuous(cprob) 
    253                 cprob.normalize() 
     248                # voting for crisp class membership, notice that 
     249                # this may not be the same class as one obtaining the 
     250                # highest probability through probability voting 
     251                if result_type == orange.GetValue or result_type == orange.GetBoth: 
     252                    cfreq = [0] * len(self.class_var.values) 
     253                    for r in res_both: 
     254                        cfreq[int(r[0][varn])] += 1 
     255                    index = cfreq.index(max(cfreq)) 
     256                    cvalue = Orange.data.Value(self.class_var, index) 
     257             
     258 
     259                if result_type == orange.GetValue: mt_value.append(cvalue) 
     260                elif result_type == orange.GetProbabilities: mt_prob.append(cprob) 
     261                else:  
     262                    mt_value.append(cvalue) 
     263                    mt_prob.append(cprob) 
     264         
     265            else: 
     266                # Handle continuous class 
     267         
     268                # voting for class probabilities 
     269                if result_type == orange.GetProbabilities or result_type == orange.GetBoth: 
     270                    probs = [ r for r in res_both] 
     271                    cprob = dict() 
     272 
     273                
     274                    for val,prob in probs: 
     275                        if prob != None: #no probability output 
     276                            a = dict(prob.items()) 
     277                        else: 
     278                            a = { val.value : 1. } 
     279                        cprob = dict( (n, a.get(n, 0)+cprob.get(n, 0)) for n in set(a)|set(cprob) ) 
     280                    cprob = Orange.statistics.distribution.Continuous(cprob) 
     281                    cprob.normalize() 
    254282                 
    255             # gather average class value 
    256             if result_type == orange.GetValue or result_type == orange.GetBoth: 
    257                 values = [c(instance).value for c in self.classifiers] 
    258                 cvalue = Orange.data.Value(self.domain.class_var, sum(values) / len(self.classifiers)) 
    259              
    260             if result_type == orange.GetValue: return cvalue 
    261             elif result_type == orange.GetProbabilities: return cprob 
    262             else: return (cvalue, cprob) 
    263              
     283                # gather average class value 
     284                if result_type == orange.GetValue or result_type == orange.GetBoth: 
     285                    values = [c(instance).value for c in self.classifiers] 
     286                    cvalue = Orange.data.Value(self.class_var, sum(values) / len(self.classifiers)) 
     287             
     288                if result_type == orange.GetValue: mt_value.append(cvalue) 
     289                elif result_type == orange.GetProbabilities: mt_prob.append(cprob) 
     290                else:  
     291                    mt_value.append(cvalue) 
     292                    mt_prob.append(cprob) 
     293         
     294        # check for singleclass when returning 
     295        if self.single_class: 
     296            if result_type == orange.GetValue: return mt_value[0] 
     297            elif result_type == orange.GetProbabilities: mt_prob[0] 
     298            else:  
     299                return [mt_value[0],mt_prob[0]]  
     300             
     301        if result_type == orange.GetValue: return tuple(mt_value) 
     302        elif result_type == orange.GetProbabilities: return tuple(mt_prob) 
     303        else:  
     304            return [tuple(mt_value),tuple(mt_prob)] 
     305 
    264306    def __reduce__(self): 
    265307        return type(self), (self.classifiers, self.name, self.domain, self.class_var), dict(self.__dict__) 
  • docs/reference/rst/Orange.evaluation.scoring.rst

    r10426 r10741  
    162162           Earth    0.2880 
    163163 
     164Two more accuracy measures based on the article by Zaragoza et al.(2011): 
     165 
     166Global accuracy (accuracy per example) over d-dimensional class variable. 
     167 
     168.. autofunction:: mt_global_accuracy 
     169 
     170Mean accuracy accuracy per class or per label over d class variables. 
     171 
     172.. autofunction:: mt_mean_accuracy    
     173 
     174References 
     175========== 
     176 
     177Zaragoza, J.H., Sucar, L.E., Morales, E.F.,Bielza, C., Larranaga, P.  (2011). 'Bayesian Chain Classifiers for Multidimensional Classification', Proc. of the International Joint Conference on Artificial Intelligence (IJCAI-2011),  pp:2192-2197. 
     178 
    164179========================== 
    165180Multi-label classification 
Note: See TracChangeset for help on using the changeset viewer.