hoppMCMC 2.2.0__tar.gz → 2.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/NEWS.txt +1 -2
- {hoppmcmc-2.2.0/src/hoppMCMC.egg-info → hoppmcmc-2.2.2}/PKG-INFO +1 -1
- {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/pyproject.toml +1 -1
- {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/setup.cfg +1 -1
- {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/src/hoppMCMC/__init__.py +1 -1
- {hoppmcmc-2.2.0 → hoppmcmc-2.2.2/src/hoppMCMC.egg-info}/PKG-INFO +1 -1
- {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/src/inferFun/__init__.py +128 -9
- {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/LICENSE +0 -0
- {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/MANIFEST.in +0 -0
- {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/README.txt +0 -0
- {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/setup.py +0 -0
- {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/src/hoppMCMC/doc/hoppMCMC_manual.pdf +0 -0
- {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/src/hoppMCMC/examples/example1.py +0 -0
- {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/src/hoppMCMC/examples/example2.py +0 -0
- {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/src/hoppMCMC/examples/example3.py +0 -0
- {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/src/hoppMCMC/examples/example4.py +0 -0
- {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/src/hoppMCMC/examples/example5.py +0 -0
- {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/src/hoppMCMC.egg-info/SOURCES.txt +0 -0
- {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/src/hoppMCMC.egg-info/dependency_links.txt +0 -0
- {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/src/hoppMCMC.egg-info/not-zip-safe +0 -0
- {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/src/hoppMCMC.egg-info/requires.txt +0 -0
- {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/src/hoppMCMC.egg-info/top_level.txt +0 -0
- {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/src/myMPI/__init__.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "hoppMCMC"
|
|
7
|
-
version = "2.2.
|
|
7
|
+
version = "2.2.2"
|
|
8
8
|
description = "An adaptive basin-hopping Markov-chain Monte Carlo algorithm for Bayesian optimisation"
|
|
9
9
|
authors = [{ name = "Kamil Erguler", email = "kerguler@gmail.com" }]
|
|
10
10
|
license = { text = "GPLv3" }
|
|
@@ -477,18 +477,137 @@ class inferABCModels:
|
|
|
477
477
|
|
|
478
478
|
def log_kernel_density(self, model_id, x, mean, kernel):
|
|
479
479
|
inferpar = self.inferpars[model_id]
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
480
|
+
x_inf = numpy.asarray(x[inferpar], dtype=float)
|
|
481
|
+
mean_inf = numpy.asarray(mean[inferpar], dtype=float)
|
|
482
|
+
d = len(inferpar)
|
|
483
483
|
|
|
484
484
|
kernel = numpy.asarray(kernel, dtype=float)
|
|
485
485
|
if kernel.ndim == 0:
|
|
486
|
-
kernel = numpy.array([[kernel]])
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
486
|
+
kernel = numpy.array([[float(kernel)]], dtype=float)
|
|
487
|
+
elif kernel.ndim == 1:
|
|
488
|
+
kernel = numpy.diag(kernel)
|
|
489
|
+
elif kernel.ndim != 2:
|
|
490
|
+
raise ValueError(
|
|
491
|
+
f"Kernel for model {model_id} ({self.model_names[model_id]}) "
|
|
492
|
+
f"must be scalar, 1D, or 2D. Got shape {kernel.shape}."
|
|
493
|
+
)
|
|
494
|
+
if kernel.shape != (d, d):
|
|
495
|
+
raise ValueError(
|
|
496
|
+
f"Kernel dimension mismatch for model {model_id} "
|
|
497
|
+
f"({self.model_names[model_id]}). "
|
|
498
|
+
f"Expected {(d, d)}, got {kernel.shape}. "
|
|
499
|
+
f"inferpar={inferpar}"
|
|
500
|
+
)
|
|
501
|
+
if not numpy.all(numpy.isfinite(x_inf)):
|
|
502
|
+
raise ValueError(
|
|
503
|
+
f"Non-finite x values for model {model_id} "
|
|
504
|
+
f"({self.model_names[model_id]}): {x_inf}"
|
|
505
|
+
)
|
|
506
|
+
if not numpy.all(numpy.isfinite(mean_inf)):
|
|
507
|
+
raise ValueError(
|
|
508
|
+
f"Non-finite kernel mean for model {model_id} "
|
|
509
|
+
f"({self.model_names[model_id]}): {mean_inf}"
|
|
510
|
+
)
|
|
511
|
+
if not numpy.all(numpy.isfinite(kernel)):
|
|
512
|
+
raise ValueError(
|
|
513
|
+
f"Non-finite kernel entries for model {model_id} "
|
|
514
|
+
f"({self.model_names[model_id]}):\n{kernel}"
|
|
515
|
+
)
|
|
516
|
+
# Symmetrise, just in case floating-point noise introduced asymmetry.
|
|
517
|
+
kernel = 0.5 * (kernel + kernel.T)
|
|
518
|
+
diag = numpy.diag(kernel)
|
|
519
|
+
if numpy.any(diag < 0):
|
|
520
|
+
raise ValueError(
|
|
521
|
+
f"Negative diagonal variance in kernel for model {model_id} "
|
|
522
|
+
f"({self.model_names[model_id]}).\n"
|
|
523
|
+
f"Diagonal={diag}\n"
|
|
524
|
+
f"Kernel=\n{kernel}"
|
|
525
|
+
)
|
|
526
|
+
eigvals, eigvecs = numpy.linalg.eigh(kernel)
|
|
527
|
+
max_eig = numpy.max(eigvals)
|
|
528
|
+
# A purely absolute jitter may be too small if the largest variance is large.
|
|
529
|
+
# This floor is both absolute and relative.
|
|
530
|
+
eig_floor = max(self.jitter, self.jitter * max(1.0, max_eig))
|
|
531
|
+
if numpy.any(eigvals <= eig_floor):
|
|
532
|
+
bad = numpy.where(eigvals <= eig_floor)[0]
|
|
533
|
+
if self.verbose:
|
|
534
|
+
print(
|
|
535
|
+
f"Warning: regularising near-singular kernel for model {model_id} "
|
|
536
|
+
f"({self.model_names[model_id]}).",
|
|
537
|
+
flush=True
|
|
538
|
+
)
|
|
539
|
+
print(f" parameter indices: {inferpar}", flush=True)
|
|
540
|
+
print(f" diagonal variances: {diag}", flush=True)
|
|
541
|
+
print(f" eigenvalues before regularisation: {eigvals}", flush=True)
|
|
542
|
+
print(f" eigenvalue floor: {eig_floor:g}", flush=True)
|
|
543
|
+
#
|
|
544
|
+
for b in bad:
|
|
545
|
+
direction = eigvecs[:, b]
|
|
546
|
+
order = numpy.argsort(numpy.abs(direction))[::-1]
|
|
547
|
+
print(
|
|
548
|
+
f" problematic eigenvalue {b}: {eigvals[b]:g}",
|
|
549
|
+
flush=True
|
|
550
|
+
)
|
|
551
|
+
print(" strongest dimensions in this direction:", flush=True)
|
|
552
|
+
for k in order[:min(5, len(order))]:
|
|
553
|
+
print(
|
|
554
|
+
f" kernel dim {k}, parameter index {inferpar[k]}, "
|
|
555
|
+
f"loading={direction[k]:g}, "
|
|
556
|
+
f"variance={diag[k]:g}",
|
|
557
|
+
flush=True
|
|
558
|
+
)
|
|
559
|
+
# Regularise eigenvalues, not only diagonal entries.
|
|
560
|
+
eigvals = numpy.maximum(eigvals, eig_floor)
|
|
561
|
+
kernel = eigvecs @ numpy.diag(eigvals) @ eigvecs.T
|
|
562
|
+
kernel = 0.5 * (kernel + kernel.T)
|
|
563
|
+
# Final check by Cholesky. This is stricter and clearer than waiting for SciPy.
|
|
564
|
+
try:
|
|
565
|
+
numpy.linalg.cholesky(kernel)
|
|
566
|
+
except numpy.linalg.LinAlgError as err:
|
|
567
|
+
eigvals_final = numpy.linalg.eigvalsh(kernel)
|
|
568
|
+
raise ValueError(
|
|
569
|
+
f"Kernel is still not positive definite for model {model_id} "
|
|
570
|
+
f"({self.model_names[model_id]}).\n"
|
|
571
|
+
f"parameter indices={inferpar}\n"
|
|
572
|
+
f"x={x_inf}\n"
|
|
573
|
+
f"mean={mean_inf}\n"
|
|
574
|
+
f"diagonal variances={numpy.diag(kernel)}\n"
|
|
575
|
+
f"eigenvalues={eigvals_final}\n"
|
|
576
|
+
f"kernel=\n{kernel}"
|
|
577
|
+
) from err
|
|
578
|
+
try:
|
|
579
|
+
value = multivariate_normal.logpdf(
|
|
580
|
+
x_inf,
|
|
581
|
+
mean=mean_inf,
|
|
582
|
+
cov=kernel,
|
|
583
|
+
allow_singular=False
|
|
584
|
+
)
|
|
585
|
+
except Exception as err:
|
|
586
|
+
eigvals_final = numpy.linalg.eigvalsh(kernel)
|
|
587
|
+
raise ValueError(
|
|
588
|
+
f"multivariate_normal.logpdf failed for model {model_id} "
|
|
589
|
+
f"({self.model_names[model_id]}).\n"
|
|
590
|
+
f"parameter indices={inferpar}\n"
|
|
591
|
+
f"x={x_inf}\n"
|
|
592
|
+
f"mean={mean_inf}\n"
|
|
593
|
+
f"diagonal variances={numpy.diag(kernel)}\n"
|
|
594
|
+
f"eigenvalues={eigvals_final}\n"
|
|
595
|
+
f"kernel=\n{kernel}"
|
|
596
|
+
) from err
|
|
597
|
+
if not numpy.isfinite(value):
|
|
598
|
+
eigvals_final = numpy.linalg.eigvalsh(kernel)
|
|
599
|
+
raise ValueError(
|
|
600
|
+
f"Non-finite kernel log density for model {model_id} "
|
|
601
|
+
f"({self.model_names[model_id]}).\n"
|
|
602
|
+
f"logpdf={value}\n"
|
|
603
|
+
f"parameter indices={inferpar}\n"
|
|
604
|
+
f"x={x_inf}\n"
|
|
605
|
+
f"mean={mean_inf}\n"
|
|
606
|
+
f"diagonal variances={numpy.diag(kernel)}\n"
|
|
607
|
+
f"eigenvalues={eigvals_final}\n"
|
|
608
|
+
f"kernel=\n{kernel}"
|
|
609
|
+
)
|
|
610
|
+
return value
|
|
492
611
|
|
|
493
612
|
def calc_weights(self, mat_new, mat_old, kernels):
|
|
494
613
|
"""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|