ltfmselector 0.1.13__py3-none-any.whl → 0.2.0__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.
ltfmselector/env.py CHANGED
@@ -14,7 +14,10 @@ capLowerValues = lambda x: 0.0 if x < 0.0 else x
14
14
 
15
15
  class Environment:
16
16
  def __init__(
17
- self, X, y, X_bg, fQueryCost, mQueryCost,
17
+ self, X, y, X_bg,
18
+ fQueryCost, fQueryFunction,
19
+ fThreshold, fCap, fRate,
20
+ mQueryCost,
18
21
  fRepeatQueryCost, p_wNoFCost, errorCost, pType,
19
22
  regression_tol, regression_error_rounding, pModels, device,
20
23
  sample_weight=None, **kwargs
@@ -42,6 +45,21 @@ class Environment:
42
45
  fQueryCost : float
43
46
  Cost of querying a feature
44
47
 
48
+ fQueryFunction : None or {'step', 'linear', 'quadratic', 'exponential'}
49
+ Function to progressively increase cost of recruiting a feature
50
+
51
+ fThreshold : None or int
52
+ If `fQueryFunction == {'step', 'linear', 'quadratic', 'exponential'}`
53
+ Threshold of number of features, before cost of recruiting
54
+ increases
55
+
56
+ fCap : None or float
57
+ If `fQueryFunction == {'step'}`, upper limit of penalty
58
+
59
+ fRate : None or float
60
+ If `fQueryFunction == {'linear', 'quadratic', 'exponential'}`, rate
61
+ individual cost functions
62
+
45
63
  mQueryCost : float
46
64
  Cost of querying a prediction model
47
65
 
@@ -87,6 +105,11 @@ class Environment:
87
105
 
88
106
  # Reward functions
89
107
  self.fQueryCost = fQueryCost
108
+ self.fQueryFunction = fQueryFunction
109
+ self.fThreshold = fThreshold
110
+ self.fCap = fCap
111
+ self.fRate = fRate
112
+
90
113
  self.mQueryCost = mQueryCost
91
114
  self.fRepeatQueryCost = fRepeatQueryCost
92
115
  self.p_wNoFCost = p_wNoFCost
@@ -204,7 +227,7 @@ class Environment:
204
227
  self.state[action] = self.X_test.iloc[0, action]
205
228
 
206
229
  # Punish for querying a feature
207
- return [self.state, -self.fQueryCost, False]
230
+ return [self.state, -self.get_fQueryCost(), False]
208
231
 
209
232
  # Punish agent for attempting to query a feature already
210
233
  # previously selected
@@ -331,6 +354,44 @@ class Environment:
331
354
 
332
355
  return [None, 0.0, True]
333
356
 
357
+ def get_fQueryCost(self):
358
+ '''
359
+ Get cost of querying a feature
360
+ '''
361
+ if self.fQueryFunction is None:
362
+ return self.fQueryCost
363
+
364
+ # Get number of total recruited features
365
+ nFSubset = (self.get_feature_mask()).sum()
366
+
367
+ if self.fQueryFunction == "step":
368
+ return self.get_fQueryCostStep(nFSubset)
369
+ elif self.fQueryFunction == "linear":
370
+ return self.get_fQueryCostLinear(nFSubset)
371
+ elif self.fQueryFunction == "quadratic":
372
+ return self.get_fQueryCostQuadratic(nFSubset)
373
+
374
+ def get_fQueryCostStep(self, _nFSubset):
375
+ '''Step function for querying feature'''
376
+ if _nFSubset > self.fThreshold:
377
+ return self.fCap
378
+ else:
379
+ return self.fQueryCost
380
+
381
+ def get_fQueryCostLinear(self, _nFSubset):
382
+ '''Linear function for querying feature'''
383
+ return max(
384
+ self.fQueryCost,
385
+ self.fQueryCost + self.fRate*(_nFSubset-self.fThreshold)
386
+ )
387
+
388
+ def get_fQueryCostQuadratic(self, _nFSubset):
389
+ '''Quadratic function for querying feature'''
390
+ if _nFSubset > self.fThreshold:
391
+ return self.fQueryCost + self.fRate*(_nFSubset-self.fThreshold)**2
392
+ else:
393
+ return self.fQueryCost
394
+
334
395
  def get_feature_mask(self):
335
396
  '''
336
397
  Get the (boolean) feature mask that indicates if a feature has
@@ -72,7 +72,9 @@ class LTFMSelector:
72
72
  def __init__(
73
73
  self, episodes, batch_size=256, tau=0.0005,
74
74
  eps_start=0.9, eps_end=0.05, eps_decay=1000,
75
- fQueryCost=0.01, mQueryCost=0.01,
75
+ fQueryCost=0.01, fQueryFunction=None,
76
+ fThreshold=None, fCap=None, fRate=None,
77
+ mQueryCost=0.01,
76
78
  fRepeatQueryCost=1.0, p_wNoFCost=5.0, errorCost=1.0,
77
79
  pType="regression", regression_tol=0.5,
78
80
  regression_error_rounding=1,
@@ -105,7 +107,32 @@ class LTFMSelector:
105
107
  Rate of exponential decay
106
108
 
107
109
  fQueryCost : float
108
- Cost of querying a feature
110
+ Cost of querying a feature.
111
+
112
+ fQueryFunction : None or {'step', 'linear', 'quadratic'}
113
+ User can also decide to progressively increase the cost of
114
+ querying features in the following manner:
115
+ 'step' :
116
+ Every additional feature adds a fixed constant, determined
117
+ by user.
118
+ 'linear' :
119
+ Cost of every additional feature linearly increases according
120
+ to user-defined gradient
121
+ 'quadratic' :
122
+ Cost of every additional feature increases quadratically,
123
+ according to a user-defined rate
124
+
125
+ fThreshold : None or int
126
+ If `fQueryFunction == {'step', 'linear', 'quadratic', 'exponential'}`
127
+ Threshold of number of features, before cost of recruiting
128
+ increases
129
+
130
+ fCap : None or float
131
+ If `fQueryFunction == {'step'}`, upper limit of penalty
132
+
133
+ fRate : None or float
134
+ If `fQueryFunction == {'linear', 'quadratic', 'exponential'}`, rate
135
+ individual cost functions
109
136
 
110
137
  mQueryCost : float
111
138
  Cost of querying a prediction model
@@ -196,6 +223,35 @@ class LTFMSelector:
196
223
 
197
224
  # Reward function
198
225
  self.fQueryCost = fQueryCost
226
+ self.fQueryFunction = fQueryFunction
227
+ self.fThreshold = fThreshold
228
+ self.fCap = fCap
229
+ self.fRate = fRate
230
+
231
+ # Options for progressive cost functions
232
+ if isinstance(self.fQueryFunction, str):
233
+ fQueryFunctions = ['step', 'linear', 'quadratic']
234
+ if not self.fQueryFunction in fQueryFunctions:
235
+ raise ValueError(
236
+ f"{self.fQueryFunction} is not a valid option. Available " +
237
+ f"options are {fQueryFunctions}"
238
+ )
239
+ else:
240
+ if not isinstance(fThreshold, int):
241
+ raise ValueError("Parameter fThreshold must be an integer!")
242
+
243
+ if self.fQueryFunction == "step":
244
+ if not (isinstance(fCap, float) or isinstance(fCap, int)):
245
+ raise ValueError("Parameter fCap must be an int or float!")
246
+ else:
247
+ self.fCap = float(fCap)
248
+ else:
249
+ if self.fQueryFunction in ["linear", "quadratic"]:
250
+ if not (isinstance(fRate, float) or isinstance(fRate, int)):
251
+ raise ValueError("Parameter fRate must be an int or float!")
252
+ else:
253
+ self.fRate = float(fRate)
254
+
199
255
  self.mQueryCost = mQueryCost
200
256
  self.fRepeatQueryCost = fRepeatQueryCost
201
257
  self.p_wNoFCost = p_wNoFCost
@@ -336,7 +392,9 @@ class LTFMSelector:
336
392
  # Initializing the environment
337
393
  env = Environment(
338
394
  self.X, self.y, self.background_dataset,
339
- self.fQueryCost, self.mQueryCost,
395
+ self.fQueryCost, self.fQueryFunction,
396
+ self.fThreshold, self.fCap, self.fRate,
397
+ self.mQueryCost,
340
398
  self.fRepeatQueryCost, self.p_wNoFCost, self.errorCost,
341
399
  self.pType, self.regression_tol, self.regression_error_rounding,
342
400
  self.pModels, self.device, sample_weight=self.sample_weight,
@@ -484,6 +542,7 @@ class LTFMSelector:
484
542
  writer.add_scalar("Metrics/Average_QValue", _res[0], monitor_count)
485
543
  writer.add_scalar("Metrics/Average_Reward", _res[1], monitor_count)
486
544
  writer.add_scalar("Metrics/Average_Target", _res[2], monitor_count)
545
+ writer.flush()
487
546
  writer.close()
488
547
 
489
548
  if returnQ:
@@ -517,7 +576,9 @@ class LTFMSelector:
517
576
  # Initializing the environment
518
577
  env = Environment(
519
578
  self.X, self.y, self.background_dataset,
520
- self.fQueryCost, self.mQueryCost,
579
+ self.fQueryCost, self.fQueryFunction,
580
+ self.fThreshold, self.fCap, self.fRate,
581
+ self.mQueryCost,
521
582
  self.fRepeatQueryCost, self.p_wNoFCost, self.errorCost,
522
583
  self.pType, self.regression_tol, self.regression_error_rounding,
523
584
  self.pModels, self.device, **kwargs
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ltfmselector
3
- Version: 0.1.13
3
+ Version: 0.2.0
4
4
  Summary: Locally-Tailored Feature and Model Selector with Deep Q-Learning
5
5
  Project-URL: GitHub, https://github.com/RenZhen95/ltfmselector/
6
6
  Author-email: RenZhen95 <j-liaw@hotmail.com>
@@ -0,0 +1,9 @@
1
+ ltfmselector/__init__.py,sha256=lf3e90CNpEDvEmNZ-0iuoHOPsA7D-WN_opbBsTYLVEA,76
2
+ ltfmselector/env.py,sha256=898o_g6-i0Rz5R-4WxZInf3xaxXHf58kPJId0KeewQM,16070
3
+ ltfmselector/ltfmselector.py,sha256=zxGTLtuaoqdWbGxM8JmQES1_kGpNad1utRfDkepPoko,32329
4
+ ltfmselector/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ ltfmselector/utils.py,sha256=VXYZSDm7x4s0p9F_58NLW8WQa3dxi0vHZewRy6miC2E,5438
6
+ ltfmselector-0.2.0.dist-info/METADATA,sha256=76QDgOBLL81otMAwr9D-eNfviT5SY76Tf70-WNGIgyg,3020
7
+ ltfmselector-0.2.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
8
+ ltfmselector-0.2.0.dist-info/licenses/LICENSE,sha256=tmIDlkkp4a0EudXuGmeTdGjHjPhmmXkEMshACXLqX2w,1092
9
+ ltfmselector-0.2.0.dist-info/RECORD,,
@@ -1,9 +0,0 @@
1
- ltfmselector/__init__.py,sha256=lf3e90CNpEDvEmNZ-0iuoHOPsA7D-WN_opbBsTYLVEA,76
2
- ltfmselector/env.py,sha256=vizWGqDSc_2Zfs9aXjFARanIAz6PTKwUHu2_Lew9s3Y,13878
3
- ltfmselector/ltfmselector.py,sha256=w47J_ktNhfmreX1RqlfFo8Di2aEYdl63oI3EHgguCPM,29571
4
- ltfmselector/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- ltfmselector/utils.py,sha256=VXYZSDm7x4s0p9F_58NLW8WQa3dxi0vHZewRy6miC2E,5438
6
- ltfmselector-0.1.13.dist-info/METADATA,sha256=dNyHk7_WXjX59D7GmVs_f_Csdngfq2_lesaan24TvEs,3021
7
- ltfmselector-0.1.13.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
8
- ltfmselector-0.1.13.dist-info/licenses/LICENSE,sha256=tmIDlkkp4a0EudXuGmeTdGjHjPhmmXkEMshACXLqX2w,1092
9
- ltfmselector-0.1.13.dist-info/RECORD,,