metacountregressor 1.0.11__py3-none-any.whl → 1.0.13__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.
- metacountregressor/main.py +10 -2
- metacountregressor/solution.py +751 -248
- {metacountregressor-1.0.11.dist-info → metacountregressor-1.0.13.dist-info}/METADATA +2 -2
- {metacountregressor-1.0.11.dist-info → metacountregressor-1.0.13.dist-info}/RECORD +7 -7
- {metacountregressor-1.0.11.dist-info → metacountregressor-1.0.13.dist-info}/WHEEL +1 -1
- {metacountregressor-1.0.11.dist-info → metacountregressor-1.0.13.dist-info}/licenses/LICENSE.txt +0 -0
- {metacountregressor-1.0.11.dist-info → metacountregressor-1.0.13.dist-info}/top_level.txt +0 -0
metacountregressor/solution.py
CHANGED
@@ -124,16 +124,17 @@ class ObjectiveFunction(object):
|
|
124
124
|
|
125
125
|
def __init__(self, x_data, y_data, **kwargs):
|
126
126
|
self.gbl_best = 1e5
|
127
|
+
self.non_sig_prints = kwargs.get('non_sig_prints', False)
|
127
128
|
self.run_numerical_hessian = kwargs.get('r_nu_hess', False)
|
128
|
-
self.run_bootstrap =
|
129
|
+
self.run_bootstrap = kwargs.get('run_bootstrap', False)
|
129
130
|
self.linear_regression = kwargs.get('linear_model', False)
|
130
|
-
self.reg_penalty = kwargs.get('reg_penalty',
|
131
|
+
self.reg_penalty = kwargs.get('reg_penalty', 0)
|
131
132
|
self.power_up_ll = False
|
132
133
|
self.nb_parma = 1
|
133
134
|
self.bic = None
|
134
135
|
self.other_bic = False
|
135
136
|
self.test_flag = 1
|
136
|
-
self.no_extra_param =0 #if true, fix dispersion. w
|
137
|
+
self.no_extra_param = 0 # if true, fix dispersion. w
|
137
138
|
if self.other_bic:
|
138
139
|
print('change this to false latter ')
|
139
140
|
|
@@ -158,14 +159,14 @@ class ObjectiveFunction(object):
|
|
158
159
|
self.rounding_point = kwargs.get('decimals_in_coeff', 4)
|
159
160
|
self.MAE = None
|
160
161
|
self.best_obj_1 = 1000000.0
|
161
|
-
self._obj_1 = kwargs.get('_obj_1', 'bic')
|
162
|
-
self._obj_2 = kwargs.get('_obj_2', 'MSE')
|
162
|
+
self._obj_1 = kwargs.get('_obj_1', 'bic')
|
163
|
+
self._obj_2 = kwargs.get('_obj_2', 'MSE')
|
163
164
|
self.numerical_hessian_calc = 0 # calculates hessian by statsmodels otherwise scipy
|
164
165
|
self.full_model = None
|
165
166
|
self.GP_parameter = 0
|
166
167
|
self.is_multi = kwargs.get('is_multi', False)
|
167
|
-
self.complexity_level = kwargs.get('complexity_level', 6)
|
168
|
-
self._max_iterations_improvement = kwargs.get("WIC",10000)
|
168
|
+
self.complexity_level = kwargs.get('complexity_level', kwargs.get('test_complexity',6))
|
169
|
+
self._max_iterations_improvement = kwargs.get("WIC", 10000)
|
169
170
|
self.generated_sln = set()
|
170
171
|
self.ave_mae = 0
|
171
172
|
# defalt paramaters for hs #TODO unpack into harmony search class
|
@@ -173,17 +174,18 @@ class ObjectiveFunction(object):
|
|
173
174
|
self._hms = 20
|
174
175
|
self._max_time = self._max_time = kwargs.get('_max_time', kwargs.get('MAX_TIME', 0.8 * 60 * 60 * 24))
|
175
176
|
self._hmcr = kwargs.get('_hmcr', .5)
|
176
|
-
self._par = 0.3
|
177
|
+
self._par = 0.3 # dont think this gets useted
|
177
178
|
self._mpai = 1
|
178
179
|
self._max_imp = kwargs.get('_max_imp', 90000000)
|
179
|
-
self._WIC =
|
180
|
+
self._WIC = kwargs.get("WIC",
|
181
|
+
10000) # Number of Iterations without Multiobjective Improvement #tod chuck into solution
|
180
182
|
self._panels = None
|
181
183
|
self.method_ll = 'Nelder-Mead-BFGS'
|
182
184
|
|
183
185
|
self.method_ll = 'L-BFGS-B' # alternatives 'BFGS_2', 'BFGS
|
184
186
|
self.method_ll = kwargs.get('method', 'BFGS_2')
|
185
|
-
|
186
|
-
#self.method_ll = 'Nelder-Mead-BFGS'
|
187
|
+
|
188
|
+
# self.method_ll = 'Nelder-Mead-BFGS'
|
187
189
|
self.Keep_Fit = 2
|
188
190
|
self.MP = 0
|
189
191
|
# Nelder-Mead-BFGS
|
@@ -192,7 +194,7 @@ class ObjectiveFunction(object):
|
|
192
194
|
|
193
195
|
self.beta_dict = dict
|
194
196
|
if 'model_terms' in kwargs:
|
195
|
-
|
197
|
+
|
196
198
|
if kwargs.get('model_terms').get('group') is not None:
|
197
199
|
kwargs['group'] = kwargs.get('model_terms').get('group')
|
198
200
|
|
@@ -208,14 +210,13 @@ class ObjectiveFunction(object):
|
|
208
210
|
if k in acceptable_keys_list:
|
209
211
|
self.__setattr__(k, self.tryeval(kwargs[k]))
|
210
212
|
|
211
|
-
|
212
213
|
if 'complexity_level' in kwargs:
|
213
214
|
self.complexity_level = kwargs['complexity_level']
|
214
215
|
|
215
216
|
if 'instance_name' in kwargs:
|
216
217
|
self.instance_name = str(kwargs['instance_name'])
|
217
218
|
else:
|
218
|
-
|
219
|
+
|
219
220
|
print('no name set, setting name as 0')
|
220
221
|
self.instance_name = f"run_{str(0)}" # set an arbitrary instance number
|
221
222
|
|
@@ -223,7 +224,8 @@ class ObjectiveFunction(object):
|
|
223
224
|
self.save_state = True
|
224
225
|
if not os.path.exists(self.instance_name):
|
225
226
|
if kwargs.get('make_directory', True):
|
226
|
-
print(
|
227
|
+
print(
|
228
|
+
'Making a Directory, if you want to stop from storing the files to this directory set argumet: make_directory:False')
|
227
229
|
os.makedirs(self.instance_name)
|
228
230
|
else:
|
229
231
|
self.save_state = False
|
@@ -243,7 +245,6 @@ class ObjectiveFunction(object):
|
|
243
245
|
|
244
246
|
self._input_data(x_data, y_data)
|
245
247
|
|
246
|
-
|
247
248
|
if y_data.ndim == 1:
|
248
249
|
y_data = pd.DataFrame(y_data)
|
249
250
|
|
@@ -257,14 +258,16 @@ class ObjectiveFunction(object):
|
|
257
258
|
self.test_percentage = float(kwargs.get('test_percentage', 0))
|
258
259
|
self.val_percentage = float(kwargs.get('val_percentage', 0))
|
259
260
|
if self.test_percentage == 0:
|
260
|
-
print(
|
261
|
+
print(
|
262
|
+
'test percentage is 0, please enter arg test_percentage as decimal if intended for multi objective optimisation, eg 0.8')
|
261
263
|
print('continuing single objective')
|
262
264
|
time.sleep(2)
|
263
265
|
self.is_multi = False
|
264
266
|
|
265
267
|
if 'panels' in kwargs and not (kwargs.get('panels') == None):
|
266
268
|
if kwargs.get('group') is not None:
|
267
|
-
self.group_names = np.asarray(
|
269
|
+
self.group_names = np.asarray(
|
270
|
+
x_data[kwargs['group']].astype('category').cat._parent.dtype.categories)
|
268
271
|
|
269
272
|
x_data[kwargs['group']] = x_data[kwargs['group']].astype(
|
270
273
|
'category').cat.codes
|
@@ -296,7 +299,7 @@ class ObjectiveFunction(object):
|
|
296
299
|
ids = np.random.choice(N, training_size, replace=False)
|
297
300
|
id_unique = np.array([i for i in range(N)])
|
298
301
|
ids = id_unique[ids]
|
299
|
-
#todo make sure its split so counts are split
|
302
|
+
# todo make sure its split so counts are split
|
300
303
|
train_idx = [ii for ii in range(len(id_unique)) if id_unique[ii] in ids]
|
301
304
|
test_idx = [ii for ii in range(len(id_unique)) if id_unique[ii] not in ids]
|
302
305
|
df_train = x_data.loc[train_idx, :]
|
@@ -304,13 +307,12 @@ class ObjectiveFunction(object):
|
|
304
307
|
y_train = y_data.loc[train_idx, :]
|
305
308
|
y_test = y_data.loc[test_idx, :]
|
306
309
|
|
307
|
-
|
308
|
-
#self.n_obs = N
|
310
|
+
# self.n_obs = N
|
309
311
|
self._characteristics_names = list(self._x_data.columns)
|
310
312
|
self._max_group_all_means = 2
|
311
313
|
|
312
314
|
exclude_this_test = [4]
|
313
|
-
|
315
|
+
|
314
316
|
if 'panels' in kwargs and not (kwargs.get('panels') == None):
|
315
317
|
self.panels = np.asarray(df_train[kwargs['panels']])
|
316
318
|
self.panels_test = np.asarray(df_test[kwargs['panels']])
|
@@ -375,7 +377,7 @@ class ObjectiveFunction(object):
|
|
375
377
|
|
376
378
|
self._samples, self._panels, self._characteristics = self._x_data.shape
|
377
379
|
|
378
|
-
|
380
|
+
|
379
381
|
|
380
382
|
else:
|
381
383
|
print('No Panels. Grouped Random Paramaters Will not be estimated')
|
@@ -400,7 +402,7 @@ class ObjectiveFunction(object):
|
|
400
402
|
YY = YY.astype('float')
|
401
403
|
self._x_data = XX.copy()
|
402
404
|
self._y_data = YY.copy()
|
403
|
-
|
405
|
+
|
404
406
|
if self.is_multi:
|
405
407
|
X, Y, panel, group = self._arrange_long_format(df_test, y_test, self.ids_test, self.ids_test, None)
|
406
408
|
if np.max(group) > 50:
|
@@ -408,7 +410,7 @@ class ObjectiveFunction(object):
|
|
408
410
|
else:
|
409
411
|
exclude_this_test = []
|
410
412
|
X, Y, panel_info = self._balance_panels(X, Y, panel)
|
411
|
-
|
413
|
+
|
412
414
|
self.N_test, self.P_test = panel_info.shape
|
413
415
|
K = X.shape[1]
|
414
416
|
self.columns_names = X.columns
|
@@ -418,10 +420,406 @@ class ObjectiveFunction(object):
|
|
418
420
|
Y = Y.astype('float')
|
419
421
|
self._x_data_test = X.copy()
|
420
422
|
self.y_data_test = Y.copy()
|
421
|
-
|
423
|
+
|
422
424
|
self._samples, self._panels, self._characteristics = self._x_data.shape
|
423
425
|
|
426
|
+
# Define the offset into the data
|
427
|
+
self.process_offset()
|
428
|
+
if self.is_multi:
|
429
|
+
self.pareto_printer = Pareto(self._obj_1, self._obj_2, True)
|
430
|
+
self._pareto_population = list()
|
431
|
+
|
432
|
+
self.Ndraws = kwargs.get('Ndraws', 200)
|
433
|
+
self.draws1 = None
|
434
|
+
self.initial_sig = 1 # pass the test of a single model
|
435
|
+
self.pvalue_sig_value = kwargs.get('pvalue_sig_value', .1)
|
436
|
+
self.observations = self._x_data.shape[0]
|
437
|
+
self.minimize_scaler = 1 / self.observations # scale the minimization function to the observations
|
438
|
+
self.minimize_scaler =1
|
439
|
+
self.batch_size = None
|
440
|
+
# open the file in the write mode
|
441
|
+
self.grab_transforms = 0
|
442
|
+
|
443
|
+
if not isinstance(self._characteristics, int):
|
444
|
+
raise Exception
|
445
|
+
if not isinstance(self._x_data, pd.DataFrame):
|
446
|
+
|
447
|
+
print('Setup Complete...')
|
448
|
+
else:
|
449
|
+
print('No Panels Supplied')
|
450
|
+
print('Setup Complete...')
|
451
|
+
self._characteristics_names = list(self._x_data.columns)
|
452
|
+
# define the variables
|
453
|
+
|
454
|
+
self._transformations = kwargs.get('_transformations', ["no", "log", "sqrt", "arcsinh", "nil"])
|
455
|
+
# self._distribution = ['triangular', 'uniform', 'normal', 'ln_normal', 'tn_normal', 'lindley']
|
456
|
+
|
457
|
+
self._distribution = kwargs.get('_distributions', ['triangular', 'uniform', 'normal', 'tn_normal', 'ln_normal'])
|
458
|
+
|
459
|
+
if self.G is not None:
|
460
|
+
# TODO need to handle this for groups
|
461
|
+
|
462
|
+
self._distribution = ["trad| " + item for item in self._distribution
|
463
|
+
] + ["grpd| " + item for item in self._distribution]
|
464
|
+
|
465
|
+
# output information
|
466
|
+
self.convergence = None
|
467
|
+
self.coeff_names = None
|
468
|
+
self._interactions = None # was 2
|
469
|
+
self.coeff_ = None
|
470
|
+
|
471
|
+
self.significant = 0
|
472
|
+
# define the states of our explanatory variables
|
473
|
+
|
474
|
+
self._discrete_values = self.define_alphas(self.complexity_level, exclude_this_test,
|
475
|
+
kwargs.get('must_include', []), extra=kwargs.get('decisions', None))
|
476
|
+
|
477
|
+
self._discrete_values = self._discrete_values + \
|
478
|
+
self.define_distributions_analyst(extra=kwargs.get('decisions', None))
|
479
|
+
|
480
|
+
if 'model_types' in kwargs or 'Model' in kwargs:
|
481
|
+
model_type_mapping = {
|
482
|
+
'POS': 0,
|
483
|
+
'NB': 1
|
484
|
+
}
|
485
|
+
model_types = kwargs.get('model_types', kwargs.get('Model', [[0, 1]]))
|
486
|
+
converted_model_types = [
|
487
|
+
[model_type_mapping.get(item, item) for item in sublist]
|
488
|
+
for sublist in model_types
|
489
|
+
]
|
490
|
+
model_types = converted_model_types
|
491
|
+
# this should be a list of list like [[0, 1]]
|
492
|
+
# also if it is [['POS', 'NB']] then it will be converted to [0, 1]
|
493
|
+
else:
|
494
|
+
|
495
|
+
model_types = [[0, 1]] # add 2 for Generalized Poisson
|
496
|
+
|
497
|
+
# model_types = [[0]]
|
498
|
+
|
499
|
+
if self.linear_regression:
|
500
|
+
model_types = [[1]]
|
501
|
+
self.grad_yes = False
|
502
|
+
|
503
|
+
print(f'Linear Model Selected: turning off gradient calculation')
|
504
|
+
|
505
|
+
model_t_dict = {'Poisson': 0,
|
506
|
+
"NB": 1}
|
507
|
+
if self.linear_regression:
|
508
|
+
# Rename key "NB" to "sigma" if it exists in the dictionary
|
509
|
+
if "NB" in model_t_dict:
|
510
|
+
model_t_dict["sigma"] = model_t_dict.pop("NB")
|
511
|
+
|
512
|
+
# Retrieve the keys (model names) corresponding to the values in model_types
|
513
|
+
model_keys = [key for key, value in model_t_dict.items() if value in model_types[0]]
|
514
|
+
# Print the formatted result
|
515
|
+
print(f'The type of models possible will consider: {", ".join(model_keys)}')
|
516
|
+
self._discrete_values = self._discrete_values + self.define_poissible_transforms(
|
517
|
+
self._transformations, kwargs.get('decisions', None)) + model_types
|
518
|
+
|
519
|
+
self._model_type_codes = ['p', 'nb',
|
520
|
+
'gp', "pl", ["nb-theta", 'nb-dis']]
|
521
|
+
self.update_model_type_codes()
|
522
|
+
self._variable = [True] * len(self._discrete_values)
|
523
|
+
self._lower_bounds = [None] * \
|
524
|
+
len(self._discrete_values) # TODO have continus
|
525
|
+
self._upper_bounds = [None] * \
|
526
|
+
len(self._discrete_values) # TODO have continous
|
527
|
+
# model specs
|
528
|
+
self.endog = None
|
529
|
+
# solution parameters
|
530
|
+
self._min_characteristics = kwargs.get('_min_vars', 3)
|
531
|
+
self._max_hurdle = 4
|
532
|
+
|
533
|
+
# Manually fit from analyst specification
|
534
|
+
manual_fit = kwargs.get('Manual_Fit', None)
|
535
|
+
if manual_fit is not None:
|
536
|
+
print('fitting manual')
|
537
|
+
self.process_manual_fit(manual_fit)
|
538
|
+
|
539
|
+
self.solution_analyst = None
|
540
|
+
|
541
|
+
def __init__v(self, x_data, y_data, **kwargs):
|
542
|
+
# Default attributes
|
543
|
+
self.gbl_best = 1e5
|
544
|
+
self.non_sig_prints = kwargs.get('non_sig_prints', False)
|
545
|
+
self.run_numerical_hessian = kwargs.get('r_nu_hess', False)
|
546
|
+
self.run_bootstrap = kwargs.get('run_bootstrap', False)
|
547
|
+
self.linear_regression = kwargs.get('linear_model', False)
|
548
|
+
self.reg_penalty = kwargs.get('reg_penalty', 1)
|
549
|
+
self.power_up_ll = False
|
550
|
+
self.nb_parma = 1
|
551
|
+
self.bic = None
|
552
|
+
self.other_bic = False
|
553
|
+
self.test_flag = 1
|
554
|
+
self.no_extra_param = 0 # Fix dispersion if true
|
555
|
+
self.constant_value = 0
|
556
|
+
self.negative_binomial_value = 1
|
557
|
+
self.verbose_safe = kwargs.get('verbose', 0)
|
558
|
+
self.please_print = kwargs.get('please_print', 0)
|
559
|
+
self.grad_yes = kwargs.get('grad_est', False)
|
560
|
+
self.hess_yes = False
|
561
|
+
self.rounding_point = kwargs.get('decimals_in_coeff', 4)
|
562
|
+
self.best_obj_1 = 1e6
|
563
|
+
self._obj_1 = kwargs.get('_obj_1', 'bic')
|
564
|
+
self._obj_2 = kwargs.get('_obj_2', 'MSE')
|
565
|
+
self.numerical_hessian_calc = 0
|
566
|
+
self.full_model = None
|
567
|
+
self.GP_parameter = 0
|
568
|
+
self.is_multi = kwargs.get('is_multi', False)
|
569
|
+
self.complexity_level = kwargs.get('complexity_level', 6)
|
570
|
+
self._max_iterations_improvement = kwargs.get("WIC", 10000)
|
571
|
+
self.generated_sln = set()
|
572
|
+
self.ave_mae = 0
|
573
|
+
|
574
|
+
# Harmony search parameters
|
575
|
+
self.algorithm = kwargs.get('algorithm', 'hs')
|
576
|
+
self._hms = 20
|
577
|
+
self._max_time = kwargs.get('_max_time', 0.8 * 60 * 60 * 24)
|
578
|
+
self._hmcr = kwargs.get('_hmcr', 0.5)
|
579
|
+
self._par = 0.3
|
580
|
+
self._mpai = 1
|
581
|
+
self._max_imp = kwargs.get('_max_imp', 90000000)
|
582
|
+
self.method_ll = kwargs.get('method', 'BFGS_2')
|
583
|
+
self._max_characteristics = kwargs.get('_max_vars', 90)
|
584
|
+
|
585
|
+
# Beta dictionary
|
586
|
+
self.beta_dict = dict
|
587
|
+
|
588
|
+
# Handle `model_terms` in kwargs
|
589
|
+
if 'model_terms' in kwargs:
|
590
|
+
if kwargs['model_terms'].get('group') is not None:
|
591
|
+
kwargs['group'] = kwargs['model_terms']['group']
|
592
|
+
if kwargs['model_terms'].get('panels') is not None:
|
593
|
+
kwargs['panels'] = kwargs['model_terms']['panels']
|
594
|
+
|
595
|
+
# Acceptable keys
|
596
|
+
acceptable_keys = [
|
597
|
+
'_par', '_max_imp', '_hmcr', 'steps', 'algorithm', '_random_seed', '_max_time',
|
598
|
+
'forcedvariables', '_obj_1', '_obj_2', 'Manuel_Estimate', 'test_percentage', 'is_multi',
|
599
|
+
'val_percentage', 'complexity_level', '_hms', '_mpai', 'group', '_max_characteristics',
|
600
|
+
'zi_force_names'
|
601
|
+
]
|
602
|
+
for k, v in kwargs.items():
|
603
|
+
if k in acceptable_keys:
|
604
|
+
setattr(self, k, self.tryeval(v))
|
605
|
+
|
606
|
+
# Instance name
|
607
|
+
self.instance_name = str(kwargs.get('instance_name', f"run_0"))
|
608
|
+
if kwargs.get('save_directory', True):
|
609
|
+
self.save_state = True
|
610
|
+
if not os.path.exists(self.instance_name):
|
611
|
+
if kwargs.get('make_directory', True):
|
612
|
+
print(f"Creating directory: {self.instance_name}")
|
613
|
+
os.makedirs(self.instance_name)
|
614
|
+
else:
|
615
|
+
self.save_state = False
|
616
|
+
|
617
|
+
# P-value penalty
|
618
|
+
self.pvalue_penalty = float(kwargs.get('pvalue_penalty', 0.5))
|
619
|
+
self.pvalue_exceed = 0
|
620
|
+
self._maximize = False
|
621
|
+
|
622
|
+
# Data processing
|
623
|
+
x_data = sm.add_constant(x_data)
|
624
|
+
if kwargs.get('standardize_data', False):
|
625
|
+
print("Standardizing data")
|
626
|
+
x_data = self.self_standardize_positive(x_data)
|
627
|
+
|
628
|
+
self._input_data(x_data, y_data)
|
629
|
+
if y_data.ndim == 1:
|
630
|
+
y_data = pd.DataFrame(y_data)
|
631
|
+
|
632
|
+
# Handle panels and groups
|
633
|
+
self.handle_panels_and_groups(x_data, y_data, kwargs)
|
634
|
+
|
635
|
+
# Define transformations and distributions
|
636
|
+
self._transformations = kwargs.get('_transformations', ["no", "log", "sqrt", "arcsinh", "nil"])
|
637
|
+
self._distribution = kwargs.get(
|
638
|
+
'_distributions', ['triangular', 'uniform', 'normal', 'tn_normal', 'ln_normal']
|
639
|
+
)
|
640
|
+
if self.G is not None:
|
641
|
+
self._distribution = ["trad| " + dist for dist in self._distribution] + \
|
642
|
+
["grpd| " + dist for dist in self._distribution]
|
643
|
+
|
644
|
+
# Output and model specs
|
645
|
+
self.convergence = None
|
646
|
+
self.coeff_names = None
|
647
|
+
self._interactions = None
|
648
|
+
self.coeff_ = None
|
649
|
+
self.significant = 0
|
650
|
+
self._min_characteristics = kwargs.get('_min_vars', 3)
|
651
|
+
self._max_hurdle = 4
|
652
|
+
self.solution_analyst = None
|
653
|
+
|
654
|
+
# Setup complete
|
655
|
+
print("Setup Complete...")
|
656
|
+
|
657
|
+
def handle_panels_and_groups(self, x_data, y_data, kwargs):
|
658
|
+
"""Handles panels and groups for the model."""
|
659
|
+
if 'panels' in kwargs and kwargs['panels'] is not None:
|
660
|
+
self.setup_panels_groups(x_data, y_data, kwargs)
|
661
|
+
else:
|
662
|
+
print("No Panels. Grouped Random Parameters Will Not Be Estimated")
|
663
|
+
self.G = None
|
664
|
+
self._Gnum = 1
|
665
|
+
self._max_group_all_means = 0
|
666
|
+
|
667
|
+
|
668
|
+
|
669
|
+
|
670
|
+
|
671
|
+
|
672
|
+
|
673
|
+
|
674
|
+
|
675
|
+
def __init__old(self, x_data, y_data, **kwargs):
|
676
|
+
|
677
|
+
# 1. GENERAL PARAMETERS
|
678
|
+
self.gbl_best = 1e5
|
679
|
+
self.non_sig_prints = kwargs.get('non_sig_prints', True)
|
680
|
+
self.run_numerical_hessian = kwargs.get('r_nu_hess', False)
|
681
|
+
self.run_bootstrap = kwargs.get('run_bootstrap', False)
|
682
|
+
self.linear_regression = kwargs.get('linear_model', False)
|
683
|
+
self.reg_penalty = kwargs.get('reg_penalty',1)
|
684
|
+
self.power_up_ll = False
|
685
|
+
self.nb_parma = 1
|
686
|
+
self.bic = None
|
687
|
+
self.other_bic = False
|
688
|
+
self.test_flag = 1
|
689
|
+
self.no_extra_param =0 #if true, fix dispersion. w
|
690
|
+
if self.other_bic:
|
691
|
+
print('change this to false latter ')
|
692
|
+
|
693
|
+
# initialize values
|
694
|
+
self.constant_value = 0
|
695
|
+
self.negative_binomial_value = 1
|
696
|
+
|
697
|
+
self.verbose_safe = kwargs.get('verbose', 0)
|
698
|
+
self.please_print = kwargs.get('please_print', 0)
|
699
|
+
self.group_halton = None
|
700
|
+
self.grad_yes = kwargs.get('grad_est', False)
|
701
|
+
self.hess_yes = False
|
702
|
+
self.group_halton_test = None
|
703
|
+
self.panels = None
|
704
|
+
self.group_names = []
|
705
|
+
self.pvalues = None
|
706
|
+
self.Last_Sol = None
|
707
|
+
self.fixed_fit = None
|
708
|
+
self.rdm_fit = None
|
709
|
+
self.rdm_cor_fit = None
|
710
|
+
self.dist_fit = None
|
711
|
+
self.rounding_point = kwargs.get('decimals_in_coeff', 4)
|
712
|
+
self.MAE = None
|
713
|
+
self.best_obj_1 = 1000000.0
|
714
|
+
self._obj_1 = kwargs.get('_obj_1', 'bic')
|
715
|
+
self._obj_2 = kwargs.get('_obj_2', 'MSE')
|
716
|
+
self.numerical_hessian_calc = 0 # calculates hessian by statsmodels otherwise scipy
|
717
|
+
self.full_model = None
|
718
|
+
self.GP_parameter = 0
|
719
|
+
self.is_multi = kwargs.get('is_multi', False)
|
720
|
+
self.complexity_level = kwargs.get('complexity_level', 6)
|
721
|
+
self._max_iterations_improvement = kwargs.get("WIC",10000)
|
722
|
+
self.generated_sln = set()
|
723
|
+
self.ave_mae = 0
|
724
|
+
# defalt paramaters for hs #TODO unpack into harmony search class
|
725
|
+
self.algorithm = kwargs.get('algorithm', 'hs') # 'sa' 'de' also avialable
|
726
|
+
self._hms = 20
|
727
|
+
self._max_time = self._max_time = kwargs.get('_max_time', kwargs.get('MAX_TIME', 0.8 * 60 * 60 * 24))
|
728
|
+
self._hmcr = kwargs.get('_hmcr', .5)
|
729
|
+
self._par = 0.3 #dont think this gets useted
|
730
|
+
self._mpai = 1
|
731
|
+
self._max_imp = kwargs.get('_max_imp', 90000000)
|
732
|
+
self._WIC = kwargs.get("WIC",10000) # Number of Iterations without Multiobjective Improvement #tod chuck into solution
|
733
|
+
self._panels = None
|
734
|
+
self.method_ll = 'Nelder-Mead-BFGS'
|
735
|
+
|
736
|
+
self.method_ll = 'L-BFGS-B' # alternatives 'BFGS_2', 'BFGS
|
737
|
+
self.method_ll = kwargs.get('method', 'BFGS_2')
|
738
|
+
|
739
|
+
#self.method_ll = 'Nelder-Mead-BFGS'
|
740
|
+
self.Keep_Fit = 2
|
741
|
+
self.MP = 0
|
742
|
+
# Nelder-Mead-BFGS
|
743
|
+
|
744
|
+
self._max_characteristics = kwargs.get('_max_vars', 90)
|
745
|
+
|
746
|
+
self.beta_dict = dict
|
747
|
+
if 'model_terms' in kwargs:
|
748
|
+
|
749
|
+
if kwargs.get('model_terms').get('group') is not None:
|
750
|
+
kwargs['group'] = kwargs.get('model_terms').get('group')
|
751
|
+
|
752
|
+
if kwargs.get('model_terms').get('panels') is not None:
|
753
|
+
kwargs['panels'] = kwargs.get('model_terms').get('panels')
|
754
|
+
acceptable_keys_list = ['_par', '_max_imp', '_hmcr', 'steps',
|
755
|
+
'algorithm', '_random_seed', '_max_time',
|
756
|
+
'forcedvariables', '_obj_1', '_obj_2', '_par',
|
757
|
+
'Manuel_Estimate', 'test_percentage', 'is_multi', 'val_percentage'
|
758
|
+
'complexity_level', '_hms', '_mpai',
|
759
|
+
'group', '_max_characteristics', 'zi_force_names']
|
760
|
+
for k in kwargs.keys():
|
761
|
+
if k in acceptable_keys_list:
|
762
|
+
self.__setattr__(k, self.tryeval(kwargs[k]))
|
763
|
+
|
764
|
+
|
765
|
+
if 'complexity_level' in kwargs:
|
766
|
+
self.complexity_level = kwargs['complexity_level']
|
767
|
+
|
768
|
+
if 'instance_name' in kwargs:
|
769
|
+
self.instance_name = str(kwargs['instance_name'])
|
770
|
+
else:
|
771
|
+
|
772
|
+
print('no name set, setting name as 0')
|
773
|
+
self.instance_name = f"run_{str(0)}" # set an arbitrary instance number
|
774
|
+
|
775
|
+
if kwargs.get('save_directory', True):
|
776
|
+
self.save_state = True
|
777
|
+
if not os.path.exists(self.instance_name):
|
778
|
+
if kwargs.get('make_directory', True):
|
779
|
+
print('Making a Directory, if you want to stop from storing the files to this directory set argumet: make_directory:False')
|
780
|
+
os.makedirs(self.instance_name)
|
781
|
+
else:
|
782
|
+
self.save_state = False
|
783
|
+
if not hasattr(self, '_obj_1'):
|
784
|
+
print('_obj_1 required, define as bic, aic, ll')
|
785
|
+
raise Exception
|
786
|
+
|
787
|
+
self.pvalue_penalty = float(kwargs.get('pvalue_penalty', 0.5))
|
788
|
+
self.pvalue_exceed = 0
|
789
|
+
self._maximize = False # do we maximize or minimize?
|
790
|
+
|
791
|
+
x_data = sm.add_constant(x_data)
|
792
|
+
standardize_the_data = 0
|
793
|
+
if standardize_the_data:
|
794
|
+
print('we are standardize the data')
|
795
|
+
x_data = self.self_standardize_positive(x_data)
|
424
796
|
|
797
|
+
self._input_data(x_data, y_data)
|
798
|
+
|
799
|
+
|
800
|
+
if y_data.ndim == 1:
|
801
|
+
y_data = pd.DataFrame(y_data)
|
802
|
+
|
803
|
+
'''
|
804
|
+
#TODO ADD THIS IN LATER
|
805
|
+
splitter = DataProcessor(x_data, y_data, kwargs)
|
806
|
+
self.copy_class_attributes(splitter) #inherit the self objects
|
807
|
+
'''
|
808
|
+
|
809
|
+
|
810
|
+
result = self.handle_data_splitting(x_data, y_data, kwargs)
|
811
|
+
if result[0] is not None: # Check if splitting was done
|
812
|
+
self.df_train, self.df_test, self.y_train, self.y_test = result
|
813
|
+
#self.n_obs = N
|
814
|
+
self._characteristics_names = list(self._x_data.columns)
|
815
|
+
self._max_group_all_means = 2
|
816
|
+
|
817
|
+
exclude_this_test = [4]
|
818
|
+
|
819
|
+
|
820
|
+
# Other initialization logic...
|
821
|
+
#TODO CHECK THIS IS RIGHT
|
822
|
+
self.process_panels_and_groups(self.df_train, self.df_test, self.y_train, self.y_test, kwargs)
|
425
823
|
#Define the offset into the data
|
426
824
|
self.process_offset()
|
427
825
|
if self.is_multi:
|
@@ -534,8 +932,7 @@ class ObjectiveFunction(object):
|
|
534
932
|
len(self._discrete_values) # TODO have continus
|
535
933
|
self._upper_bounds = [None] * \
|
536
934
|
len(self._discrete_values) # TODO have continous
|
537
|
-
|
538
|
-
self.endog = None
|
935
|
+
|
539
936
|
# solution parameters
|
540
937
|
self._min_characteristics = kwargs.get('_min_vars', 3)
|
541
938
|
self._max_hurdle = 4
|
@@ -561,7 +958,221 @@ class ObjectiveFunction(object):
|
|
561
958
|
# Update the _model_type_codes list
|
562
959
|
self._model_type_codes = replace_nb_with_sigma(self._model_type_codes)
|
563
960
|
|
961
|
+
def process_panels_and_groups(self, df_train, df_test, y_train, y_test, kwargs):
|
962
|
+
"""
|
963
|
+
Process panels and groups for grouped random parameters.
|
964
|
+
|
965
|
+
Args:
|
966
|
+
df_train (DataFrame): Training feature data.
|
967
|
+
df_test (DataFrame): Testing feature data.
|
968
|
+
y_train (DataFrame): Training target data.
|
969
|
+
y_test (DataFrame): Testing target data.
|
970
|
+
kwargs (dict): Keyword arguments with configurations.
|
971
|
+
|
972
|
+
Returns:
|
973
|
+
None. Updates instance variables for panel processing.
|
974
|
+
"""
|
975
|
+
|
976
|
+
|
977
|
+
if 'panels' in kwargs and kwargs.get('panels') is not None:
|
978
|
+
# Extract panel and group information
|
979
|
+
self.panels = np.asarray(df_train[kwargs['panels']])
|
980
|
+
self.panels_test = np.asarray(df_test[kwargs['panels']])
|
981
|
+
self.ids = np.asarray(df_train[kwargs['panels']])
|
982
|
+
self.ids_test = np.asarray(df_test[kwargs['panels']])
|
983
|
+
|
984
|
+
# Process group information if provided
|
985
|
+
if kwargs.get('group') is not None:
|
986
|
+
groupll = np.asarray(df_train[kwargs['group']].astype('category').cat.codes)
|
987
|
+
group_test = np.asarray(df_test[kwargs['group']].astype('category').cat.codes)
|
988
|
+
else:
|
989
|
+
groupll = None
|
990
|
+
|
991
|
+
# Arrange data in long format
|
992
|
+
X, Y, panel, group = self._arrange_long_format(df_train, y_train, self.ids, self.ids, groupll)
|
993
|
+
self.group_halton = group.copy()
|
994
|
+
self.group_dummies = pd.get_dummies(group)
|
995
|
+
|
996
|
+
# Balance panels for training data
|
997
|
+
Xnew, Ynew, panel_info = self._balance_panels(X, Y, panel)
|
998
|
+
Xnew = pd.DataFrame(Xnew, columns=X.columns)
|
999
|
+
self.panel_info = panel_info
|
1000
|
+
self.N, self.P = panel_info.shape
|
1001
|
+
|
1002
|
+
# Drop panel and group columns
|
1003
|
+
Xnew.drop(kwargs['panels'], axis=1, inplace=True)
|
1004
|
+
Xnew.drop(kwargs['group'], axis=1, inplace=True)
|
1005
|
+
|
1006
|
+
# Reshape data
|
1007
|
+
K = Xnew.shape[1]
|
1008
|
+
self._characteristics_names = list(Xnew.columns)
|
1009
|
+
XX = Xnew.values.reshape(self.N, self.P, K).astype('float')
|
1010
|
+
YY = Ynew.values.reshape(self.N, self.P, 1).astype('float')
|
1011
|
+
|
1012
|
+
self._x_data = XX.copy()
|
1013
|
+
self._y_data = YY.copy()
|
1014
|
+
|
1015
|
+
# Process test data
|
1016
|
+
X, Y, panel, group = self._arrange_long_format(df_test, y_test, self.ids_test, self.panels_test, group_test)
|
1017
|
+
if np.max(group) > 50:
|
1018
|
+
exclude_this_test = [4]
|
1019
|
+
self._max_group_all_means = 0
|
1020
|
+
else:
|
1021
|
+
exclude_this_test = []
|
1022
|
+
|
1023
|
+
self.group_halton_test = group.copy()
|
1024
|
+
X, Y, panel_info = self._balance_panels(X, Y, panel)
|
1025
|
+
X.drop(kwargs['panels'], axis=1, inplace=True)
|
1026
|
+
X.drop(kwargs['group'], axis=1, inplace=True)
|
1027
|
+
|
1028
|
+
# Reshape test data
|
1029
|
+
self.N_test, self.P_test = panel_info.shape
|
1030
|
+
self.G = 1
|
1031
|
+
self._Gnum = self.group_dummies.shape[2]
|
1032
|
+
self.group_dummies_test = pd.get_dummies(group).values.reshape(self.N_test, self.P_test, -1)
|
1033
|
+
|
1034
|
+
K = X.shape[1]
|
1035
|
+
self.columns_names = X.columns
|
1036
|
+
X = X.values.reshape(self.N_test, self.P_test, K).astype('float')
|
1037
|
+
Y = Y.values.reshape(self.N_test, self.P_test, 1).astype('float')
|
1038
|
+
|
1039
|
+
self._x_data_test = X.copy()
|
1040
|
+
self.y_data_test = Y.copy()
|
1041
|
+
self.y_data_test = self.y_data_test.astype('float')
|
1042
|
+
|
1043
|
+
# Update shape attributes
|
1044
|
+
self._samples, self._panels, self._characteristics = self._x_data.shape
|
1045
|
+
|
1046
|
+
else:
|
1047
|
+
print('No Panels. Grouped Random Parameters Will not be estimated')
|
1048
|
+
# Handle case with no panels
|
1049
|
+
self.G = None
|
1050
|
+
self._Gnum = 1
|
1051
|
+
self._max_group_all_means = 0
|
1052
|
+
self.ids = np.asarray(df_train.index)
|
1053
|
+
self.ids_test = np.asarray(df_test.index)
|
1054
|
+
|
1055
|
+
# Arrange and balance training data
|
1056
|
+
groupll = None
|
1057
|
+
X, Y, panel, group = self._arrange_long_format(df_train, y_train, self.ids, self.ids, groupll)
|
1058
|
+
Xnew, Ynew, panel_info = self._balance_panels(X, Y, panel)
|
1059
|
+
self.panel_info = panel_info
|
1060
|
+
self.N, self.P = panel_info.shape
|
1061
|
+
|
1062
|
+
K = Xnew.shape[1]
|
1063
|
+
self._characteristics_names = list(Xnew.columns)
|
1064
|
+
XX = Xnew.values.reshape(self.N, self.P, K).astype('float')
|
1065
|
+
YY = Ynew.values.reshape(self.N, self.P, 1).astype('float')
|
1066
|
+
|
1067
|
+
self._x_data = XX.copy()
|
1068
|
+
self._y_data = YY.copy()
|
1069
|
+
|
1070
|
+
# Arrange and balance test data if multi-objective optimization is enabled
|
1071
|
+
if self.is_multi:
|
1072
|
+
X, Y, panel, group = self._arrange_long_format(df_test, y_test, self.ids_test, self.ids_test, None)
|
1073
|
+
if np.max(group) > 50:
|
1074
|
+
exclude_this_test = [4]
|
1075
|
+
else:
|
1076
|
+
exclude_this_test = []
|
1077
|
+
|
1078
|
+
X, Y, panel_info = self._balance_panels(X, Y, panel)
|
1079
|
+
self.N_test, self.P_test = panel_info.shape
|
1080
|
+
K = X.shape[1]
|
1081
|
+
self.columns_names = X.columns
|
1082
|
+
X = X.values.reshape(self.N_test, self.P_test, K).astype('float')
|
1083
|
+
Y = Y.values.reshape(self.N_test, self.P_test, 1).astype('float')
|
1084
|
+
|
1085
|
+
self._x_data_test = X.copy()
|
1086
|
+
self.y_data_test = Y.copy()
|
1087
|
+
|
1088
|
+
# Update shape attributes
|
1089
|
+
self._samples, self._panels, self._characteristics = self._x_data.shape
|
1090
|
+
|
1091
|
+
def handle_data_splitting(self, x_data, y_data, kwargs):
|
1092
|
+
"""
|
1093
|
+
Handle data splitting for training and testing based on objectives and panels.
|
1094
|
+
|
1095
|
+
Args:
|
1096
|
+
x_data (DataFrame): Input feature data.
|
1097
|
+
y_data (DataFrame): Input target data.
|
1098
|
+
kwargs (dict): Dictionary of configuration options.
|
1099
|
+
|
1100
|
+
Returns:
|
1101
|
+
tuple: (df_train, df_test, y_train, y_test) - Split datasets.
|
1102
|
+
"""
|
1103
|
+
|
1104
|
+
|
1105
|
+
# Check if the objectives involve multi-objective metrics
|
1106
|
+
if self._obj_1 == 'MAE' or self._obj_2 in ["MAE", "RMSE", "MSE", "RMSE_IN", "RMSE_TEST"]:
|
1107
|
+
# Retrieve test and validation percentages
|
1108
|
+
self.test_percentage = float(kwargs.get('test_percentage', 0))
|
1109
|
+
self.val_percentage = float(kwargs.get('val_percentage', 0))
|
1110
|
+
|
1111
|
+
# Handle zero test percentage
|
1112
|
+
if self.test_percentage == 0:
|
1113
|
+
print("Test percentage is 0. Please provide 'test_percentage' as a decimal (e.g., 0.8) for multi-objective optimization.")
|
1114
|
+
print("Continuing with single-objective optimization.")
|
1115
|
+
time.sleep(2)
|
1116
|
+
self.is_multi = False
|
1117
|
+
|
1118
|
+
# Handle panels if provided
|
1119
|
+
if 'panels' in kwargs and kwargs.get('panels') is not None:
|
1120
|
+
# Handle group information if provided
|
1121
|
+
if kwargs.get('group') is not None:
|
1122
|
+
self.group_names = np.asarray(x_data[kwargs['group']].astype('category').cat.categories)
|
1123
|
+
x_data[kwargs['group']] = x_data[kwargs['group']].astype('category').cat.codes
|
1124
|
+
|
1125
|
+
# Set complexity level
|
1126
|
+
self.complexity_level = 6
|
1127
|
+
|
1128
|
+
# Prepare test and training dataset splits based on panels
|
1129
|
+
try:
|
1130
|
+
x_data[kwargs['panels']] = x_data[kwargs['panels']].rank(method='dense').astype(int)
|
1131
|
+
x_data[kwargs['panels']] -= x_data[kwargs['panels']].min() - 1
|
1132
|
+
|
1133
|
+
N = len(np.unique(x_data[kwargs['panels']].values))
|
1134
|
+
id_unique = np.unique(x_data[kwargs['panels']].values)
|
1135
|
+
except KeyError:
|
1136
|
+
N = len(np.unique(x_data[kwargs['panels']]))
|
1137
|
+
id_unique = np.unique(x_data[kwargs['panels']].values)
|
1138
|
+
|
1139
|
+
# Calculate training size and split IDs
|
1140
|
+
training_size = int((1 - self.test_percentage - self.val_percentage) * N)
|
1141
|
+
ids = np.random.choice(N, training_size, replace=False)
|
1142
|
+
ids = id_unique[ids]
|
1143
|
+
|
1144
|
+
# Create training and testing indices
|
1145
|
+
train_idx = [ii for ii, id_val in enumerate(x_data[kwargs['panels']]) if id_val in ids]
|
1146
|
+
test_idx = [ii for ii, id_val in enumerate(x_data[kwargs['panels']]) if id_val not in ids]
|
1147
|
+
|
1148
|
+
# Split datasets
|
1149
|
+
df_train = x_data.loc[train_idx, :]
|
1150
|
+
df_test = x_data.loc[test_idx, :]
|
1151
|
+
y_train = y_data.loc[train_idx, :]
|
1152
|
+
y_test = y_data.loc[test_idx, :]
|
1153
|
+
else:
|
1154
|
+
# Handle case when panels are not provided
|
1155
|
+
N = len(x_data)
|
1156
|
+
training_size = int((1 - self.test_percentage - self.val_percentage) * N)
|
1157
|
+
ids = np.random.choice(N, training_size, replace=False)
|
1158
|
+
id_unique = np.array([i for i in range(N)])
|
1159
|
+
ids = id_unique[ids]
|
1160
|
+
|
1161
|
+
# Create training and testing indices
|
1162
|
+
train_idx = [ii for ii in range(len(id_unique)) if id_unique[ii] in ids]
|
1163
|
+
test_idx = [ii for ii in range(len(id_unique)) if id_unique[ii] not in ids]
|
1164
|
+
|
1165
|
+
# Split datasets
|
1166
|
+
df_train = x_data.loc[train_idx, :]
|
1167
|
+
df_test = x_data.loc[test_idx, :]
|
1168
|
+
y_train = y_data.loc[train_idx, :]
|
1169
|
+
y_test = y_data.loc[test_idx, :]
|
1170
|
+
|
1171
|
+
return df_train, df_test, y_train, y_test
|
564
1172
|
|
1173
|
+
else:
|
1174
|
+
print("No multi-objective metrics detected. No data splitting performed.")
|
1175
|
+
return None, None, None, None
|
565
1176
|
def over_ride_self(self, **kwargs):
|
566
1177
|
"""
|
567
1178
|
Dynamically sets attributes on the instance based on the provided keyword arguments.
|
@@ -2774,27 +3385,6 @@ class ObjectiveFunction(object):
|
|
2774
3385
|
def get_termination_iter(self):
|
2775
3386
|
return self._max_iterations_improvement
|
2776
3387
|
|
2777
|
-
def score(self, params):
|
2778
|
-
"""
|
2779
|
-
Poisson model score (gradient) vector of the log-likelihood
|
2780
|
-
Parameters
|
2781
|
-
----------
|
2782
|
-
params : array_like
|
2783
|
-
The parameters of the model
|
2784
|
-
Returns
|
2785
|
-
-------
|
2786
|
-
score : ndarray, 1-D
|
2787
|
-
The score vector of the model, i.e. the first derivative of the
|
2788
|
-
loglikelihood function, evaluated at `params`
|
2789
|
-
Notes
|
2790
|
-
-----
|
2791
|
-
.. math:: \\frac{\\partial\\ln L}{\\partial\\beta}=\\sum_{i=1}^{n}\\left(y_{i}-\\lambda_{i}\\right)x_{i}
|
2792
|
-
where the loglinear model is assumed
|
2793
|
-
.. math:: \\ln\\lambda_{i}=x_{i}\\beta
|
2794
|
-
"""
|
2795
|
-
X = self.exog
|
2796
|
-
L = np.exp(np.dot(X, params))
|
2797
|
-
return np.dot(self.endog - L, X)
|
2798
3388
|
|
2799
3389
|
def GenPos_Score(self, params, y, mu, X, p=0, obs_specific=False):
|
2800
3390
|
|
@@ -3020,68 +3610,7 @@ class ObjectiveFunction(object):
|
|
3020
3610
|
print(exc_type, fname, exc_tb.tb_lineno)
|
3021
3611
|
raise Exception
|
3022
3612
|
|
3023
|
-
def NB_score_lindley(self, params, y, mu, X, Q=0, obs_specific=False):
|
3024
|
-
"""
|
3025
|
-
Calculate the score (gradient) vector of the Negative Binomial-Lindley log-likelihood
|
3026
|
-
Parameters
|
3027
|
-
----------
|
3028
|
-
params : array_like
|
3029
|
-
The parameters of the model
|
3030
|
-
params[-1]: is the dispersion parameter
|
3031
|
-
y: array_like
|
3032
|
-
Vector of true counts N long
|
3033
|
-
mu: array_like
|
3034
|
-
Vector of predicted counts N long
|
3035
|
-
X: array_like
|
3036
|
-
Matrix of explanatory variables len N* (D-1)
|
3037
|
-
a: float or None, optional
|
3038
|
-
Optional parameter, if not None the function calculates the score for the NB-Lindley model with Lindley parameter a,
|
3039
|
-
otherwise, it calculates the score for the Negative Binomial model.
|
3040
|
-
Returns
|
3041
|
-
-------
|
3042
|
-
score : ndarray, 1-D
|
3043
|
-
The score vector of the model, i.e. the first derivative of the
|
3044
|
-
loglikelihood function, evaluated at `params`
|
3045
|
-
"""
|
3046
|
-
|
3047
|
-
alpha = params[-1]
|
3048
|
-
a = params[-2]
|
3049
|
-
a1 = 1 / alpha * mu
|
3050
|
-
prob = a1 / (a1 + mu)
|
3051
|
-
exog = X
|
3052
|
-
|
3053
|
-
# Calculate the score of the Negative Binomial model
|
3054
|
-
dgpart = sc.digamma(y + alpha * mu) - sc.digamma(alpha * mu)
|
3055
|
-
dparams = exog * alpha * (np.log(prob) + dgpart)
|
3056
|
-
dalpha = ((alpha * (y - mu * np.log(prob) -
|
3057
|
-
mu * (dgpart + 1)) -
|
3058
|
-
mu * (np.log(prob) +
|
3059
|
-
dgpart)) /
|
3060
|
-
(alpha ** 2 * (alpha + 1)))
|
3061
|
-
|
3062
|
-
# If a is not None, calculate the score of the NB-Lindley model
|
3063
|
-
if a is not None:
|
3064
|
-
a1 = (1 + a) / (alpha + a + mu)
|
3065
|
-
prob = a1 / (a1 + mu)
|
3066
|
-
dgpart = sc.digamma(y + alpha * mu + a) - \
|
3067
|
-
sc.digamma(alpha * mu + a)
|
3068
|
-
dparams_lindley = exog * (alpha + a) * (np.log(prob) + dgpart)
|
3069
|
-
dalpha_lindley = (((alpha + a) * (y - mu * np.log(prob) -
|
3070
|
-
mu * (dgpart + 1)) -
|
3071
|
-
mu * (np.log(prob) +
|
3072
|
-
dgpart)) /
|
3073
|
-
((alpha + a) ** 2 * (alpha + a + 1)))
|
3074
|
-
|
3075
|
-
if obs_specific is False:
|
3076
|
-
return np.r_[dparams.sum(0), dalpha_lindley.sum(), dalpha.sum()]
|
3077
|
-
# return np.r_[dparams.sum(0) + dparams_lindley.sum(0), dalpha_lindley.sum(), dalpha.sum()]
|
3078
|
-
else:
|
3079
|
-
return np.concatenate((dparams, dalpha_lindley, dalpha), axis=1)
|
3080
|
-
# return np.concatenate((dparams + dparams_lindley, dalpha_lindley, dalpha), axis=1)
|
3081
|
-
# return np.r_[dparams.sum(0), dalpha, dparams_lindley.sum(0), dalpha_lindley]
|
3082
3613
|
|
3083
|
-
else:
|
3084
|
-
return np.r_[dparams.sum(0), dalpha]
|
3085
3614
|
|
3086
3615
|
def PoissonNegLogLikelihood(self, lam, y, penalty=0, X=None):
|
3087
3616
|
"""computers the negative log-likelihood for a poisson random variable"""
|
@@ -3173,71 +3702,7 @@ class ObjectiveFunction(object):
|
|
3173
3702
|
p = np.exp(-ltheta)
|
3174
3703
|
return r, p
|
3175
3704
|
|
3176
|
-
def negative_binomial_lindley_pmf(self, y, r, theta2, mu):
|
3177
|
-
"""
|
3178
|
-
Calculate the probability mass function (PMF) of the Negative Binomial Lindley (NB-L) distribution
|
3179
|
-
for a given count y, mean lambda, dispersion r, shape alpha, and scale beta.
|
3180
|
-
|
3181
|
-
Parameters:
|
3182
|
-
y (int or array-like): The count(s) of interest.
|
3183
|
-
mu (float): The mean parameter of the Negative Binomial distribution.
|
3184
|
-
r (float): The dispersion parameter of the Negative Binomial distribution.
|
3185
|
-
theta2: The shape parameter of the Lindley distribution.
|
3186
|
-
|
3187
|
-
|
3188
|
-
Returns:
|
3189
|
-
pmf (float or ndarray): The probability mass function evaluated at the count(s) y.
|
3190
|
-
"""
|
3191
|
-
|
3192
|
-
theta = self.my_lindley(y, theta2)
|
3193
|
-
mu1 = mu * theta
|
3194
|
-
|
3195
|
-
var = mu1 + 1 / r * mu1 ** 2
|
3196
|
-
p = (var - mu1) / var
|
3197
|
-
numerator = math.comb(r + y.ravel() - 1.0, y.ravel()
|
3198
|
-
) * ((theta ** 2) / (theta + 1))
|
3199
|
-
denominator = 0
|
3200
|
-
for j in range(y + 1):
|
3201
|
-
denominator += math.comb(y, j) * ((-1) ** j) * \
|
3202
|
-
((theta + r + j + 1) / ((theta + r + j) ** 2))
|
3203
|
-
|
3204
|
-
please = numerator / denominator * p ** y * (1 - p) ** r
|
3205
|
-
return please
|
3206
|
-
|
3207
|
-
def negative_binomial_lindley_pmf_gradient(self, y, r, theta2, mu):
|
3208
|
-
"""
|
3209
|
-
Calculate the gradient of the probability mass function (PMF) of the Negative Binomial Lindley (NB-L)
|
3210
|
-
distribution for a given count y, mean lambda, dispersion r, shape alpha, and scale beta.
|
3211
|
-
|
3212
|
-
Parameters:
|
3213
|
-
y (int or array-like): The count(s) of interest.
|
3214
|
-
mu (float): The mean parameter of the Negative Binomial distribution.
|
3215
|
-
r (float): The dispersion parameter of the Negative Binomial distribution.
|
3216
|
-
theta2: The shape parameter of the Lindley distribution.
|
3217
|
-
|
3218
|
-
|
3219
|
-
Returns:
|
3220
|
-
gradient (ndarray): The gradient of the probability mass function evaluated at the count(s) y.
|
3221
|
-
"""
|
3222
3705
|
|
3223
|
-
theta = self.my_lindley(y, theta2)
|
3224
|
-
mu = mu * mu + theta
|
3225
|
-
var = mu + 1 / r * mu ** 2
|
3226
|
-
p = (var - mu) / var
|
3227
|
-
numerator = math.comb(r + y - 1, y) * ((theta ** 2) / (theta + 1))
|
3228
|
-
denominator = 0
|
3229
|
-
for j in range(y + 1):
|
3230
|
-
denominator += math.comb(y, j) * ((-1) ** j) * \
|
3231
|
-
((theta + r + j + 1) / ((theta + r + j) ** 2))
|
3232
|
-
|
3233
|
-
dtheta = numerator * (y * (2 * theta + 1) - theta * (theta + 1)) / denominator ** 2
|
3234
|
-
dmu = (y - mu) * p / (1 - p)
|
3235
|
-
dr = -r ** 2 / var + r / var * (y - r * mu / (1 - p))
|
3236
|
-
dtheta2 = theta * (y * (theta + 1) / (theta + 1 + mu) -
|
3237
|
-
(theta2 + 1) / (theta2 + mu)) / denominator
|
3238
|
-
|
3239
|
-
gradient = np.array([dtheta2, dmu, dr])
|
3240
|
-
return gradient
|
3241
3706
|
|
3242
3707
|
def dnbl(self, x, r, theta):
|
3243
3708
|
|
@@ -4041,48 +4506,7 @@ class ObjectiveFunction(object):
|
|
4041
4506
|
eVd = np.exp(np.clip(eta, None, EXP_UPPER_LIMIT))
|
4042
4507
|
return eVd
|
4043
4508
|
|
4044
|
-
|
4045
|
-
from scipy._lib._util import _lazywhere
|
4046
|
-
from statsmodels.discrete.discrete_model import Logit
|
4047
|
-
self.k_inflate = k_inflate
|
4048
|
-
self.exog = exog.to_numpy()
|
4049
|
-
self.endog = y_values.values.ravel()
|
4050
|
-
exog = exog.to_numpy()
|
4051
|
-
exog_infl = exog_infl.to_numpy()
|
4052
|
-
|
4053
|
-
def _argcheck(self, mu, alpha, p):
|
4054
|
-
return (mu >= 0) & (alpha == alpha) & (p > 0)
|
4055
|
-
|
4056
|
-
def loglik_obs_poisson(params, y):
|
4057
|
-
"""
|
4058
|
-
Loglikelihood for observations of Poisson model
|
4059
|
-
|
4060
|
-
Parameters
|
4061
|
-
----------
|
4062
|
-
params : array_like
|
4063
|
-
The parameters of the model.
|
4064
|
-
|
4065
|
-
Returns
|
4066
|
-
-------
|
4067
|
-
loglike : array_like
|
4068
|
-
The log likelihood for each observation of the model evaluated
|
4069
|
-
at `params`. See Notes
|
4070
|
-
|
4071
|
-
Notes
|
4072
|
-
-----
|
4073
|
-
.. math:: \\ln L_{i}=\\left[-\\lambda_{i}+y_{i}x_{i}^{\\prime}\\beta-\\ln y_{i}!\\right]
|
4074
|
-
|
4075
|
-
for observations :math:`i=1,...,n`
|
4076
|
-
"""
|
4077
|
-
offset = getattr(self, "offset", 0)
|
4078
|
-
exposure = getattr(self, "exposure", 0)
|
4079
|
-
XB = np.dot(self.exog, params) + offset + exposure
|
4080
|
-
|
4081
|
-
# np.sum(stats.poisson.logpmf(endog, np.exp(XB)))
|
4082
|
-
return -np.exp(XB) + y * XB - sc.gammaln(y + 1)
|
4083
|
-
|
4084
|
-
|
4085
|
-
|
4509
|
+
|
4086
4510
|
def dpoisl(self, x, theta, log=False):
|
4087
4511
|
# if theta < 0:
|
4088
4512
|
# raise ValueError("theta must be positive!")
|
@@ -4205,6 +4629,43 @@ class ObjectiveFunction(object):
|
|
4205
4629
|
pch[pch == 0] = 0.00001
|
4206
4630
|
return pch
|
4207
4631
|
|
4632
|
+
|
4633
|
+
|
4634
|
+
|
4635
|
+
|
4636
|
+
|
4637
|
+
def compute_gradient_central(self, betas, Xd, y, draws=None, Xf=None, Xr=None, batch_size=None, return_gradient=False,
|
4638
|
+
return_gradient_n=False, dispersion=0, test_set=0, return_EV=False, verbose=0,
|
4639
|
+
corr_list=None, zi_list=None, exog_infl=None, draws_grouped=None, Xgroup=None,
|
4640
|
+
model_nature=None, kwarg=None, **kwargs)->np.ndarray:
|
4641
|
+
# {
|
4642
|
+
params = np.array(betas)
|
4643
|
+
|
4644
|
+
delta = np.ones_like(params) * 1e-5 #
|
4645
|
+
gradient = np.zeros_like(params) # create an array
|
4646
|
+
for i in range(len(params)):
|
4647
|
+
# {
|
4648
|
+
orig = params[i]
|
4649
|
+
params[i] = orig + delta[i]
|
4650
|
+
case_1 = self._loglik_gradient(
|
4651
|
+
params, Xd, y, draws=draws, Xf=Xf, Xr=Xr, batch_size=batch_size, return_gradient=return_gradient,
|
4652
|
+
return_gradient_n=return_gradient_n, dispersion=dispersion, test_set=test_set, return_EV=return_EV,
|
4653
|
+
verbose=verbose, corr_list=corr_list, zi_list=zi_list, exog_infl=exog_infl, draws_grouped=draws_grouped,
|
4654
|
+
Xgroup=Xgroup, model_nature=model_nature, kwarg=kwarg, **kwargs
|
4655
|
+
)
|
4656
|
+
params[i] = orig - delta[i]
|
4657
|
+
case_2 = self._loglik_gradient(
|
4658
|
+
params, Xd, y, draws=draws, Xf=Xf, Xr=Xr, batch_size=batch_size, return_gradient=return_gradient,
|
4659
|
+
return_gradient_n=return_gradient_n, dispersion=dispersion, test_set=test_set, return_EV=return_EV,
|
4660
|
+
verbose=verbose, corr_list=corr_list, zi_list=zi_list, exog_infl=exog_infl, draws_grouped=draws_grouped,
|
4661
|
+
Xgroup=Xgroup, model_nature=model_nature, kwarg=kwarg, **kwargs
|
4662
|
+
)
|
4663
|
+
params[i] = orig # restore value
|
4664
|
+
gradient[i] = (case_1 - case_2) / (2.0 * delta[i])
|
4665
|
+
# }
|
4666
|
+
return gradient
|
4667
|
+
|
4668
|
+
|
4208
4669
|
def gradient_calc_est(self, N, Kf, Kr, Kchol, dispersion, proba_n, eVd, br, brstd, draws_, Xdf, Xdr, y, R, lik,
|
4209
4670
|
alpha=0.5, betas=None, Br=None, panels=None, model_nature=None, br_h=None, br_hs=None):
|
4210
4671
|
|
@@ -4451,7 +4912,7 @@ class ObjectiveFunction(object):
|
|
4451
4912
|
(self._group_Y[key].ravel() - sub_eVd[i].ravel())[:, None] * Xd[key])
|
4452
4913
|
|
4453
4914
|
# todo make dummies with grouped
|
4454
|
-
|
4915
|
+
grad_g = np.concatenate(der_list, axis=0)
|
4455
4916
|
grad_n = np.concatenate(der_n, axis=1)
|
4456
4917
|
grad = grad_n.sum(axis=0)
|
4457
4918
|
# grad = grad_n.sum(axis = 1)
|
@@ -4467,17 +4928,22 @@ class ObjectiveFunction(object):
|
|
4467
4928
|
der = grad_n.sum(axis=0)
|
4468
4929
|
# to do prob product arcross panel
|
4469
4930
|
|
4470
|
-
return np.nan_to_num(der, nan=
|
4471
|
-
posinf=
|
4472
|
-
neginf=-
|
4931
|
+
return np.nan_to_num(der, nan=200, posinf=200, neginf=-200), np.nan_to_num(grad_n, nan=200,
|
4932
|
+
posinf=200,
|
4933
|
+
neginf=-200)
|
4473
4934
|
|
4474
4935
|
if obs_specific:
|
4475
4936
|
grad_n_p = (y - eVd)[:, :, :] * Xd
|
4476
4937
|
grad_n = self._prob_product_across_panels(grad_n_p, self.panel_info)
|
4477
4938
|
der = grad_n.sum(axis=0)
|
4478
|
-
return np.nan_to_num(der, nan=
|
4939
|
+
return np.nan_to_num(der, nan=200, posinf=200, neginf=-200)
|
4479
4940
|
else:
|
4941
|
+
n, p, k = Xd.shape
|
4480
4942
|
grad_n_p = (y - eVd)[:, :, :] * Xd
|
4943
|
+
#residual = (y - eVd).squeeze(axis = -1)
|
4944
|
+
# grad = np.zeros(k)
|
4945
|
+
#for j in range(p):
|
4946
|
+
# grad += Xd[:, j, :].T @ residual[:, j] # Shape: (k,)
|
4481
4947
|
grad_n = self._prob_product_across_panels(grad_n_p, self.panel_info)
|
4482
4948
|
der = grad_n.sum(axis=0)
|
4483
4949
|
|
@@ -4497,11 +4963,7 @@ class ObjectiveFunction(object):
|
|
4497
4963
|
y, eVd, Xd, obs_specific=True)
|
4498
4964
|
return np.nan_to_num(der, nan=200, posinf=200, neginf=-200), np.nan_to_num(grad_n, nan=140, posinf=140,
|
4499
4965
|
neginf=-140)
|
4500
|
-
elif dispersion == 3:
|
4501
|
-
|
4502
|
-
der, grad_n = self.poisson_lindley_gradient(betas, Xd, y)
|
4503
4966
|
|
4504
|
-
return der, grad_n
|
4505
4967
|
|
4506
4968
|
|
4507
4969
|
elif dispersion == 'poisson_lognormal':
|
@@ -4509,7 +4971,7 @@ class ObjectiveFunction(object):
|
|
4509
4971
|
der, grad_n = self.poisson_lognormal_glm_score(betas, y, Xd, sig)
|
4510
4972
|
return der, grad_n
|
4511
4973
|
|
4512
|
-
return np.nan_to_num(der, nan=
|
4974
|
+
return np.nan_to_num(der, nan=200, posinf=200, neginf=-200)
|
4513
4975
|
|
4514
4976
|
def prob_obs_draws(self, eVi, y, disp, dispersion=0.0, disp2=0):
|
4515
4977
|
|
@@ -4523,12 +4985,10 @@ class ObjectiveFunction(object):
|
|
4523
4985
|
|
4524
4986
|
proba_r = self.general_poisson_pmf(eVi, y, disp)
|
4525
4987
|
|
4526
|
-
|
4527
|
-
proba_r = self.poisson_lindley_pmf(eVi, disp2, y)
|
4988
|
+
|
4528
4989
|
# proba_r = self.dpoisl(y, eVi)
|
4529
4990
|
|
4530
|
-
|
4531
|
-
proba_r = self.dnegbimonli(y, eVi, disp)
|
4991
|
+
|
4532
4992
|
|
4533
4993
|
else:
|
4534
4994
|
raise Exception
|
@@ -4810,13 +5270,13 @@ class ObjectiveFunction(object):
|
|
4810
5270
|
if self.is_dispersion(dispersion):
|
4811
5271
|
penalty, main_disper = self._penalty_dispersion(dispersion, main_disper, eVd, y, penalty,
|
4812
5272
|
model_nature)
|
4813
|
-
b_pen = self.custom_betas_to_penalise(betas, dispersion)
|
4814
|
-
penalty = self.regularise_l2(betas) + self.regularise_l1(betas)
|
4815
|
-
penalty = self.custom_penalty(betas, penalty)
|
5273
|
+
#b_pen = self.custom_betas_to_penalise(betas, dispersion)
|
5274
|
+
#penalty = self.regularise_l2(betas) + self.regularise_l1(betas)
|
5275
|
+
#penalty = self.custom_penalty(betas, penalty)
|
4816
5276
|
|
4817
5277
|
betas[-1] = main_disper
|
4818
5278
|
|
4819
|
-
b_pen = self.custom_betas_to_penalise(betas, dispersion)
|
5279
|
+
#b_pen = self.custom_betas_to_penalise(betas, dispersion)
|
4820
5280
|
penalty = self.regularise_l2(betas) + self.regularise_l1(betas)
|
4821
5281
|
penalty = self.custom_penalty(betas, penalty)
|
4822
5282
|
|
@@ -4841,7 +5301,7 @@ class ObjectiveFunction(object):
|
|
4841
5301
|
loglik += 2*loglik
|
4842
5302
|
print('am i powering up')
|
4843
5303
|
|
4844
|
-
b_pen = self.custom_betas_to_penalise(betas, dispersion)
|
5304
|
+
#b_pen = self.custom_betas_to_penalise(betas, dispersion)
|
4845
5305
|
penalty = self.regularise_l2(betas) + self.regularise_l1(betas)
|
4846
5306
|
penalty = self.custom_penalty(betas, penalty)
|
4847
5307
|
|
@@ -4855,13 +5315,26 @@ class ObjectiveFunction(object):
|
|
4855
5315
|
der, grad_n = self.simple_score_grad(
|
4856
5316
|
betas, y, eVd, Xd, dispersion, both=True)
|
4857
5317
|
#return (-loglik + penalty, -der, grad_n)*self.minimize_scaler
|
4858
|
-
scaled_tuple = tuple(x * self.minimize_scaler for x in (-loglik + penalty,
|
5318
|
+
scaled_tuple = tuple(x * self.minimize_scaler for x in (-loglik + penalty, der.ravel(), grad_n))
|
5319
|
+
|
4859
5320
|
return scaled_tuple
|
4860
5321
|
else:
|
4861
5322
|
der = self.simple_score_grad(
|
4862
5323
|
betas, y, eVd, Xd, dispersion, both=False)
|
5324
|
+
#arguments = locals() # Capture all current arguments
|
5325
|
+
#arguments["return_gradient"] = False # Change `dispersion` to 1
|
5326
|
+
#del arguments["self"] # Remove `self` from arguments (not needed in the call)
|
5327
|
+
'''
|
5328
|
+
der_alt = self.compute_gradient_central(betas, Xd, y, draws=draws, Xf=Xf, Xr=Xr, batch_size=batch_size, return_gradient=False,
|
5329
|
+
return_gradient_n=False, dispersion=dispersion, test_set=test_set, return_EV=return_EV, verbose=verbose, corr_list=corr_list,
|
5330
|
+
zi_list=zi_list, exog_infl=exog_infl, draws_grouped=draws_grouped, Xgroup=Xgroup, model_nature=model_nature, kwarg=kwarg,
|
5331
|
+
**kwargs)
|
5332
|
+
'''
|
4863
5333
|
scaled_tuple = tuple(
|
4864
5334
|
x * self.minimize_scaler for x in (-loglik + penalty, -der.ravel()))
|
5335
|
+
|
5336
|
+
|
5337
|
+
|
4865
5338
|
return scaled_tuple
|
4866
5339
|
#return (-loglik + penalty, -der.ravel())*self.minimize_scaler
|
4867
5340
|
else:
|
@@ -5203,9 +5676,7 @@ class ObjectiveFunction(object):
|
|
5203
5676
|
traceback.print_exc()
|
5204
5677
|
print(e, 'where loglik')
|
5205
5678
|
|
5206
|
-
|
5207
|
-
r'Takes the logliklihood function and tranforms it to a more handed minimization function'
|
5208
|
-
return loglike/self.n_obs
|
5679
|
+
|
5209
5680
|
def print_chol_mat(self, betas):
|
5210
5681
|
print(self.chol_mat)
|
5211
5682
|
self.get_br_and_bstd(betas)
|
@@ -5703,7 +6174,9 @@ class ObjectiveFunction(object):
|
|
5703
6174
|
coeff_ = optim_res['x']
|
5704
6175
|
penalty = 0
|
5705
6176
|
stderr_opg = None
|
5706
|
-
if self.
|
6177
|
+
if self.run_bootstrap:
|
6178
|
+
stderr_opg = self.stderr
|
6179
|
+
elif self.run_numerical_hessian:
|
5707
6180
|
|
5708
6181
|
stderr_opg = self.stderr
|
5709
6182
|
|
@@ -5717,7 +6190,8 @@ class ObjectiveFunction(object):
|
|
5717
6190
|
else:
|
5718
6191
|
covariance = np.diag(np.ones(len(optim_res.x)))
|
5719
6192
|
covariance = self.handle_covariance(covariance)
|
5720
|
-
|
6193
|
+
self
|
6194
|
+
covariance = np.clip(covariance, 0, self.N)
|
5721
6195
|
stderr = np.sqrt(np.diag(covariance))
|
5722
6196
|
if stderr_opg is not None:
|
5723
6197
|
stderr = np.minimum(stderr, stderr_opg)
|
@@ -6071,6 +6545,12 @@ class ObjectiveFunction(object):
|
|
6071
6545
|
tol=tol.get('ftol', 1e-6), # Use 'ftol' as the default tolerance
|
6072
6546
|
options=options
|
6073
6547
|
)
|
6548
|
+
|
6549
|
+
#print(result.summary())
|
6550
|
+
|
6551
|
+
|
6552
|
+
#i want to compare this to stats model.s
|
6553
|
+
|
6074
6554
|
if optimization_result.message == 'NaN result encountered.':
|
6075
6555
|
optimization_result = self._minimize(self._loglik_gradient,
|
6076
6556
|
initial_params,
|
@@ -6114,7 +6594,7 @@ class ObjectiveFunction(object):
|
|
6114
6594
|
bounds=bounds,
|
6115
6595
|
tol=tol,
|
6116
6596
|
mod=mod,
|
6117
|
-
n_bootstraps=
|
6597
|
+
n_bootstraps=6
|
6118
6598
|
)
|
6119
6599
|
self.stderr = std_errors
|
6120
6600
|
|
@@ -6260,6 +6740,7 @@ class ObjectiveFunction(object):
|
|
6260
6740
|
optimization_result, simple_fit=False, is_dispersion=dispersion
|
6261
6741
|
)
|
6262
6742
|
|
6743
|
+
|
6263
6744
|
# Validation metrics if test data is available (in-sample and out-of-sample MAE)
|
6264
6745
|
in_sample_mae = None
|
6265
6746
|
out_sample_mae = None
|
@@ -6377,7 +6858,7 @@ class ObjectiveFunction(object):
|
|
6377
6858
|
total = sum(self.get_num_params()) + dispersion_param
|
6378
6859
|
return total
|
6379
6860
|
|
6380
|
-
def _build_initial_params(self, num_coefficients, dispersion):
|
6861
|
+
def _build_initial_params(self, num_coefficients, dispersion, XX, y):
|
6381
6862
|
"""
|
6382
6863
|
Build the initial parameter array for optimization.
|
6383
6864
|
|
@@ -6389,7 +6870,27 @@ class ObjectiveFunction(object):
|
|
6389
6870
|
Initial parameter array.
|
6390
6871
|
"""
|
6391
6872
|
# Generate random initial coefficients
|
6392
|
-
|
6873
|
+
# call in statsmodels
|
6874
|
+
try:
|
6875
|
+
if dispersion ==0:
|
6876
|
+
model = sm.GLM(y.squeeze(axis=-1), XX.squeeze(axis=1), family=sm.families.Poisson())
|
6877
|
+
else:
|
6878
|
+
model = sm.NegativeBinomial(y.squeeze(axis=-1), XX.squeeze(axis=1))
|
6879
|
+
result = model.fit()
|
6880
|
+
initial_params = result.params # then exten to num_coefficients
|
6881
|
+
if len(initial_params) < num_coefficients:
|
6882
|
+
initial_params = np.concatenate([
|
6883
|
+
initial_params,
|
6884
|
+
np.random.uniform(-0.01, 0.03, size=num_coefficients - len(initial_params))
|
6885
|
+
])
|
6886
|
+
|
6887
|
+
else:
|
6888
|
+
initial_params = np.random.uniform(-0.01, 0.3, size=num_coefficients)
|
6889
|
+
except:
|
6890
|
+
print('pre fit failed')
|
6891
|
+
initial_params = np.random.uniform(-0.01, 0.01, size=num_coefficients)
|
6892
|
+
|
6893
|
+
|
6393
6894
|
parma_sum = sum(self.get_num_params()[:2])
|
6394
6895
|
|
6395
6896
|
|
@@ -6419,7 +6920,7 @@ class ObjectiveFunction(object):
|
|
6419
6920
|
try:
|
6420
6921
|
dispersion = mod.get('dispersion', dispersion)
|
6421
6922
|
# Preprocessing
|
6422
|
-
tol = {'ftol': 1e-
|
6923
|
+
tol = {'ftol': 1e-10, 'gtol': 1e-6, 'xtol': 1e-7}
|
6423
6924
|
y, X, Xr, XG, XH = mod.get('y'), mod.get('X'), mod.get('Xr'), mod.get('XG'), mod.get('XH')
|
6424
6925
|
|
6425
6926
|
# Validate input data
|
@@ -6434,7 +6935,7 @@ class ObjectiveFunction(object):
|
|
6434
6935
|
num_coefficients = self._calculate_num_coefficients(mod, dispersion)
|
6435
6936
|
|
6436
6937
|
# Build initial parameters and bounds
|
6437
|
-
initial_params = self._build_initial_params(num_coefficients, dispersion)
|
6938
|
+
initial_params = self._build_initial_params(num_coefficients, dispersion, XX, y)
|
6438
6939
|
bounds = self._set_bounds(initial_params, dispersion)
|
6439
6940
|
|
6440
6941
|
|
@@ -7575,9 +8076,11 @@ class ObjectiveFunction(object):
|
|
7575
8076
|
|
7576
8077
|
|
7577
8078
|
else:
|
7578
|
-
if self.significant == 1 and obj_1['layout'] is not None and obj_1['pval_exceed'] == 0:
|
7579
|
-
self.summary_alternative(model=dispersion, solution=obj_1)
|
7580
8079
|
|
8080
|
+
if self.significant == 1 and obj_1['layout'] is not None:
|
8081
|
+
self.summary_alternative(long_print = self.non_sig_prints, model=dispersion, solution=obj_1)
|
8082
|
+
elif self.significant == 1 and obj_1['layout'] is not None and obj_1['pval_exceed'] == 0:
|
8083
|
+
self.summary_alternative(model=dispersion, solution=obj_1)
|
7581
8084
|
return obj_1, model_nature
|
7582
8085
|
|
7583
8086
|
def get_X_tril(self):
|