CUQIpy 1.1.1.post0.dev78__py3-none-any.whl → 1.1.1.post0.dev86__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.

Potentially problematic release.


This version of CUQIpy might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: CUQIpy
3
- Version: 1.1.1.post0.dev78
3
+ Version: 1.1.1.post0.dev86
4
4
  Summary: Computational Uncertainty Quantification for Inverse problems in Python
5
5
  Maintainer-email: "Nicolai A. B. Riis" <nabr@dtu.dk>, "Jakob S. Jørgensen" <jakj@dtu.dk>, "Amal M. Alghamdi" <amaal@dtu.dk>, Chao Zhang <chaz@dtu.dk>
6
6
  License: Apache License
@@ -1,6 +1,6 @@
1
1
  cuqi/__init__.py,sha256=LsGilhl-hBLEn6Glt8S_l0OJzAA1sKit_rui8h-D-p0,488
2
2
  cuqi/_messages.py,sha256=fzEBrZT2kbmfecBBPm7spVu7yHdxGARQB4QzXhJbCJ0,415
3
- cuqi/_version.py,sha256=gD2Xsdgd9KtxRR21WMPf1lwpL2_y736taJdOyU6AmrE,509
3
+ cuqi/_version.py,sha256=uA6Xuy9UVnhc1O0rUPg4oXOvsCaEZeojsh5XqGatgOA,509
4
4
  cuqi/config.py,sha256=wcYvz19wkeKW2EKCGIKJiTpWt5kdaxyt4imyRkvtTRA,526
5
5
  cuqi/diagnostics.py,sha256=5OrbJeqpynqRXOe5MtOKKhe7EAVdOEpHIqHnlMW9G_c,3029
6
6
  cuqi/array/__init__.py,sha256=-EeiaiWGNsE3twRS4dD814BIlfxEsNkTCZUc5gjOXb0,30
@@ -34,12 +34,12 @@ cuqi/distribution/_posterior.py,sha256=zAfL0GECxekZ2lBt1W6_LN0U_xskMwK4VNce5xAF7
34
34
  cuqi/distribution/_smoothed_laplace.py,sha256=p-1Y23mYA9omwiHGkEuv3T2mwcPAAoNlCr7T8osNkjE,2925
35
35
  cuqi/distribution/_uniform.py,sha256=7xJmCZH_LPhuGkwEDGh-_CTtzcWKrXMOxtTJUFb7Ydo,1607
36
36
  cuqi/experimental/__init__.py,sha256=vhZvyMX6rl8Y0haqCzGLPz6PSUKyu75XMQbeDHqTTrw,83
37
- cuqi/experimental/mcmc/__init__.py,sha256=8Ce1mHvfbKPe0A5gCDl5Bj4ok8bvbn90LEDvfePfNT4,536
37
+ cuqi/experimental/mcmc/__init__.py,sha256=1sn0U6Ep0x5zv2602og2DkV3Bs8hNFOiq7C3VcMimVw,4472
38
38
  cuqi/experimental/mcmc/_conjugate.py,sha256=VNPQkGity0mposcqxrx4UIeXm35EvJvZED4p2stffvA,9924
39
39
  cuqi/experimental/mcmc/_conjugate_approx.py,sha256=uEnY2ea9su5ivcNagyRAwpQP2gBY98sXU7N0y5hTADo,3653
40
40
  cuqi/experimental/mcmc/_cwmh.py,sha256=BQE7-4kbiC32TJ38rlVtfSQieoKBK5GDca3HCqHJ7zE,7135
41
41
  cuqi/experimental/mcmc/_direct.py,sha256=9pQS_2Qk2-ybt6m8WTfPoKetcxQ00WaTRN85-Z0FrBY,777
42
- cuqi/experimental/mcmc/_gibbs.py,sha256=JwQQgKd-5IPVErUgMyxtG4sCVhf7gdzSr8ttn3trktY,12596
42
+ cuqi/experimental/mcmc/_gibbs.py,sha256=W0g-BY278XoGcpWvatCJWMKnm0sfaWv60I7YDtNZRXE,12622
43
43
  cuqi/experimental/mcmc/_hmc.py,sha256=h63KT0jYq86H541hQzhHHzuLEn7vrRE_2r1o1mTEcZo,19261
