⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ownomogram.py

📁 orange源码 数据挖掘技术
💻 PY
📖 第 1 页 / 共 3 页
字号:
"""
<name>Nomogram</name>
<description>Nomogram viewer for Naive Bayesian, logistic regression or linear SVM classifiers.</description>
<icon>icons/Nomogram.png</icon>
<contact>Martin Mozina (martin.mozina(@at@)fri.uni-lj.si)</contact> 
<priority>2500</priority>
"""

#
# Nomogram is a Orange widget for
# for visualization of the knowledge
# obtained with Naive Bayes or logistic regression classifier
#

import math
import orange

import OWGUI
from OWWidget import *
from OWNomogramGraph import *

import orngLR
import orngLR_Jakulin



aproxZero = 0.0001

def getStartingPoint(d, min):
    if min<0:
        curr_num = Numeric.arange(-min+d, step=d)
        curr_num = curr_num[len(curr_num)-1]
        curr_num = -curr_num
    elif min - d <= 0:
        curr_num = 0
    else:
        curr_num = Numeric.arange(min-d, step=d)
        curr_num = curr_num[len(curr_num)-1]
    return curr_num

def getRounding(d):
    rndFac = math.floor(math.log10(d));
    if rndFac<-2:
        rndFac = int(-rndFac)
    else:
        rndFac = 2
    return rndFac

def avg(l):
    return sum(l)/len(l)
    

class OWNomogram(OWWidget):
    settingsList = ["alignType", "contType", "bubble", "histogram", "histogram_size", "confidence_percent", "sort_type"]

    def __init__(self,parent=None, signalManager = None):
        OWWidget.__init__(self, parent, signalManager, "Nomogram", 1)
        
        self.setWFlags(Qt.WResizeNoErase | Qt.WRepaintNoErase) #this works like magic.. no flicker during repaint!
        self.parent = parent        
#        self.setWFlags(self.getWFlags()+Qt.WStyle_Maximize)

        self.callbackDeposit = [] # deposit for OWGUI callback functions
        self.alignType = 0
        self.contType = 0
        self.yAxis = 0
        self.probability = 0
        self.showBaseLine = 1
        self.table = 0
        self.verticalSpacing = 60
        self.verticalSpacingContinuous = 100
        self.diff_between_ordinal = 30
        self.fontSize = 9
        self.lineWidth = 1
        self.bubble = 1
        self.histogram = 1
        self.histogram_size = 10
        self.data = None
        self.cl = None
        self.confidence_check = 0
        self.confidence_percent = 95
