Changeset 9737:585926e9995e in orange


Ignore:
Timestamp:
02/06/12 15:33:49 (2 years ago)
Author:
Miha Stajdohar <miha.stajdohar@…>
Branch:
default
rebase_source:
290cd19ac90c6e94bb1a404648f3d55e3bb641b0
Message:

Moved createDichotomousClass to rules.py.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • Orange/orng/orngABML.py

    r9671 r9737  
    99import math 
    1010 
     11from Orange.classification.rules import create_dichotomous_class as createDichotomousClass 
     12from Orange.classification.rules import ConvertClass 
    1113# regular expressions 
    1214# exppression for testing validity of a set of arguments: 
     
    4244    else: 
    4345        if leave_ref: 
    44             return str(domain[arg.position].name)+strSign(arg.oper) 
     46            return str(domain[arg.position].name) + strSign(arg.oper) 
    4547        else: 
    46             return str(domain[arg.position].name)+strSign(arg.oper)+str(arg.ref) 
    47              
    48 def listOfAttributeNames(rule, leave_ref = False): 
     48            return str(domain[arg.position].name) + strSign(arg.oper) + str(arg.ref) 
     49 
     50def listOfAttributeNames(rule, leave_ref=False): 
    4951    if not rule.filter.conditions: 
    5052        return "" 
     
    5658    list += strArg(rule.filter.conditions[-1], rule.filter.domain, lr) 
    5759    return list 
    58          
    59      
     60 
     61 
    6062class Argumentation: 
    6163    """ Class that describes a set of positive and negative arguments 
     
    6668        self.not_yet_computed_arguments = [] # Arguments that need the whole data set 
    6769                                          # when processing are stored here  
    68      
     70 
    6971    # add an argument that supports the class of the example 
    7072    def addPositive(self, argument): 
     
    7678 
    7779    def addNotYetComputed(self, argument, notyet, positive): 
    78         self.not_yet_computed_arguments.append((argument,notyet,positive)) 
     80        self.not_yet_computed_arguments.append((argument, notyet, positive)) 
    7981 
    8082    def __str__(self): 
     
    8284        # iterate through positive arguments (rules) and 
    8385        # write them down as a text list 
    84         if len(self.positive_arguments)>0: 
    85             for (i,pos) in enumerate(self.positive_arguments[:-1]): 
    86                 retValue+="{"+listOfAttributeNames(pos)+"}" 
    87                 retValue+="," 
    88             retValue+="{"+listOfAttributeNames(self.positive_arguments[-1])+"}" 
     86        if len(self.positive_arguments) > 0: 
     87            for (i, pos) in enumerate(self.positive_arguments[:-1]): 
     88                retValue += "{" + listOfAttributeNames(pos) + "}" 
     89                retValue += "," 
     90            retValue += "{" + listOfAttributeNames(self.positive_arguments[-1]) + "}" 
    8991            # do the same thing for negative argument, 
    9092            # just that this time use sign "~" in front of the list 
    91         if len(self.negative_arguments)>0: 
    92             if len(retValue)>0: 
     93        if len(self.negative_arguments) > 0: 
     94            if len(retValue) > 0: 
    9395                retValue += "," 
    94             for (i,neg) in enumerate(self.negative_arguments[:-1]): 
    95                 retValue+="~" 
    96                 retValue+="{"+listOfAttributeNames(neg,leave_ref=True)+"}" 
    97                 retValue+="," 
    98             retValue+="~{"+listOfAttributeNames(self.negative_arguments[-1],leave_ref=True)+"}" 
     96            for (i, neg) in enumerate(self.negative_arguments[:-1]): 
     97                retValue += "~" 
     98                retValue += "{" + listOfAttributeNames(neg, leave_ref=True) + "}" 
     99                retValue += "," 
     100            retValue += "~{" + listOfAttributeNames(self.negative_arguments[-1], leave_ref=True) + "}" 
    99101        return retValue 
    100102 
     
    106108        """ convert str to val - used for creating variables. """ 
    107109        return self.filestr2val(strV, None) 
    108      
     110 
    109111    def filestr2val(self, strV, example=None): 
    110112        """ write arguments (from string in file) to value - used also as a function for reading from data. """ 
    111113        mt = testVal.match(strV) 
    112114        if not mt or not mt.end() == len(strV): 
    113             warnings.warn(strV+" is a badly formed argument.") 
     115            warnings.warn(strV + " is a badly formed argument.") 
    114116            return Orange.core.PythonValueSpecial(2) # return special if argument doesnt match the formal form  
    115117 
     
    119121 
    120122        # get a set of arguments 
    121         splitedSet = filter(lambda x:x!='' and x!='"', argRE.split(strV)) 
     123        splitedSet = filter(lambda x:x != '' and x != '"', argRE.split(strV)) 
    122124 
    123125        # create an Argumentation object - an empty set of arguments 
     
    130132                continue 
    131133            argument = Orange.core.Rule(filter=Orange.core.Filter_values(domain=domain)) 
    132             argument.setattr("unspecialized_argument",False) 
    133              
    134             reasonValues = filter(lambda x:x!='' and x!='"', argAt.split(sp)) # reasons in this argument 
     134            argument.setattr("unspecialized_argument", False) 
     135 
     136            reasonValues = filter(lambda x:x != '' and x != '"', argAt.split(sp)) # reasons in this argument 
    135137            # iterate through argument names 
    136138            for r in reasonValues: 
    137                 r=string.strip(r)   # Remove all white characters on both sides 
     139                r = string.strip(r)   # Remove all white characters on both sides 
    138140                try: 
    139141                    attribute = domain[r] 
     
    141143                    attribute = None 
    142144                if attribute: # only attribute name is mentioned as a reason 
    143                     if domain.index(attribute)<0: 
    144                         warnings.warn("Meta attribute %s used in argument. Is this intentional?"%r) 
     145                    if domain.index(attribute) < 0: 
     146                        warnings.warn("Meta attribute %s used in argument. Is this intentional?" % r) 
    145147                        continue 
    146148                    value = example[attribute] 
    147149                    if attribute.varType == Orange.core.VarTypes.Discrete: # discrete argument 
    148150                        argument.filter.conditions.append(Orange.core.ValueFilter_discrete( 
    149                                                             position = domain.attributes.index(attribute), 
     151                                                            position=domain.attributes.index(attribute), 
    150152                                                            values=[value], 
    151                                                             acceptSpecial = 0)) 
    152                         argument.filter.conditions[-1].setattr("unspecialized_condition",False) 
     153                                                            acceptSpecial=0)) 
     154                        argument.filter.conditions[-1].setattr("unspecialized_condition", False) 
    153155                    else: # continuous but without reference point 
    154                         warnings.warn("Continous attributes (%s) in arguments should not be used without a comparison sign (<,<=,>,>=)"%r)             
    155              
     156                        warnings.warn("Continous attributes (%s) in arguments should not be used without a comparison sign (<,<=,>,>=)" % r) 
     157 
    156158                else: # attribute and something name is the reason, probably cont. attribute 
    157159                    # one of four possible delimiters should be found, <,>,<=,>= 
    158                     splitReason = filter(lambda x:x!='' and x!='"', argCompare.split(r)) 
    159                     if len(splitReason)>2 or len(splitReason)==0: 
    160                         warnings.warn("Reason %s is a badly formed part of an argument."%r) 
     160                    splitReason = filter(lambda x:x != '' and x != '"', argCompare.split(r)) 
     161                    if len(splitReason) > 2 or len(splitReason) == 0: 
     162                        warnings.warn("Reason %s is a badly formed part of an argument." % r) 
    161163                        continue 
    162164                    # get attribute name and continous reference value 
     
    175177                        attribute = domain[attributeName] 
    176178                    except: 
    177                         warnings.warn("Attribute %s is not a part of the domain"%attributeName) 
     179                        warnings.warn("Attribute %s is not a part of the domain" % attributeName) 
    178180                        continue 
    179                     if domain.index(attribute)<0: 
    180                         warnings.warn("Meta attribute %s used in argument. Is this intentional?"%r) 
     181                    if domain.index(attribute) < 0: 
     182                        warnings.warn("Meta attribute %s used in argument. Is this intentional?" % r) 
    181183                        continue 
    182184                    if refValue: 
     
    184186                            ref = eval(refValue) 
    185187                        except: 
    186                             warnings.warn("Error occured while reading value by argument's reason. Argument: %s, value: %s"%(r,refValue)) 
     188                            warnings.warn("Error occured while reading value by argument's reason. Argument: %s, value: %s" % (r, refValue)) 
    187189                            continue 
    188190                    else: 
    189                         ref = 0.                         
     191                        ref = 0. 
    190192                    if sign == "<": oper = Orange.core.ValueFilter_continuous.Less 
    191193                    elif sign == ">": oper = Orange.core.ValueFilter_continuous.Greater 
     
    193195                    else: oper = Orange.core.ValueFilter_continuous.GreaterEqual 
    194196                    argument.filter.conditions.append(Orange.core.ValueFilter_continuous( 
    195                                                 position = domain.attributes.index(attribute), 
     197                                                position=domain.attributes.index(attribute), 
    196198                                                oper=oper, 
    197199                                                ref=ref, 
    198                                                 acceptSpecial = 0)) 
     200                                                acceptSpecial=0)) 
    199201                    if not refValue and type == POSITIVE: 
    200                         argument.filter.conditions[-1].setattr("unspecialized_condition",True) 
    201                         argument.setattr("unspecialized_argument",True) 
     202                        argument.filter.conditions[-1].setattr("unspecialized_condition", True) 
     203                        argument.setattr("unspecialized_argument", True) 
    202204                    else: 
    203                         argument.filter.conditions[-1].setattr("unspecialized_condition",False) 
     205                        argument.filter.conditions[-1].setattr("unspecialized_condition", False) 
    204206 
    205207            if example.domain.classVar: 
    206                 argument.classifier = Orange.core.DefaultClassifier(defaultVal = example.getclass()) 
     208                argument.classifier = Orange.core.DefaultClassifier(defaultVal=example.getclass()) 
    207209            argument.complexity = len(argument.filter.conditions) 
    208210 
     
    212214                argumentation.addNegative(argument) 
    213215            type = POSITIVE 
    214         return argumentation                     
     216        return argumentation 
    215217 
    216218 
     
    221223    # used for writing to string 
    222224    def val2str(self, val): 
    223         return str(val)         
    224  
    225      
     225        return str(val) 
     226 
     227 
    226228class ArgumentFilter_hasSpecial: 
    227     def __call__(self, examples, attribute, target_class=-1, negate=0): 
    228         indices = [0]*len(examples) 
     229    def __call__(self, examples, attribute, target_class= -1, negate=0): 
     230        indices = [0] * len(examples) 
    229231        for i in range(len(examples)): 
    230232            if examples[i][attribute].isSpecial(): 
    231                 indices[i]=1 
    232             elif target_class>-1 and not int(examples[i].getclass()) == target_class: 
    233                 indices[i]=1 
     233                indices[i] = 1 
     234            elif target_class > -1 and not int(examples[i].getclass()) == target_class: 
     235                indices[i] = 1 
    234236            elif len(examples[i][attribute].value.positive_arguments) == 0: 
    235                 indices[i]=1 
    236         return examples.select(indices,0,negate=negate) 
    237  
    238 def evaluateAndSortArguments(examples, argAtt, evaluateFunction = None, apriori = None): 
     237                indices[i] = 1 
     238        return examples.select(indices, 0, negate=negate) 
     239 
     240def evaluateAndSortArguments(examples, argAtt, evaluateFunction=None, apriori=None): 
    239241    """ Evaluate positive arguments and sort them by quality. """ 
    240242    if not apriori: 
    241         apriori = Orange.core.Distribution(examples.domain.classVar,examples) 
     243        apriori = Orange.core.Distribution(examples.domain.classVar, examples) 
    242244    if not evaluateFunction: 
    243245        evaluateFunction = Orange.core.RuleEvaluator_Laplace() 
    244          
     246 
    245247    for e in examples: 
    246248        if not e[argAtt].isSpecial(): 
    247249            for r in e[argAtt].value.positive_arguments: 
    248250                r.filterAndStore(examples, 0, e[examples.domain.classVar]) 
    249                 r.quality = evaluateFunction(r,examples,0,int(e[examples.domain.classVar]),apriori) 
    250             e[argAtt].value.positive_arguments.sort(lambda x,y: -cmp(x.quality, y.quality)) 
     251                r.quality = evaluateFunction(r, examples, 0, int(e[examples.domain.classVar]), apriori) 
     252            e[argAtt].value.positive_arguments.sort(lambda x, y:-cmp(x.quality, y.quality)) 
    251253 
    252254def isGreater(oper): 
     
    261263        return True 
    262264    return False 
    263  
    264 class ConvertClass: 
    265     """ Converting class variables into dichotomous class variable. """ 
    266     def __init__(self, classAtt, classValue, newClassAtt): 
    267         self.classAtt = classAtt 
    268         self.classValue = classValue 
    269         self.newClassAtt = newClassAtt 
    270  
    271     def __call__(self,example, returnWhat): 
    272         if example[self.classAtt] == self.classValue: 
    273             return Orange.core.Value(self.newClassAtt, self.classValue+"_") 
    274         else: 
    275             return Orange.core.Value(self.newClassAtt, "not " + self.classValue) 
    276  
    277 def createDichotomousClass(domain, att, value, negate, removeAtt = None): 
    278     # create new variable 
    279     newClass = Orange.core.EnumVariable(att.name+"_", values = [str(value)+"_", "not " + str(value)]) 
    280     positive = Orange.core.Value(newClass, str(value)+"_") 
    281     negative = Orange.core.Value(newClass, "not " + str(value)) 
    282     newClass.getValueFrom = ConvertClass(att,str(value),newClass) 
    283      
    284     att = [a for a in domain.attributes] 
    285     newDomain = Orange.core.Domain(att+[newClass]) 
    286     newDomain.addmetas(domain.getmetas()) 
    287     if negate==1: 
    288         return (newDomain, negative) 
    289     else: 
    290         return (newDomain, positive) 
    291  
    292265 
    293266class ConvertCont: 
     
    298271        self.newAtt = newAtt 
    299272 
    300     def __call__(self,example, returnWhat): 
     273    def __call__(self, example, returnWhat): 
    301274        if example[self.position].isSpecial(): 
    302275            return example[self.position] 
    303276        if isLess(self.oper): 
    304             if example[self.position]<self.value: 
     277            if example[self.position] < self.value: 
    305278                return Orange.core.Value(self.newAtt, self.value) 
    306279            else: 
    307280                return Orange.core.Value(self.newAtt, float(example[self.position])) 
    308281        else: 
    309             if example[self.position]>self.value: 
     282            if example[self.position] > self.value: 
    310283                return Orange.core.Value(self.newAtt, self.value) 
    311284            else: 
     
    316289    """ Main task of this function is to add probabilistic errors to examples.""" 
    317290    for ex_i, ex in enumerate(test_data): 
    318         (cl,prob) = classifier(ex,Orange.core.GetBoth) 
    319         ex.setmeta("ProbError", float(ex.getmeta("ProbError")) + 1.-prob[ex.getclass()])  
    320  
    321 def nCrossValidation(data,learner,weightID=0,folds=5,n=4,gen=0,argument_id="Arguments"): 
     291        (cl, prob) = classifier(ex, Orange.core.GetBoth) 
     292        ex.setmeta("ProbError", float(ex.getmeta("ProbError")) + 1. - prob[ex.getclass()]) 
     293 
     294def nCrossValidation(data, learner, weightID=0, folds=5, n=4, gen=0, argument_id="Arguments"): 
    322295    """ Function performs n x fold crossvalidation. For each classifier 
    323296        test set is updated by calling function addErrors. """ 
     
    326299    for d in data: 
    327300        rules[float(d["SerialNumberPE"])] = [] 
    328     pick = Orange.core.MakeRandomIndicesCV(folds=folds, randseed=gen, stratified = Orange.core.MakeRandomIndices.StratifiedIfPossible)     
     301    pick = Orange.core.MakeRandomIndicesCV(folds=folds, randseed=gen, stratified=Orange.core.MakeRandomIndices.StratifiedIfPossible) 
    329302    for n_i in range(n): 
    330         pick.randseed = gen+10*n_i 
     303        pick.randseed = gen + 10 * n_i 
    331304        selection = pick(data) 
    332305        for folds_i in range(folds): 
    333             for data_i,e in enumerate(data): 
     306            for data_i, e in enumerate(data): 
    334307                try: 
    335308                    if e[argument_id]: # examples with arguments do not need to be tested 
    336                         selection[data_i]=folds_i+1 
     309                        selection[data_i] = folds_i + 1 
    337310                except: 
    338311                    pass 
    339             train_data = data.selectref(selection, folds_i,negate=1) 
    340             test_data = data.selectref(selection, folds_i,negate=0) 
    341             classifier = learner(train_data,weightID) 
     312            train_data = data.selectref(selection, folds_i, negate=1) 
     313            test_data = data.selectref(selection, folds_i, negate=0) 
     314            classifier = learner(train_data, weightID) 
    342315            addErrors(test_data, classifier) 
    343316            # add rules 
     
    348321    # normalize prob errors 
    349322    for d in data: 
    350         d["ProbError"]=d["ProbError"]/n 
     323        d["ProbError"] = d["ProbError"] / n 
    351324    return rules 
    352325 
    353 def findProb(learner,examples,weightID=0,folds=5,n=4,gen=0,thr=0.5,argument_id="Arguments"): 
     326def findProb(learner, examples, weightID=0, folds=5, n=4, gen=0, thr=0.5, argument_id="Arguments"): 
    354327    """ General method for calling to find problematic example. 
    355328        It returns all critial examples along with average probabilistic errors that ought to be higher then thr. 
     
    373346 
    374347    # it returns a list of examples now: (index of example-starting with 0, example, prob error, rules covering example 
    375     rules = nCrossValidation(newExamples,learner,weightID=weightID, folds=folds, n=n, gen=gen, argument_id=argument_id) 
     348    rules = nCrossValidation(newExamples, learner, weightID=weightID, folds=folds, n=n, gen=gen, argument_id=argument_id) 
    376349    return [(ei, examples[ei], float(e["ProbError"]), rules[float(e["SerialNumberPE"])]) for ei, e in enumerate(newExamples) if e["ProbError"] > thr] 
    377    
     350 
Note: See TracChangeset for help on using the changeset viewer.