Changeset 8761:2bc79ec9451f in orange


Ignore:
Timestamp:
08/24/11 15:18:40 (3 years ago)
Author:
matejd <matejd@…>
Branch:
default
Convert:
1de0ec146a000ce3eb84211f2e43deb961ad9624
Message:

Ported python implementation of freeviz to sphereviz and linproj3d. Very slow, math could be wrong

Location:
orange
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • orange/Orange/projection/linear.py

    r8042 r8761  
    284284        if not attr_indices: return 
    285285 
    286         if self.implementation == FAST_IMPLEMENTATION: 
     286        if self.implementation == FAST_IMPLEMENTATION and not hasattr(self, '_use_3d'): # TODO 
    287287            return self.optimize_fast_separation(steps, single_step, distances) 
    288288 
     
    293293        elif self.implementation == LDA_IMPLEMENTATION: 
    294294            impl = self.optimize_lda_separation 
    295         xanchors = None; yanchors = None 
    296  
    297         for c in range((single_step and 1) or 50): 
    298             for i in range(steps): 
    299                 if self.__class__ != FreeViz and self.cancel_optimization == 1: 
    300                     return 
    301                 self.graph.anchorData, (xanchors, yanchors) = impl(attr_indices, 
    302                                                                    self.graph.anchorData, 
    303                                                                    xanchors, 
    304                                                                    yanchors) 
    305             if self.__class__ != FreeViz: qApp.processEvents() 
    306             if hasattr(self.graph, "updateGraph"): self.graph.updateData() 
    307             #self.recomputeEnergy() 
     295        xanchors = None 
     296        yanchors = None 
     297        zanchors = None 
     298 
     299        if hasattr(self, '_use_3D'): 
     300            if self.implementation == SLOW_IMPLEMENTATION: 
     301                impl = self.optimize_slow_separation_3D 
     302            elif self.implementation == LDA_IMPLEMENTATION: 
     303                impl = self.optimize_lda_separation_3D 
     304            else: 
     305                print('Unimplemented method!') 
     306                return 
     307 
     308            for c in range((single_step and 1) or 50): 
     309                for i in range(steps): 
     310                    if self.__class__ != FreeViz and self.cancel_optimization == 1: 
     311                        return 
     312                    self.graph.anchorData, (xanchors, yanchors, zanchors) = impl(attr_indices, 
     313                                                                                 self.graph.anchorData, 
     314                                                                                 xanchors, 
     315                                                                                 yanchors, 
     316                                                                                 zanchors) 
     317                if self.__class__ != FreeViz: qApp.processEvents() 
     318                if hasattr(self.graph, "updateGraph"): self.graph.updateData() 
     319        else: 
     320            for c in range((single_step and 1) or 50): 
     321                for i in range(steps): 
     322                    if self.__class__ != FreeViz and self.cancel_optimization == 1: 
     323                        return 
     324                    self.graph.anchorData, (xanchors, yanchors) = impl(attr_indices, 
     325                                                                       self.graph.anchorData, 
     326                                                                       xanchors, 
     327                                                                       yanchors) 
     328                if self.__class__ != FreeViz: qApp.processEvents() 
     329                if hasattr(self.graph, "updateGraph"): self.graph.updateData() 
    308330 
    309331    optimizeSeparation = optimize_separation 
     
    590612    optimize_SLOW_Separation = optimize_slow_separation 
    591613 
     614 
     615    @deprecated_keywords({"attrIndices": "attr_indices", 
     616                          "anchorData": "anchor_data", 
     617                          "XAnchors": "xanchors", 
     618                          "YAnchors": "yanchors"}) 
     619    def optimize_lda_separation_3D(self, attr_indices, anchor_data, xanchors = None, yanchors = None, zanchors = None): 
     620        if (not self.graph.haveData or len(self.graph.rawData) == 0 
     621            or not self.graph.dataHasDiscreteClass):  
     622            return anchor_data, (xanchors, yanchors, zanchors) 
     623        class_count = len(self.graph.dataDomain.classVar.values) 
     624        valid_data = self.graph.getValidList(attr_indices) 
     625        selected_data = numpy.compress(valid_data, 
     626                                       numpy.take(self.graph.noJitteringScaledData, 
     627                                                  attr_indices, axis = 0), 
     628                                       axis = 1) 
     629 
     630        if xanchors == None: 
     631            xanchors = numpy.array([a[0] for a in anchor_data], numpy.float) 
     632        if yanchors == None: 
     633            yanchors = numpy.array([a[1] for a in anchor_data], numpy.float) 
     634        if zanchors == None: 
     635            zanchors = numpy.array([a[2] for a in anchor_data], numpy.float) 
     636 
     637        trans_proj_data = self.graph.createProjectionAsNumericArray(attr_indices, 
     638                                                                    valid_data = valid_data, 
     639                                                                    xanchors = xanchors, 
     640                                                                    yanchors = yanchors, 
     641                                                                    zanchors = zanchors, 
     642                                                                    scaleFactor = self.graph.scaleFactor, 
     643                                                                    normalize = self.graph.normalizeExamples, 
     644                                                                    useAnchorData = 1) 
     645        if trans_proj_data == None: 
     646            return anchor_data, (xanchors, yanchors, zanchors) 
     647 
     648        proj_data = numpy.transpose(trans_proj_data) 
     649        x_positions, y_positions, z_positions, classData = (proj_data[0], 
     650                                                            proj_data[1], 
     651                                                            proj_data[2], 
     652                                                            proj_data[3]) 
     653 
     654        averages = [] 
     655        for i in range(class_count): 
     656            ind = classData == i 
     657            xpos = numpy.compress(ind, x_positions) 
     658            ypos = numpy.compress(ind, y_positions) 
     659            zpos = numpy.compress(ind, z_positions) 
     660            xave = numpy.sum(xpos)/len(xpos) 
     661            yave = numpy.sum(ypos)/len(ypos) 
     662            zave = numpy.sum(zpos)/len(zpos) 
     663            averages.append((xave, yave, zave)) 
     664 
     665        # compute the positions of all the points. we will try to move all points so that the center will be in the (0,0) 
     666        x_center_vector = -numpy.sum(x_positions) / len(x_positions) 
     667        y_center_vector = -numpy.sum(y_positions) / len(y_positions) 
     668        z_center_vector = -numpy.sum(z_positions) / len(z_positions) 
     669        center_vector_length = math.sqrt(x_center_vector*x_center_vector + 
     670                                         y_center_vector*y_center_vector + 
     671                                         z_center_vector*z_center_vector) 
     672 
     673        mean_destination_vectors = [] 
     674 
     675        for i in range(class_count): 
     676            xdir = 0.0; ydir = 0.0; zdir = 0.0; rs = 0.0 
     677            for j in range(class_count): 
     678                if i==j: continue 
     679                r = math.sqrt((averages[i][0] - averages[j][0])**2 + 
     680                              (averages[i][1] - averages[j][1])**2) 
     681                if r == 0.0: 
     682                    xdir += math.cos((i/float(class_count))*2*math.pi) 
     683                    ydir += math.sin((i/float(class_count))*2*math.pi) 
     684                    r = 0.0001 
     685                else: 
     686                    xdir += (1/r**3) * ((averages[i][0] - averages[j][0])) 
     687                    ydir += (1/r**3) * ((averages[i][1] - averages[j][1])) 
     688                #rs += 1/r 
     689            #actualDirAmpl = math.sqrt(xDir**2 + yDir**2) 
     690            #s = abs(xDir)+abs(yDir) 
     691            #xDir = rs * (xDir/s) 
     692            #yDir = rs * (yDir/s) 
     693            mean_destination_vectors.append((xdir, ydir)) 
     694 
     695 
     696        maxlength = math.sqrt(max([x**2 + y**2 for (x,y) 
     697                                   in mean_destination_vectors])) 
     698        mean_destination_vectors = [(x/(2*maxlength), y/(2*maxlength)) for (x,y) 
     699                                    in mean_destination_vectors]     # normalize destination vectors to some normal values 
     700        mean_destination_vectors = [(mean_destination_vectors[i][0]+averages[i][0], 
     701                                     mean_destination_vectors[i][1]+averages[i][1]) 
     702                                    for i in range(len(mean_destination_vectors))]    # add destination vectors to the class averages 
     703        #mean_destination_vectors = [(x + x_center_vector/5, y + y_center_vector/5) for (x,y) in mean_destination_vectors]   # center mean values 
     704        mean_destination_vectors = [(x + x_center_vector, y + y_center_vector) 
     705                                    for (x,y) in mean_destination_vectors]   # center mean values 
     706 
     707        fxs = numpy.zeros(len(x_positions), numpy.float)        # forces 
     708        fys = numpy.zeros(len(x_positions), numpy.float) 
     709 
     710        for c in range(class_count): 
     711            ind = (classData == c) 
     712            numpy.putmask(fxs, ind, mean_destination_vectors[c][0]-x_positions) 
     713            numpy.putmask(fys, ind, mean_destination_vectors[c][1]-y_positions) 
     714 
     715        # compute gradient for all anchors 
     716        gxs = numpy.array([sum(fxs * selected_data[i]) 
     717                           for i in range(len(anchor_data))], numpy.float) 
     718        gys = numpy.array([sum(fys * selected_data[i]) 
     719                           for i in range(len(anchor_data))], numpy.float) 
     720 
     721        m = max(max(abs(gxs)), max(abs(gys))) 
     722        gxs /= (20*m); gys /= (20*m) 
     723 
     724        newxanchors = xanchors + gxs 
     725        newyanchors = yanchors + gys 
     726 
     727        # normalize so that the anchor most far away will lie on the circle 
     728        m = math.sqrt(max(newxanchors**2 + newyanchors**2)) 
     729        newxanchors /= m 
     730        newyanchors /= m 
     731 
     732        #self.parentWidget.updateGraph() 
     733 
     734        """ 
     735        for a in range(len(anchor_data)): 
     736            x = anchor_data[a][0]; y = anchor_data[a][1]; 
     737            self.parentWidget.graph.addCurve("lll%i" % i, QColor(0, 0, 0), QColor(0, 0, 0), 10, style = QwtPlotCurve.Lines, symbol = QwtSymbol.NoSymbol, xData = [x, x+gxs[a]], yData = [y, y+gys[a]], forceFilledSymbols = 1, lineWidth=3) 
     738 
     739        for i in range(class_count): 
     740            self.parentWidget.graph.addCurve("lll%i" % i, QColor(0, 0, 0), QColor(0, 0, 0), 10, style = QwtPlotCurve.Lines, symbol = QwtSymbol.NoSymbol, xData = [averages[i][0], mean_destination_vectors[i][0]], yData = [averages[i][1], mean_destination_vectors[i][1]], forceFilledSymbols = 1, lineWidth=3) 
     741            self.parentWidget.graph.addCurve("lll%i" % i, QColor(0, 0, 0), QColor(0, 0, 0), 10, style = QwtPlotCurve.Lines, xData = [averages[i][0], averages[i][0]], yData = [averages[i][1], averages[i][1]], forceFilledSymbols = 1, lineWidth=5) 
     742        """ 
     743        #self.parentWidget.graph.repaint() 
     744        #self.graph.anchor_data = [(newxanchors[i], newyanchors[i], anchor_data[i][2]) for i in range(len(anchor_data))] 
     745        #self.graph.updateData(attrs, 0) 
     746        return [(newxanchors[i], newyanchors[i], anchor_data[i][2]) 
     747                for i in range(len(anchor_data))], (newxanchors, newyanchors) 
     748 
     749    optimize_LDA_Separation_3D = optimize_lda_separation_3D 
     750 
     751    @deprecated_keywords({"attrIndices": "attr_indices", 
     752                          "anchorData": "anchor_data", 
     753                          "XAnchors": "xanchors", 
     754                          "YAnchors": "yanchors"}) 
     755    def optimize_slow_separation_3D(self, attr_indices, anchor_data, xanchors = None, yanchors = None, zanchors = None): 
     756        if (not self.graph.haveData or len(self.graph.rawData) == 0 
     757            or not self.graph.dataHasDiscreteClass):  
     758            return anchor_data, (xanchors, yanchors, zanchors) 
     759        valid_data = self.graph.getValidList(attr_indices) 
     760        selected_data = numpy.compress(valid_data, numpy.take(self.graph.noJitteringScaledData, 
     761                                                              attr_indices, 
     762                                                              axis = 0), 
     763                                       axis = 1) 
     764 
     765        if xanchors == None: 
     766            xanchors = numpy.array([a[0] for a in anchor_data], numpy.float) 
     767        if yanchors == None: 
     768            yanchors = numpy.array([a[1] for a in anchor_data], numpy.float) 
     769        if zanchors == None: 
     770            zanchors = numpy.array([a[2] for a in anchor_data], numpy.float) 
     771 
     772        trans_proj_data = self.graph.createProjectionAsNumericArray(attr_indices, 
     773                                                                    valid_data = valid_data, 
     774                                                                    XAnchors = xanchors, 
     775                                                                    YAnchors = yanchors, 
     776                                                                    ZAnchors = zanchors, 
     777                                                                    scaleFactor = self.graph.scaleFactor, 
     778                                                                    normalize = self.graph.normalizeExamples, 
     779                                                                    useAnchorData = 1) 
     780        if trans_proj_data == None: 
     781            return anchor_data, (xanchors, yanchors, zanchors) 
     782 
     783        proj_data = numpy.transpose(trans_proj_data) 
     784        x_positions = proj_data[0]; x_positions2 = numpy.array(x_positions) 
     785        y_positions = proj_data[1]; y_positions2 = numpy.array(y_positions) 
     786        z_positions = proj_data[2]; z_positions2 = numpy.array(z_positions) 
     787        class_data = proj_data[3];  class_data2 = numpy.array(class_data) 
     788 
     789        fxs = numpy.zeros(len(x_positions), numpy.float)        # forces 
     790        fys = numpy.zeros(len(x_positions), numpy.float) 
     791        fzs = numpy.zeros(len(x_positions), numpy.float) 
     792        gxs = numpy.zeros(len(anchor_data), numpy.float)        # gradients 
     793        gys = numpy.zeros(len(anchor_data), numpy.float) 
     794        gzs = numpy.zeros(len(anchor_data), numpy.float) 
     795 
     796        rotate_array = range(len(x_positions)) 
     797        rotate_array = rotate_array[1:] + [0] 
     798        for i in range(len(x_positions)-1): 
     799            x_positions2 = numpy.take(x_positions2, rotate_array) 
     800            y_positions2 = numpy.take(y_positions2, rotate_array) 
     801            z_positions2 = numpy.take(z_positions2, rotate_array) 
     802            class_data2 = numpy.take(class_data2, rotate_array) 
     803            dx = x_positions2 - x_positions 
     804            dy = y_positions2 - y_positions 
     805            dz = z_positions2 - z_positions 
     806            rs2 = dx**2 + dy**2 + dz**2 
     807            rs2 += numpy.where(rs2 == 0.0, 0.0001, 0.0)    # replace zeros to avoid divisions by zero 
     808            rs = numpy.sqrt(rs2) 
     809 
     810            F = numpy.zeros(len(x_positions), numpy.float) 
     811            classDiff = numpy.where(class_data == class_data2, 1, 0) 
     812            numpy.putmask(F, classDiff, 150*self.attract_g*rs2) 
     813            numpy.putmask(F, 1-classDiff, -self.repel_g/rs2) 
     814            fxs += F * dx / rs 
     815            fys += F * dy / rs 
     816            fzs += F * dz / rs 
     817 
     818        # compute gradient for all anchors 
     819        gxs = numpy.array([sum(fxs * selected_data[i]) 
     820                           for i in range(len(anchor_data))], numpy.float) 
     821        gys = numpy.array([sum(fys * selected_data[i]) 
     822                           for i in range(len(anchor_data))], numpy.float) 
     823        gzs = numpy.array([sum(fzs * selected_data[i]) 
     824                           for i in range(len(anchor_data))], numpy.float) 
     825 
     826        m = max(max(abs(gxs)), max(abs(gys)), max(abs(gzs))) 
     827        gxs /= (20*m) 
     828        gys /= (20*m) 
     829        gzs /= (20*m) 
     830 
     831        newxanchors = xanchors + gxs 
     832        newyanchors = yanchors + gys 
     833        newzanchors = zanchors + gzs 
     834 
     835        # normalize so that the anchor most far away will lie on the circle 
     836        m = math.sqrt(max(newxanchors**2 + newyanchors**2 + newzanchors**2)) 
     837        newxanchors /= m 
     838        newyanchors /= m 
     839        newzanchors /= m 
     840        return [(newxanchors[i], newyanchors[i], newzanchors[i], anchor_data[i][3]) 
     841                for i in range(len(anchor_data))], (newxanchors, newyanchors, newzanchors) 
     842 
     843    optimize_SLOW_Separation_3D = optimize_slow_separation_3D 
     844 
     845 
     846 
    592847    # ############################################################### 
    593848    # S2N HEURISTIC FUNCTIONS 
  • orange/OrangeWidgets/Visualize Qt/OWLinProj3DPlot.py

    r8756 r8761  
    125125                x, y, z, label = anchor 
    126126 
    127                 direction = QVector3D(x, y, z) 
     127                direction = QVector3D(x, y, z).normalized() 
    128128                up = QVector3D(0, 1, 0) 
    129129                right = QVector3D.crossProduct(direction, up).normalized() 
    130                 up = QVector3D.crossProduct(right, direction) 
     130                up = QVector3D.crossProduct(right, direction).normalized() 
    131131                rotation = QMatrix4x4() 
    132132                rotation.setColumn(0, QVector4D(right, 0)) 
     
    176176        self.value_lines = [] 
    177177 
    178         if not self.have_data or len(labels) < 3: 
     178        if not self.have_data or (setAnchors and labels == None): 
    179179            self.anchor_data = [] 
    180180            self.updateGL() 
  • orange/OrangeWidgets/Visualize Qt/OWLinProjQt.py

    r8756 r8761  
    131131 
    132132        # freeviz dialog 
    133         if "radviz" in name_lower or "linear projection" in name_lower: 
     133        if "radviz" in name_lower or "linear projection" in name_lower or "sphereviz" in name_lower: 
    134134            self.freeVizDlg = FreeVizOptimization(self, self.signalManager, self.graph, name) 
    135135            self.wdChildDialogs.append(self.freeVizDlg) 
     
    138138                self.freeVizLearner = FreeVizLearner(self.freeVizDlg) 
    139139                self.send("FreeViz Learner", self.freeVizLearner) 
     140            if "3d" in name_lower: 
     141                # Patch a method in Freeviz 
     142                get_shown_attribute_list = lambda: [anchor[3] for anchor in self.graph.anchorData] 
     143                self.freeVizDlg.get_shown_attribute_list = get_shown_attribute_list 
     144                self.freeVizDlg._use_3D = True 
    140145 
    141146##        self.clusterDetectionDlgButton = OWGUI.button(self.optimizationButtons, self, "Cluster", callback = self.clusterDlg.reshow, debuggingEnabled = 0) 
Note: See TracChangeset for help on using the changeset viewer.