CUQIpy 0.5.0.post0.dev5__py3-none-any.whl → 0.5.0.post0.dev9__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: 0.5.0.post0.dev5
3
+ Version: 0.5.0.post0.dev9
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>
6
6
  License: Apache License
@@ -1,6 +1,6 @@
1
1
  cuqi/__init__.py,sha256=K0ss2HNqoLUX7wGpSZdaPKxIaKdRS452fcJm4D0pcEs,433
2
2
  cuqi/_messages.py,sha256=fzEBrZT2kbmfecBBPm7spVu7yHdxGARQB4QzXhJbCJ0,415
3
- cuqi/_version.py,sha256=WVjSXW13o8zy07cCEoHRqZbhu68pBwi9VKjaFhBJ6kk,508
3
+ cuqi/_version.py,sha256=vnMFIrl_UUi9EYW6QMKBgDq_UFPEIOG2z_1uTDOOpjk,508
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
@@ -47,7 +47,7 @@ cuqi/sampler/_conjugate.py,sha256=Ip3HM12j8Bq9T0925N007_o-2xrKsn6q-KMf6vqYPVs,15
47
47
  cuqi/sampler/_conjugate_approx.py,sha256=xX-X71EgxGnZooOY6CIBhuJTs3dhcKfoLnoFxX3CO2g,1938
48
48
  cuqi/sampler/_cwmh.py,sha256=VlAVT1SXQU0yD5ZeR-_ckWvX-ifJrMweFFdFbxdfB_k,7775
49
49
  cuqi/sampler/_gibbs.py,sha256=4q4PGqLpbGTe5-n8nwzCNEoCKYO43T4lxkFJ5H-eQNQ,8626
50
- cuqi/sampler/_hmc.py,sha256=S83pTw25oHk9R7o1dwXX-pymrZQpn6t-3Tf2wP1hSTw,12140
50
+ cuqi/sampler/_hmc.py,sha256=76nPkvNU0wLSg4qvm-1s048MzQasl5Qk94sHpyeJ5hM,14819
51
51
  cuqi/sampler/_langevin_algorithm.py,sha256=Xk6BkhzwJesKMZEIZMYtbc-2KU7Essdk6abLvthMkRY,7860
52
52
  cuqi/sampler/_laplace_approximation.py,sha256=TyvigbxB1L2ClPhk5xL2WEwv12wMvS6hRV5NMDsyek8,6456
53
53
  cuqi/sampler/_mh.py,sha256=V5tIdn-KdfWo4J_Nbf-AH6XwKWblWUyc4BeuSikUHsE,7062
@@ -63,8 +63,8 @@ cuqi/testproblem/_testproblem.py,sha256=1a52jc92NqsLRGyM5DLySNW0lVVOC6tkyKM_QV4K
63
63
  cuqi/utilities/__init__.py,sha256=EfxHLdsyDNugbmbzs43nV_AeKcycM9sVBjG9WZydagA,351
64
64
  cuqi/utilities/_get_python_variable_name.py,sha256=QwlBVj2koJRA8s8pWd554p7-ElcI7HUwY32HknaR92E,1827
65
65
  cuqi/utilities/_utilities.py,sha256=rjycaxDWExdskIfYXV1z5ZlB0JTlqv3tCmKf08i6U5c,7973
66
- CUQIpy-0.5.0.post0.dev5.dist-info/LICENSE,sha256=kJWRPrtRoQoZGXyyvu50Uc91X6_0XRaVfT0YZssicys,10799
67
- CUQIpy-0.5.0.post0.dev5.dist-info/METADATA,sha256=MQZGzMO78uAG0Y7GTwpZdTPFqcHHlTld_ysBXszItiU,16420
68
- CUQIpy-0.5.0.post0.dev5.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
69
- CUQIpy-0.5.0.post0.dev5.dist-info/top_level.txt,sha256=AgmgMc6TKfPPqbjV0kvAoCBN334i_Lwwojc7HE3ZwD0,5
70
- CUQIpy-0.5.0.post0.dev5.dist-info/RECORD,,
66
+ CUQIpy-0.5.0.post0.dev9.dist-info/LICENSE,sha256=kJWRPrtRoQoZGXyyvu50Uc91X6_0XRaVfT0YZssicys,10799
67
+ CUQIpy-0.5.0.post0.dev9.dist-info/METADATA,sha256=YH1Nh4y7MOu3BrNEdBfqonhGEOVclxTImBL3_TOGUTg,16420
68
+ CUQIpy-0.5.0.post0.dev9.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
69
+ CUQIpy-0.5.0.post0.dev9.dist-info/top_level.txt,sha256=AgmgMc6TKfPPqbjV0kvAoCBN334i_Lwwojc7HE3ZwD0,5
70
+ CUQIpy-0.5.0.post0.dev9.dist-info/RECORD,,
cuqi/_version.py CHANGED
@@ -8,11 +8,11 @@ import json
8
8
 
