GroupMultiNeSS 0.0.2__tar.gz → 0.0.4__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.
- {groupmultiness-0.0.2 → groupmultiness-0.0.4}/GroupMultiNeSS/MASE.py +20 -5
- {groupmultiness-0.0.2 → groupmultiness-0.0.4}/GroupMultiNeSS/data_generation.py +63 -0
- {groupmultiness-0.0.2 → groupmultiness-0.0.4}/GroupMultiNeSS/group_multiness.py +0 -1
- {groupmultiness-0.0.2 → groupmultiness-0.0.4}/GroupMultiNeSS/utils.py +16 -14
- {groupmultiness-0.0.2 → groupmultiness-0.0.4}/GroupMultiNeSS.egg-info/PKG-INFO +4 -4
- {groupmultiness-0.0.2 → groupmultiness-0.0.4}/PKG-INFO +4 -4
- {groupmultiness-0.0.2 → groupmultiness-0.0.4}/README.md +3 -3
- {groupmultiness-0.0.2 → groupmultiness-0.0.4}/setup.py +1 -1
- {groupmultiness-0.0.2 → groupmultiness-0.0.4}/GroupMultiNeSS/__init__.py +0 -0
- {groupmultiness-0.0.2 → groupmultiness-0.0.4}/GroupMultiNeSS/base.py +0 -0
- {groupmultiness-0.0.2 → groupmultiness-0.0.4}/GroupMultiNeSS/multiness.py +0 -0
- {groupmultiness-0.0.2 → groupmultiness-0.0.4}/GroupMultiNeSS/shared_space_hunting.py +0 -0
- {groupmultiness-0.0.2 → groupmultiness-0.0.4}/GroupMultiNeSS.egg-info/SOURCES.txt +0 -0
- {groupmultiness-0.0.2 → groupmultiness-0.0.4}/GroupMultiNeSS.egg-info/dependency_links.txt +0 -0
- {groupmultiness-0.0.2 → groupmultiness-0.0.4}/GroupMultiNeSS.egg-info/requires.txt +0 -0
- {groupmultiness-0.0.2 → groupmultiness-0.0.4}/GroupMultiNeSS.egg-info/top_level.txt +0 -0
- {groupmultiness-0.0.2 → groupmultiness-0.0.4}/LICENSE +0 -0
- {groupmultiness-0.0.2 → groupmultiness-0.0.4}/setup.cfg +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
from typing import List
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
from .utils import truncated_svd, truncated_eigen_decomposition
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
def MASE(As: np.array, d_shared: int, d_individs: List[int]):
|
|
@@ -42,7 +43,8 @@ def MASE(As: np.array, d_shared: int, d_individs: List[int]):
|
|
|
42
43
|
return ps, u_joint, rs
|
|
43
44
|
|
|
44
45
|
|
|
45
|
-
def ASE(A: np.array, d: int, check_if_symmetric=True
|
|
46
|
+
def ASE(A: np.array, d: int, check_if_symmetric: bool = True,
|
|
47
|
+
indef_inner_prod: bool = True, return_signature=False):
|
|
46
48
|
"""
|
|
47
49
|
Compute the Adjacency Spectral Embedding (ASE) of a symmetric adjacency matrix.
|
|
48
50
|
|
|
@@ -54,6 +56,11 @@ def ASE(A: np.array, d: int, check_if_symmetric=True):
|
|
|
54
56
|
Embedding dimension.
|
|
55
57
|
check_if_symmetric : bool, optional
|
|
56
58
|
Whether to check symmetry of A. Default is True.
|
|
59
|
+
indef_inner_prod: bool, optional
|
|
60
|
+
If True, indefinite inner product with signature (p, d - p) is assumed (GRDPG model).
|
|
61
|
+
If False, standard inner product is assumed (RDPG model)
|
|
62
|
+
return_signature: bool, optional
|
|
63
|
+
Whether to return_signature of the inner product. Only used when indef_inner_prod is TrueDefault is False.
|
|
57
64
|
|
|
58
65
|
Returns
|
|
59
66
|
-------
|
|
@@ -67,6 +74,14 @@ def ASE(A: np.array, d: int, check_if_symmetric=True):
|
|
|
67
74
|
"""
|
|
68
75
|
if check_if_symmetric:
|
|
69
76
|
assert np.allclose(A, A.T), "A should be a symmetric matrix"
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
77
|
+
eigvals, eigvecs = truncated_eigen_decomposition(A, max_rank=d, which="LM" if indef_inner_prod else "LA")
|
|
78
|
+
if indef_inner_prod:
|
|
79
|
+
sort_idx = np.argsort(eigvals)[::-1]
|
|
80
|
+
eigvals = eigvals[sort_idx]
|
|
81
|
+
eigvecs = eigvecs[:, :sort_idx]
|
|
82
|
+
signature = np.where(eigvals > 0, 1., -1)
|
|
83
|
+
ase = eigvecs @ np.diag(np.sqrt(np.abs(eigvals)))
|
|
84
|
+
return (ase, signature) if return_signature else ase
|
|
85
|
+
else:
|
|
86
|
+
ase = eigvecs @ np.diag(np.sqrt(np.clip(eigvals, a_min=0, a_max=None)))
|
|
87
|
+
return ase
|
|
@@ -6,6 +6,39 @@ from .utils import sigmoid, generate_matrices_given_pairwise_max_cosines
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class LatentPositionGenerator:
|
|
9
|
+
"""
|
|
10
|
+
Generator of latent positions for MultiNeSS model.
|
|
11
|
+
|
|
12
|
+
This class simulates multiple network layers that share a common latent component and
|
|
13
|
+
layer-specific deviations. It supports normal and Bernoulli edge generation models
|
|
14
|
+
and can impose angle constraints between latent spaces.
|
|
15
|
+
|
|
16
|
+
Parameters
|
|
17
|
+
----------
|
|
18
|
+
n_nodes : int
|
|
19
|
+
Number of nodes in each network layer.
|
|
20
|
+
n_layers : int
|
|
21
|
+
Number of network layers to generate.
|
|
22
|
+
edge_distrib : {'normal', 'bernoulli'}, default='normal'
|
|
23
|
+
Type of edge distribution. If 'normal', edges are generated with Gaussian noise.
|
|
24
|
+
If 'bernoulli', edges are drawn as Bernoulli random variables.
|
|
25
|
+
noise_sigma : float, default=1.0
|
|
26
|
+
Standard deviation of the Gaussian noise for normal-distributed edges.
|
|
27
|
+
loops_allowed : bool, default=True
|
|
28
|
+
Whether self-loops (diagonal entries) are allowed.
|
|
29
|
+
d_shared : int, default=2
|
|
30
|
+
Dimension of the shared latent space component.
|
|
31
|
+
d_individs : int or list of int, default=2
|
|
32
|
+
Dimension(s) of the individual latent spaces for each layer.
|
|
33
|
+
s_vu : float, default=0.0
|
|
34
|
+
Target cosine similarity between shared and individual latent components.
|
|
35
|
+
s_uu : float, default=0.0
|
|
36
|
+
Target cosine similarity among individual latent components.
|
|
37
|
+
comps_max_cosine_mat : np.ndarray, optional
|
|
38
|
+
Custom cosine similarity matrix between components.
|
|
39
|
+
min_V_max_U_eigval_ratio : float, optional
|
|
40
|
+
Ratio to scale individual latent components relative to the shared component.
|
|
41
|
+
"""
|
|
9
42
|
def __init__(self, n_nodes, n_layers, *,
|
|
10
43
|
edge_distrib: str = "normal",
|
|
11
44
|
noise_sigma: float = 1.,
|
|
@@ -110,6 +143,36 @@ class LatentPositionGenerator:
|
|
|
110
143
|
|
|
111
144
|
|
|
112
145
|
class GroupLatentPositionGenerator(LatentPositionGenerator):
|
|
146
|
+
"""
|
|
147
|
+
Generator of latent positions for GroupMultiNeSS model.
|
|
148
|
+
|
|
149
|
+
Parameters
|
|
150
|
+
----------
|
|
151
|
+
n_nodes : int
|
|
152
|
+
Number of nodes in each network layer.
|
|
153
|
+
n_layers : int
|
|
154
|
+
Number of network layers to generate.
|
|
155
|
+
group_indices : list of int
|
|
156
|
+
Group index for each layer, specifying which group latent component applies.
|
|
157
|
+
edge_distrib : {'normal', 'bernoulli'}, default='normal'
|
|
158
|
+
Type of edge distribution for generated networks.
|
|
159
|
+
noise_sigma : float, default=1.0
|
|
160
|
+
Standard deviation of Gaussian noise for normal-distributed edges.
|
|
161
|
+
loops_allowed : bool, default=True
|
|
162
|
+
Whether self-loops (diagonal entries) are allowed.
|
|
163
|
+
d_shared : int, default=2
|
|
164
|
+
Dimension of the shared latent space component.
|
|
165
|
+
d_individs : int or list of int, default=2
|
|
166
|
+
Dimension(s) of individual latent spaces for each layer.
|
|
167
|
+
d_groups : int or list of int, default=2
|
|
168
|
+
Dimension(s) of group-specific latent spaces.
|
|
169
|
+
s_vw, s_vu, s_ww, s_wu, s_uu : float, default=0.0
|
|
170
|
+
Target cosine similarities among shared, group, and individual components.
|
|
171
|
+
comps_max_cosine_mat : np.ndarray, optional
|
|
172
|
+
Predefined cosine similarity matrix among all latent components.
|
|
173
|
+
min_V_max_W_eigval_ratio : float, optional
|
|
174
|
+
Ratio to scale group latent spaces relative to the shared component.
|
|
175
|
+
"""
|
|
113
176
|
def __init__(self, n_nodes: int, n_layers: int, *,
|
|
114
177
|
group_indices: List[int],
|
|
115
178
|
edge_distrib: str = "normal",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import numpy as np
|
|
2
|
-
from scipy.sparse.linalg import svds
|
|
2
|
+
from scipy.sparse.linalg import svds, eigsh
|
|
3
3
|
from typing import List, Union, Tuple
|
|
4
4
|
from copy import copy
|
|
5
|
-
from scipy.
|
|
5
|
+
from scipy.linalg import sqrtm
|
|
6
6
|
from sklearn.model_selection import KFold
|
|
7
7
|
|
|
8
8
|
|
|
@@ -197,18 +197,13 @@ def soft_thresholding_operator(A, threshold, max_rank=None):
|
|
|
197
197
|
return u @ np.diag(s) @ vt
|
|
198
198
|
|
|
199
199
|
|
|
200
|
-
def matrix_power(A: np.array, p: Union[int, float], eps=1e-8):
|
|
201
|
-
if isinstance(p, int):
|
|
202
|
-
return np.linalg.matrix_power(A, p)
|
|
203
|
-
u, s, vt = np.linalg.svd(A)
|
|
204
|
-
assert np.all(s > eps), "float powers defined only for matrices with all positive singular values"
|
|
205
|
-
return u @ np.diag(s ** p) @ vt
|
|
206
|
-
|
|
207
|
-
|
|
208
200
|
def frobenius_error(A_true, A_pred, relative=False, include_offdiag=True):
|
|
209
201
|
assert A_true.shape == A_pred.shape
|
|
210
202
|
assert A_true.ndim <= 2
|
|
211
|
-
|
|
203
|
+
if include_offdiag or A_true.ndim == 1:
|
|
204
|
+
mask = np.ones(A_true.shape, dtype=bool)
|
|
205
|
+
else:
|
|
206
|
+
mask = ~np.eye(A_true.shape[0], dtype=bool)
|
|
212
207
|
abs_error = np.sqrt(np.sum((A_true - A_pred) ** 2, where=mask))
|
|
213
208
|
return abs_error / np.sqrt(np.sum(A_true ** 2, where=mask)) if relative else abs_error
|
|
214
209
|
|
|
@@ -280,7 +275,9 @@ def rectangular_eye(n: int, d: int):
|
|
|
280
275
|
return eye
|
|
281
276
|
|
|
282
277
|
|
|
283
|
-
def generate_matrices_given_pairwise_max_cosines(n: int,
|
|
278
|
+
def generate_matrices_given_pairwise_max_cosines(n: int,
|
|
279
|
+
ds: list[int], pairwise_cos_mat: np.ndarray,
|
|
280
|
+
eps=1e-6):
|
|
284
281
|
assert pairwise_cos_mat.ndim == 2
|
|
285
282
|
assert len(ds) == len(pairwise_cos_mat)
|
|
286
283
|
assert np.allclose(pairwise_cos_mat, pairwise_cos_mat.T), "pairwise_cos_mat should be symmetric"
|
|
@@ -288,11 +285,16 @@ def generate_matrices_given_pairwise_max_cosines(n: int, ds: list[int], pairwise
|
|
|
288
285
|
assert np.allclose(np.diag(pairwise_cos_mat), 1)
|
|
289
286
|
assert np.all(pairwise_cos_mat >= 0) & np.all(pairwise_cos_mat <= 1), "pairwise_cos_mat entries should be in [0, 1]"
|
|
290
287
|
m = len(ds)
|
|
291
|
-
|
|
288
|
+
d_total = sum(ds)
|
|
289
|
+
stacked_Vs = np.random.randn(n, d_total)
|
|
292
290
|
cur_gram_mat = stacked_Vs.T @ stacked_Vs / n
|
|
293
291
|
target_gram_mat = np.block([[pairwise_cos_mat[i, j] * rectangular_eye(ds[i], ds[j]) for j in range(m)]
|
|
294
292
|
for i in range(m)])
|
|
295
|
-
|
|
293
|
+
|
|
294
|
+
sqrt_cur_gram_mat = np.real(sqrtm(cur_gram_mat + eps * np.eye(d_total)))
|
|
295
|
+
sqrt_target_gram_mat = np.real(sqrtm(target_gram_mat + eps * np.eye(d_total)))
|
|
296
|
+
|
|
297
|
+
stacked_Vs = stacked_Vs @ np.linalg.pinv(sqrt_cur_gram_mat) @ sqrt_target_gram_mat
|
|
296
298
|
cumsum_ds = [0] + list(np.cumsum(ds))
|
|
297
299
|
return [stacked_Vs[:, s: e] for s, e in zip(cumsum_ds[:-1], cumsum_ds[1:])]
|
|
298
300
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: GroupMultiNeSS
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.4
|
|
4
4
|
Summary: GroupMultiNeSS package
|
|
5
5
|
Author: Alexander Kagan
|
|
6
6
|
Author-email: <amkagan@umich.edu>
|
|
@@ -34,11 +34,11 @@ Dynamic: summary
|
|
|
34
34
|
|
|
35
35
|
# GroupMultiNeSS
|
|
36
36
|
|
|
37
|
-
GroupMultiNeSS is a package for statistical modeling of multilayer networks. It implements multiple approaches allowing to extract shared, group, and individual latent structures from a collection of networks on a shared set of nodes. Specifically, it contains the implementation of fitting sampling procedures for the following models:
|
|
37
|
+
GroupMultiNeSS is a package for statistical modeling of multilayer networks. It implements multiple approaches allowing to extract shared, group, and individual latent structures from a collection of networks on a shared set of nodes. Specifically, it contains the implementation of fitting and sampling procedures for the following models:
|
|
38
38
|
- GroupMultiNeSS [Kagan et al. (2025)] - likelihood based approach with nuclear norm penalization, accounts for the additional group latent structure
|
|
39
39
|
- MultiNeSS [[MacDonald et al. (2021)](https://arxiv.org/abs/2012.14409)] - likelihood based approach with nuclear norm penalization
|
|
40
40
|
- MultiNeSS [[Tian et al. (2024)](https://arxiv.org/abs/2412.02151)] - likelihood based approach with pre-estimation of latent ranks via Shared Space Hunting algorithm
|
|
41
|
-
- COSIE
|
|
41
|
+
- COSIE [[Arroyo et al. (2020)](https://arxiv.org/abs/1906.10026)] - spectral-based Multiple Adjacency Spectral Embedding algorithm
|
|
42
42
|
|
|
43
43
|
## Installation
|
|
44
44
|
|
|
@@ -81,7 +81,7 @@ print(group_multiness.make_final_error_report(S_true, Qs_true, Rs_true, Ps=Ps_tr
|
|
|
81
81
|
|
|
82
82
|
MIT License
|
|
83
83
|
|
|
84
|
-
Copyright (c)
|
|
84
|
+
Copyright (c) 2025 Alexander Kagan
|
|
85
85
|
|
|
86
86
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
87
87
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: GroupMultiNeSS
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.4
|
|
4
4
|
Summary: GroupMultiNeSS package
|
|
5
5
|
Author: Alexander Kagan
|
|
6
6
|
Author-email: <amkagan@umich.edu>
|
|
@@ -34,11 +34,11 @@ Dynamic: summary
|
|
|
34
34
|
|
|
35
35
|
# GroupMultiNeSS
|
|
36
36
|
|
|
37
|
-
GroupMultiNeSS is a package for statistical modeling of multilayer networks. It implements multiple approaches allowing to extract shared, group, and individual latent structures from a collection of networks on a shared set of nodes. Specifically, it contains the implementation of fitting sampling procedures for the following models:
|
|
37
|
+
GroupMultiNeSS is a package for statistical modeling of multilayer networks. It implements multiple approaches allowing to extract shared, group, and individual latent structures from a collection of networks on a shared set of nodes. Specifically, it contains the implementation of fitting and sampling procedures for the following models:
|
|
38
38
|
- GroupMultiNeSS [Kagan et al. (2025)] - likelihood based approach with nuclear norm penalization, accounts for the additional group latent structure
|
|
39
39
|
- MultiNeSS [[MacDonald et al. (2021)](https://arxiv.org/abs/2012.14409)] - likelihood based approach with nuclear norm penalization
|
|
40
40
|
- MultiNeSS [[Tian et al. (2024)](https://arxiv.org/abs/2412.02151)] - likelihood based approach with pre-estimation of latent ranks via Shared Space Hunting algorithm
|
|
41
|
-
- COSIE
|
|
41
|
+
- COSIE [[Arroyo et al. (2020)](https://arxiv.org/abs/1906.10026)] - spectral-based Multiple Adjacency Spectral Embedding algorithm
|
|
42
42
|
|
|
43
43
|
## Installation
|
|
44
44
|
|
|
@@ -81,7 +81,7 @@ print(group_multiness.make_final_error_report(S_true, Qs_true, Rs_true, Ps=Ps_tr
|
|
|
81
81
|
|
|
82
82
|
MIT License
|
|
83
83
|
|
|
84
|
-
Copyright (c)
|
|
84
|
+
Copyright (c) 2025 Alexander Kagan
|
|
85
85
|
|
|
86
86
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
87
87
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# GroupMultiNeSS
|
|
2
2
|
|
|
3
|
-
GroupMultiNeSS is a package for statistical modeling of multilayer networks. It implements multiple approaches allowing to extract shared, group, and individual latent structures from a collection of networks on a shared set of nodes. Specifically, it contains the implementation of fitting sampling procedures for the following models:
|
|
3
|
+
GroupMultiNeSS is a package for statistical modeling of multilayer networks. It implements multiple approaches allowing to extract shared, group, and individual latent structures from a collection of networks on a shared set of nodes. Specifically, it contains the implementation of fitting and sampling procedures for the following models:
|
|
4
4
|
- GroupMultiNeSS [Kagan et al. (2025)] - likelihood based approach with nuclear norm penalization, accounts for the additional group latent structure
|
|
5
5
|
- MultiNeSS [[MacDonald et al. (2021)](https://arxiv.org/abs/2012.14409)] - likelihood based approach with nuclear norm penalization
|
|
6
6
|
- MultiNeSS [[Tian et al. (2024)](https://arxiv.org/abs/2412.02151)] - likelihood based approach with pre-estimation of latent ranks via Shared Space Hunting algorithm
|
|
7
|
-
- COSIE
|
|
7
|
+
- COSIE [[Arroyo et al. (2020)](https://arxiv.org/abs/1906.10026)] - spectral-based Multiple Adjacency Spectral Embedding algorithm
|
|
8
8
|
|
|
9
9
|
## Installation
|
|
10
10
|
|
|
@@ -47,7 +47,7 @@ print(group_multiness.make_final_error_report(S_true, Qs_true, Rs_true, Ps=Ps_tr
|
|
|
47
47
|
|
|
48
48
|
MIT License
|
|
49
49
|
|
|
50
|
-
Copyright (c)
|
|
50
|
+
Copyright (c) 2025 Alexander Kagan
|
|
51
51
|
|
|
52
52
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
53
53
|
of this software and associated documentation files (the "Software"), to deal
|
|
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
|