1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
|
import copy
from Orange.classification import CalibratedLearner, ThresholdLearner, \
NaiveBayesLearner
from Orange.data import Table
from Orange.modelling import Learner
from Orange.widgets import gui
from Orange.widgets.widget import Input
from Orange.widgets.settings import Setting
from Orange.widgets.utils.owlearnerwidget import OWBaseLearner
from Orange.widgets.utils.widgetpreview import WidgetPreview
class OWCalibratedLearner(OWBaseLearner):
name = "Calibrated Learner"
description = "Wraps another learner with probability calibration and " \
"decision threshold optimization"
icon = "icons/CalibratedLearner.svg"
priority = 20
keywords = "calibrated learner, calibration, threshold"
LEARNER = CalibratedLearner
SigmoidCalibration, IsotonicCalibration, NoCalibration = range(3)
CalibrationOptions = ("Sigmoid calibration",
"Isotonic calibration",
"No calibration")
CalibrationShort = ("Sigmoid", "Isotonic", "")
CalibrationMap = {
SigmoidCalibration: CalibratedLearner.Sigmoid,
IsotonicCalibration: CalibratedLearner.Isotonic}
OptimizeCA, OptimizeF1, NoThresholdOptimization = range(3)
ThresholdOptions = ("Optimize classification accuracy",
"Optimize F1 score",
"No threshold optimization")
ThresholdShort = ("CA", "F1", "")
ThresholdMap = {
OptimizeCA: ThresholdLearner.OptimizeCA,
OptimizeF1: ThresholdLearner.OptimizeF1}
learner_name = Setting("", schema_only=True)
calibration = Setting(SigmoidCalibration)
threshold = Setting(OptimizeCA)
class Inputs(OWBaseLearner.Inputs):
base_learner = Input("Base Learner", Learner)
def __init__(self):
super().__init__()
self.base_learner = None
def add_main_layout(self):
gui.radioButtons(
self.controlArea, self, "calibration", self.CalibrationOptions,
box="Probability calibration",
callback=self.calibration_options_changed)
gui.radioButtons(
self.controlArea, self, "threshold", self.ThresholdOptions,
box="Decision threshold optimization",
callback=self.calibration_options_changed)
@Inputs.base_learner
def set_learner(self, learner):
self.base_learner = learner
self._set_default_name()
self.learner = self.model = None
def _set_default_name(self):
if self.base_learner is None:
self.set_default_learner_name("")
else:
name = " + ".join(part for part in (
self.base_learner.name.title(),
self.CalibrationShort[self.calibration],
self.ThresholdShort[self.threshold]) if part)
self.set_default_learner_name(name)
def calibration_options_changed(self):
self._set_default_name()
self.apply()
def create_learner(self):
if self.base_learner is None:
return None
learner = self.base_learner
if self.calibration != self.NoCalibration:
learner = CalibratedLearner(learner,
self.CalibrationMap[self.calibration])
if self.threshold != self.NoThresholdOptimization:
learner = ThresholdLearner(learner,
self.ThresholdMap[self.threshold])
if learner is self.base_learner:
learner = copy.deepcopy(learner)
if self.preprocessors:
learner.preprocessors = (self.preprocessors, )
assert learner is not self.base_learner
return learner
def get_learner_parameters(self):
return (("Calibrate probabilities",
self.CalibrationOptions[self.calibration]),
("Threshold optimization",
self.ThresholdOptions[self.threshold]))
if __name__ == "__main__": # pragma: no cover
WidgetPreview(OWCalibratedLearner).run(
Table("heart_disease"),
set_learner=NaiveBayesLearner())
|