metacountregressor 0.1.239__py3-none-any.whl → 0.1.310__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/helperprocess.py +43 -2
- metacountregressor/main.py +1 -1
- metacountregressor/metaheuristics.py +9 -4
- metacountregressor/solution.py +369 -65
- {metacountregressor-0.1.239.dist-info → metacountregressor-0.1.310.dist-info}/METADATA +4 -2
- {metacountregressor-0.1.239.dist-info → metacountregressor-0.1.310.dist-info}/RECORD +9 -9
- {metacountregressor-0.1.239.dist-info → metacountregressor-0.1.310.dist-info}/WHEEL +1 -1
- {metacountregressor-0.1.239.dist-info → metacountregressor-0.1.310.dist-info/licenses}/LICENSE.txt +0 -0
- {metacountregressor-0.1.239.dist-info → metacountregressor-0.1.310.dist-info}/top_level.txt +0 -0
@@ -4,7 +4,7 @@ import pandas as pd
|
|
4
4
|
import csv
|
5
5
|
import matplotlib.pyplot as plt
|
6
6
|
from scipy import stats as st
|
7
|
-
from sklearn.preprocessing import StandardScaler
|
7
|
+
from sklearn.preprocessing import StandardScaler, MinMaxScaler
|
8
8
|
import os
|
9
9
|
import shutil
|
10
10
|
plt.style.use('https://github.com/dhaitz/matplotlib-stylesheets/raw/master/pitayasmoothie-dark.mplstyle')
|
@@ -413,6 +413,10 @@ def transform_dataframe(df, config):
|
|
413
413
|
# Apply custom function
|
414
414
|
data = data.apply(settings['apply_func'])
|
415
415
|
output_df[column] = data
|
416
|
+
elif settings['type'] == 'normalized':
|
417
|
+
# Normalize the column
|
418
|
+
scaler = MinMaxScaler
|
419
|
+
output_df[column] = scaler.fit_transform(df[[column]]).flatten()
|
416
420
|
|
417
421
|
elif settings['type'] == 'none':
|
418
422
|
# Leave the column unchanged
|
@@ -447,7 +451,7 @@ def guess_column_type(column_name, series):
|
|
447
451
|
# Otherwise, fallback to continuous standardization
|
448
452
|
return {
|
449
453
|
'type': 'continuous',
|
450
|
-
'apply_func': (lambda x: (x - series.mean()) / series.std())
|
454
|
+
'apply_func': (lambda x: ((x - series.mean()) / series.std()) + abs(((series - series.mean()) / series.std()).min()) + 0.001)
|
451
455
|
}
|
452
456
|
else:
|
453
457
|
# Default fallback (leave the column unchanged)
|
@@ -539,6 +543,37 @@ def check_list_type(lst, check_type):
|
|
539
543
|
raise TypeError(f"All elements in the list must be of type {check_type}")
|
540
544
|
|
541
545
|
|
546
|
+
def plot_fitness_progress(iterations, iteration_fitnesses, best_fitnesses, average_fitness):
|
547
|
+
"""
|
548
|
+
Plots the fitness values over iterations.
|
549
|
+
|
550
|
+
Args:
|
551
|
+
iterations (list): List of iteration numbers.
|
552
|
+
iteration_fitnesses (list): List of fitness values for each iteration.
|
553
|
+
best_fitnesses (list): List of best fitness values across iterations.
|
554
|
+
average_fitness (list): List of average fitness values across iterations.
|
555
|
+
"""
|
556
|
+
plt.figure(figsize=(10, 6))
|
557
|
+
|
558
|
+
# Plot iteration fitnesses
|
559
|
+
plt.plot(iterations, iteration_fitnesses, label='Iteration Fitnesses', marker='o', color='blue')
|
560
|
+
# Plot best fitnesses
|
561
|
+
plt.plot(iterations, best_fitnesses, label='Best Fitnesses', marker='s', color='green')
|
562
|
+
# Plot average fitness
|
563
|
+
plt.plot(iterations, average_fitness, label='Average Fitness', marker='d', color='orange')
|
564
|
+
|
565
|
+
# Add labels and title
|
566
|
+
plt.xlabel('Iteration')
|
567
|
+
plt.ylabel('Fitness')
|
568
|
+
plt.title('Fitness Progression Over Iterations')
|
569
|
+
plt.legend()
|
570
|
+
plt.grid(True)
|
571
|
+
|
572
|
+
# Show the plot
|
573
|
+
plt.show()
|
574
|
+
|
575
|
+
|
576
|
+
|
542
577
|
def results_printer(results, algorithm='hs', is_multi=1, obj_1='bic', obj_2='MSE'):
|
543
578
|
if algorithm == 'hs':
|
544
579
|
plt.scatter([x['bic'] for x in results.harmony_memories], [x['MAE'] for x in results.harmony_memories])
|
@@ -565,6 +600,12 @@ def results_printer(results, algorithm='hs', is_multi=1, obj_1='bic', obj_2='MSE
|
|
565
600
|
results.iteration, results.iter_solution, results.best_solutions, results.best_fitness,
|
566
601
|
# type: ignore
|
567
602
|
results.best_struct, results.average_best)) # type: ignore
|
603
|
+
plot_fitness_progress(
|
604
|
+
iterations=results.iteration, # Replace with actual iteration numbers
|
605
|
+
iteration_fitnesses=results.iter_solution, # Replace with actual iteration fitnesses
|
606
|
+
best_fitnesses=results.best_solutions, # Replace with the best fitnesses
|
607
|
+
average_fitness=results.average_best # Replace with average fitnesses
|
608
|
+
)
|
568
609
|
elif algorithm == 'sa':
|
569
610
|
print(
|
570
611
|
'Elapsed time: {}\nIterations: {}'.format(
|
metacountregressor/main.py
CHANGED
@@ -187,7 +187,7 @@ def main(args, **kwargs):
|
|
187
187
|
a_des, df = helperprocess.set_up_analyst_constraints(df, model_terms)
|
188
188
|
# some example argument, these are defualt so the following line is just for claritity
|
189
189
|
args = {'algorithm': 'hs', 'test_percentage': 0.15, 'test_complexity': 6, 'instance_number': 1,
|
190
|
-
'val_percentage': 0.15, 'obj_1': 'bic', '_obj_2': 'RMSE_TEST', "MAX_TIME":
|
190
|
+
'val_percentage': 0.15, 'obj_1': 'bic', '_obj_2': 'RMSE_TEST', "MAX_TIME": 600, 'desicions':a_des, 'is_multi': 1}
|
191
191
|
# Fit the model with metacountregressor
|
192
192
|
# Step 5: Transform the dataset based on the configuration
|
193
193
|
#data_new = helperprocess.transform_dataframe(dataset, config)
|
@@ -236,15 +236,17 @@ def differential_evolution(objective_function, initial_slns=None, **kwargs):
|
|
236
236
|
else:
|
237
237
|
de = DifferentialEvolution(objective_function, **kwargs)
|
238
238
|
|
239
|
-
iterations, solutions, best_solutions, best_fitness, best_struct
|
239
|
+
iterations, solutions, best_solutions, best_fitness, best_struct = de.differential_evolution_run(
|
240
240
|
initial_slns=initial_slns, mod_init=man)
|
241
|
-
|
241
|
+
AVERAGE_BEST = st.mean(best_solutions)
|
242
242
|
end = datetime.now()
|
243
|
+
|
243
244
|
elapsed_time = end - start
|
245
|
+
print(f'elapsed time{elapsed_time}')
|
244
246
|
return DifferentialEvolutionResults(elapsed_time=elapsed_time, iteration=iterations,
|
245
247
|
iter_solution=solutions, best_solutions=best_solutions,
|
246
248
|
best_fitness=best_fitness,
|
247
|
-
best_struct=best_struct, average_best=
|
249
|
+
best_struct=best_struct, average_best=AVERAGE_BEST)
|
248
250
|
|
249
251
|
|
250
252
|
def simulated_annealing(objective_function, initial_slns=None, **kwargs):
|
@@ -403,6 +405,7 @@ class DifferentialEvolution(object):
|
|
403
405
|
"""
|
404
406
|
|
405
407
|
def __init__(self, objective_function, **kwargs):
|
408
|
+
objective_function.algorithm = 'de'
|
406
409
|
self._obj_fun = objective_function
|
407
410
|
if self._obj_fun._obj_1 is None:
|
408
411
|
print('no objective found, automatically selecting BIC')
|
@@ -419,6 +422,7 @@ class DifferentialEvolution(object):
|
|
419
422
|
self.iter = kwargs.get('_max_iter', 10000)
|
420
423
|
self.cr = kwargs.get('_crossover_perc') or kwargs.get('_cr', 0.2)
|
421
424
|
self.instance_number = str(kwargs.get('instance_number', 1))
|
425
|
+
self.instance_number = objective_function.instance_number
|
422
426
|
self.get_directory()
|
423
427
|
|
424
428
|
self._population = list()
|
@@ -778,7 +782,7 @@ class SimulatedAnnealing(object):
|
|
778
782
|
"""
|
779
783
|
|
780
784
|
def __init__(self, objective_function, **kwargs):
|
781
|
-
|
785
|
+
objective_function.algorithm = 'sa'
|
782
786
|
self._STEPS_PER_TEMP = int(kwargs.get('STEPS_PER_TEMP', 2)) or int(kwargs.get('_ts', 2))
|
783
787
|
self._INITAL_ACCEPT_RATE = float(kwargs.get('INTL_ACPT', 0.5))
|
784
788
|
self._NUM_INITIAL_SLNS = int(kwargs.get('_num_intl_slns', 20))
|
@@ -1245,6 +1249,7 @@ class HarmonySearch(object):
|
|
1245
1249
|
"""
|
1246
1250
|
Initialize HS with the specified objective function. Note that this objective function must implement ObjectiveFunctionInterface.
|
1247
1251
|
"""
|
1252
|
+
objective_function.algorithm = 'hs'
|
1248
1253
|
self._obj_fun = objective_function
|
1249
1254
|
## NEW CODE, TRYING TO EXCTACT OUT THE PARAMATERS
|
1250
1255
|
self._hms = kwargs.get('_hms', 20)
|
metacountregressor/solution.py
CHANGED
@@ -30,9 +30,11 @@ from scipy.special import gammaln
|
|
30
30
|
from sklearn.metrics import mean_absolute_error as MAE
|
31
31
|
from sklearn.metrics import mean_squared_error as MSPE
|
32
32
|
from statsmodels.tools.numdiff import approx_fprime, approx_hess
|
33
|
+
|
33
34
|
from sklearn.preprocessing import StandardScaler, MinMaxScaler
|
34
35
|
from texttable import Texttable
|
35
36
|
import time
|
37
|
+
|
36
38
|
try:
|
37
39
|
from ._device_cust import device as dev
|
38
40
|
from .pareto_file import Pareto, Solution
|
@@ -122,14 +124,16 @@ class ObjectiveFunction(object):
|
|
122
124
|
|
123
125
|
def __init__(self, x_data, y_data, **kwargs):
|
124
126
|
self.gbl_best = 1000000.0
|
127
|
+
self.run_numerical_hessian = kwargs.get('r_nu_hess', False)
|
128
|
+
self.run_bootstrap = kwargs.get('run_bootstrap', False)
|
125
129
|
self.linear_regression = kwargs.get('linear_model', False)
|
126
|
-
self.reg_penalty =
|
130
|
+
self.reg_penalty = kwargs.get('reg_penalty',1)
|
127
131
|
self.power_up_ll = False
|
128
132
|
self.nb_parma = 1
|
129
133
|
self.bic = None
|
130
134
|
self.other_bic = False
|
131
135
|
self.test_flag = 1
|
132
|
-
self.no_extra_param =
|
136
|
+
self.no_extra_param =0 #if true, fix dispersion. w
|
133
137
|
if self.other_bic:
|
134
138
|
print('change this to false latter ')
|
135
139
|
|
@@ -151,7 +155,7 @@ class ObjectiveFunction(object):
|
|
151
155
|
self.rdm_fit = None
|
152
156
|
self.rdm_cor_fit = None
|
153
157
|
self.dist_fit = None
|
154
|
-
self.rounding_point = kwargs.get('decimals_in_coeff',
|
158
|
+
self.rounding_point = kwargs.get('decimals_in_coeff', 4)
|
155
159
|
self.MAE = None
|
156
160
|
self.best_obj_1 = 1000000.0
|
157
161
|
self._obj_1 = kwargs.get('_obj_1', 'bic')
|
@@ -174,7 +178,6 @@ class ObjectiveFunction(object):
|
|
174
178
|
self._max_imp = kwargs.get('_max_imp', 90000000)
|
175
179
|
self._WIC = kwargs.get("WIC",10000) # Number of Iterations without Multiobjective Improvement #tod chuck into solution
|
176
180
|
self._panels = None
|
177
|
-
self.is_multi = True
|
178
181
|
self.method_ll = 'Nelder-Mead-BFGS'
|
179
182
|
|
180
183
|
self.method_ll = 'L-BFGS-B' # alternatives 'BFGS_2', 'BFGS
|
@@ -185,7 +188,7 @@ class ObjectiveFunction(object):
|
|
185
188
|
self.MP = 0
|
186
189
|
# Nelder-Mead-BFGS
|
187
190
|
|
188
|
-
self._max_characteristics = kwargs.get('_max_vars',
|
191
|
+
self._max_characteristics = kwargs.get('_max_vars', 90)
|
189
192
|
|
190
193
|
self.beta_dict = dict
|
191
194
|
if 'model_terms' in kwargs:
|
@@ -426,7 +429,7 @@ class ObjectiveFunction(object):
|
|
426
429
|
|
427
430
|
|
428
431
|
|
429
|
-
self.Ndraws = kwargs.get('Ndraws',
|
432
|
+
self.Ndraws = kwargs.get('Ndraws', 100)
|
430
433
|
self.draws1 = None
|
431
434
|
self.initial_sig = 1 # pass the test of a single model
|
432
435
|
self.pvalue_sig_value = .1
|
@@ -449,10 +452,10 @@ class ObjectiveFunction(object):
|
|
449
452
|
# define the variables
|
450
453
|
|
451
454
|
|
452
|
-
self._transformations = kwargs.get('_transformations', ["no", "log", "sqrt", "arcsinh"])
|
455
|
+
self._transformations = kwargs.get('_transformations', ["no", "log", "sqrt", "arcsinh", "nil"])
|
453
456
|
# self._distribution = ['triangular', 'uniform', 'normal', 'ln_normal', 'tn_normal', 'lindley']
|
454
457
|
|
455
|
-
self._distribution = kwargs.get('_distributions', ['triangular', 'uniform', 'normal', '
|
458
|
+
self._distribution = kwargs.get('_distributions', ['triangular', 'uniform', 'normal', 'tn_normal'])
|
456
459
|
|
457
460
|
if self.G is not None:
|
458
461
|
#TODO need to handle this for groups
|
@@ -485,8 +488,8 @@ class ObjectiveFunction(object):
|
|
485
488
|
model_types = [[0, 1]] # add 2 for Generalized Poisson
|
486
489
|
#model_types = [[0]]
|
487
490
|
|
488
|
-
if self:
|
489
|
-
model_types = [[
|
491
|
+
if self.linear_regression:
|
492
|
+
model_types = [[1]]
|
490
493
|
self.grad_yes = False
|
491
494
|
|
492
495
|
print(f'Linear Model Selected: turning off gradient calculation')
|
@@ -494,6 +497,11 @@ class ObjectiveFunction(object):
|
|
494
497
|
|
495
498
|
model_t_dict = {'Poisson':0,
|
496
499
|
"NB":1}
|
500
|
+
if self.linear_regression:
|
501
|
+
# Rename key "NB" to "sigma" if it exists in the dictionary
|
502
|
+
if "NB" in model_t_dict:
|
503
|
+
model_t_dict["sigma"] = model_t_dict.pop("NB")
|
504
|
+
|
497
505
|
# Retrieve the keys (model names) corresponding to the values in model_types
|
498
506
|
model_keys = [key for key, value in model_t_dict.items() if value in model_types[0]]
|
499
507
|
# Print the formatted result
|
@@ -503,6 +511,7 @@ class ObjectiveFunction(object):
|
|
503
511
|
|
504
512
|
self._model_type_codes = ['p', 'nb',
|
505
513
|
'gp', "pl", ["nb-theta", 'nb-dis']]
|
514
|
+
self.update_model_type_codes()
|
506
515
|
self._variable = [True] * len(self._discrete_values)
|
507
516
|
self._lower_bounds = [None] * \
|
508
517
|
len(self._discrete_values) # TODO have continus
|
@@ -522,7 +531,18 @@ class ObjectiveFunction(object):
|
|
522
531
|
|
523
532
|
self.solution_analyst = None
|
524
533
|
|
534
|
+
def update_model_type_codes(self):
|
535
|
+
if self.linear_regression:
|
536
|
+
# Recursively update all occurrences of 'nb' to 'sigma'
|
537
|
+
def replace_nb_with_sigma(item):
|
538
|
+
if isinstance(item, list):
|
539
|
+
return [replace_nb_with_sigma(sub_item) for sub_item in item]
|
540
|
+
elif item == 'nb':
|
541
|
+
return 'sigma'
|
542
|
+
return item
|
525
543
|
|
544
|
+
# Update the _model_type_codes list
|
545
|
+
self._model_type_codes = replace_nb_with_sigma(self._model_type_codes)
|
526
546
|
|
527
547
|
|
528
548
|
def over_ride_self(self, **kwargs):
|
@@ -584,6 +604,7 @@ class ObjectiveFunction(object):
|
|
584
604
|
self.set_defined_seed(42) # Set a specific seed
|
585
605
|
|
586
606
|
modified_fit = self.modify_initial_fit(manual_fit) # Modify the initial fit based on manual_fit
|
607
|
+
self.significant = 1
|
587
608
|
self.makeRegression(modified_fit) # Perform regression with the modified fit
|
588
609
|
|
589
610
|
|
@@ -592,11 +613,12 @@ class ObjectiveFunction(object):
|
|
592
613
|
Function to for proceccing testing, and finding a suitable initial coefficient (linear intercept)
|
593
614
|
"""
|
594
615
|
if hard_code:
|
616
|
+
# Grouped Terrs TODO
|
595
617
|
manual_fit_spec = {
|
596
618
|
'fixed_terms': ['Constant', 'US', 'RSMS', 'MCV'],
|
597
619
|
'rdm_terms': ['RSHS:normal', 'AADT:normal', 'Curve50:normal'],
|
598
620
|
'rdm_cor_terms': [],
|
599
|
-
'
|
621
|
+
'group_rdm': [],
|
600
622
|
'hetro_in_means': [],
|
601
623
|
'transformations': ['no', 'log', 'log', 'no', 'no', 'no', 'no'],
|
602
624
|
'dispersion': 1
|
@@ -618,7 +640,7 @@ class ObjectiveFunction(object):
|
|
618
640
|
'fixed_terms': ['const'],
|
619
641
|
'rdm_terms': [],
|
620
642
|
'rdm_cor_terms': [],
|
621
|
-
'
|
643
|
+
'group_rdm': [],
|
622
644
|
'hetro_in_means': [],
|
623
645
|
'transformations': ['no'],
|
624
646
|
'dispersion': 1
|
@@ -820,6 +842,10 @@ class ObjectiveFunction(object):
|
|
820
842
|
|
821
843
|
if dispersion == 0:
|
822
844
|
return None
|
845
|
+
if dispersion == 1:
|
846
|
+
return np.clip(np.exp(betas[-1]),None, 2)
|
847
|
+
|
848
|
+
|
823
849
|
elif dispersion == 2 or dispersion == 1:
|
824
850
|
if self.no_extra_param:
|
825
851
|
return self.nb_parma
|
@@ -1126,27 +1152,30 @@ class ObjectiveFunction(object):
|
|
1126
1152
|
print("-" * 80)
|
1127
1153
|
|
1128
1154
|
if solution is not None:
|
1129
|
-
|
1155
|
+
if self.is_multi:
|
1156
|
+
print(f"{self._obj_2}: {self.round_with_padding(solution[self._obj_2], 2)}")
|
1130
1157
|
|
1131
1158
|
self.pvalues = [self.round_with_padding(
|
1132
1159
|
x, 2) for x in self.pvalues]
|
1133
1160
|
signif_list = self.pvalue_asterix_add(self.pvalues)
|
1134
1161
|
if model == 1:
|
1135
|
-
|
1136
|
-
|
1162
|
+
# raise to the exponential
|
1163
|
+
self.coeff_[-1] = np.maximum([np.exp(self.coeff_[-1]),2])
|
1137
1164
|
if self.no_extra_param:
|
1138
1165
|
self.coeff_ = np.append(self.coeff_, self.nb_parma)
|
1139
1166
|
self.stderr = np.append(self.stderr, 0.00001)
|
1140
1167
|
self.zvalues = np.append(self.zvalues, 50)
|
1141
1168
|
|
1142
|
-
elif self.coeff_[-1] < 0.25:
|
1143
|
-
print(self.coeff_[-1], 'Warning Check Dispersion')
|
1144
|
-
print(np.exp(self.coeff_[-1]))
|
1169
|
+
#elif self.coeff_[-1] < 0.25:
|
1170
|
+
#print(self.coeff_[-1], 'Warning Check Dispersion')
|
1171
|
+
#print(f'dispession is para,aters {np.exp(self.coeff_[-1])}')
|
1145
1172
|
#self.coeff_[-1] = np.exp(self.coeff_[-1]) # min possible value for negbinom
|
1173
|
+
|
1146
1174
|
|
1147
1175
|
|
1176
|
+
|
1177
|
+
self.coeff_ = self.convert_coefficients(self.coeff_, model)
|
1148
1178
|
self.coeff_ = [self.round_with_padding(x, self.rounding_point) for x in self.coeff_]
|
1149
|
-
|
1150
1179
|
self.stderr = [self.round_with_padding(x, 2) for x in self.stderr]
|
1151
1180
|
self.zvalues = [self.round_with_padding(
|
1152
1181
|
x, 2) for x in self.zvalues]
|
@@ -1199,6 +1228,7 @@ class ObjectiveFunction(object):
|
|
1199
1228
|
if model is not None:
|
1200
1229
|
caption_parts = []
|
1201
1230
|
if self.algorithm is not None:
|
1231
|
+
|
1202
1232
|
caption_parts.append(
|
1203
1233
|
f"{self._model_type_codes[model]} model found through the {self.algorithm} algorithm.")
|
1204
1234
|
|
@@ -1209,7 +1239,8 @@ class ObjectiveFunction(object):
|
|
1209
1239
|
caption_parts.append(f"Log-Likelihood: {self.round_with_padding(self.log_lik, 2)}")
|
1210
1240
|
|
1211
1241
|
if solution is not None:
|
1212
|
-
|
1242
|
+
if self.is_multi:
|
1243
|
+
caption_parts.append(f"{self._obj_2}: {self.round_with_padding(solution[self._obj_2], 2)}")
|
1213
1244
|
|
1214
1245
|
caption = " ".join(caption_parts)
|
1215
1246
|
# print(latextable.draw_latex(table, caption=caption, caption_above = True))
|
@@ -1549,7 +1580,12 @@ class ObjectiveFunction(object):
|
|
1549
1580
|
fixed_vars, random_vars, random_var_cor) # TODO handle distrubution
|
1550
1581
|
|
1551
1582
|
distributions = alpha_rdm.copy()
|
1552
|
-
|
1583
|
+
if self.linear_regression:
|
1584
|
+
|
1585
|
+
transformations = ['nil'] * len(alpha) # todo add transformations
|
1586
|
+
else:
|
1587
|
+
transformations = ['no'] * len(alpha) # todo add transformations
|
1588
|
+
|
1553
1589
|
cnt = 0
|
1554
1590
|
joined_alpha = np.add(alpha_rdm, alpha_rdm_cor)
|
1555
1591
|
for i, x in enumerate(joined_alpha):
|
@@ -1961,7 +1997,7 @@ class ObjectiveFunction(object):
|
|
1961
1997
|
subpvalues = pvalues.copy()
|
1962
1998
|
else:
|
1963
1999
|
slice_this_amount = self.num_dispersion_params(dispersion)
|
1964
|
-
|
2000
|
+
|
1965
2001
|
if pvalues[-1] > sig_value:
|
1966
2002
|
vio_counts += 1
|
1967
2003
|
subpvalues = pvalues[:-slice_this_amount].copy()
|
@@ -3253,6 +3289,35 @@ class ObjectiveFunction(object):
|
|
3253
3289
|
print('output', out)
|
3254
3290
|
return out
|
3255
3291
|
|
3292
|
+
def custom_betas_to_penalise(self, params, dispersion):
|
3293
|
+
num_params = self.get_num_params()
|
3294
|
+
skip_count = sum(num_params[:2])
|
3295
|
+
betas_start = params[:skip_count]
|
3296
|
+
if dispersion:
|
3297
|
+
betas_end = params[-dispersion:]
|
3298
|
+
betas_ = np.concatenate((betas_start,betas_end))
|
3299
|
+
return betas_
|
3300
|
+
else: return betas_start
|
3301
|
+
|
3302
|
+
|
3303
|
+
def convert_coefficients(self, params, dispersion):
|
3304
|
+
num_params = self.get_num_params()
|
3305
|
+
skip_count = sum(num_params[:2])
|
3306
|
+
remain_params = num_params[2:]
|
3307
|
+
params[skip_count:skip_count+remain_params[1]] = np.abs(params[skip_count:skip_count+remain_params[1]])
|
3308
|
+
return params
|
3309
|
+
|
3310
|
+
|
3311
|
+
|
3312
|
+
def custom_penalty(self, params, penalty):
|
3313
|
+
num_params = self.get_num_params()
|
3314
|
+
skip_count = sum(num_params[:2])
|
3315
|
+
|
3316
|
+
for i in params[skip_count:-1]:
|
3317
|
+
if i < 0.25:
|
3318
|
+
penalty += self.reg_penalty*np.maximum(0, 2.25 -i)**2
|
3319
|
+
return penalty
|
3320
|
+
|
3256
3321
|
# p is the paramaterisation GP1 is at 0
|
3257
3322
|
def general_poisson(self, mu, y, nu, p=0): # TODO laxywhere??
|
3258
3323
|
|
@@ -3915,8 +3980,10 @@ class ObjectiveFunction(object):
|
|
3915
3980
|
|
3916
3981
|
|
3917
3982
|
if dispersion:
|
3983
|
+
sigma = dispersion
|
3918
3984
|
eta= np.dot(Xd, params_main)[:, :, None] + np.array(offset[:, :, :])
|
3919
3985
|
|
3986
|
+
epsilon = np.random.normal(loc=0, scale=sigma, size=eta.shape)
|
3920
3987
|
#eta= np.dot(Xd, params_main)[:, :, None] + np.array(offset[:, :, :])+dispersion
|
3921
3988
|
#print('check if this holds size')
|
3922
3989
|
else:
|
@@ -4591,6 +4658,41 @@ class ObjectiveFunction(object):
|
|
4591
4658
|
pass
|
4592
4659
|
"""
|
4593
4660
|
pass
|
4661
|
+
def _linear_logliklihood(self, y, eta, sigma):
|
4662
|
+
"""
|
4663
|
+
Calculate the log-likelihood for a linear regression model with random parameters.
|
4664
|
+
|
4665
|
+
Parameters:
|
4666
|
+
y (np.ndarray): Observed responses (n_samples,).
|
4667
|
+
eta (np.ndarray): Predicted values (linear predictor) (n_samples, 1, n_draws).
|
4668
|
+
sigma (float): Standard deviation of the error term.
|
4669
|
+
|
4670
|
+
Returns:
|
4671
|
+
float: The log-likelihood value aggregated across all draws.
|
4672
|
+
"""
|
4673
|
+
n_samples, _, n_draws = eta.shape # Number of observations and draws
|
4674
|
+
|
4675
|
+
# Repeat y to match the shape of eta
|
4676
|
+
y_repeated = np.repeat(y, n_draws, axis=2) # Shape (n_samples, 1, n_draws)
|
4677
|
+
|
4678
|
+
# Calculate residuals for each draw
|
4679
|
+
residuals = y_repeated - eta # Shape (n_samples, 1, n_draws)
|
4680
|
+
|
4681
|
+
# Calculate the residual sum of squares (RSS) for each draw
|
4682
|
+
rss = np.sum(residuals ** 2, axis=(0, 1)) # Shape (n_draws,)
|
4683
|
+
|
4684
|
+
# Log-likelihood for each draw
|
4685
|
+
log_likelihood_per_draw = (
|
4686
|
+
-0.5 * n_samples * np.log(2 * np.pi) # Constant term
|
4687
|
+
- 0.5 * n_samples * np.log(sigma**2) # Variance term
|
4688
|
+
- 0.5 * rss / sigma**2 # Residual term
|
4689
|
+
) # Shape (n_draws,)
|
4690
|
+
|
4691
|
+
# Aggregate across draws (e.g., take the mean log-likelihood)
|
4692
|
+
log_likelihood_value = np.mean(log_likelihood_per_draw)
|
4693
|
+
|
4694
|
+
return log_likelihood_value
|
4695
|
+
|
4594
4696
|
def _loglik_gradient(self, betas, Xd, y, draws=None, Xf=None, Xr=None, batch_size=None, return_gradient=False,
|
4595
4697
|
return_gradient_n=False, dispersion=0, test_set=0, return_EV=False, verbose=0, corr_list=None,
|
4596
4698
|
zi_list=None, exog_infl=None, draws_grouped=None, Xgroup=None, model_nature=None, kwarg=None,
|
@@ -4649,13 +4751,21 @@ class ObjectiveFunction(object):
|
|
4649
4751
|
if self.is_dispersion(dispersion):
|
4650
4752
|
penalty, main_disper = self._penalty_dispersion(dispersion, main_disper, eVd, y, penalty,
|
4651
4753
|
model_nature)
|
4754
|
+
b_pen = self.custom_betas_to_penalise(betas, dispersion)
|
4755
|
+
penalty = self.regularise_l2(betas) + self.regularise_l1(betas)
|
4756
|
+
penalty = self.custom_penalty(betas, penalty)
|
4652
4757
|
|
4653
4758
|
betas[-1] = main_disper
|
4654
4759
|
|
4760
|
+
b_pen = self.custom_betas_to_penalise(betas, dispersion)
|
4761
|
+
penalty = self.regularise_l2(betas) + self.regularise_l1(betas)
|
4762
|
+
penalty = self.custom_penalty(betas, penalty)
|
4763
|
+
|
4655
4764
|
if self.linear_regression:
|
4656
4765
|
# LINEAR MODEL PROCESS
|
4657
|
-
mse =
|
4658
|
-
|
4766
|
+
mse = self._linear_logliklihood(y, eVd, main_disper)
|
4767
|
+
#mse = np.mean((y - eVd) ** 2)
|
4768
|
+
return (-mse + penalty)*self.minimize_scaler
|
4659
4769
|
|
4660
4770
|
### GLM PROCESS ########
|
4661
4771
|
llf_main = self.loglik_obs(
|
@@ -4671,7 +4781,10 @@ class ObjectiveFunction(object):
|
|
4671
4781
|
|
4672
4782
|
loglik += 2*loglik
|
4673
4783
|
print('am i powering up')
|
4674
|
-
|
4784
|
+
|
4785
|
+
b_pen = self.custom_betas_to_penalise(betas, dispersion)
|
4786
|
+
penalty = self.regularise_l2(betas) + self.regularise_l1(betas)
|
4787
|
+
penalty = self.custom_penalty(betas, penalty)
|
4675
4788
|
|
4676
4789
|
if not np.isreal(loglik):
|
4677
4790
|
loglik = - 10000000.0
|
@@ -4888,12 +5001,24 @@ class ObjectiveFunction(object):
|
|
4888
5001
|
betas_hetro_sd = None
|
4889
5002
|
|
4890
5003
|
Vdr = dev.cust_einsum("njk,nkr -> njr", Xdr, Br) # (N,P,R)
|
4891
|
-
if self:
|
5004
|
+
if self.linear_regression:
|
4892
5005
|
### LINEAR MODEL WAY #######
|
4893
5006
|
eVd = np.clip(
|
4894
5007
|
Vdf[:, :, None] + Vdr + Vdh + dev.np.array(offset), None, None)
|
4895
|
-
|
4896
|
-
|
5008
|
+
main_disper = self.get_dispersion_paramaters(betas, dispersion)
|
5009
|
+
penalty, main_disper = self._penalty_dispersion(
|
5010
|
+
dispersion, main_disper, eVd, y, penalty, model_nature)
|
5011
|
+
error_term = np.random.normal(loc=0, scale=main_disper, size=eVd.shape)
|
5012
|
+
b_pen = self.custom_betas_to_penalise(betas, dispersion)
|
5013
|
+
penalty += self.regularise_l2(b_pen) + self.regularise_l1(b_pen)
|
5014
|
+
#penalty = 0
|
5015
|
+
penalty = self.custom_penalty(betas, penalty)
|
5016
|
+
# LINEAR MODEL PROCESS
|
5017
|
+
mse = self._linear_logliklihood(y, eVd, main_disper)
|
5018
|
+
#mse = np.mean((y - eVd) ** 2)
|
5019
|
+
|
5020
|
+
return -mse + penalty
|
5021
|
+
|
4897
5022
|
|
4898
5023
|
##### GLM WAY #####
|
4899
5024
|
eVd = dev.np.exp(np.clip(
|
@@ -4935,11 +5060,12 @@ class ObjectiveFunction(object):
|
|
4935
5060
|
proba_ = proba_n.sum(axis =1)
|
4936
5061
|
|
4937
5062
|
"""""
|
4938
|
-
|
5063
|
+
main_disper = self.get_dispersion_paramaters(betas, dispersion)
|
5064
|
+
|
4939
5065
|
|
4940
5066
|
# print(betas_last)
|
4941
5067
|
proba_, proba_n = self.prob_obs_draws_all_at_once(
|
4942
|
-
eVd, np.atleast_3d(y),
|
5068
|
+
eVd, np.atleast_3d(y), main_disper, dispersion)
|
4943
5069
|
# self._prob_product_against_panels()
|
4944
5070
|
|
4945
5071
|
# print(top_stats)
|
@@ -4959,7 +5085,7 @@ class ObjectiveFunction(object):
|
|
4959
5085
|
if self.power_up_ll:
|
4960
5086
|
penalty += self.regularise_l2(betas)
|
4961
5087
|
|
4962
|
-
penalty += self.regularise_l2(betas)
|
5088
|
+
penalty += self.regularise_l2(betas) + self.regularise_l1(betas)
|
4963
5089
|
if not return_gradient:
|
4964
5090
|
|
4965
5091
|
output = ((-loglik + penalty)*self.minimize_scaler,)
|
@@ -5022,6 +5148,11 @@ class ObjectiveFunction(object):
|
|
5022
5148
|
else:
|
5023
5149
|
return -self.reg_penalty*sum(np.square(betas.copy()))
|
5024
5150
|
|
5151
|
+
def regularise_l1(self, betas, backwards = False):
|
5152
|
+
if backwards == False:
|
5153
|
+
return self.reg_penalty*sum(np.square(betas.copy()))
|
5154
|
+
else:
|
5155
|
+
return -self.reg_penalty*sum(np.abs(betas.copy()))
|
5025
5156
|
|
5026
5157
|
def _concat_gradients(self, gr_f):
|
5027
5158
|
gr = np.concatenate((gr_f), axis=1)
|
@@ -5474,15 +5605,42 @@ class ObjectiveFunction(object):
|
|
5474
5605
|
return covariance
|
5475
5606
|
|
5476
5607
|
|
5608
|
+
# Numerical Hessian (finite differences)
|
5609
|
+
def numerical_hessian_post(self, f, theta, epsilon=1e-5):
|
5610
|
+
n = len(theta)
|
5611
|
+
hessian = np.zeros((n, n))
|
5612
|
+
for i in range(n):
|
5613
|
+
for j in range(n):
|
5614
|
+
theta_ij_plus = theta.copy()
|
5615
|
+
theta_ij_minus = theta.copy()
|
5616
|
+
theta_ij_plus[i] += epsilon
|
5617
|
+
theta_ij_plus[j] += epsilon
|
5618
|
+
theta_ij_minus[i] += epsilon
|
5619
|
+
theta_ij_minus[j] -= epsilon
|
5620
|
+
|
5621
|
+
f_ij_plus = f(theta_ij_plus)
|
5622
|
+
f_ij_minus = f(theta_ij_minus)
|
5623
|
+
f_original = f(theta)
|
5624
|
+
|
5625
|
+
hessian[i, j] = (f_ij_plus - 2 * f_original + f_ij_minus) / (epsilon ** 2)
|
5626
|
+
return hessian
|
5627
|
+
|
5628
|
+
|
5477
5629
|
def _post_fit_ll_aic_bic(self, optim_res, verbose=1, robust=False, simple_fit=True, is_dispersion=0):
|
5478
5630
|
# sample_size = len(self._x_data) - len(optim_res['x']) -1
|
5479
5631
|
sample_size = len(self._x_data)
|
5480
5632
|
convergence = optim_res['success']
|
5481
5633
|
coeff_ = optim_res['x']
|
5482
5634
|
penalty = 0
|
5483
|
-
|
5484
|
-
|
5485
|
-
|
5635
|
+
stderr_opg = None
|
5636
|
+
if self.run_numerical_hessian:
|
5637
|
+
|
5638
|
+
stderr_opg = self.stderr
|
5639
|
+
|
5640
|
+
|
5641
|
+
|
5642
|
+
|
5643
|
+
|
5486
5644
|
if 'hess_inv' in optim_res:
|
5487
5645
|
covariance = self._robust_covariance(optim_res['hess_inv'], optim_res['grad_n']) \
|
5488
5646
|
if robust else optim_res['hess_inv']
|
@@ -5491,21 +5649,14 @@ class ObjectiveFunction(object):
|
|
5491
5649
|
covariance = self.handle_covariance(covariance)
|
5492
5650
|
covariance = np.clip(covariance, 0, None)
|
5493
5651
|
stderr = np.sqrt(np.diag(covariance))
|
5494
|
-
|
5495
|
-
|
5496
|
-
|
5652
|
+
if stderr_opg is not None:
|
5653
|
+
stderr = np.minimum(stderr, stderr_opg)
|
5654
|
+
|
5655
|
+
|
5656
|
+
|
5497
5657
|
if is_dispersion:
|
5498
5658
|
stderr[-1] = random.uniform(0.001, 0.005)
|
5499
|
-
|
5500
|
-
# gets the number of parmas before the correlations
|
5501
|
-
pre_cor_pams = sum(self.get_num_params()[:3])
|
5502
|
-
# gets the number of correlated rpm
|
5503
|
-
post_cor_pams = sum(self.get_num_params()[:5])
|
5504
|
-
|
5505
|
-
|
5506
|
-
# this calculation takes into account the correlated rpms distinct values
|
5507
|
-
for i in range(pre_cor_pams, post_cor_pams):
|
5508
|
-
stderr[i] = stderr[i] / np.sqrt(sample_size)
|
5659
|
+
|
5509
5660
|
|
5510
5661
|
if np.isnan(stderr).any():
|
5511
5662
|
raise ValueError("Error: Matrix contains NaN values")
|
@@ -5518,6 +5669,9 @@ class ObjectiveFunction(object):
|
|
5518
5669
|
optim_res['fun'] = 10.0 ** 10
|
5519
5670
|
if self.power_up_ll:
|
5520
5671
|
loglikelihood =-optim_res['fun']/2 - penalty
|
5672
|
+
elif self.linear_regression:
|
5673
|
+
loglikelihood= -optim_res['fun']
|
5674
|
+
|
5521
5675
|
else:
|
5522
5676
|
loglikelihood = -optim_res['fun']/self.minimize_scaler - penalty
|
5523
5677
|
|
@@ -5792,6 +5946,9 @@ class ObjectiveFunction(object):
|
|
5792
5946
|
else:
|
5793
5947
|
self.draws = 0
|
5794
5948
|
|
5949
|
+
def hessian_loglik_function(self, params, *args):
|
5950
|
+
return self._loglik_gradient(params, *args)
|
5951
|
+
|
5795
5952
|
def _run_optimization(self, XX, y, dispersion, initial_params, bounds, tol, mod):
|
5796
5953
|
"""
|
5797
5954
|
Run the optimization process with draws logic and update the Solution object.
|
@@ -5817,11 +5974,15 @@ class ObjectiveFunction(object):
|
|
5817
5974
|
draws_grouped = self._prepare_grouped_draws(XG, mod) if XG is not None else None
|
5818
5975
|
|
5819
5976
|
# Optimization method and options
|
5820
|
-
method = self.method_ll
|
5821
|
-
|
5822
|
-
method = 'Nelder-Mead-BFGS'
|
5823
|
-
options = {'gtol': tol['gtol'], 'ftol': tol['ftol'], 'maxiter': 2000}
|
5977
|
+
method = self.method_ll if bounds is None else 'L-BFGS-B'
|
5978
|
+
|
5824
5979
|
|
5980
|
+
#method = 'Nelder-Mead-BFGS'
|
5981
|
+
options = {'gtol': tol['gtol'], 'ftol': tol['ftol'], 'maxiter': 20000}
|
5982
|
+
args=(
|
5983
|
+
X, y, draws, X, Xr, self.batch_size, self.grad_yes, self.hess_yes, dispersion, 0, False, 0,
|
5984
|
+
self.rdm_cor_fit, None, None, draws_grouped, XG, mod
|
5985
|
+
)
|
5825
5986
|
# Run optimization
|
5826
5987
|
optimization_result = self._minimize(
|
5827
5988
|
self._loglik_gradient,
|
@@ -5832,12 +5993,126 @@ class ObjectiveFunction(object):
|
|
5832
5993
|
),
|
5833
5994
|
method=method,
|
5834
5995
|
bounds=bounds,
|
5835
|
-
tol=tol.get('ftol', 1e-
|
5996
|
+
tol=tol.get('ftol', 1e-6), # Use 'ftol' as the default tolerance
|
5836
5997
|
options=options
|
5837
5998
|
)
|
5999
|
+
if optimization_result.message == 'NaN result encountered.':
|
6000
|
+
optimization_result = self._minimize(self._loglik_gradient,
|
6001
|
+
initial_params,
|
6002
|
+
args=(
|
6003
|
+
X, y, draws, X, Xr, self.batch_size, self.grad_yes, self.hess_yes, dispersion, 0, False, 0,
|
6004
|
+
self.rdm_cor_fit, None, None, draws_grouped, XG, mod
|
6005
|
+
),
|
6006
|
+
method='Nelder-Mead-BFGS',
|
6007
|
+
bounds=bounds,
|
6008
|
+
tol=tol.get('ftol', 1e-4), # Use 'ftol' as the default tolerance
|
6009
|
+
options=options
|
6010
|
+
)
|
6011
|
+
|
6012
|
+
|
6013
|
+
if self.run_numerical_hessian:
|
6014
|
+
std_errors = self.bootstrap_std_dev(
|
6015
|
+
initial_params=optimization_result.x,
|
6016
|
+
XX=XX,
|
6017
|
+
y=y,
|
6018
|
+
dispersion=dispersion,
|
6019
|
+
bounds=bounds,
|
6020
|
+
tol=tol,
|
6021
|
+
mod=mod,
|
6022
|
+
n_bootstraps=5
|
6023
|
+
)
|
6024
|
+
self.stderr = std_errors
|
6025
|
+
|
6026
|
+
|
6027
|
+
|
6028
|
+
|
6029
|
+
|
6030
|
+
|
6031
|
+
# Run the bootstrap to calculate standard errors
|
6032
|
+
if self.run_bootstrap:
|
6033
|
+
|
6034
|
+
std_errors = self.bootstrap_std_dev(
|
6035
|
+
initial_params=optimization_result.x,
|
6036
|
+
XX=XX,
|
6037
|
+
y=y,
|
6038
|
+
dispersion=dispersion,
|
6039
|
+
bounds=bounds,
|
6040
|
+
tol=tol,
|
6041
|
+
mod=mod,
|
6042
|
+
n_bootstraps=100
|
6043
|
+
)
|
6044
|
+
self.stderr = std_errors
|
6045
|
+
|
6046
|
+
|
6047
|
+
|
6048
|
+
|
5838
6049
|
return optimization_result
|
5839
6050
|
|
6051
|
+
|
5840
6052
|
|
6053
|
+
|
6054
|
+
def bootstrap_std_dev(self, initial_params, XX, y, dispersion, bounds, tol, mod, n_bootstraps=100):
|
6055
|
+
"""
|
6056
|
+
Perform bootstrap resampling to estimate the standard deviations of the parameters.
|
6057
|
+
|
6058
|
+
Parameters:
|
6059
|
+
self: Reference to the class instance.
|
6060
|
+
initial_params: Initial parameter estimates from the optimization.
|
6061
|
+
XX: Design matrix.
|
6062
|
+
y: Observed outcomes.
|
6063
|
+
dispersion: Dispersion parameter (0=Poisson, 1=NB, 2=GP).
|
6064
|
+
bounds: List of bounds for each parameter.
|
6065
|
+
tol: Tolerance for the optimization process (dictionary with ftol and gtol).
|
6066
|
+
mod: Dictionary containing additional data.
|
6067
|
+
n_bootstraps: Number of bootstrap resamples (default=100).
|
6068
|
+
|
6069
|
+
Returns:
|
6070
|
+
std_devs: Standard deviations of the parameter estimates (from bootstrap resampling).
|
6071
|
+
"""
|
6072
|
+
# List to store parameter estimates from each bootstrap iteration
|
6073
|
+
bootstrap_estimates = []
|
6074
|
+
|
6075
|
+
# Extract design matrices and additional components from `mod`
|
6076
|
+
X, Xr, XG = mod.get('X'), mod.get('Xr'), mod.get('XG')
|
6077
|
+
distribution = mod.get('dist_fit')
|
6078
|
+
|
6079
|
+
# Prepare draws
|
6080
|
+
draws = self._prepare_draws(Xr, distribution)
|
6081
|
+
draws_grouped = self._prepare_grouped_draws(XG, mod) if XG is not None else None
|
6082
|
+
|
6083
|
+
# Perform bootstrap iterations
|
6084
|
+
for _ in range(n_bootstraps):
|
6085
|
+
# Resample data with replacement
|
6086
|
+
indices = np.random.choice(len(y), size=len(y), replace=True)
|
6087
|
+
X_resampled = X[indices]
|
6088
|
+
y_resampled = y[indices]
|
6089
|
+
|
6090
|
+
# Refit the model with resampled data
|
6091
|
+
bootstrap_result = self._minimize(
|
6092
|
+
self._loglik_gradient,
|
6093
|
+
initial_params,
|
6094
|
+
args=(
|
6095
|
+
X_resampled, y_resampled, draws, X_resampled, Xr, self.batch_size, self.grad_yes,
|
6096
|
+
self.hess_yes, dispersion, 0, False, 0, self.rdm_cor_fit, None, None,
|
6097
|
+
draws_grouped, XG, mod
|
6098
|
+
),
|
6099
|
+
method=self.method_ll,
|
6100
|
+
bounds=bounds,
|
6101
|
+
tol=tol.get('ftol', 1e-6), # Use 'ftol' as the default tolerance
|
6102
|
+
options={'gtol': tol['gtol'], 'ftol': tol['ftol'], 'maxiter': 200}
|
6103
|
+
)
|
6104
|
+
|
6105
|
+
# Store the parameter estimates from this bootstrap iteration
|
6106
|
+
bootstrap_estimates.append(bootstrap_result.x)
|
6107
|
+
|
6108
|
+
# Convert bootstrap parameter estimates to a NumPy array
|
6109
|
+
bootstrap_estimates = np.array(bootstrap_estimates)
|
6110
|
+
|
6111
|
+
# Compute the standard deviations of the parameter estimates
|
6112
|
+
std_devs = np.std(bootstrap_estimates, axis=0)
|
6113
|
+
|
6114
|
+
return std_devs
|
6115
|
+
|
5841
6116
|
def _initialize_params_and_bounds(self, XX, dispersion):
|
5842
6117
|
"""Initialize parameters and set bounds for optimization."""
|
5843
6118
|
num_params = XX.shape[2] # Number of features
|
@@ -5913,6 +6188,7 @@ class ObjectiveFunction(object):
|
|
5913
6188
|
# Validation metrics if test data is available (in-sample and out-of-sample MAE)
|
5914
6189
|
in_sample_mae = None
|
5915
6190
|
out_sample_mae = None
|
6191
|
+
out_sample_validation = None
|
5916
6192
|
if self.is_multi and XX_test is not None:
|
5917
6193
|
in_sample_mae = self.validation(
|
5918
6194
|
optimization_result['x'], y, XX, dispersion=dispersion, model_nature=mod, testing=0
|
@@ -5920,13 +6196,17 @@ class ObjectiveFunction(object):
|
|
5920
6196
|
out_sample_mae = self.validation(
|
5921
6197
|
optimization_result['x'], y_test, XX_test, dispersion=dispersion, model_nature=mod
|
5922
6198
|
)
|
6199
|
+
if self.val_percentage > 0:
|
6200
|
+
out_sample_validation = self.validation(
|
6201
|
+
optimization_result['x'], y_test, XX_test, dispersion=dispersion, model_nature=mod, testing=1
|
6202
|
+
)
|
5923
6203
|
|
5924
|
-
return log_ll, aic, bic, stderr, zvalues, pvalue_alt, in_sample_mae, out_sample_mae
|
6204
|
+
return log_ll, aic, bic, stderr, zvalues, pvalue_alt, in_sample_mae, out_sample_mae, out_sample_validation
|
5925
6205
|
|
5926
6206
|
else:
|
5927
6207
|
# Optimization failed, return None for all metrics
|
5928
6208
|
print("Optimization failed.")
|
5929
|
-
return None, None, None, None, None, None, None, None
|
6209
|
+
return None, None, None, None, None, None, None, None, None
|
5930
6210
|
def _prepare_data_and_bounds(self, mod, dispersion):
|
5931
6211
|
"""Prepare the data matrices, bounds, and initial parameters."""
|
5932
6212
|
# Prepare data matrices
|
@@ -5963,7 +6243,13 @@ class ObjectiveFunction(object):
|
|
5963
6243
|
if dispersion == 0:
|
5964
6244
|
return [(-30, 30) for _ in initial_params]
|
5965
6245
|
elif dispersion == 1:
|
5966
|
-
|
6246
|
+
num_params = self.get_num_params()
|
6247
|
+
skip_count = sum(num_params[:2])
|
6248
|
+
|
6249
|
+
|
6250
|
+
bounds = [(-3, 3) for _ in initial_params[:-1]] + [(-1, 1)]
|
6251
|
+
bounds[skip_count: -1] = [(0.02, None) for _ in bounds[skip_count: -1]]
|
6252
|
+
return bounds
|
5967
6253
|
elif dispersion == 2:
|
5968
6254
|
return [(-5, 5) for _ in initial_params[:-1]] + [(0.1, 0.99)]
|
5969
6255
|
else:
|
@@ -6010,8 +6296,9 @@ class ObjectiveFunction(object):
|
|
6010
6296
|
|
6011
6297
|
# Dispersion adds one additional parameter if enabled
|
6012
6298
|
dispersion_param = 1 if dispersion > 0 else 0
|
6013
|
-
|
6014
|
-
|
6299
|
+
total = sum(self.get_num_params()) + dispersion_param
|
6300
|
+
return total
|
6301
|
+
|
6015
6302
|
def _build_initial_params(self, num_coefficients, dispersion):
|
6016
6303
|
"""
|
6017
6304
|
Build the initial parameter array for optimization.
|
@@ -6024,15 +6311,20 @@ class ObjectiveFunction(object):
|
|
6024
6311
|
Initial parameter array.
|
6025
6312
|
"""
|
6026
6313
|
# Generate random initial coefficients
|
6027
|
-
initial_params = np.random.uniform(
|
6314
|
+
initial_params = np.random.uniform(0.0000, 0.01, size=num_coefficients)
|
6315
|
+
parma_sum = sum(self.get_num_params()[:2])
|
6316
|
+
|
6317
|
+
|
6318
|
+
initial_params[parma_sum:-dispersion] =0.0001
|
6028
6319
|
|
6029
6320
|
# Add dispersion parameter if applicable
|
6030
6321
|
if dispersion > 0:
|
6031
|
-
initial_params
|
6322
|
+
initial_params[-1] = 0.0
|
6323
|
+
#initial_params[0] =3
|
6032
6324
|
|
6033
6325
|
return initial_params
|
6034
6326
|
|
6035
|
-
def fitRegression(self, mod, dispersion=0, maxiter=
|
6327
|
+
def fitRegression(self, mod, dispersion=0, maxiter=20000, batch_size=None, num_hess=False, **kwargs):
|
6036
6328
|
"""
|
6037
6329
|
Fits a Poisson regression, NB regression (dispersion=1), or GP regression (dispersion=2).
|
6038
6330
|
|
@@ -6047,8 +6339,9 @@ class ObjectiveFunction(object):
|
|
6047
6339
|
obj_1, log_lik, betas, stderr, pvalues, zvalues, is_halton, is_delete
|
6048
6340
|
"""
|
6049
6341
|
try:
|
6342
|
+
dispersion = mod.get('dispersion', dispersion)
|
6050
6343
|
# Preprocessing
|
6051
|
-
tol = {'ftol': 1e-
|
6344
|
+
tol = {'ftol': 1e-6, 'gtol': 1e-6, 'xtol': 1e-6}
|
6052
6345
|
y, X, Xr, XG, XH = mod.get('y'), mod.get('X'), mod.get('Xr'), mod.get('XG'), mod.get('XH')
|
6053
6346
|
|
6054
6347
|
# Validate input data
|
@@ -6073,10 +6366,10 @@ class ObjectiveFunction(object):
|
|
6073
6366
|
)
|
6074
6367
|
|
6075
6368
|
# Post-process results
|
6076
|
-
log_lik, aic, bic, stderr, zvalues, pvalues, in_sample_mae, out_sample_mae = self._postprocess_results(
|
6369
|
+
log_lik, aic, bic, stderr, zvalues, pvalues, in_sample_mae, out_sample_mae, out_sample_val = self._postprocess_results(
|
6077
6370
|
optimization_result, XX, XX_test, y, mod.get('y_test'), dispersion, mod
|
6078
6371
|
)
|
6079
|
-
|
6372
|
+
|
6080
6373
|
# Extract other outputs
|
6081
6374
|
betas = optimization_result['x'] if optimization_result is not None else None
|
6082
6375
|
is_halton = Xr is not None and Xr.size > 0 # Halton draws used if `Xr` is not empty
|
@@ -6105,10 +6398,14 @@ class ObjectiveFunction(object):
|
|
6105
6398
|
|
6106
6399
|
# Add metrics to solution object
|
6107
6400
|
sol = Solution() # Assuming Solution is the appropriate class to store results
|
6401
|
+
|
6108
6402
|
sol.add_objective(
|
6109
6403
|
bic=bic,
|
6110
6404
|
aic=aic,
|
6111
6405
|
loglik=log_ll,
|
6406
|
+
TRAIN=in_sample_mae,
|
6407
|
+
TEST=out_sample_mae,
|
6408
|
+
VAL=out_sample_val,
|
6112
6409
|
num_parm=paramNum,
|
6113
6410
|
GOF=other_measures
|
6114
6411
|
)
|
@@ -7125,7 +7422,7 @@ class ObjectiveFunction(object):
|
|
7125
7422
|
obj_1[self._obj_1] = 10 ** 100
|
7126
7423
|
|
7127
7424
|
else:
|
7128
|
-
print('
|
7425
|
+
print('Did not converge')
|
7129
7426
|
obj_1[self._obj_1] = 10 ** 100
|
7130
7427
|
|
7131
7428
|
self.significant = 3
|
@@ -7369,7 +7666,7 @@ class ObjectiveFunction(object):
|
|
7369
7666
|
sequence.append(n_th_number)
|
7370
7667
|
return sequence
|
7371
7668
|
|
7372
|
-
def _generate_halton_draws(self, sample_size, n_draws, n_vars, shuffled=False, drop=
|
7669
|
+
def _generate_halton_draws(self, sample_size, n_draws, n_vars, shuffled=False, drop=10, primes=None,
|
7373
7670
|
long=False) -> np.ndarray:
|
7374
7671
|
"""Generate Halton draws for multiple random variables using different primes as base"""
|
7375
7672
|
if primes is None:
|
@@ -7398,6 +7695,7 @@ class ObjectiveFunction(object):
|
|
7398
7695
|
i += 1
|
7399
7696
|
t += 1
|
7400
7697
|
seq = seq[drop:length + drop]
|
7698
|
+
seq = np.clip(seq, 1e-4, 1-1e-4)
|
7401
7699
|
if shuffled:
|
7402
7700
|
np.random.shuffle(seq)
|
7403
7701
|
return seq
|
@@ -7451,6 +7749,12 @@ class ObjectiveFunction(object):
|
|
7451
7749
|
(1 - x) * np.random.gamma(2, scale=theta, size=n)
|
7452
7750
|
return b
|
7453
7751
|
|
7752
|
+
|
7753
|
+
|
7754
|
+
|
7755
|
+
|
7756
|
+
|
7757
|
+
|
7454
7758
|
def _compute_derivatives(self, betas, draws, betas_std=None, distribution=None):
|
7455
7759
|
# N, N_draws, K = len(draws)/self.Ndraws, self.Ndraws, len(self._distribution)
|
7456
7760
|
# N, D = draws.shape[0], draws.shape[1]
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: metacountregressor
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.310
|
4
4
|
Summary: Extensive Testing for Estimation of Data Count Models
|
5
5
|
Home-page: https://github.com/zahern/CountDataEstimation
|
6
6
|
Author: Zeke Ahern
|
@@ -17,12 +17,14 @@ Requires-Dist: pandas
|
|
17
17
|
Requires-Dist: scikit-learn>=1.3.1
|
18
18
|
Requires-Dist: statsmodels
|
19
19
|
Requires-Dist: psutil
|
20
|
+
Requires-Dist: pybind11>=2.12
|
20
21
|
Dynamic: author
|
21
22
|
Dynamic: author-email
|
22
23
|
Dynamic: description
|
23
24
|
Dynamic: description-content-type
|
24
25
|
Dynamic: home-page
|
25
26
|
Dynamic: license
|
27
|
+
Dynamic: license-file
|
26
28
|
Dynamic: requires-dist
|
27
29
|
Dynamic: requires-python
|
28
30
|
Dynamic: summary
|
@@ -3,18 +3,18 @@ metacountregressor/_device_cust.py,sha256=759fnKmTYccJm4Lpi9_1reurh6OB9d6q9soPR0
|
|
3
3
|
metacountregressor/app_main.py,sha256=vY3GczTbGbBRalbzMkl_9jVW7RMgEOc6z2Dr1IZJv9c,10014
|
4
4
|
metacountregressor/data_split_helper.py,sha256=M2fIMdIO8znUaYhx5wlacRyNWdQjNYu1z1wkE-kFUYU,3373
|
5
5
|
metacountregressor/halton.py,sha256=jhovA45UBoZYU9g-hl6Lb2sBIx_ZBTNdPrpgkzR9fng,9463
|
6
|
-
metacountregressor/helperprocess.py,sha256=
|
7
|
-
metacountregressor/main.py,sha256=
|
6
|
+
metacountregressor/helperprocess.py,sha256=8PFxX3KTsWH0MlfhniDzKQOJQ63LmJ0eg6cYhQP_fRA,26162
|
7
|
+
metacountregressor/main.py,sha256=tGOm8DdbdyDf316qIxDAre6l6GzfJIWYNYIBaSeIemI,23685
|
8
8
|
metacountregressor/main_old.py,sha256=eTS4ygq27MnU-dZ_j983Ucb-D5XfbVF8OJQK2hVVLZc,24123
|
9
|
-
metacountregressor/metaheuristics.py,sha256=
|
9
|
+
metacountregressor/metaheuristics.py,sha256=P0Xjlvhp1cEwZFACrqeeets6x8BK7F2iDyu1OfS4bog,107010
|
10
10
|
metacountregressor/pareto_file.py,sha256=whySaoPAUWYjyI8zo0hwAOa3rFk6SIUlHSpqZiLur0k,23096
|
11
11
|
metacountregressor/pareto_logger__plot.py,sha256=mEU2QN4wmsM7t39GJ_XhJ_jjsdl09JOmG0U2jICrAkI,30037
|
12
12
|
metacountregressor/setup.py,sha256=5UcQCCLR8Fm5odA3MX78WwahavxFq4mVD6oq0IuQvAY,936
|
13
13
|
metacountregressor/single_objective_finder.py,sha256=jVG7GJBqzSP4_riYr-kMMKy_LE3SlGmKMunNhHYxgRg,8011
|
14
|
-
metacountregressor/solution.py,sha256=
|
14
|
+
metacountregressor/solution.py,sha256=h-sHkShA-P5oWJuowCRt0J2wixcxCgoL_tlyM2NCBxQ,319693
|
15
15
|
metacountregressor/test_generated_paper2.py,sha256=pwOoRzl1jJIIOUAAvbkT6HmmTQ81mwpsshn9SLdKOg8,3927
|
16
|
-
metacountregressor-0.1.
|
17
|
-
metacountregressor-0.1.
|
18
|
-
metacountregressor-0.1.
|
19
|
-
metacountregressor-0.1.
|
20
|
-
metacountregressor-0.1.
|
16
|
+
metacountregressor-0.1.310.dist-info/licenses/LICENSE.txt,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
17
|
+
metacountregressor-0.1.310.dist-info/METADATA,sha256=ahasic-4LXNYf9FJiny3p97mdTCrFtsEISCm_J-1FAA,23581
|
18
|
+
metacountregressor-0.1.310.dist-info/WHEEL,sha256=DK49LOLCYiurdXXOXwGJm6U4DkHkg4lcxjhqwRa0CP4,91
|
19
|
+
metacountregressor-0.1.310.dist-info/top_level.txt,sha256=zGG7UC5WIpr76gsFUpwJ4En2aCcoNTONBaS3OewwjR0,19
|
20
|
+
metacountregressor-0.1.310.dist-info/RECORD,,
|
{metacountregressor-0.1.239.dist-info → metacountregressor-0.1.310.dist-info/licenses}/LICENSE.txt
RENAMED
File without changes
|
File without changes
|