9
9
  version_json = '''
10
10
  {
11
- "date": "2023-09-14T11:43:13+0200",
11
+ "date": "2023-09-20T08:59:50+0200",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "10df75286cece2b7b0876697501f4d2354b36f5f",
15
- "version": "0.5.0.post0.dev5"
14
+ "full-revisionid": "5aa5af171cc495556f93f0ceecc78606ad9b9185",
15
+ "version": "0.5.0.post0.dev9"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
cuqi/sampler/_hmc.py CHANGED
@@ -58,20 +58,75 @@ class NUTS(Sampler):
58
58
  # Plot samples
59
59
  samples.plot_pair()
60
60
 
61
+ After running the NUTS sampler, run diagnostics can be accessed via the
62
+ following attributes:
63
+
64
+ .. code-block:: python
65
+
66
+ # Number of tree nodes created each NUTS iteration
67
+ sampler.num_tree_node_list
68
+
69
+ # Step size used in each NUTS iteration
70
+ sampler.epsilon_list
71
+
72
+ # Suggested step size during adaptation (the value of this step size is
73
+ # only used after adaptation). The suggested step size is None if
74
+ # adaptation is not requested.
75
+ sampler.epsilon_bar_list
76
+
77
+ # Additionally, iterations' number can be accessed via
78
+ sampler.iteration_list
79
+
61
80
  """
62
81
  def __init__(self, target, x0=None, max_depth=15, adapt_step_size=True, opt_acc_rate=0.6, **kwargs):
63
82
  super().__init__(target, x0=x0, **kwargs)
64
83
  self.max_depth = max_depth
65
84
  self.adapt_step_size = adapt_step_size
66
85
  self.opt_acc_rate = opt_acc_rate
67
-
86
+
87
+ # NUTS run diagnostic
88
+ # number of tree nodes created each NUTS iteration
89
+ self._num_tree_node = 0
90
+ # Create lists to store NUTS run diagnostics
91
+ self._create_run_diagnostic_attributes()
92
+
93
+ def _create_run_diagnostic_attributes(self):
94
+ """A method to create attributes to store NUTS run diagnostic."""
95
+ self._reset_run_diagnostic_attributes()
96
+
97
+ def _reset_run_diagnostic_attributes(self):
98
+ """A method to reset attributes to store NUTS run diagnostic."""
99
+ # NUTS iterations
100
+ self.iteration_list = []
101
+ # List to store number of tree nodes created each NUTS iteration
102
+ self.num_tree_node_list = []
103
+ # List of step size used in each NUTS iteration
104
+ self.epsilon_list = []
105
+ # List of burn-in step size suggestion during adaptation
106
+ # only used when adaptation is done
107
+ # remains fixed after adaptation (after burn-in)
108
+ self.epsilon_bar_list = []
109
+
110
+ def _update_run_diagnostic_attributes(self, k, n_tree, eps, eps_bar):
111
+ """A method to update attributes to store NUTS run diagnostic."""
112
+ # Store the current iteration number k
113
+ self.iteration_list.append(k)
114
+ # Store the number of tree nodes created in iteration k
115
+ self.num_tree_node_list.append(n_tree)
116
+ # Store the step size used in iteration k
117
+ self.epsilon_list.append(eps)
118
+ # Store the step size suggestion during adaptation in iteration k
119
+ self.epsilon_bar_list.append(eps_bar)
120
+
68
121
  def _nuts_target(self, x): # returns logposterior tuple evaluation-gradient
69
122
  return self.target.logd(x), self.target.gradient(x)
70
123
 
71
124
  def _sample_adapt(self, N, Nb):
72
125
  return self._sample(N, Nb)
73
-
126
+
74
127
  def _sample(self, N, Nb):
128
+ # Reset run diagnostic attributes
129
+ self._reset_run_diagnostic_attributes()
75
130
 
76
131
  if self.adapt_step_size is True and Nb == 0:
77
132
  raise ValueError("Adaptive step size is True but number of burn-in steps is 0. Please set Nb > 0.")
@@ -86,6 +141,9 @@ class NUTS(Sampler):
86
141
  theta[:, 0] = self.x0
87
142
  joint_eval[0], grad = self._nuts_target(self.x0)
88
143
 
144
+ # Step size variables
145
+ epsilon, epsilon_bar = None, None
146
+
89
147
  # parameters dual averaging
90
148
  if (self.adapt_step_size == True):
91
149
  epsilon = self._FindGoodEpsilon(theta[:, 0], joint_eval[0], grad)
@@ -101,6 +159,9 @@ class NUTS(Sampler):
101
159
 
102
160
  # run NUTS
103
161
  for k in range(1, Ns):
162
+ # reset number of tree nodes for each iteration
163
+ self._num_tree_node = 0
164
+
104
165
  theta_k, joint_k = theta[:, k-1], joint_eval[k-1] # initial position (parameters)
105
166
  r_k = self._Kfun(1, 'sample') # resample momentum vector
106
167
  Ham = joint_k - self._Kfun(r_k, 'eval') # Hamiltonian
@@ -143,6 +204,10 @@ class NUTS(Sampler):
143
204
  s = s_prime * int((dtheta @ r_minus.T) >= 0) * int((dtheta @ r_plus.T) >= 0)
144
205
  j += 1
145
206
 
207
+ # update run diagnostic attributes
208
+ self._update_run_diagnostic_attributes(
209
+ k, self._num_tree_node, epsilon, epsilon_bar)
210
+
146
211
  # adapt epsilon during burn-in using dual averaging
147
212
  if (k <= Nb) and (self.adapt_step_size == True):
148
213
  eta1 = 1/(k + t_0)
@@ -160,7 +225,7 @@ class NUTS(Sampler):
160
225
 
161
226
  if np.isnan(joint_eval[k]):
162
227
  raise NameError('NaN potential func')
163
-
228
+
164
229
  # apply burn-in
165
230
  theta = theta[:, Nb:]
166
231
  joint_eval = joint_eval[Nb:]
@@ -211,6 +276,9 @@ class NUTS(Sampler):
211
276
  #=========================================================================
212
277
  # @functools.lru_cache(maxsize=128)
213
278
  def _BuildTree(self, theta, r, grad, Ham, log_u, v, j, epsilon, Delta_max=1000):
279
+ # Increment the number of tree nodes counter
280
+ self._num_tree_node += 1
281
+
214
282
  if (j == 0): # base case
215
283
  # single leapfrog step in the direction v
216
284
  theta_prime, r_prime, joint_prime, grad_prime = self._Leapfrog(theta, r, grad, v*epsilon)