44
44
  cuqi/experimental/mcmc/_langevin_algorithm.py,sha256=GKC_mlix3si_3J8E6I58ozh3ErB0XPmHMjV7sFyKLEQ,8200
45
45
  cuqi/experimental/mcmc/_laplace_approximation.py,sha256=rdiE3cMQFq6FLQcOQwPpuGIxrTAp3aoGPxMDSdeopV0,5688
@@ -76,8 +76,8 @@ cuqi/sampler/_mh.py,sha256=V5tIdn-KdfWo4J_Nbf-AH6XwKWblWUyc4BeuSikUHsE,7062
76
76
  cuqi/sampler/_pcn.py,sha256=F0h9-nUFtkqn-o-1s8BCsmr8V7u6R7ycoCOeeV1uhj0,8601
77
77
  cuqi/sampler/_rto.py,sha256=-AtMiYq4fh7pF9zVqfYjYtQbIIEGayrWyRGTj8KecfE,11518
78
78
  cuqi/sampler/_sampler.py,sha256=TkZ_WAS-5Q43oICa-Elc2gftsRTBd7PEDUMDZ9tTGmU,5712
79
- cuqi/samples/__init__.py,sha256=E7B9IBUsiOBr-HAKH9o3_Lqhq4KeWO87hmesHkdbwTY,30
80
- cuqi/samples/_samples.py,sha256=axcneMWISG9Lz9fPac03Gs_-ouB4podTfBj0e74KvRs,34738
79
+ cuqi/samples/__init__.py,sha256=vCs6lVk-pi8RBqa6cIN5wyn6u-K9oEf1Na4k1ZMrYv8,44
80
+ cuqi/samples/_samples.py,sha256=hUc8OnCF9CTCuDTrGHwwzv3wp8mG_6vsJAFvuQ-x0uA,35832
81
81
  cuqi/solver/__init__.py,sha256=DGl8IdUnochRXHNDEy_13o_VT0vLFY6FjMmmSH6YUkY,169
82
82
  cuqi/solver/_solver.py,sha256=eRmpBkHv_RXFdZTWhYqebH-toNbQcPgEgklNd5zOyOw,22803
83
83
  cuqi/testproblem/__init__.py,sha256=DWTOcyuNHMbhEuuWlY5CkYkNDSAqhvsKmJXBLivyblU,202
@@ -85,8 +85,8 @@ cuqi/testproblem/_testproblem.py,sha256=x769LwwRdJdzIiZkcQUGb_5-vynNTNALXWKato7s
85
85
  cuqi/utilities/__init__.py,sha256=H7xpJe2UinjZftKvE2JuXtTi4DqtkR6uIezStAXwfGg,428
86
86
  cuqi/utilities/_get_python_variable_name.py,sha256=QwlBVj2koJRA8s8pWd554p7-ElcI7HUwY32HknaR92E,1827
87
87
  cuqi/utilities/_utilities.py,sha256=Jc4knn80vLoA7kgw9FzXwKVFGaNBOXiA9kgvltZU3Ao,11777
88
- CUQIpy-1.1.1.post0.dev78.dist-info/LICENSE,sha256=kJWRPrtRoQoZGXyyvu50Uc91X6_0XRaVfT0YZssicys,10799
89
- CUQIpy-1.1.1.post0.dev78.dist-info/METADATA,sha256=7AYkCLYMaKu0ow2DU_n9p2aq-1NPGYlgFHKb9sRGGGc,18410
90
- CUQIpy-1.1.1.post0.dev78.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
91
- CUQIpy-1.1.1.post0.dev78.dist-info/top_level.txt,sha256=AgmgMc6TKfPPqbjV0kvAoCBN334i_Lwwojc7HE3ZwD0,5
92
- CUQIpy-1.1.1.post0.dev78.dist-info/RECORD,,
88
+ CUQIpy-1.1.1.post0.dev86.dist-info/LICENSE,sha256=kJWRPrtRoQoZGXyyvu50Uc91X6_0XRaVfT0YZssicys,10799
89
+ CUQIpy-1.1.1.post0.dev86.dist-info/METADATA,sha256=2maTuUA5SybQincsfkR-eQhNYRNGNoPUxuER4K6FJpk,18410
90
+ CUQIpy-1.1.1.post0.dev86.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
91
+ CUQIpy-1.1.1.post0.dev86.dist-info/top_level.txt,sha256=AgmgMc6TKfPPqbjV0kvAoCBN334i_Lwwojc7HE3ZwD0,5
92
+ CUQIpy-1.1.1.post0.dev86.dist-info/RECORD,,
cuqi/_version.py CHANGED
@@ -8,11 +8,11 @@ import json
8
8
 