#        self.notTargetClassIndex = 1
        self.sort_type = 0
        
        self.loadSettings()

        self.pointsName = ["Points","Log OR"]
        self.totalPointsName = ["Total Points","Log OR Sum"]
        self.bnomogram = None


        #inputs
        self.inputs=[("Classifier", orange.Classifier, self.classifier)]
        
        # GUI definition
        self.tabs = QTabWidget(self.controlArea, 'tabWidget')
        
        # GENERAL TAB
        GeneralTab = QVGroupBox(self)

        self.alignRadio = OWGUI.radioButtonsInBox(GeneralTab, self,  'alignType', ['Left', '0-point'], box='Align',
                                                  tooltips=['Attributes in nomogram are left aligned', 'Attributes are not aligned, top scale represents true (normalized) regression coefficient value'],
                                                  callback=self.showNomogram)
        self.yAxisRadio = OWGUI.radioButtonsInBox(GeneralTab, self, 'yAxis', ['100', 'log OR'], 'yAxis',  
                                tooltips=['values are normalized on a 0-100 point scale','values on top axis show log-linear contribution of attribute to full model'],
                                callback=self.showNomogram)
        self.ContRadio = OWGUI.radioButtonsInBox(GeneralTab, self, 'contType',   ['1D', '2D'], 'Continuous',
                                tooltips=['Continuous attribute are presented on a single scale', 'Two dimensional space is used to present continuous attributes in nomogram.'],
                                callback=self.showNomogram)

        #target combo box
        self.TargetClassIndex = 0
        self.target = ""
        self.targetCombo = OWGUI.comboBox(GeneralTab, self, "target", " Target Class ", tooltip='Select target (prediction) class in the model.', callback = self.setTarget, sendSelectedValue = 1, valueType = str)
        
        #self.yAxisRadio.setDisabled(True)
        self.probabilityCheck = OWGUI.checkBox(GeneralTab, self, 'probability','Show prediction',  tooltip='', callback = self.setProbability)
        #self.probabilityCheck.setDisabled(True)
        self.tableCheck = OWGUI.checkBox(GeneralTab, self, 'table','Show table',  tooltip='Show table of selected attribute values?')
        self.bubbleCheck = OWGUI.checkBox(GeneralTab, self, 'bubble', 'Show details bubble',  tooltip='Show details of selected attribute value in a roll-over blob.')
        self.tableCheck.setDisabled(True)

        self.sortBox = OWGUI.comboBox(GeneralTab, self, "sort_type", box="Sorting", label="Criteria: ", items=["No sorting", "Absolute importance", "Positive influence", "Negative influence"], callback = self.sortNomogram)
    
        self.tabs.insertTab(GeneralTab, "General")
        
        # TREE TAB
        NomogramStyleTab = QVGroupBox(self)

        self.verticalSpacingLabel = OWGUI.spin(NomogramStyleTab, self, 'verticalSpacing', 15, 100, box = 'Vertical spacing:',  tooltip='Define space (pixels) between adjacent attributes.', callback = self.showNomogram)
        self.verticalSpacingLabel.setDisabled(True)
        self.fontSizeLabel = OWGUI.spin(NomogramStyleTab, self, 'fontSize', 4, 14, box = 'Font size:', tooltip='Font size of nomogram labels.')
        self.fontSizeLabel.setDisabled(True)
        self.lineWidthLabel = OWGUI.spin(NomogramStyleTab, self, 'lineWidth', 1, 10, box = 'Line width:',  tooltip='Define width of lines shown in nomogram.')
        self.lineWidthLabel.setDisabled(True)
        self.histogramCheck, self.histogramLabel = OWGUI.checkWithSpin(NomogramStyleTab, self, 'Histogram, max. size:', min=1, max=30, checked='histogram', value='histogram_size', step = 1, tooltip='-(TODO)-', checkCallback=self.showNomogram, spinCallback = self.showNomogram)
        self.histogramCheck.setChecked(False)
        self.histogramCheck.setDisabled(True)
        self.histogramLabel.setDisabled(True)

        # save button
        self.connect(self.graphButton, SIGNAL("clicked()"), self.saveToFileCanvas)

        # objects/gui widgets in settings tab for showing and adjusting confidence intervals properties       
        self.CICheck, self.CILabel = OWGUI.checkWithSpin(NomogramStyleTab, self, 'Confidence Interval (%):', min=1, max=99, step = 1, checked='confidence_check', value='confidence_percent', tooltip='-(TODO)-', checkCallback=self.showNomogram, spinCallback = self.showNomogram)
        self.CICheck.setChecked(False)
        self.CICheck.setDisabled(True)
        self.CILabel.setDisabled(True)
        self.showBaseLineCB = OWGUI.checkBox(NomogramStyleTab, self, 'showBaseLine', 'Show Base Line (at 0-point)', callback = self.setBaseLine)
        
        self.tabs.insertTab(NomogramStyleTab, "Settings")
        
        #add a graph widget
        self.box=QBoxLayout(self.mainArea, QVBoxLayout.TopToBottom, 0)
        self.graph=OWNomogramGraph(self.bnomogram, self.mainArea)
        self.graph.setMinimumWidth(200)
        self.header = OWNomogramHeader(None, self.mainArea)
        self.header.setMinimumHeight(self.verticalSpacing)
        self.header.setMaximumHeight(self.verticalSpacing)
        self.footer = OWNomogramHeader(None, self.mainArea)
        self.footer.setMinimumHeight(self.verticalSpacing*2+10)
        self.footer.setMaximumHeight(self.verticalSpacing*2+10)

        self.box.addWidget(self.header)
        self.box.addWidget(self.graph)
        self.box.addWidget(self.footer)
        self.resize(700,500)
        self.repaint()
        self.update()

        # mouse pressed flag
        self.mousepr = False


    # Input channel: the Bayesian classifier   
    def nbClassifier(self, cl):
        # thisd subroutine computes standard error of estimated beta. Note that it is used only for discrete data,
        # continuous data have a different computation.
        def errOld(e, priorError, key, data):
            inf = 0.0
            sume = e[0]+e[1]
            for d in data:
                if d[at]==key:
                    inf += (e[0]*e[1]/sume/sume)
            inf = max(inf, aproxZero)
            var = max(1/inf - priorError*priorError, 0)
            return (math.sqrt(var))

        def err(condDist, att, value, targetClass, priorError, data):
            sumE = sum(condDist)
            valueE = condDist[targetClass]
            distAtt = orange.Distribution(att, data)
            inf = distAtt[value]*(valueE/sumE)*(1-valueE/sumE)
            inf = max(inf, aproxZero)
            var = max(1/inf - priorError*priorError, 0)
            return (math.sqrt(var))

        classVal = cl.domain.classVar
        att = cl.domain.attributes

        # calculate prior probability
        dist1 = max(aproxZero, 1-cl.distribution[classVal[self.TargetClassIndex]])
        dist0 = max(aproxZero, cl.distribution[classVal[self.TargetClassIndex]])
        prior = dist0/dist1
        if self.data:
            sumd = dist1+dist0
            priorError = math.sqrt(1/((dist1*dist0/sumd/sumd)*len(self.data)))
        else:
            priorError = 0
        self.bnomogram = BasicNomogram(self, AttValue("Constant", math.log(prior), error = priorError))

        if self.data:
            stat = orange.DomainBasicAttrStat(self.data)

        for at in range(len(att)):
            if att[at].varType == orange.VarTypes.Discrete:
                if att[at].ordered:
                    a = AttrLineOrdered(att[at].name, self.bnomogram)
                else:
                    a = AttrLine(att[at].name, self.bnomogram)
                for cd in cl.conditionalDistributions[at].keys():
                    # calculuate thickness
                    conditional0 = max(cl.conditionalDistributions[at][cd][classVal[self.TargetClassIndex]], aproxZero)
                    conditional1 = max(1-cl.conditionalDistributions[at][cd][classVal[self.TargetClassIndex]], aproxZero)
                    beta = math.log(conditional0/conditional1/prior)
                    if self.data:
                        #thickness = int(round(4.*float(len(self.data.filter({att[at].name:str(cd)})))/float(len(self.data))))
                        thickness = float(len(self.data.filter({att[at].name:str(cd)})))/float(len(self.data))
                        se = err(cl.conditionalDistributions[at][cd], att[at], cd, classVal[self.TargetClassIndex], priorError, self.data) # standar error of beta 
                    else:
                        thickness = 0
                        se = 0
                        
                    a.addAttValue(AttValue(str(cd), beta, lineWidth=thickness, error = se))
            else:
                a = AttrLineCont(att[at].name, self.bnomogram)
                numOfPartitions = 50 

                if self.data:
                    maxAtValue = stat[at].max
                    minAtValue = stat[at].min
                else:
                    maxAtValue = cl.conditionalDistributions[at].keys()[len(cl.conditionalDistributions[at].keys())-1]
                    minAtValue = cl.conditionalDistributions[at].keys()[0]

                d = maxAtValue-minAtValue
                d = getDiff(d/numOfPartitions)

                # get curr_num = starting point for continuous att. sampling
                curr_num = getStartingPoint(d, minAtValue)
                rndFac = getRounding(d)                

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -