source: orange/Orange/OrangeWidgets/Regression/OWLinearRegression.py @ 10794:39d5727f34b3

Revision 10794:39d5727f34b3, 8.1 KB checked in by Lan Zagar <lan.zagar@…>, 2 years ago (diff)

Corrected model statistics, when not using intercept.

Line 
1"""
2<name>Linear Regression</name>
3<description>Linear Regression</name>
4<icon>icons/LinearRegression.png</icon>
5<priority>10</priority>
6<category>Regression</category>
7<keywords>linear, model, ridge, regression, lasso, least, absolute, shrinkage</keywords>
8
9"""
10
11import os, sys
12from OWWidget import *
13
14import Orange
15from Orange.regression import linear, lasso
16from orngWrap import PreprocessedLearner
17from Orange import feature as variable
18
19class OWLinearRegression(OWWidget):
20    settingsList = ["name", "intercept", "use_ridge", "ridge_lambda",
21                    "use_lasso", "t", "tol"]
22   
23    def __init__(self, parent=None, signalManager=None, title="Linear Regression"):
24        OWWidget.__init__(self, parent, signalManager, title, wantMainArea=False)
25       
26        self.inputs = [("Data", Orange.data.Table, self.set_data),
27                       ("Preprocessor", PreprocessedLearner, self.set_preprocessor)]
28       
29        self.outputs = [("Learner", Orange.core.Learner), 
30                        ("Predictor", Orange.core.Classifier),
31                        ("Model Statistics", Orange.data.Table)]
32       
33        ##########
34        # Settings
35        ##########
36         
37        self.name = "Linear Regression"
38        self.intercept = True
39        self.use_ridge = False
40        self.ridge_lambda = 1.0
41        self.use_lasso = False
42        self.t = 1.0
43        self.tol = 1e-3
44       
45        self.loadSettings()
46       
47        #####
48        # GUI
49        #####
50       
51        OWGUI.lineEdit(self.controlArea, self, "name", box="Learner/predictor name",   
52                       tooltip="Name of the learner/predictor")
53       
54        OWGUI.checkBox(self.controlArea, self, 'intercept', 'Intercept')
55       
56        bbox = OWGUI.radioButtonsInBox(self.controlArea, self, "use_lasso", [], 
57                                       box=None,
58                                       callback=self.on_method_changed
59                                       )
60        rb = OWGUI.appendRadioButton(bbox, self, "use_lasso",
61                                     label="Ordinary/Ridge Linear Regression",
62                                     tooltip="",
63                                     insertInto=bbox)
64
65        self.lm_box = box = OWGUI.indentedBox(self.controlArea, 
66                                sep=OWGUI.checkButtonOffsetHint(rb))
67        self.lm_box.setEnabled(not self.use_lasso)
68       
69        OWGUI.doubleSpin(box, self, "ridge_lambda", 0.1, 100, step=0.1,
70                         label="Ridge lambda", checked="use_ridge",
71                         tooltip="Ridge lambda for ridge regression")
72
73        rb = OWGUI.appendRadioButton(bbox, self, "use_lasso",
74                                     label="LASSO Regression",
75                                     tooltip="",
76                                     insertInto=bbox)
77       
78        self.lasso_box = box = OWGUI.indentedBox(self.controlArea, 
79                                sep=OWGUI.checkButtonOffsetHint(rb))
80        self.lasso_box.setEnabled(self.use_lasso)       
81       
82        OWGUI.doubleSpin(box, self, "t", 0.0, 1e4, 0.1,
83                         label="Lasso bound",
84                         tooltip="Tuning parameter, upper bound for the L1-norm of the regression coefficients",
85                         )
86       
87        OWGUI.doubleSpin(box, self, "tol", 0.0, 1.0, 0.01,
88                         label="Tolerance", 
89                         tooltip="Tolerance parameter, regression coefficients (absoulute value) under tolerance are set to 0",
90                         )
91       
92        OWGUI.rubber(self.controlArea)
93       
94        OWGUI.button(self.controlArea, self, "&Apply",
95                     callback=self.apply,
96                     tooltip="Send the learner on",
97                     autoDefault=True)
98       
99        self.data = None
100        self.preprocessor = None
101        self.resize(300, 100)
102        self.apply()
103       
104    def set_data(self, data=None):
105        if not self.isDataWithClass(data, Orange.core.VarTypes.Continuous, 
106                                    checkMissing=True):
107            data = None
108        self.data = data
109           
110    def set_preprocessor(self, pproc=None):
111        self.preprocessor = pproc
112       
113    def handleNewSignals(self):
114        self.apply()
115           
116    def on_method_changed(self):
117        self.lm_box.setEnabled(not self.use_lasso)
118        self.lasso_box.setEnabled(self.use_lasso)
119   
120    def apply(self):
121        if self.use_lasso:
122            self.apply_lasso()
123        else:
124            self.apply_ridge()
125           
126    def apply_ridge(self):
127        if self.use_ridge:
128            learner = linear.LinearRegressionLearner(name=self.name,
129                intercept=self.intercept, ridgeLambda=self.ridge_lambda)
130        else:
131            learner = linear.LinearRegressionLearner(name=self.name,
132                intercept=self.intercept)
133        predictor = None
134        if self.preprocessor:
135            learner = self.preprocessor.wrapLearner(learner)
136       
137        self.error(0)
138        if self.data is not None:
139            try:
140                predictor = learner(self.data)
141                predictor.name = self.name
142            except Exception, ex:
143                self.error(0, "An error during learning: %r" % ex)
144           
145        self.send("Learner", learner)
146        self.send("Predictor", predictor)
147        self.send("Model Statistics", self.statistics_olr(predictor))
148
149    def apply_lasso(self):
150        learner = lasso.LassoRegressionLearner(t=self.t,
151                            tol=self.tol, n_boot=0, n_perm=0,
152                            name=self.name)
153        predictor = None
154       
155        if self.preprocessor is not None:
156            learner = self.preprocessor.wrapLearner(learner)
157
158        self.error(0)
159        try:
160            if self.data is not None:
161                ll = lasso.LassoRegressionLearner(t=self.t,
162                            tol=self.tol, n_boot=10, n_perm=10)
163                predictor = ll(self.data)
164                predictor.name = self.name
165        except Exception, ex:
166            self.error(0, "An error during learning: %r" % ex)
167           
168        self.send("Learner", learner)
169        self.send("Predictor", predictor)
170        self.send("Model Statistics", self.statistics_lasso(predictor))
171       
172    def statistics_olr(self, m):
173        if m is None:
174            return None
175       
176        columns = [variable.String("Variable"),
177                   variable.Continuous("Coeff Est"),
178                   variable.Continuous("Std Error"),
179                   variable.Continuous("t-value"),
180                   variable.Continuous("p"),]
181       
182        domain = Orange.data.Domain(columns, None)
183        vars = ["Intercept"] if m.intercept else []
184        vars.extend([a.name for a in m.domain.attributes])
185        stats = []
186        geti = lambda list, i: list[i] if list is not None else "?"
187       
188        for i, var in enumerate(vars):
189            coef = m.coefficients[i]
190            std_err = geti(m.std_error, i)
191            t_val = geti(m.t_scores, i)
192            p = geti(m.p_vals, i)
193            stats.append([var, coef, std_err, t_val, p])
194               
195        return Orange.data.Table(domain, stats)
196   
197    def statistics_lasso(self, m):
198        if m is None:
199            return None
200       
201        columns = [variable.String("Variable"),
202                   variable.Continuous("Coeff Est"),
203                   variable.Continuous("Std Error"),
204                   variable.Continuous("p"),]
205       
206        domain = Orange.data.Domain(columns, None)
207        vars = []
208        vars.extend([a.name for a in m.domain.attributes])
209        stats = [["Intercept", m.coef0, "?", "?"]]
210        geti = lambda list, i: list[i] if list is not None else "?"
211       
212        for i, var in enumerate(vars):
213            coef = m.coefficients[i]
214            std_err = geti(m.std_errors_fixed_t, i)
215            p = geti(m.p_vals, i)
216            stats.append([var, coef, std_err, p])
217       
218        return Orange.data.Table(domain, stats)
219       
220       
221if __name__ == "__main__":
222    app = QApplication(sys.argv)
223    w = OWLinearRegression()
224    w.set_data(Orange.data.Table("housing"))
225    w.show()
226    app.exec_()
227#    w.saveSettings()
Note: See TracBrowser for help on using the repository browser.