Skip to content

Commit 75a7b7d

Browse files
author
John Halloran
committed
style: update docstring defaults
1 parent 915f052 commit 75a7b7d

File tree

2 files changed

+29
-27
lines changed

2 files changed

+29
-27
lines changed

src/diffpy/snmf/main.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import numpy as np
22
from snmf_class import SNMFOptimizer
33

4-
init_components_file = np.loadtxt("input/X0.txt", dtype=float)
5-
source_matrix_file = np.loadtxt("input/MM.txt", dtype=float)
6-
init_stretch_file = np.loadtxt("input/A0.txt", dtype=float)
7-
init_weights_file = np.loadtxt("input/W0.txt", dtype=float)
4+
# Example input files (not provided)
5+
init_components_file = np.loadtxt("input/init_components.txt", dtype=float)
6+
source_matrix_file = np.loadtxt("input/source_matrix.txt", dtype=float)
7+
init_stretch_file = np.loadtxt("input/init_stretch.txt", dtype=float)
8+
init_weights_file = np.loadtxt("input/init_weights.txt", dtype=float)
89

910
my_model = SNMFOptimizer(
1011
source_matrix=source_matrix_file,

src/diffpy/snmf/snmf_class.py

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class SNMFOptimizer:
1818
----------
1919
source_matrix : ndarray
2020
The original, unmodified data to be decomposed and later, compared against.
21-
Shape is (length_of_signal, number_of_conditions).
21+
Shape is (length_of_signal, number_of_signals).
2222
stretch : ndarray
2323
The best guess (or while running, the current guess) for the stretching
2424
factor matrix.
@@ -47,14 +47,14 @@ class SNMFOptimizer:
4747
The number of components to extract from source_matrix. Must be provided when and only when
4848
Y0 is not provided.
4949
random_state : int
50-
The seed for the initial guesses at the matrices (A, X, and Y) created by
50+
The seed for the initial guesses at the matrices (stretch, components, and weights) created by
5151
the decomposition.
5252
num_updates : int
53-
The total number of times that any of (A, X, and Y) have had their values changed.
53+
The total number of times that any of (stretch, components, and weights) have had their values changed.
5454
If not terminated by other means, this value is used to stop when reaching max_iter.
5555
objective_function: float
5656
The value corresponding to the minimization of the difference between the source_matrix and the
57-
products of A, X, and Y. For full details see the sNMF paper. Smaller corresponds to
57+
products of (stretch, components, and weights). For full details see the sNMF paper. Smaller corresponds to
5858
better agreement and is desirable.
5959
objective_difference : float
6060
The change in the objective function value since the last update. A negative value
@@ -67,8 +67,8 @@ def __init__(
6767
init_weights=None,
6868
init_components=None,
6969
init_stretch=None,
70-
rho=1e12,
71-
eta=610,
70+
rho=0,
71+
eta=0,
7272
max_iter=500,
7373
tol=5e-7,
7474
n_components=None,
@@ -80,35 +80,36 @@ def __init__(
8080
----------
8181
source_matrix : ndarray
8282
The data to be decomposed. Shape is (length_of_signal, number_of_conditions).
83-
init_weights : ndarray
83+
init_weights : ndarray Optional Default = rng.beta(a=2.5, b=1.5, size=(n_components, n_signals))
8484
The initial guesses for the component weights at each stretching condition.
85-
Shape is (number_of_components, number_of_conditions) Must provide exactly one
85+
Shape is (number_of_components, number_of_signals) Must provide exactly one
8686
of this or n_components.
87-
init_components : ndarray
87+
init_components : ndarray Optional Default = rng.random((self.signal_length, self.n_components))
8888
The initial guesses for the intensities of each component per
8989
row/sample/angle. Shape is (length_of_signal, number_of_components).
90-
init_stretch : ndarray
90+
init_stretch : ndarray Optional Default = np.ones((self.n_components, self.n_signals)) + self._rng.normal(
91+
0, 1e-3, size=(self.n_components, self.n_signals)
9192
The initial guesses for the stretching factor for each component, at each
92-
condition. Shape is (number_of_components, number_of_conditions).
93-
rho : float
93+
condition (for each signal). Shape is (number_of_components, number_of_signals).
94+
rho : float Optional Default = 0
9495
The stretching factor that influences the decomposition. Zero corresponds to no
9596
stretching present. Relatively insensitive and typically adjusted in powers of 10.
96-
eta : float
97+
eta : int Optional Default = 0
9798
The sparsity factor that influences the decomposition. Should be set to zero for
9899
non-sparse data such as PDF. Can be used to improve results for sparse data such
99100
as XRD, but due to instability, should be used only after first selecting the
100101
best value for rho. Suggested adjustment is by powers of 2.
101-
max_iter : int
102+
max_iter : int Optional Default = 500
102103
The maximum number of times to update each of A, X, and Y before stopping
103104
the optimization.
104-
tol : float
105+
tol : float Optional Default = 5e-7
105106
The convergence threshold. This is the minimum fractional improvement in the
106107
objective function to allow without terminating the optimization. Note that
107108
a minimum of 20 updates are run before this parameter is checked.
108-
n_components : int
109+
n_components : int Optional Default = None
109110
The number of components to extract from source_matrix. Must be provided when and only when
110111
Y0 is not provided.
111-
random_state : int
112+
random_state : int Optional Default = None
112113
The seed for the initial guesses at the matrices (A, X, and Y) created by
113114
the decomposition.
114115
"""
@@ -157,10 +158,10 @@ def __init__(
157158
self.weights = np.maximum(0, self.weights)
158159

159160
# Second-order spline: Tridiagonal (-2 on diagonal, 1 on sub/superdiagonals)
160-
self.spline_smooth_operator = 0.25 * diags(
161+
self._spline_smooth_operator = 0.25 * diags(
161162
[1, -2, 1], offsets=[0, 1, 2], shape=(self.n_signals - 2, self.n_signals)
162163
)
163-
self.spline_smooth_penalty = self.spline_smooth_operator.T @ self.spline_smooth_operator
164+
self._spline_smooth_penalty = self._spline_smooth_operator.T @ self._spline_smooth_operator
164165

165166
# Set up residual matrix, objective function, and history
166167
self.residuals = self.get_residual_matrix()
@@ -173,7 +174,7 @@ def __init__(
173174
self.grad_components = np.zeros_like(self.components) # Gradient of X (zeros for now)
174175
self._prev_grad_components = np.zeros_like(self.components) # Previous gradient of X (zeros for now)
175176

176-
regularization_term = 0.5 * rho * np.linalg.norm(self.spline_smooth_operator @ self.stretch.T, "fro") ** 2
177+
regularization_term = 0.5 * rho * np.linalg.norm(self._spline_smooth_operator @ self.stretch.T, "fro") ** 2
177178
sparsity_term = eta * np.sum(np.sqrt(self.components)) # Square root penalty
178179
print(
179180
f"Start, Objective function: {self.objective_function:.5e}"
@@ -185,7 +186,7 @@ def __init__(
185186
self.optimize_loop()
186187
# Print diagnostics
187188
regularization_term = (
188-
0.5 * rho * np.linalg.norm(self.spline_smooth_operator @ self.stretch.T, "fro") ** 2
189+
0.5 * rho * np.linalg.norm(self._spline_smooth_operator @ self.stretch.T, "fro") ** 2
189190
)
190191
sparsity_term = eta * np.sum(np.sqrt(self.components)) # Square root penalty
191192
print(
@@ -333,7 +334,7 @@ def get_objective_function(self, residuals=None, stretch=None):
333334
if stretch is None:
334335
stretch = self.stretch
335336
residual_term = 0.5 * np.linalg.norm(residuals, "fro") ** 2
336-
regularization_term = 0.5 * self.rho * np.linalg.norm(self.spline_smooth_operator @ stretch.T, "fro") ** 2
337+
regularization_term = 0.5 * self.rho * np.linalg.norm(self._spline_smooth_operator @ stretch.T, "fro") ** 2
337338
sparsity_term = self.eta * np.sum(np.sqrt(self.components)) # Square root penalty
338339
# Final objective function value
339340
function = residual_term + regularization_term + sparsity_term
@@ -652,7 +653,7 @@ def regularize_function(self, stretch=None):
652653
)
653654
der_reshaped = np.asarray(tiled_derivative).reshape((self.n_signals, self.n_components), order="F")
654655
func_grad = (
655-
der_reshaped.T + self.rho * stretch @ self.spline_smooth_operator.T @ self.spline_smooth_operator
656+
der_reshaped.T + self.rho * stretch @ self._spline_smooth_operator.T @ self._spline_smooth_operator
656657
)
657658

658659
return reg_func, func_grad

0 commit comments

Comments
 (0)