9
9
  version_json = '''
10
10
  {
11
- "date": "2024-09-11T08:37:02+0200",
11
+ "date": "2024-09-12T20:00:34+0200",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "e332fa9b589e70ff3171d724fcc381c556631eb4",
15
- "version": "1.1.1.post0.dev78"
14
+ "full-revisionid": "464aa149f16618852db3d404a3d6702f34ffed0d",
15
+ "version": "1.1.1.post0.dev86"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
@@ -1,4 +1,112 @@
1
- """ Re-implementation of sampler module in a more object oriented way. """
1
+ """
2
+ Re-implementation of sampler module in a more object-oriented way.
3
+
4
+ Main changes for users
5
+ ----------------------
6
+
7
+ 1. Sampling API
8
+ ^^^^^^^^^^^^
9
+
10
+ Previously one would call the `.sample` or `sample_adapt` methods of a sampler instance at :py:mod:`cuqi.sampler` to sample from a target distribution and store the samples as the output as follows:
11
+
12
+ .. code-block:: python
13
+
14
+ from cuqi.sampler import MH
15
+ from cuqi.distribution import DistributionGallery
16
+
17
+ # Target distribution
18
+ target = DistributionGallery("donut")
19
+
20
+ # Set up sampler
21
+ sampler = MH(target)
22
+
23
+ # Sample from the target distribution (Alternatively calling sample with explicit scale parameter set in sampler)
24
+ samples = sampler.sample_adapt(Ns=100, Nb=100) # Burn-in (Nb) removed by default
25
+
26
+ This has now changed to to a more object-oriented API which provides more flexibility and control over the sampling process.
27
+
28
+ For example one can now more explicitly control when the sampler is tuned (warmup) and when it is sampling with fixed parameters.
29
+
30
+ .. code-block:: python
31
+
32
+ from cuqi.experimental.mcmc import MH
33
+ from cuqi.distribution import DistributionGallery
34
+
35
+ # Target distribution
36
+ target = DistributionGallery("donut")
37
+
38
+ # Set up sampler
39
+ sampler = MH(target)
40
+
41
+ # Sample from the target distribution
42
+ sampler.warmup(Nb=100) # Explicit warmup (tuning) of sampler
43
+ sampler.sample(Ns=100) # Sampling with fixed parameters
44
+ samples = sampler.get_samples().burnthin(Nb=100) # Getting samples and removing burn-in from warmup
45
+
46
+ Importantly, the removal of burn-in from e.g. warmup is now a separate step that is done after the sampling process is complete.
47
+
48
+ 2. Sampling API for BayesianProblem
49
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
50
+
51
+ :py:class:`cuqi.problem.BayesianProblem` continues to have the same API for `sample_posterior` and the `UQ` method.
52
+
53
+ There is now a flag `experimental` that can be set to `True` to use the new MCMC samplers.
54
+
55
+ By default, the flag is set to `False` and the old samplers are used.
56
+
57
+ For this more high-level interface, burn-in is automatically removed from the samples as was the case before.
58
+
59
+
60
+ 3. More options for Gibbs sampling
61
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
62
+
63
+ There are now more options for Gibbs sampling. Previously it was only possible to sample with Gibbs for samplers :py:class:`cuqi.sampler.LinearRTO`, :py:class:`cuqi.sampler.RegularizedLinearRTO`, :py:class:`cuqi.sampler.Conjugate`, and :py:class:`cuqi.sampler.ConjugateApprox`.
64
+
65
+ Now, it is possible to define a Gibbs sampling scheme using any sampler from the :py:mod:`cuqi.experimental.mcmc` module.
66
+
67
+ **Example using a NUTS-within-Gibbs scheme for a 1D deconvolution problem:**
68
+
69
+ .. code-block:: python
70
+
71
+ import cuqi
72
+ import numpy as np
73
+ from cuqi.distribution import Gamma, Gaussian, GMRF, JointDistribution
74
+ from cuqi.experimental.mcmc import NUTS, HybridGibbs, Conjugate
75
+ from cuqi.testproblem import Deconvolution1D
76
+
77
+ # Forward problem
78
+ A, y_data, info = Deconvolution1D(dim=128, phantom='sinc', noise_std=0.001).get_components()
79
+
80
+ # Bayesian Inverse Problem
81
+ s = Gamma(1, 1e-4)
82
+ x = GMRF(np.zeros(A.domain_dim), 50)
83
+ y = Gaussian(A @ x, lambda s: 1 / s)
84
+
85
+ # Posterior
86
+ target = JointDistribution(y, x, s)(y=y_data)
87
+
88
+ # Gibbs sampling strategy. Note we can define initial_points and various parameters for each sampler
89
+ sampling_strategy = {
90
+ "x": NUTS(max_depth=10, initial_point=np.zeros(A.domain_dim)),
91
+ "s": Conjugate()
92
+ }
93
+
94
+ # Here we do 10 internal steps with NUTS for each Gibbs step
95
+ num_sampling_steps = {
96
+ "x": 10,
97
+ "s": 1
98
+ }
99
+
100
+ sampler = HybridGibbs(target, sampling_strategy, num_sampling_steps)
101
+
102
+ sampler.warmup(50)
103
+ sampler.sample(200)
104
+ samples = sampler.get_samples().burnthin(Nb=50)
105
+
106
+ samples["x"].plot_ci(exact=info.exactSolution)
107
+ """
108
+
109
+
2
110
 
3
111
  from ._sampler import Sampler, ProposalBasedSampler
4
112
  from ._langevin_algorithm import ULA, MALA
@@ -1,6 +1,6 @@
1
1
  from cuqi.distribution import JointDistribution
2
2
  from cuqi.experimental.mcmc import Sampler
3
- from cuqi.samples import Samples
3
+ from cuqi.samples import Samples, JointSamples
4
4
  from cuqi.experimental.mcmc import NUTS
5
5
  from typing import Dict
6
6
  import numpy as np
@@ -197,7 +197,7 @@ class HybridGibbs:
197
197
  return self
198
198
 
199
199
  def get_samples(self) -> Dict[str, Samples]:
200
- samples_object = {}
200
+ samples_object = JointSamples()
201
201
  for par_name in self.par_names:
202
202
  samples_array = np.array(self.samples[par_name]).T
203
203
  samples_object[par_name] = Samples(samples_array, self.target.get_density(par_name).geometry)
cuqi/samples/__init__.py CHANGED
@@ -1 +1 @@
1
- from ._samples import Samples
1
+ from ._samples import Samples, JointSamples
cuqi/samples/_samples.py CHANGED
@@ -867,3 +867,23 @@ class Samples(object):
867
867
  "Geometry:\n {}\n\n".format(self.geometry) + \
868
868
  "Shape:\n {}\n\n".format(self.shape) + \
869
869
  "Samples:\n {}\n\n".format(self.samples)
870
+
871
+ class JointSamples(dict):
872
+ """ An object used to store samples from :class:`cuqi.distribution.JointDistribution`.
873
+
874
+ This object is a simple overload of the dictionary class to allow easy access to certain methods
875
+ of Samples objects without having to iterate over each key in the dictionary.
876
+
877
+ """
878
+
879
+ def burnthin(self, Nb, Nt=1):
880
+ """ Remove burn-in and thin samples for all samples in the dictionary. Returns a copy of the samples stored in the dictionary. """
881
+ return JointSamples({key: samples.burnthin(Nb, Nt) for key, samples in self.items()})
882
+
883
+ def __repr__(self) -> str:
884
+ return "CUQIpy JointSamples Dict:\n" + \
885
+ "-------------------------\n\n" + \
886
+ "Keys:\n {}\n\n".format(list(self.keys())) + \
887
+ "Ns (number of samples):\n {}\n\n".format({key: samples.Ns for key, samples in self.items()}) + \
888
+ "Geometry:\n {}\n\n".format({key: samples.geometry for key, samples in self.items()}) + \
889
+ "Shape:\n {}\n\n".format({key: samples.shape for key, samples in self.items()})