rulelearn-ripper-interactive 0.2.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rulelearn_ri/__init__.py +6 -0
- rulelearn_ri/algorithms/__init__.py +0 -0
- rulelearn_ri/algorithms/r2n/__init__.py +0 -0
- rulelearn_ri/algorithms/r2n/base.py +28 -0
- rulelearn_ri/algorithms/r2n/functions.py +25 -0
- rulelearn_ri/algorithms/r2n/mask.py +58 -0
- rulelearn_ri/algorithms/r2n/preprocessing_layers.py +192 -0
- rulelearn_ri/algorithms/r2n/r2n_algo.py +287 -0
- rulelearn_ri/algorithms/r2n/simple_rulenet.py +75 -0
- rulelearn_ri/algorithms/r2n/training.py +34 -0
- rulelearn_ri/algorithms/r2n/utilities.py +117 -0
- rulelearn_ri/algorithms/rbm/__init__.py +0 -0
- rulelearn_ri/algorithms/rbm/boolean_rule_cg.py +65 -0
- rulelearn_ri/algorithms/rbm/rbm/BRCG.py +69 -0
- rulelearn_ri/algorithms/rbm/rbm/GLRM.py +98 -0
- rulelearn_ri/algorithms/rbm/rbm/__init__.py +6 -0
- rulelearn_ri/algorithms/rbm/rbm/beam_search.py +302 -0
- rulelearn_ri/algorithms/rbm/rbm/boolean_rule_cg.py +245 -0
- rulelearn_ri/algorithms/rbm/rbm/features.py +544 -0
- rulelearn_ri/algorithms/rbm/rbm/linear_regression.py +393 -0
- rulelearn_ri/algorithms/rbm/rbm/logistic_regression.py +447 -0
- rulelearn_ri/algorithms/rbm/utils.py +13 -0
- rulelearn_ri/algorithms/ripper/__init__.py +10 -0
- rulelearn_ri/algorithms/ripper/base.py +81 -0
- rulelearn_ri/algorithms/ripper/binding.py +541 -0
- rulelearn_ri/algorithms/ripper/mdl.py +97 -0
- rulelearn_ri/algorithms/ripper/pruning.py +212 -0
- rulelearn_ri/algorithms/ripper/ripper.py +600 -0
- rulelearn_ri/algorithms/ripper/ripper_ruleset_generator.py +26 -0
- rulelearn_ri/algorithms/ripper/single_rule.py +425 -0
- rulelearn_ri/dise.py +64 -0
- rulelearn_ri/trxf/__init__.py +0 -0
- rulelearn_ri/trxf/classifier/__init__.py +0 -0
- rulelearn_ri/trxf/classifier/ruleset_classifier.py +153 -0
- rulelearn_ri/trxf/core/__init__.py +5 -0
- rulelearn_ri/trxf/core/boolean_evaluator.py +15 -0
- rulelearn_ri/trxf/core/conjunction.py +50 -0
- rulelearn_ri/trxf/core/dnf_ruleset.py +64 -0
- rulelearn_ri/trxf/core/feature.py +155 -0
- rulelearn_ri/trxf/core/predicate.py +98 -0
- rulelearn_ri/trxf/core/ruleset_generator.py +25 -0
- rulelearn_ri/trxf/core/utils.py +40 -0
- rulelearn_ri/trxf/metrics.py +98 -0
- rulelearn_ri/trxf/pmml_export/__init__.py +4 -0
- rulelearn_ri/trxf/pmml_export/__version__.py +1 -0
- rulelearn_ri/trxf/pmml_export/models/__init__.py +24 -0
- rulelearn_ri/trxf/pmml_export/models/attribute.py +24 -0
- rulelearn_ri/trxf/pmml_export/models/characteristics.py +20 -0
- rulelearn_ri/trxf/pmml_export/models/data_dictionary.py +53 -0
- rulelearn_ri/trxf/pmml_export/models/mining_schema.py +25 -0
- rulelearn_ri/trxf/pmml_export/models/pmml_ruleset_model.py +16 -0
- rulelearn_ri/trxf/pmml_export/models/predicate.py +42 -0
- rulelearn_ri/trxf/pmml_export/models/rule.py +26 -0
- rulelearn_ri/trxf/pmml_export/models/ruleset.py +28 -0
- rulelearn_ri/trxf/pmml_export/models/ruleset_model.py +16 -0
- rulelearn_ri/trxf/pmml_export/models/scorecard.py +35 -0
- rulelearn_ri/trxf/pmml_export/pmml_exporter.py +18 -0
- rulelearn_ri/trxf/pmml_export/reader/__init__.py +2 -0
- rulelearn_ri/trxf/pmml_export/reader/abstract_reader.py +16 -0
- rulelearn_ri/trxf/pmml_export/reader/trxf_reader.py +113 -0
- rulelearn_ri/trxf/pmml_export/serializer/__init__.py +2 -0
- rulelearn_ri/trxf/pmml_export/serializer/abstract_serializer.py +11 -0
- rulelearn_ri/trxf/pmml_export/serializer/nyoka_serializer.py +162 -0
- rulelearn_ri/trxf/scorecard/__init__.py +3 -0
- rulelearn_ri/trxf/scorecard/bins.py +253 -0
- rulelearn_ri/trxf/scorecard/partition.py +71 -0
- rulelearn_ri/trxf/scorecard/scorecard.py +78 -0
- rulelearn_ripper_interactive-0.2.3.dist-info/METADATA +164 -0
- rulelearn_ripper_interactive-0.2.3.dist-info/RECORD +73 -0
- rulelearn_ripper_interactive-0.2.3.dist-info/WHEEL +5 -0
- rulelearn_ripper_interactive-0.2.3.dist-info/licenses/LICENSE +201 -0
- rulelearn_ripper_interactive-0.2.3.dist-info/licenses/NOTICE +11 -0
- rulelearn_ripper_interactive-0.2.3.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
from numbers import Real
|
|
3
|
+
from typing import Dict, Set, Any, Optional
|
|
4
|
+
from rulelearn_ri.trxf.core import Feature
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Bin(abc.ABC):
|
|
8
|
+
"""
|
|
9
|
+
Defines a set of values of interest for a particular feature along with an associated sub-score.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
def __init__(self, feature: Feature):
|
|
13
|
+
"""
|
|
14
|
+
@param feature: An instance of trxf.core.Feature. Specifies the feature with which this bin is associated.
|
|
15
|
+
"""
|
|
16
|
+
self._feature = feature
|
|
17
|
+
|
|
18
|
+
@abc.abstractmethod
|
|
19
|
+
def evaluate(self, assignment: Dict[str, Any]) -> float:
|
|
20
|
+
"""
|
|
21
|
+
Computes the sub-score for the bin based on the feature value.
|
|
22
|
+
|
|
23
|
+
@param assignment: dict mapping variable name to value
|
|
24
|
+
@return: float sub-score for the bin
|
|
25
|
+
"""
|
|
26
|
+
raise NotImplementedError('Method evaluate in Bin not implemented')
|
|
27
|
+
|
|
28
|
+
@abc.abstractmethod
|
|
29
|
+
def contains(self, assignment: Dict[str, Any]) -> bool:
|
|
30
|
+
"""
|
|
31
|
+
Checks if the value of the feature belongs to this bin or not.
|
|
32
|
+
|
|
33
|
+
@param assignment: dict mapping variable name to value
|
|
34
|
+
@return: bool, true if the feature value belongs to the bin and false otherwise
|
|
35
|
+
"""
|
|
36
|
+
raise NotImplementedError('Method contains in Bin not implemented.')
|
|
37
|
+
|
|
38
|
+
@abc.abstractmethod
|
|
39
|
+
def overlaps(self, other: 'Bin') -> bool:
|
|
40
|
+
"""
|
|
41
|
+
Checks whether this bin overlaps with the given other bin.
|
|
42
|
+
|
|
43
|
+
@param other: An instance of the same class as self specifying the other bin
|
|
44
|
+
@return: bool, true if the bins share at least one element and false otherwise
|
|
45
|
+
"""
|
|
46
|
+
raise NotImplementedError('Method overlaps in Bin not implemented.')
|
|
47
|
+
|
|
48
|
+
@abc.abstractmethod
|
|
49
|
+
def __str__(self):
|
|
50
|
+
raise NotImplementedError('Method __str__ in Bin not implemented.')
|
|
51
|
+
|
|
52
|
+
@abc.abstractmethod
|
|
53
|
+
def __repr__(self):
|
|
54
|
+
raise NotImplementedError('Method __repr__ in Bin not implemented.')
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def feature(self) -> Feature:
|
|
58
|
+
return self._feature
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class LinearIntervalBin(Bin):
|
|
62
|
+
"""
|
|
63
|
+
Defines a Bin specified by a half-open interval [left_end, right_end) where the sub-score is calculated using
|
|
64
|
+
a linear function of the feature value (requires the feature to evaluate to a numerical value).
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
def __init__(self, feature: Feature, const_part: Real, linear_multiplier: Real, left_end: Optional[Real] = None,
|
|
68
|
+
right_end: Optional[Real] = None):
|
|
69
|
+
"""
|
|
70
|
+
@param feature: An instance of trxf.core.Feature associated with this bin. This must be a numerical feature.
|
|
71
|
+
@param const_part: The constant additive part used in calculating the sub-score.
|
|
72
|
+
@param linear_multiplier: The sub-score will be calculated as linear_multiplier * feature_value + const_part
|
|
73
|
+
@param left_end: The left endpoint of the interval. Set to -infinity if not specified.
|
|
74
|
+
@param right_end: The right endpoint of the interval. Set to +infinity if not specified.
|
|
75
|
+
"""
|
|
76
|
+
if left_end is None:
|
|
77
|
+
left_end = float('-inf')
|
|
78
|
+
if right_end is None:
|
|
79
|
+
right_end = float('inf')
|
|
80
|
+
|
|
81
|
+
if left_end >= right_end:
|
|
82
|
+
raise ValueError('Need left_end < right_end but left_end = "{}" and right_end = "{}"'
|
|
83
|
+
.format(left_end, right_end))
|
|
84
|
+
|
|
85
|
+
super(LinearIntervalBin, self).__init__(feature)
|
|
86
|
+
self._left_end = left_end
|
|
87
|
+
self._right_end = right_end
|
|
88
|
+
self._linear_multiplier = linear_multiplier
|
|
89
|
+
self._const_part = const_part
|
|
90
|
+
|
|
91
|
+
def evaluate(self, assignment: Dict[str, Any]) -> float:
|
|
92
|
+
"""
|
|
93
|
+
Computes the sub-score for the bin based on the feature value. The sub-score is zero if the feature value lies
|
|
94
|
+
outside the bin and is given by linear_multiplier * feature_value + const_part otherwise.
|
|
95
|
+
|
|
96
|
+
@param assignment: dict mapping variable name to value
|
|
97
|
+
@return: float sub-score for the bin
|
|
98
|
+
"""
|
|
99
|
+
if self.contains(assignment):
|
|
100
|
+
return self.linear_multiplier * self._get_feature_value(assignment) + self.const_part
|
|
101
|
+
return 0.0
|
|
102
|
+
|
|
103
|
+
def contains(self, assignment: Dict[str, Any]) -> bool:
|
|
104
|
+
"""
|
|
105
|
+
Returns true if left_end <= feature_value < right_end for the given variable assignment.
|
|
106
|
+
|
|
107
|
+
@param assignment: dict mapping variable name to value
|
|
108
|
+
@return: bool True if the feature value belongs to the bin and False otherwise
|
|
109
|
+
"""
|
|
110
|
+
return self.left_end <= self._get_feature_value(assignment) < self.right_end
|
|
111
|
+
|
|
112
|
+
def overlaps(self, other: 'LinearIntervalBin') -> bool:
|
|
113
|
+
"""
|
|
114
|
+
Checks whether this bin overlaps with the given other bin.
|
|
115
|
+
|
|
116
|
+
@param other: An instance of LinearIntervalBin or a subclass thereof
|
|
117
|
+
@return: bool, true if the bins share at least one element and false otherwise
|
|
118
|
+
"""
|
|
119
|
+
if not isinstance(other, LinearIntervalBin):
|
|
120
|
+
raise ValueError('other must be an instance of LinearIntervalBin or a subclass thereof but it'
|
|
121
|
+
'is an instance of "{}"'.format(str(other.__class__)))
|
|
122
|
+
return (self.left_end < other.right_end) and (self.right_end > other.left_end)
|
|
123
|
+
|
|
124
|
+
def _get_feature_value(self, assignment: Dict[str, Any]) -> Real:
|
|
125
|
+
"""
|
|
126
|
+
Evaluates the value of the feature for the specified variable assignment. Raises ValueError if the feature
|
|
127
|
+
evaluates to a non-numerical value.
|
|
128
|
+
|
|
129
|
+
@param assignment: dict mapping variable name to value
|
|
130
|
+
@return: float, value of the feature
|
|
131
|
+
"""
|
|
132
|
+
feature_value = self.feature.evaluate(assignment)
|
|
133
|
+
if isinstance(feature_value, Real):
|
|
134
|
+
return feature_value
|
|
135
|
+
raise ValueError('Need the feature to evaluate to a numerical value but the type of returned value is "{}"'
|
|
136
|
+
.format(type(feature_value)))
|
|
137
|
+
|
|
138
|
+
def __str__(self):
|
|
139
|
+
return ' '.join([str(self.left_end), '<=', str(self.feature), '<', str(self.right_end), '->',
|
|
140
|
+
str(self.linear_multiplier), '*', 'x', '+', str(self.const_part)])
|
|
141
|
+
|
|
142
|
+
def __repr__(self):
|
|
143
|
+
return '%s(%r, [%r, %r), %r * x + %r)' % (self.__class__, self.feature, self.left_end, self.right_end,
|
|
144
|
+
self.linear_multiplier, self.const_part)
|
|
145
|
+
|
|
146
|
+
@property
|
|
147
|
+
def left_end(self) -> Real:
|
|
148
|
+
return self._left_end
|
|
149
|
+
|
|
150
|
+
@property
|
|
151
|
+
def right_end(self) -> Real:
|
|
152
|
+
return self._right_end
|
|
153
|
+
|
|
154
|
+
@property
|
|
155
|
+
def linear_multiplier(self) -> Real:
|
|
156
|
+
return self._linear_multiplier
|
|
157
|
+
|
|
158
|
+
@property
|
|
159
|
+
def const_part(self) -> Real:
|
|
160
|
+
return self._const_part
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
class IntervalBin(LinearIntervalBin):
|
|
164
|
+
"""
|
|
165
|
+
Defines a bin specified by an interval [left_end, right_end) with a constant sub-score
|
|
166
|
+
"""
|
|
167
|
+
|
|
168
|
+
def __init__(self, feature: Feature, sub_score: Real, left_end: Optional[Real] = None,
|
|
169
|
+
right_end: Optional[Real] = None):
|
|
170
|
+
"""
|
|
171
|
+
@param feature: An instance of trxf.core.Feature. Specifies the feature to which this bin is associated.
|
|
172
|
+
@param sub_score: The constant sub-score associated with this bin
|
|
173
|
+
@param left_end: The left endpoint on the interval. Set to -infinity if not specified.
|
|
174
|
+
@param right_end: The right endpoint of the interval. Set to +infinity if not specified.
|
|
175
|
+
"""
|
|
176
|
+
super(IntervalBin, self).__init__(feature, sub_score, 0.0, left_end, right_end)
|
|
177
|
+
|
|
178
|
+
def __str__(self):
|
|
179
|
+
return ' '.join([str(self.left_end), '<=', str(self.feature), '<', str(self.right_end), '->',
|
|
180
|
+
str(self.const_part)])
|
|
181
|
+
|
|
182
|
+
def __repr__(self):
|
|
183
|
+
return '%s(%r, [%r, %r), %r)' % (self.__class__, self.feature, self.left_end, self.right_end, self.const_part)
|
|
184
|
+
|
|
185
|
+
@property
|
|
186
|
+
def sub_score(self) -> Real:
|
|
187
|
+
return self.const_part
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
class SetBin(Bin):
|
|
191
|
+
"""
|
|
192
|
+
Defines a Bin specified by a finite set of values and a constant sub-score
|
|
193
|
+
"""
|
|
194
|
+
|
|
195
|
+
def __init__(self, feature: Feature, sub_score: Real, values: Set[Any]):
|
|
196
|
+
"""
|
|
197
|
+
@param feature: An instance of trxf.core.Feature. Specifies the feature to which this bin is associated.
|
|
198
|
+
@param sub_score: The constant sub-score associated with this bin.
|
|
199
|
+
@param values: The set of values that belong to this bin
|
|
200
|
+
"""
|
|
201
|
+
if len(values) == 0:
|
|
202
|
+
raise ValueError('Expected len(values) > 0, received len(values) == "{}"'.format(len(values)))
|
|
203
|
+
|
|
204
|
+
super(SetBin, self).__init__(feature)
|
|
205
|
+
self._values = values
|
|
206
|
+
self._sub_score = sub_score
|
|
207
|
+
|
|
208
|
+
def evaluate(self, assignment: Dict[str, Any]) -> float:
|
|
209
|
+
"""
|
|
210
|
+
Computes the sub-score for the bin based on the feature value. The sub-score is zero if the feature value lies
|
|
211
|
+
outside the bin and is given by sub_score otherwise.
|
|
212
|
+
|
|
213
|
+
@param assignment: dict mapping variable name to value
|
|
214
|
+
@return: float sub-score for the bin
|
|
215
|
+
"""
|
|
216
|
+
if self.contains(assignment):
|
|
217
|
+
return float(self.sub_score)
|
|
218
|
+
return 0.0
|
|
219
|
+
|
|
220
|
+
def contains(self, assignment: Dict[str, Any]) -> bool:
|
|
221
|
+
"""
|
|
222
|
+
Returns true if the feature value belongs to the set of values in this bin and false otherwise
|
|
223
|
+
|
|
224
|
+
@param assignment: dict mapping variable name to value
|
|
225
|
+
@return: bool, true if the feature value belongs to the bin and false otherwise
|
|
226
|
+
"""
|
|
227
|
+
return self.feature.evaluate(assignment) in self.values
|
|
228
|
+
|
|
229
|
+
def overlaps(self, other: 'SetBin') -> bool:
|
|
230
|
+
"""
|
|
231
|
+
Checks whether this bin overlaps with the given other bin.
|
|
232
|
+
|
|
233
|
+
@param other: An instance of SetBin or a subclass thereof
|
|
234
|
+
@return: bool, true if the bins share at least one element and false otherwise
|
|
235
|
+
"""
|
|
236
|
+
if not isinstance(other, SetBin):
|
|
237
|
+
raise ValueError('other must be an instance of SetBin or a subclass thereof but it'
|
|
238
|
+
'is an instance of "{}"'.format(str(other.__class__)))
|
|
239
|
+
return len(self.values.intersection(other.values)) > 0
|
|
240
|
+
|
|
241
|
+
def __str__(self):
|
|
242
|
+
return ' '.join([str(self.feature), 'in', str(self.values), '->', str(self.sub_score)])
|
|
243
|
+
|
|
244
|
+
def __repr__(self):
|
|
245
|
+
return '%s(%r, %r, %r)' % (self.__class__, self.feature, self.values, self.sub_score)
|
|
246
|
+
|
|
247
|
+
@property
|
|
248
|
+
def values(self) -> Set[Any]:
|
|
249
|
+
return self._values
|
|
250
|
+
|
|
251
|
+
@property
|
|
252
|
+
def sub_score(self) -> Real:
|
|
253
|
+
return self._sub_score
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
from typing import List, Dict, Any
|
|
2
|
+
from rulelearn_ri.trxf.core import Feature
|
|
3
|
+
from rulelearn_ri.trxf.scorecard import Bin
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Partition(object):
|
|
7
|
+
"""
|
|
8
|
+
A Partition is a set of non-overlapping bins of the same type associated with the same feature
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
def __init__(self, bins: List[Bin]):
|
|
12
|
+
"""
|
|
13
|
+
@param bins: A list of instances of a subclass of GeneralizedBin. All elements must have the same type.
|
|
14
|
+
"""
|
|
15
|
+
if len(bins) == 0:
|
|
16
|
+
raise ValueError('Need len(bins) > 0 but len(bins) = "{}"'.format(len(bins)))
|
|
17
|
+
|
|
18
|
+
# Check that all bins are associated with the same feature and have the same type
|
|
19
|
+
self._feature = bins[0].feature
|
|
20
|
+
bin_type = type(bins[0])
|
|
21
|
+
for idx, curr_bin in enumerate(bins):
|
|
22
|
+
if curr_bin.feature != self._feature:
|
|
23
|
+
raise ValueError('All bins must be associated with the same feature but bins[0] was associated with'
|
|
24
|
+
'"{}" whereas bins["{}"] was associated with "{}"'.format(self._feature, idx,
|
|
25
|
+
curr_bin.feature))
|
|
26
|
+
if type(curr_bin) != bin_type:
|
|
27
|
+
raise ValueError('All bins must have the same type but bins[0] has type "{}" while bins["{}"]'
|
|
28
|
+
'has type "{}"'.format(bin_type, idx, type(curr_bin)))
|
|
29
|
+
|
|
30
|
+
# Check that bins do not overlap
|
|
31
|
+
for idx1 in range(len(bins)):
|
|
32
|
+
for idx2 in range(idx1 + 1, len(bins)):
|
|
33
|
+
if bins[idx1].overlaps(bins[idx2]):
|
|
34
|
+
raise ValueError('Bins must be non-overlapping but bin "{}" overlaps with bin "{}"'
|
|
35
|
+
.format(bins[idx1], bins[idx2]))
|
|
36
|
+
|
|
37
|
+
self._bins = bins
|
|
38
|
+
|
|
39
|
+
def evaluate(self, assignment: Dict[str, Any]) -> float:
|
|
40
|
+
"""
|
|
41
|
+
Computes the sub-score for the feature associated with this partition. This score is given by the sub-score of
|
|
42
|
+
the first bin in the partition to which the feature value belongs. Raises ValueError if the feature value does
|
|
43
|
+
not belong to any of the bins.
|
|
44
|
+
|
|
45
|
+
@param assignment: dict mapping variable name to value
|
|
46
|
+
@return: float sub-score associated with this partition.
|
|
47
|
+
"""
|
|
48
|
+
for curr_bin in self.bins:
|
|
49
|
+
if curr_bin.contains(assignment):
|
|
50
|
+
return curr_bin.evaluate(assignment)
|
|
51
|
+
raise ValueError('Value "{}" of the feature does not belong to any of the bins'
|
|
52
|
+
.format(self._feature.evaluate(assignment)))
|
|
53
|
+
|
|
54
|
+
def __str__(self):
|
|
55
|
+
return '\n'.join([str(self.feature)] + ['\t' + str(curr_bin) for curr_bin in self.bins])
|
|
56
|
+
|
|
57
|
+
def __repr__(self):
|
|
58
|
+
return '\n'.join([str(self.__class__)] + ['\t' + repr(self.feature)] +
|
|
59
|
+
['\t' + repr(curr_bin) for curr_bin in self.bins])
|
|
60
|
+
|
|
61
|
+
@property
|
|
62
|
+
def num_bins(self) -> int:
|
|
63
|
+
return len(self.bins)
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def bins(self) -> List[Bin]:
|
|
67
|
+
return self._bins
|
|
68
|
+
|
|
69
|
+
@property
|
|
70
|
+
def feature(self) -> Feature:
|
|
71
|
+
return self._feature
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
from numbers import Real
|
|
2
|
+
from typing import List, Tuple, Dict, Any
|
|
3
|
+
from rulelearn_ri.trxf.core import Feature
|
|
4
|
+
from rulelearn_ri.trxf.scorecard import Partition
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Scorecard(object):
|
|
8
|
+
"""
|
|
9
|
+
Defines the representation of a scorecard
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
def __init__(self, partitions: List[Partition], bias: Real = 0.0):
|
|
13
|
+
"""
|
|
14
|
+
@param partitions: A list of instances of class Partition, each specifying the bins for a particular feature.
|
|
15
|
+
Elements in the list must correspond to distinct features.
|
|
16
|
+
@param bias: The global bias term used during scorecard evaluation
|
|
17
|
+
"""
|
|
18
|
+
if len(partitions) == 0:
|
|
19
|
+
raise ValueError('Need len(partitions) > 0 but found len(partitions) == "{}"'.format(len(partitions)))
|
|
20
|
+
|
|
21
|
+
# Check that all partitions use different features
|
|
22
|
+
seen = []
|
|
23
|
+
for idx, partition in enumerate(partitions):
|
|
24
|
+
try:
|
|
25
|
+
prev_idx = seen.index(partition.feature)
|
|
26
|
+
except ValueError:
|
|
27
|
+
seen.append(partition.feature)
|
|
28
|
+
continue
|
|
29
|
+
raise ValueError('The instances in partitions must correspond to distinct features but the instance'
|
|
30
|
+
'at index "{}" and "{}" use the same feature "{}"'
|
|
31
|
+
.format(prev_idx, idx, partition.feature))
|
|
32
|
+
|
|
33
|
+
self._partitions = partitions
|
|
34
|
+
self._bias = bias
|
|
35
|
+
|
|
36
|
+
def evaluate(self, assignment: Dict[str, Any]) -> float:
|
|
37
|
+
"""
|
|
38
|
+
Computes the output of the scorecard for the given assignment of variables. This output is computed as the
|
|
39
|
+
sum of sub-scores for each partition in the scorecard and the bias term.
|
|
40
|
+
|
|
41
|
+
@param assignment: dict mapping variable names to values
|
|
42
|
+
@return: float score computed using the scorecard
|
|
43
|
+
"""
|
|
44
|
+
score = self.bias
|
|
45
|
+
for partition in self.partitions:
|
|
46
|
+
score += partition.evaluate(assignment)
|
|
47
|
+
return float(score)
|
|
48
|
+
|
|
49
|
+
def __str__(self):
|
|
50
|
+
return '\n'.join([str(partition) for partition in self.partitions] + ['Bias="{}"'.format(self.bias)])
|
|
51
|
+
|
|
52
|
+
def __repr__(self):
|
|
53
|
+
return '\n'.join([str(self.__class__)] + [repr(partition) for partition in self.partitions] +
|
|
54
|
+
['Bias="{}"'.format(self.bias)])
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def bias(self) -> Real:
|
|
58
|
+
return self._bias
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
def partitions(self) -> List[Partition]:
|
|
62
|
+
return self._partitions
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
def features(self) -> List[Feature]:
|
|
66
|
+
return [partition.feature for partition in self.partitions]
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def num_features(self) -> int:
|
|
70
|
+
return len(self.partitions)
|
|
71
|
+
|
|
72
|
+
@property
|
|
73
|
+
def bins_per_feature(self) -> List[Tuple[Feature, int]]:
|
|
74
|
+
return [(partition.feature, partition.num_bins) for partition in self.partitions]
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
def total_bins(self) -> int:
|
|
78
|
+
return sum([partition.num_bins for partition in self.partitions])
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rulelearn-ripper-interactive
|
|
3
|
+
Version: 0.2.3
|
|
4
|
+
Summary: Rule induction toolkit (fork of IBM rulelearn) with interactive, constrained single-rule RIPPER optimization
|
|
5
|
+
Author-email: Aaron Kurz <aaron.kurz@unisg.ch>, Hagen Voelzer <hagen.voelzer@unisg.ch>
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Project-URL: Repository, https://github.com/aaronkurz/rulelearn-ripper-interactive
|
|
8
|
+
Project-URL: Upstream, https://github.com/IBM/rulelearn
|
|
9
|
+
Keywords: rule induction,ripper,interpretable machine learning,explainability,rule learning
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Science/Research
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
License-File: NOTICE
|
|
24
|
+
Requires-Dist: numpy
|
|
25
|
+
Requires-Dist: pandas
|
|
26
|
+
Requires-Dist: scikit-learn
|
|
27
|
+
Requires-Dist: numba
|
|
28
|
+
Requires-Dist: nyoka==5.4.0
|
|
29
|
+
Provides-Extra: rbm
|
|
30
|
+
Requires-Dist: cvxpy; extra == "rbm"
|
|
31
|
+
Requires-Dist: ecos; extra == "rbm"
|
|
32
|
+
Requires-Dist: matplotlib; extra == "rbm"
|
|
33
|
+
Provides-Extra: r2n
|
|
34
|
+
Requires-Dist: torch; extra == "r2n"
|
|
35
|
+
Provides-Extra: all
|
|
36
|
+
Requires-Dist: rulelearn-ripper-interactive[r2n,rbm]; extra == "all"
|
|
37
|
+
Dynamic: license-file
|
|
38
|
+
|
|
39
|
+
# rulelearn-ripper-interactive
|
|
40
|
+
|
|
41
|
+
A rule induction toolkit for learning readable, editable rules from data. It is a fork of
|
|
42
|
+
[IBM's rulelearn](https://github.com/IBM/rulelearn) that adds **interactive, constrained
|
|
43
|
+
single-rule optimization** for RIPPER. You can grow and prune a single conjunctive rule
|
|
44
|
+
while forcing some features or predicates into it and keeping others out.
|
|
45
|
+
|
|
46
|
+
The package installs as `rulelearn_ri`, so it can be installed side by side with the
|
|
47
|
+
upstream `rulelearn` package.
|
|
48
|
+
|
|
49
|
+
## Installation
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pip install rulelearn-ripper-interactive
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
or, to add it to a [uv](https://docs.astral.sh/uv/) project:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
uv add rulelearn-ripper-interactive
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The core install covers RIPPER and TRXF (rule interchange, metrics and PMML export).
|
|
62
|
+
The other algorithms need heavier dependencies, available as extras:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pip install "rulelearn-ripper-interactive[rbm]" # BRCG / GLRM (cvxpy, ecos, matplotlib)
|
|
66
|
+
pip install "rulelearn-ripper-interactive[r2n]" # Relational Rule Network (torch)
|
|
67
|
+
pip install "rulelearn-ripper-interactive[all]" # everything
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
With uv, use `uv add "rulelearn-ripper-interactive[rbm]"` (or `[r2n]`, `[all]`) instead.
|
|
71
|
+
|
|
72
|
+
Requires Python 3.10 or newer.
|
|
73
|
+
|
|
74
|
+
## Single-rule optimization
|
|
75
|
+
|
|
76
|
+
`optimize_single_rule` learns one conjunctive rule for a target label and returns it as a
|
|
77
|
+
TRXF `Conjunction`:
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
import pandas as pd
|
|
81
|
+
from rulelearn_ri.algorithms.ripper import optimize_single_rule
|
|
82
|
+
|
|
83
|
+
df = pd.DataFrame({
|
|
84
|
+
'x': [1.0, 2.0, 3.0, 4.0],
|
|
85
|
+
'target': ['True', 'True', 'False', 'False'],
|
|
86
|
+
})
|
|
87
|
+
X, y = df.drop(columns='target'), df['target']
|
|
88
|
+
|
|
89
|
+
rule = optimize_single_rule(X, y, target_label='True')
|
|
90
|
+
print(rule)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Constraints let you steer the rule:
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
from rulelearn_ri.trxf.core import Feature, Predicate, Relation
|
|
97
|
+
|
|
98
|
+
# Force the feature `x` to appear in the rule (the boundary is still optimized)
|
|
99
|
+
optimize_single_rule(X, y, target_label='True', fixed_attributes=['x'])
|
|
100
|
+
|
|
101
|
+
# Force a specific predicate, with a fixed boundary, into the rule
|
|
102
|
+
optimize_single_rule(
|
|
103
|
+
X, y, target_label='True',
|
|
104
|
+
fixed_predicates=[Predicate(Feature('x'), Relation.LE, 2.5)],
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
# Keep a feature out of the rule (must not clash with any forced feature or predicate)
|
|
108
|
+
optimize_single_rule(X, y, target_label='True', forbidden_attributes=['x'])
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Further options: `pruning_threshold` (minimum number of instances for the grow/prune
|
|
112
|
+
split, default 20), `random_state` (seed for the split, default 0) and `ratio`
|
|
113
|
+
(fraction of the data used for growing, default 2/3).
|
|
114
|
+
|
|
115
|
+
## Included algorithms
|
|
116
|
+
|
|
117
|
+
- Fast Effective Rule Induction (RIPPER) ([William W Cohen, 1995](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.107.2612&rep=rep1&type=pdf)),
|
|
118
|
+
including the full rule-set learner `RipperExplainer`
|
|
119
|
+
- Boolean Decision Rules via Column Generation (Light Edition) ([Dash et al., 2018](https://papers.nips.cc/paper/7716-boolean-decision-rules-via-column-generation)), extra `rbm`
|
|
120
|
+
- Generalized Linear Rule Models ([Wei et al., 2019](http://proceedings.mlr.press/v97/wei19a.html)), extra `rbm`
|
|
121
|
+
- Relational Rule Network (R2N) ([Kusters et al., 2022](https://arxiv.org/abs/2201.06515)), extra `r2n`
|
|
122
|
+
- TRXF (Technical Rule Interchange Format): a common rule-set representation with evaluation tools
|
|
123
|
+
and PMML export
|
|
124
|
+
|
|
125
|
+
Example notebooks are in the [`examples/`](https://github.com/aaronkurz/rulelearn-ripper-interactive/tree/main/examples) directory of the repository.
|
|
126
|
+
|
|
127
|
+
## Development
|
|
128
|
+
|
|
129
|
+
This project uses [uv](https://docs.astral.sh/uv/):
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
git clone git@github.com:aaronkurz/rulelearn-ripper-interactive.git
|
|
133
|
+
cd rulelearn-ripper-interactive
|
|
134
|
+
uv sync --all-extras
|
|
135
|
+
uv run pytest
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Releasing
|
|
139
|
+
|
|
140
|
+
1. Bump `version` in `pyproject.toml`.
|
|
141
|
+
2. Build and check the distributions:
|
|
142
|
+
```bash
|
|
143
|
+
rm -rf dist && uv build
|
|
144
|
+
uvx twine check --strict dist/*
|
|
145
|
+
```
|
|
146
|
+
3. Upload to TestPyPI first, then check it installs in a clean environment:
|
|
147
|
+
```bash
|
|
148
|
+
uv publish --publish-url https://test.pypi.org/legacy/ --token <testpypi-token>
|
|
149
|
+
```
|
|
150
|
+
4. Upload to PyPI and tag the release:
|
|
151
|
+
```bash
|
|
152
|
+
uv publish --token <pypi-token>
|
|
153
|
+
git tag v<version> && git push origin v<version>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Acknowledgements
|
|
157
|
+
|
|
158
|
+
This package is derived from [rulelearn](https://github.com/IBM/rulelearn) by IBM,
|
|
159
|
+
originally released as part of [AI Explainability 360](https://github.com/Trusted-AI/AIX360).
|
|
160
|
+
See [NOTICE](https://github.com/aaronkurz/rulelearn-ripper-interactive/blob/main/NOTICE) for details.
|
|
161
|
+
|
|
162
|
+
## License
|
|
163
|
+
|
|
164
|
+
Apache License 2.0. See [LICENSE](https://github.com/aaronkurz/rulelearn-ripper-interactive/blob/main/LICENSE).
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
rulelearn_ri/__init__.py,sha256=jNP9W3mpGoFFPe7vGg37q3mIj8dJr4NsRQUUXUkS-2g,163
|
|
2
|
+
rulelearn_ri/dise.py,sha256=kwQOoUQE6xqqInANdwD5X3KIMAhXuYaSWVMRZLzcsgk,1988
|
|
3
|
+
rulelearn_ri/algorithms/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
rulelearn_ri/algorithms/r2n/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
+
rulelearn_ri/algorithms/r2n/base.py,sha256=DoXsmM3t6PdEGDEWi5qrNnGn5b4gtq0HpTMleZNZw84,1017
|
|
6
|
+
rulelearn_ri/algorithms/r2n/functions.py,sha256=NqX1kcT1tUeBchfuA-SymD6ZGs1kTjKbtTIqGNAcJDs,682
|
|
7
|
+
rulelearn_ri/algorithms/r2n/mask.py,sha256=GWjw8oFQ2kFmbtCY3ozSU31Fk6GnUk4nnD-C3FWZmoI,1595
|
|
8
|
+
rulelearn_ri/algorithms/r2n/preprocessing_layers.py,sha256=8zYlw-T3d-CrugmqjVDfQf64cHG8omzZkP439WrIsuI,6971
|
|
9
|
+
rulelearn_ri/algorithms/r2n/r2n_algo.py,sha256=eGv1V6tAbGPTOwcupQL7Nmo-Fleh1F6HBiTm5RmEPPI,12690
|
|
10
|
+
rulelearn_ri/algorithms/r2n/simple_rulenet.py,sha256=GNHeSQoAXst2Do-AYxtl0a95sZuA0jY563VTNsLNeoM,2547
|
|
11
|
+
rulelearn_ri/algorithms/r2n/training.py,sha256=jxMDM_H6wipd8TF1wnEEjfbMWfcXIFKklR7gQtC3E4w,1085
|
|
12
|
+
rulelearn_ri/algorithms/r2n/utilities.py,sha256=E5wd3BW1umu4tlv8ENm1NAWbxzWCRvOSb_lTjNMzKdY,4251
|
|
13
|
+
rulelearn_ri/algorithms/rbm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
+
rulelearn_ri/algorithms/rbm/boolean_rule_cg.py,sha256=ipntWEQt5_hFyLwCBjUcydVZB47vfP3Nt26Mtu-QKII,2224
|
|
15
|
+
rulelearn_ri/algorithms/rbm/utils.py,sha256=bluMLTwFTKd_ai1Pu2nBI6-hYC4Mqxuj-kXFEFq3r1c,315
|
|
16
|
+
rulelearn_ri/algorithms/rbm/rbm/BRCG.py,sha256=e8BfIEm9B9QIn8dlZs-4X2cXwfZoKoIHGunGTixXn74,2522
|
|
17
|
+
rulelearn_ri/algorithms/rbm/rbm/GLRM.py,sha256=tg_8C8HA5_bWQlX4p7xNNfVCFBw5xtdM4F49axrPqqI,3739
|
|
18
|
+
rulelearn_ri/algorithms/rbm/rbm/__init__.py,sha256=fMtOjJTkGbYsd8yOPDkgRzXx068O5eg7T1_UyK_Qye4,281
|
|
19
|
+
rulelearn_ri/algorithms/rbm/rbm/beam_search.py,sha256=KjKDw-ye5KiTveDIfUw60msmjJlmW9TFTPAnqNcLG6o,13057
|
|
20
|
+
rulelearn_ri/algorithms/rbm/rbm/boolean_rule_cg.py,sha256=x5pwI9k_Kri26Z8j3R85dADNvXMgb8hXd9bvI_3yqLY,9907
|
|
21
|
+
rulelearn_ri/algorithms/rbm/rbm/features.py,sha256=FtYZEYtlVrSd7sIIiZqQ0wIElQkyJWi2IE1i_CgENpw,24215
|
|
22
|
+
rulelearn_ri/algorithms/rbm/rbm/linear_regression.py,sha256=_-bZzAM8zg1OWb73xkeXemFxA9LUzKELapgLxaBO_A0,17602
|
|
23
|
+
rulelearn_ri/algorithms/rbm/rbm/logistic_regression.py,sha256=Omlpzj9diHMAmCNcV1sxYwzwmhodZeZBjNAJ1M2Gweo,19789
|
|
24
|
+
rulelearn_ri/algorithms/ripper/__init__.py,sha256=j4kVSsvxKRss9nMppbcQxpqD-fXibDTTwT9PdzIs8HM,228
|
|
25
|
+
rulelearn_ri/algorithms/ripper/base.py,sha256=2tS0hmm5E-EEJPouXrlln78zJoI8L2FR7NHD1ce0jGM,2764
|
|
26
|
+
rulelearn_ri/algorithms/ripper/binding.py,sha256=aAx70HKYFAIccA1j7KmEP_Xqvj0m4WgDyqQZxMknCWc,11920
|
|
27
|
+
rulelearn_ri/algorithms/ripper/mdl.py,sha256=Npg5ycPpWPk9JonMfPoezPrNsHL1osNdZo5tNwNchKk,2015
|
|
28
|
+
rulelearn_ri/algorithms/ripper/pruning.py,sha256=7Po1puPJpufREwY6sLfkS6FEaOj2rXRWzWpUrfgrTT8,4456
|
|
29
|
+
rulelearn_ri/algorithms/ripper/ripper.py,sha256=D3qCbwMWE7jkjwvp31k10T8nIieqbI4hey5ufCHu89Q,21564
|
|
30
|
+
rulelearn_ri/algorithms/ripper/ripper_ruleset_generator.py,sha256=Snz5gJ457m4JDx5d_FQAb_BPmopmtnNmpUv7QkltNuQ,902
|
|
31
|
+
rulelearn_ri/algorithms/ripper/single_rule.py,sha256=HEx_rITY100d15Xim9QIwdjPytSjwQjIPHWSIl0-O_w,16221
|
|
32
|
+
rulelearn_ri/trxf/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
33
|
+
rulelearn_ri/trxf/metrics.py,sha256=JEkfVrnxbeUAHqW5uZ-70iZ34e6vQqCTS63oMRS8o7c,4265
|
|
34
|
+
rulelearn_ri/trxf/classifier/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
35
|
+
rulelearn_ri/trxf/classifier/ruleset_classifier.py,sha256=6lLz8siaiaOJ6Ks9Z0l-RuoPt7_n0J2QLLT_L1AyOp4,6282
|
|
36
|
+
rulelearn_ri/trxf/core/__init__.py,sha256=jBMUQkndUnDU72BxsM49zh8JCb9gkepZcAhsxzlXsEA,193
|
|
37
|
+
rulelearn_ri/trxf/core/boolean_evaluator.py,sha256=MpDnozNaDoCd2cckawFW5AEzj78jgctgNmhPHlAsVTY,397
|
|
38
|
+
rulelearn_ri/trxf/core/conjunction.py,sha256=VaWUK7e5EmWhbpHiCmmnzjJBO4BsC5FmFKZO64QSW54,1539
|
|
39
|
+
rulelearn_ri/trxf/core/dnf_ruleset.py,sha256=QluNdrkL7r6BigXCsfc4gsVSutzW4T1alviXmAP74G0,2317
|
|
40
|
+
rulelearn_ri/trxf/core/feature.py,sha256=kQ8O1ECUubjNvr4mbQ6QgWdWP4M168rF-itZf6twXDk,5255
|
|
41
|
+
rulelearn_ri/trxf/core/predicate.py,sha256=KNChRF2Q5yy7iwTtMj_D7thijZgob68UyXLrbmbM2QM,3162
|
|
42
|
+
rulelearn_ri/trxf/core/ruleset_generator.py,sha256=DCF2PrbTgwCx0o06IFR3hBTKWxbLH5CkbmB7_bCCGaE,816
|
|
43
|
+
rulelearn_ri/trxf/core/utils.py,sha256=vqJXV0Tt8vQEcPOY065jCgQlzkpy6iuGt1OAsZsFU9A,1245
|
|
44
|
+
rulelearn_ri/trxf/pmml_export/__init__.py,sha256=6CZ_EJzb3kGIs7gpq5XAlHsVQFEF9r_UuBYqJXe_PmY,180
|
|
45
|
+
rulelearn_ri/trxf/pmml_export/__version__.py,sha256=p6UlmKJFsYomZzmxB_Ks3LTBru51FpBAY_hQw9_jogY,18
|
|
46
|
+
rulelearn_ri/trxf/pmml_export/pmml_exporter.py,sha256=h612wn9wzQC49T5me3lZg5lhQ8xxHHXZAtkvjCAkb80,782
|
|
47
|
+
rulelearn_ri/trxf/pmml_export/models/__init__.py,sha256=eKRbZhTx88mHsDGTI3QkR1D8RKulegYF5I-hniMWMGs,981
|
|
48
|
+
rulelearn_ri/trxf/pmml_export/models/attribute.py,sha256=-oI9pnx0vbnTlUzkIW1vBjnSa2D5ZYxeVIoN76vwIrE,617
|
|
49
|
+
rulelearn_ri/trxf/pmml_export/models/characteristics.py,sha256=5TWHHdfbrPvlL7h9BSUxfiN0y8VxUS3IZDj51onr3vE,381
|
|
50
|
+
rulelearn_ri/trxf/pmml_export/models/data_dictionary.py,sha256=tj7eGXqM3rg2LiiJEyL5SMPXOflwNo4QJxqZrcaCccs,1123
|
|
51
|
+
rulelearn_ri/trxf/pmml_export/models/mining_schema.py,sha256=riUUs2Z93NbxGt087VrNKmON79re2jsAwQjSDkx1fiw,554
|
|
52
|
+
rulelearn_ri/trxf/pmml_export/models/pmml_ruleset_model.py,sha256=6VZK4Acr0qzIOlS0QIxZT5hAbqbHEl-u9FeuyJQqx2g,435
|
|
53
|
+
rulelearn_ri/trxf/pmml_export/models/predicate.py,sha256=IHN9T3BjnUzABK3479wxzryu1LbnyB6Ly35QTvf5Nyg,965
|
|
54
|
+
rulelearn_ri/trxf/pmml_export/models/rule.py,sha256=SAgvKsv4R30eKeSJxskWtzKPCxPr2lazxLri4ZeNGfc,805
|
|
55
|
+
rulelearn_ri/trxf/pmml_export/models/ruleset.py,sha256=P3aBgYZ4p5EqWl4V7iu4RsICvoo7Gw4m35PtFh1yMu4,763
|
|
56
|
+
rulelearn_ri/trxf/pmml_export/models/ruleset_model.py,sha256=UsdesNQGj5NxK1HfNbN6HhsrJj2_nDhWYfPxO0-n23Y,396
|
|
57
|
+
rulelearn_ri/trxf/pmml_export/models/scorecard.py,sha256=cvJj6jPhSsSbJw-sQVP2kd1xZPEnb_SkPIsJosXox4Q,799
|
|
58
|
+
rulelearn_ri/trxf/pmml_export/reader/__init__.py,sha256=2woCITEi5QaUrmrCzVqcsEY6ntnLrYYXqciJo7U799c,80
|
|
59
|
+
rulelearn_ri/trxf/pmml_export/reader/abstract_reader.py,sha256=qPcbytFtzjZTQF4XFrAxS8AyKDcC5SCOw4Icw9hD3sE,311
|
|
60
|
+
rulelearn_ri/trxf/pmml_export/reader/trxf_reader.py,sha256=8sXWEKqBkObrj64s7dUt7nLT_XQXwO3Xn7JZqtKQi5M,5567
|
|
61
|
+
rulelearn_ri/trxf/pmml_export/serializer/__init__.py,sha256=NqjAw_feiNUUm0d4X2ZgjcMQzIO3F3xOyTkE00SH9B8,98
|
|
62
|
+
rulelearn_ri/trxf/pmml_export/serializer/abstract_serializer.py,sha256=qiNH4oYHnDzkUxYyLhRHfr92ln4rDfJ4Y3mQapcgeEM,246
|
|
63
|
+
rulelearn_ri/trxf/pmml_export/serializer/nyoka_serializer.py,sha256=NyWBDD3GTtjR9mNGLVrawNZsv3CN-TL4nVipA889Kks,8848
|
|
64
|
+
rulelearn_ri/trxf/scorecard/__init__.py,sha256=VeDCZDno8xpRrajbUt19ptz5egsdykjloy4oXhLaZT0,128
|
|
65
|
+
rulelearn_ri/trxf/scorecard/bins.py,sha256=Sm_hKfQcUSTfFJRkf-KX8WbNf-ajOBT4qKwHIQCCimc,10335
|
|
66
|
+
rulelearn_ri/trxf/scorecard/partition.py,sha256=4LyEZJvnenJmsb21NsyL5C9XiRFHlOyPNVdGkorSxjg,3097
|
|
67
|
+
rulelearn_ri/trxf/scorecard/scorecard.py,sha256=Y-Fa-5hrqEKcnIP4bCYdGxg3GQ9iio1tmaEBJy80LQI,2942
|
|
68
|
+
rulelearn_ripper_interactive-0.2.3.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
69
|
+
rulelearn_ripper_interactive-0.2.3.dist-info/licenses/NOTICE,sha256=BcNidS_aDOBStBdw7jUKMWqT56Md-7NEU8qDhPBWfRE,494
|
|
70
|
+
rulelearn_ripper_interactive-0.2.3.dist-info/METADATA,sha256=0ksyaCeKnfzYBvbaP5NS-mFbP7d_heIg4TCzouhh6sc,6116
|
|
71
|
+
rulelearn_ripper_interactive-0.2.3.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
72
|
+
rulelearn_ripper_interactive-0.2.3.dist-info/top_level.txt,sha256=Skh2-5pMO7dqQWvCJk_gDP3JkVz8EuX0cH5oLrfXiv8,13
|
|
73
|
+
rulelearn_ripper_interactive-0.2.3.dist-info/RECORD,,
|