edgepoint 2.0.0__tar.gz → 2.0.2__tar.gz
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.
- {edgepoint-2.0.0 → edgepoint-2.0.2}/PKG-INFO +83 -62
- {edgepoint-2.0.0 → edgepoint-2.0.2}/README.md +82 -61
- edgepoint-2.0.2/edgepoint/main.py +713 -0
- {edgepoint-2.0.0 → edgepoint-2.0.2}/edgepoint/train_combo.py +1 -1
- {edgepoint-2.0.0 → edgepoint-2.0.2}/edgepoint.egg-info/PKG-INFO +83 -62
- {edgepoint-2.0.0 → edgepoint-2.0.2}/pyproject.toml +1 -1
- {edgepoint-2.0.0 → edgepoint-2.0.2}/setup.py +1 -1
- edgepoint-2.0.0/edgepoint/main.py +0 -642
- {edgepoint-2.0.0 → edgepoint-2.0.2}/LICENSE +0 -0
- {edgepoint-2.0.0 → edgepoint-2.0.2}/edgepoint/__init__.py +0 -0
- {edgepoint-2.0.0 → edgepoint-2.0.2}/edgepoint/core.py +0 -0
- {edgepoint-2.0.0 → edgepoint-2.0.2}/edgepoint/core_v1.py +0 -0
- {edgepoint-2.0.0 → edgepoint-2.0.2}/edgepoint/validations.py +0 -0
- {edgepoint-2.0.0 → edgepoint-2.0.2}/edgepoint.egg-info/SOURCES.txt +0 -0
- {edgepoint-2.0.0 → edgepoint-2.0.2}/edgepoint.egg-info/dependency_links.txt +0 -0
- {edgepoint-2.0.0 → edgepoint-2.0.2}/edgepoint.egg-info/requires.txt +0 -0
- {edgepoint-2.0.0 → edgepoint-2.0.2}/edgepoint.egg-info/top_level.txt +0 -0
- {edgepoint-2.0.0 → edgepoint-2.0.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: edgepoint
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.2
|
|
4
4
|
Summary: Find the point in a numeric column above which a binary outcome becomes meaningfully and reliably better.
|
|
5
5
|
Author: Henry
|
|
6
6
|
License: MIT
|
|
@@ -147,7 +147,6 @@ df = pd.DataFrame({
|
|
|
147
147
|
})
|
|
148
148
|
```
|
|
149
149
|
|
|
150
|
-
|
|
151
150
|
### Running it
|
|
152
151
|
|
|
153
152
|
```python
|
|
@@ -156,15 +155,19 @@ from edgepoint import search
|
|
|
156
155
|
train_results_df, test_results_df, top_combos = search(
|
|
157
156
|
df,
|
|
158
157
|
outcome_col="hit",
|
|
159
|
-
|
|
158
|
+
train_split=60, # 24 train / 16 test → both ≥ min_rows
|
|
159
|
+
min_rows=15,
|
|
160
160
|
min_coverage=20,
|
|
161
|
+
mode="quick",
|
|
161
162
|
top_combos_n=2,
|
|
162
|
-
show_progress=
|
|
163
|
+
show_progress=False,
|
|
163
164
|
)
|
|
164
165
|
```
|
|
165
166
|
|
|
166
|
-
|
|
167
|
-
`show_progress=
|
|
167
|
+
With `show_progress=False` the call above runs silently and just returns
|
|
168
|
+
the three values. Turning `show_progress=True` on the exact same call
|
|
169
|
+
prints the full five-stage log so you can see how the split, the
|
|
170
|
+
single-column search, and the combo search actually got there:
|
|
168
171
|
|
|
169
172
|
```
|
|
170
173
|
EDGEPOINT.
|
|
@@ -173,101 +176,117 @@ EDGEPOINT.
|
|
|
173
176
|
🟡 STANDARD > 3 mins
|
|
174
177
|
🔴 DEEP > 10 mins
|
|
175
178
|
|
|
176
|
-
start : 2026-07-
|
|
179
|
+
start : 2026-07-17 07:10:14.
|
|
177
180
|
|
|
178
181
|
[1/5] Train / Test Split
|
|
179
182
|
--------------------------------
|
|
180
183
|
|
|
181
|
-
|
|
184
|
+
Sample Size (n) - Full = 40 . Train = 24 . Test = 16 .
|
|
182
185
|
|
|
183
|
-
|
|
186
|
+
Hit Rate (%) - Full = 47.50. Train = 50.00. Test = 43.75.
|
|
184
187
|
|
|
188
|
+
done in 0mins 0 secs | elapsed 0mins 1 secs | 07:10:15.
|
|
185
189
|
|
|
186
|
-
|
|
190
|
+
|
|
191
|
+
[2/5] Single-Column Search (train, n=24)
|
|
187
192
|
--------------------------------
|
|
188
193
|
|
|
189
|
-
column edge_point hit_rate miss_rate
|
|
190
|
-
0 score
|
|
191
|
-
1 age
|
|
194
|
+
column edge_point hit_rate miss_rate gap n coverage
|
|
195
|
+
0 score 49.46 75.00 25.00 50.00 16 66.67
|
|
196
|
+
1 age 39.50 57.14 42.86 14.29 14 58.33
|
|
192
197
|
|
|
193
|
-
done in 0mins 0 secs | elapsed 0mins 1 secs |
|
|
198
|
+
done in 0mins 0 secs | elapsed 0mins 1 secs | 07:10:16.
|
|
194
199
|
|
|
195
200
|
|
|
196
|
-
[3/5] Single-Column Evaluation (test, n=
|
|
201
|
+
[3/5] Single-Column Evaluation (test, n=16)
|
|
197
202
|
--------------------------------
|
|
198
203
|
|
|
199
|
-
column edge_point hit_rate miss_rate gap
|
|
200
|
-
0 score
|
|
201
|
-
1 age
|
|
204
|
+
column edge_point hit_rate miss_rate gap n coverage
|
|
205
|
+
0 score 49.46 77.78 22.22 55.56 9 56.25
|
|
206
|
+
1 age 39.50 42.86 57.14 -14.29 7 43.75
|
|
202
207
|
|
|
203
|
-
done in 0mins 0 secs | elapsed 0mins 2 secs |
|
|
208
|
+
done in 0mins 0 secs | elapsed 0mins 2 secs | 07:10:16.
|
|
204
209
|
|
|
205
210
|
|
|
206
211
|
[4/5] Combo Generation & Evaluation (train, mode='quick') ..This may take a while.
|
|
207
212
|
--------------------------------
|
|
208
213
|
|
|
209
|
-
|
|
214
|
+
3 combo(s) qualified (train). sample size (n) = 24. hit rate (%) = 50.00.
|
|
210
215
|
|
|
211
216
|
combo_num combo hit_rate miss_rate gap n coverage
|
|
212
|
-
0
|
|
213
|
-
1
|
|
217
|
+
0 3 score, age 80.00 20.00 60.00 10 41.67
|
|
218
|
+
1 1 score 75.00 25.00 50.00 16 66.67
|
|
219
|
+
2 2 age 57.14 42.86 14.29 14 58.33
|
|
214
220
|
|
|
215
|
-
done in 0mins 0 secs | elapsed 0mins 2 secs |
|
|
221
|
+
done in 0mins 0 secs | elapsed 0mins 2 secs | 07:10:17.
|
|
216
222
|
|
|
217
223
|
|
|
218
224
|
[5/5] Combo Validation (test, mode='quick')
|
|
219
225
|
--------------------------------
|
|
220
226
|
|
|
221
|
-
|
|
227
|
+
3 combo(s) qualified (test). sample size (n) = 16. hit rate (%) = 43.75.
|
|
222
228
|
|
|
223
|
-
combo_num combo hit_rate coverage
|
|
224
|
-
0
|
|
225
|
-
1
|
|
229
|
+
combo_num combo hit_rate coverage n train_hit_rate train_coverage score
|
|
230
|
+
0 3 score, age 60.00 31.25 5 80.00 41.67 21.49
|
|
231
|
+
1 1 score 77.78 56.25 9 75.00 66.67 1.00
|
|
232
|
+
2 2 age 42.86 43.75 7 57.14 58.33 -29.50
|
|
226
233
|
|
|
227
|
-
done in 0mins 0 secs | elapsed 0mins 3 secs |
|
|
234
|
+
done in 0mins 0 secs | elapsed 0mins 3 secs | 07:10:17.
|
|
228
235
|
|
|
229
236
|
|
|
230
237
|
TOP 2 COMBOS (test)
|
|
231
238
|
--------------------------------
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
239
|
+
|
|
240
|
+
Sample Size (n) - Full = 40 . Train = 24 . Test = 16 .
|
|
241
|
+
Hit Rate (%) - Full = 47.50. Train = 50.00. Test = 43.75.
|
|
242
|
+
|
|
243
|
+
: combo #3 combo #1
|
|
244
|
+
Score : 49.46 49.46
|
|
245
|
+
Age : 39.5 -
|
|
235
246
|
......................................................
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
247
|
+
Hit_rate : 60.0 77.78
|
|
248
|
+
Coverage : 31.25 56.25
|
|
249
|
+
Train_hit_rate : 80.0 75.0
|
|
250
|
+
Train_coverage : 41.67 66.67
|
|
251
|
+
Combo_sample_size : 5 9
|
|
252
|
+
Test_sample_size : 16 16
|
|
253
|
+
Baseline_hit_rate (full df) : 47.50 47.50
|
|
254
|
+
Vs_baseline : 12.50 + 30.28 +
|
|
255
|
+
|
|
256
|
+
COMPLETE - total duration 0mins 4 secs (end 07:10:18).
|
|
244
257
|
```
|
|
245
258
|
|
|
246
259
|
And the three values `search()` returns:
|
|
247
260
|
|
|
248
261
|
```python
|
|
249
262
|
>>> train_results_df
|
|
250
|
-
column edge_point hit_rate miss_rate
|
|
251
|
-
0 score
|
|
252
|
-
1 age
|
|
263
|
+
column edge_point hit_rate miss_rate gap n coverage
|
|
264
|
+
0 score 49.46 75.00 25.00 50.00 16 66.67
|
|
265
|
+
1 age 39.50 57.14 42.86 14.29 14 58.33
|
|
253
266
|
|
|
254
267
|
>>> test_results_df
|
|
255
|
-
column edge_point hit_rate miss_rate gap
|
|
256
|
-
0 score
|
|
257
|
-
1 age
|
|
268
|
+
column edge_point hit_rate miss_rate gap n coverage
|
|
269
|
+
0 score 49.46 77.78 22.22 55.56 9 56.25
|
|
270
|
+
1 age 39.50 42.86 57.14 -14.29 7 43.75
|
|
258
271
|
|
|
259
272
|
>>> top_combos
|
|
260
|
-
[{'combo_num':
|
|
261
|
-
'train_hit_rate':
|
|
262
|
-
|
|
263
|
-
|
|
273
|
+
[{'combo_num': 3, 'edges': {'score': 49.46, 'age': 39.5}, 'hit_rate': 60.0, 'coverage': 31.25,
|
|
274
|
+
'train_hit_rate': 80.0, 'train_coverage': 41.67, 'combo_sample_size': 5, 'test_sample_size': 16,
|
|
275
|
+
'baseline_hit_rate': 47.5, 'vs_baseline': 12.5},
|
|
276
|
+
{'combo_num': 1, 'edges': {'score': 49.46}, 'hit_rate': 77.78, 'coverage': 56.25,
|
|
277
|
+
'train_hit_rate': 75.0, 'train_coverage': 66.67, 'combo_sample_size': 9, 'test_sample_size': 16,
|
|
278
|
+
'baseline_hit_rate': 47.5, 'vs_baseline': 30.28}]
|
|
264
279
|
```
|
|
265
280
|
|
|
266
|
-
Reading this: `score`'s threshold of
|
|
267
|
-
hit rate over
|
|
268
|
-
at
|
|
269
|
-
Adding `age`
|
|
270
|
-
|
|
281
|
+
Reading this: `score`'s threshold of 49.46 looked solid on train (75.00%
|
|
282
|
+
hit rate over 66.67% of rows) and, replayed unchanged against test, held up
|
|
283
|
+
even better at 77.78% over 56.25% of rows, comfortably ahead of the 47.5%
|
|
284
|
+
baseline hit rate. Adding `age` into the combo (`score >= 49.46 AND age >=
|
|
285
|
+
39.5`) tightens things further on train (80.00% hit rate) but shrinks
|
|
286
|
+
coverage a lot (down to 5 rows on test), and its test hit rate of 60.00%,
|
|
287
|
+
while still above baseline, is the less reliable of the two picks precisely
|
|
288
|
+
because it's resting on so few rows, exactly the kind of honest trade-off
|
|
289
|
+
`search()` is built to surface rather than hide.
|
|
271
290
|
|
|
272
291
|
---
|
|
273
292
|
|
|
@@ -384,14 +403,16 @@ list of up to `top_combos_n` dicts otherwise. Each dict:
|
|
|
384
403
|
|
|
385
404
|
```python
|
|
386
405
|
{
|
|
387
|
-
"combo_num":
|
|
388
|
-
"edges": {"score":
|
|
389
|
-
"hit_rate":
|
|
390
|
-
"coverage":
|
|
391
|
-
"train_hit_rate":
|
|
392
|
-
"train_coverage":
|
|
393
|
-
"combo_sample_size":
|
|
394
|
-
"test_sample_size":
|
|
406
|
+
"combo_num": 3,
|
|
407
|
+
"edges": {"score": 49.46, "age": 39.5}, # {column: edge_point} used by this combo
|
|
408
|
+
"hit_rate": 60.0, # test-side
|
|
409
|
+
"coverage": 31.25, # test-side
|
|
410
|
+
"train_hit_rate": 80.0, # carried over from train, unchanged
|
|
411
|
+
"train_coverage": 41.67, # carried over from train, unchanged
|
|
412
|
+
"combo_sample_size": 5, # rows clearing the combo on test
|
|
413
|
+
"test_sample_size": 16, # total test rows
|
|
414
|
+
"baseline_hit_rate": 47.5, # "do nothing" hit rate on the full df
|
|
415
|
+
"vs_baseline": 12.5, # test hit_rate - baseline_hit_rate, in points
|
|
395
416
|
}
|
|
396
417
|
```
|
|
397
418
|
|
|
@@ -119,7 +119,6 @@ df = pd.DataFrame({
|
|
|
119
119
|
})
|
|
120
120
|
```
|
|
121
121
|
|
|
122
|
-
|
|
123
122
|
### Running it
|
|
124
123
|
|
|
125
124
|
```python
|
|
@@ -128,15 +127,19 @@ from edgepoint import search
|
|
|
128
127
|
train_results_df, test_results_df, top_combos = search(
|
|
129
128
|
df,
|
|
130
129
|
outcome_col="hit",
|
|
131
|
-
|
|
130
|
+
train_split=60, # 24 train / 16 test → both ≥ min_rows
|
|
131
|
+
min_rows=15,
|
|
132
132
|
min_coverage=20,
|
|
133
|
+
mode="quick",
|
|
133
134
|
top_combos_n=2,
|
|
134
|
-
show_progress=
|
|
135
|
+
show_progress=False,
|
|
135
136
|
)
|
|
136
137
|
```
|
|
137
138
|
|
|
138
|
-
|
|
139
|
-
`show_progress=
|
|
139
|
+
With `show_progress=False` the call above runs silently and just returns
|
|
140
|
+
the three values. Turning `show_progress=True` on the exact same call
|
|
141
|
+
prints the full five-stage log so you can see how the split, the
|
|
142
|
+
single-column search, and the combo search actually got there:
|
|
140
143
|
|
|
141
144
|
```
|
|
142
145
|
EDGEPOINT.
|
|
@@ -145,101 +148,117 @@ EDGEPOINT.
|
|
|
145
148
|
🟡 STANDARD > 3 mins
|
|
146
149
|
🔴 DEEP > 10 mins
|
|
147
150
|
|
|
148
|
-
start : 2026-07-
|
|
151
|
+
start : 2026-07-17 07:10:14.
|
|
149
152
|
|
|
150
153
|
[1/5] Train / Test Split
|
|
151
154
|
--------------------------------
|
|
152
155
|
|
|
153
|
-
|
|
156
|
+
Sample Size (n) - Full = 40 . Train = 24 . Test = 16 .
|
|
154
157
|
|
|
155
|
-
|
|
158
|
+
Hit Rate (%) - Full = 47.50. Train = 50.00. Test = 43.75.
|
|
156
159
|
|
|
160
|
+
done in 0mins 0 secs | elapsed 0mins 1 secs | 07:10:15.
|
|
157
161
|
|
|
158
|
-
|
|
162
|
+
|
|
163
|
+
[2/5] Single-Column Search (train, n=24)
|
|
159
164
|
--------------------------------
|
|
160
165
|
|
|
161
|
-
column edge_point hit_rate miss_rate
|
|
162
|
-
0 score
|
|
163
|
-
1 age
|
|
166
|
+
column edge_point hit_rate miss_rate gap n coverage
|
|
167
|
+
0 score 49.46 75.00 25.00 50.00 16 66.67
|
|
168
|
+
1 age 39.50 57.14 42.86 14.29 14 58.33
|
|
164
169
|
|
|
165
|
-
done in 0mins 0 secs | elapsed 0mins 1 secs |
|
|
170
|
+
done in 0mins 0 secs | elapsed 0mins 1 secs | 07:10:16.
|
|
166
171
|
|
|
167
172
|
|
|
168
|
-
[3/5] Single-Column Evaluation (test, n=
|
|
173
|
+
[3/5] Single-Column Evaluation (test, n=16)
|
|
169
174
|
--------------------------------
|
|
170
175
|
|
|
171
|
-
column edge_point hit_rate miss_rate gap
|
|
172
|
-
0 score
|
|
173
|
-
1 age
|
|
176
|
+
column edge_point hit_rate miss_rate gap n coverage
|
|
177
|
+
0 score 49.46 77.78 22.22 55.56 9 56.25
|
|
178
|
+
1 age 39.50 42.86 57.14 -14.29 7 43.75
|
|
174
179
|
|
|
175
|
-
done in 0mins 0 secs | elapsed 0mins 2 secs |
|
|
180
|
+
done in 0mins 0 secs | elapsed 0mins 2 secs | 07:10:16.
|
|
176
181
|
|
|
177
182
|
|
|
178
183
|
[4/5] Combo Generation & Evaluation (train, mode='quick') ..This may take a while.
|
|
179
184
|
--------------------------------
|
|
180
185
|
|
|
181
|
-
|
|
186
|
+
3 combo(s) qualified (train). sample size (n) = 24. hit rate (%) = 50.00.
|
|
182
187
|
|
|
183
188
|
combo_num combo hit_rate miss_rate gap n coverage
|
|
184
|
-
0
|
|
185
|
-
1
|
|
189
|
+
0 3 score, age 80.00 20.00 60.00 10 41.67
|
|
190
|
+
1 1 score 75.00 25.00 50.00 16 66.67
|
|
191
|
+
2 2 age 57.14 42.86 14.29 14 58.33
|
|
186
192
|
|
|
187
|
-
done in 0mins 0 secs | elapsed 0mins 2 secs |
|
|
193
|
+
done in 0mins 0 secs | elapsed 0mins 2 secs | 07:10:17.
|
|
188
194
|
|
|
189
195
|
|
|
190
196
|
[5/5] Combo Validation (test, mode='quick')
|
|
191
197
|
--------------------------------
|
|
192
198
|
|
|
193
|
-
|
|
199
|
+
3 combo(s) qualified (test). sample size (n) = 16. hit rate (%) = 43.75.
|
|
194
200
|
|
|
195
|
-
combo_num combo hit_rate coverage
|
|
196
|
-
0
|
|
197
|
-
1
|
|
201
|
+
combo_num combo hit_rate coverage n train_hit_rate train_coverage score
|
|
202
|
+
0 3 score, age 60.00 31.25 5 80.00 41.67 21.49
|
|
203
|
+
1 1 score 77.78 56.25 9 75.00 66.67 1.00
|
|
204
|
+
2 2 age 42.86 43.75 7 57.14 58.33 -29.50
|
|
198
205
|
|
|
199
|
-
done in 0mins 0 secs | elapsed 0mins 3 secs |
|
|
206
|
+
done in 0mins 0 secs | elapsed 0mins 3 secs | 07:10:17.
|
|
200
207
|
|
|
201
208
|
|
|
202
209
|
TOP 2 COMBOS (test)
|
|
203
210
|
--------------------------------
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
211
|
+
|
|
212
|
+
Sample Size (n) - Full = 40 . Train = 24 . Test = 16 .
|
|
213
|
+
Hit Rate (%) - Full = 47.50. Train = 50.00. Test = 43.75.
|
|
214
|
+
|
|
215
|
+
: combo #3 combo #1
|
|
216
|
+
Score : 49.46 49.46
|
|
217
|
+
Age : 39.5 -
|
|
207
218
|
......................................................
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
219
|
+
Hit_rate : 60.0 77.78
|
|
220
|
+
Coverage : 31.25 56.25
|
|
221
|
+
Train_hit_rate : 80.0 75.0
|
|
222
|
+
Train_coverage : 41.67 66.67
|
|
223
|
+
Combo_sample_size : 5 9
|
|
224
|
+
Test_sample_size : 16 16
|
|
225
|
+
Baseline_hit_rate (full df) : 47.50 47.50
|
|
226
|
+
Vs_baseline : 12.50 + 30.28 +
|
|
227
|
+
|
|
228
|
+
COMPLETE - total duration 0mins 4 secs (end 07:10:18).
|
|
216
229
|
```
|
|
217
230
|
|
|
218
231
|
And the three values `search()` returns:
|
|
219
232
|
|
|
220
233
|
```python
|
|
221
234
|
>>> train_results_df
|
|
222
|
-
column edge_point hit_rate miss_rate
|
|
223
|
-
0 score
|
|
224
|
-
1 age
|
|
235
|
+
column edge_point hit_rate miss_rate gap n coverage
|
|
236
|
+
0 score 49.46 75.00 25.00 50.00 16 66.67
|
|
237
|
+
1 age 39.50 57.14 42.86 14.29 14 58.33
|
|
225
238
|
|
|
226
239
|
>>> test_results_df
|
|
227
|
-
column edge_point hit_rate miss_rate gap
|
|
228
|
-
0 score
|
|
229
|
-
1 age
|
|
240
|
+
column edge_point hit_rate miss_rate gap n coverage
|
|
241
|
+
0 score 49.46 77.78 22.22 55.56 9 56.25
|
|
242
|
+
1 age 39.50 42.86 57.14 -14.29 7 43.75
|
|
230
243
|
|
|
231
244
|
>>> top_combos
|
|
232
|
-
[{'combo_num':
|
|
233
|
-
'train_hit_rate':
|
|
234
|
-
|
|
235
|
-
|
|
245
|
+
[{'combo_num': 3, 'edges': {'score': 49.46, 'age': 39.5}, 'hit_rate': 60.0, 'coverage': 31.25,
|
|
246
|
+
'train_hit_rate': 80.0, 'train_coverage': 41.67, 'combo_sample_size': 5, 'test_sample_size': 16,
|
|
247
|
+
'baseline_hit_rate': 47.5, 'vs_baseline': 12.5},
|
|
248
|
+
{'combo_num': 1, 'edges': {'score': 49.46}, 'hit_rate': 77.78, 'coverage': 56.25,
|
|
249
|
+
'train_hit_rate': 75.0, 'train_coverage': 66.67, 'combo_sample_size': 9, 'test_sample_size': 16,
|
|
250
|
+
'baseline_hit_rate': 47.5, 'vs_baseline': 30.28}]
|
|
236
251
|
```
|
|
237
252
|
|
|
238
|
-
Reading this: `score`'s threshold of
|
|
239
|
-
hit rate over
|
|
240
|
-
at
|
|
241
|
-
Adding `age`
|
|
242
|
-
|
|
253
|
+
Reading this: `score`'s threshold of 49.46 looked solid on train (75.00%
|
|
254
|
+
hit rate over 66.67% of rows) and, replayed unchanged against test, held up
|
|
255
|
+
even better at 77.78% over 56.25% of rows, comfortably ahead of the 47.5%
|
|
256
|
+
baseline hit rate. Adding `age` into the combo (`score >= 49.46 AND age >=
|
|
257
|
+
39.5`) tightens things further on train (80.00% hit rate) but shrinks
|
|
258
|
+
coverage a lot (down to 5 rows on test), and its test hit rate of 60.00%,
|
|
259
|
+
while still above baseline, is the less reliable of the two picks precisely
|
|
260
|
+
because it's resting on so few rows, exactly the kind of honest trade-off
|
|
261
|
+
`search()` is built to surface rather than hide.
|
|
243
262
|
|
|
244
263
|
---
|
|
245
264
|
|
|
@@ -356,14 +375,16 @@ list of up to `top_combos_n` dicts otherwise. Each dict:
|
|
|
356
375
|
|
|
357
376
|
```python
|
|
358
377
|
{
|
|
359
|
-
"combo_num":
|
|
360
|
-
"edges": {"score":
|
|
361
|
-
"hit_rate":
|
|
362
|
-
"coverage":
|
|
363
|
-
"train_hit_rate":
|
|
364
|
-
"train_coverage":
|
|
365
|
-
"combo_sample_size":
|
|
366
|
-
"test_sample_size":
|
|
378
|
+
"combo_num": 3,
|
|
379
|
+
"edges": {"score": 49.46, "age": 39.5}, # {column: edge_point} used by this combo
|
|
380
|
+
"hit_rate": 60.0, # test-side
|
|
381
|
+
"coverage": 31.25, # test-side
|
|
382
|
+
"train_hit_rate": 80.0, # carried over from train, unchanged
|
|
383
|
+
"train_coverage": 41.67, # carried over from train, unchanged
|
|
384
|
+
"combo_sample_size": 5, # rows clearing the combo on test
|
|
385
|
+
"test_sample_size": 16, # total test rows
|
|
386
|
+
"baseline_hit_rate": 47.5, # "do nothing" hit rate on the full df
|
|
387
|
+
"vs_baseline": 12.5, # test hit_rate - baseline_hit_rate, in points
|
|
367
388
|
}
|
|
368
389
|
```
|
|
369
390
|
|