nystrom-ncut 0.1.5__py3-none-any.whl → 0.1.7__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.
- nystrom_ncut/nystrom/distance_realization.py +4 -4
- nystrom_ncut/nystrom/nystrom_utils.py +38 -39
- nystrom_ncut/visualize_utils.py +2 -3
- {nystrom_ncut-0.1.5.dist-info → nystrom_ncut-0.1.7.dist-info}/METADATA +1 -1
- {nystrom_ncut-0.1.5.dist-info → nystrom_ncut-0.1.7.dist-info}/RECORD +8 -8
- {nystrom_ncut-0.1.5.dist-info → nystrom_ncut-0.1.7.dist-info}/LICENSE +0 -0
- {nystrom_ncut-0.1.5.dist-info → nystrom_ncut-0.1.7.dist-info}/WHEEL +0 -0
- {nystrom_ncut-0.1.5.dist-info → nystrom_ncut-0.1.7.dist-info}/top_level.txt +0 -0
@@ -128,9 +128,9 @@ class DistanceRealization(OnlineNystromSubsampleFit):
|
|
128
128
|
features: torch.Tensor,
|
129
129
|
precomputed_sampled_indices: torch.Tensor = None,
|
130
130
|
) -> torch.Tensor:
|
131
|
-
V
|
132
|
-
return V * (
|
131
|
+
V = OnlineNystromSubsampleFit.fit_transform(self, features, precomputed_sampled_indices)
|
132
|
+
return V * (self.eigenvalues_ ** 0.5)
|
133
133
|
|
134
134
|
def transform(self, features: torch.Tensor = None) -> torch.Tensor:
|
135
|
-
V
|
136
|
-
return V * (
|
135
|
+
V = OnlineNystromSubsampleFit.transform(self, features)
|
136
|
+
return V * (self.eigenvalues_ ** 0.5)
|
@@ -20,7 +20,7 @@ EigSolverOptions = Literal["svd_lowrank", "lobpcg", "svd", "eigh"]
|
|
20
20
|
|
21
21
|
|
22
22
|
class OnlineKernel:
|
23
|
-
def fit(self, features: torch.Tensor) ->
|
23
|
+
def fit(self, features: torch.Tensor) -> "OnlineKernel": # [n x d]
|
24
24
|
raise NotImplementedError()
|
25
25
|
|
26
26
|
def update(self, features: torch.Tensor) -> torch.Tensor: # [m x d] -> [m x n]
|
@@ -47,7 +47,6 @@ class OnlineNystrom:
|
|
47
47
|
self.n_components: int = n_components
|
48
48
|
self.kernel: OnlineKernel = kernel
|
49
49
|
self.eig_solver: EigSolverOptions = eig_solver
|
50
|
-
self.inverse_approximation_dim: int = None
|
51
50
|
|
52
51
|
self.chunk_size = chunk_size
|
53
52
|
|
@@ -61,13 +60,13 @@ class OnlineNystrom:
|
|
61
60
|
# Updated matrices
|
62
61
|
self.S: torch.Tensor = None # [n x n]
|
63
62
|
self.transform_matrix: torch.Tensor = None # [n x n_components]
|
64
|
-
self.
|
63
|
+
self.eigenvalues_: torch.Tensor = None # [n]
|
65
64
|
|
66
|
-
def _update_to_kernel(self) -> Tuple[torch.Tensor, torch.Tensor]:
|
65
|
+
def _update_to_kernel(self, d: int) -> Tuple[torch.Tensor, torch.Tensor]:
|
67
66
|
self.A = self.S = self.kernel.transform()
|
68
67
|
U, L = solve_eig(
|
69
68
|
self.A,
|
70
|
-
num_eig=
|
69
|
+
num_eig=d + 1, # d * (d + 3) // 2 + 1,
|
71
70
|
eig_solver=self.eig_solver,
|
72
71
|
) # [n x (? + 1)], [? + 1]
|
73
72
|
self.Ahinv_UL = U * (L ** -0.5) # [n x (? + 1)]
|
@@ -75,57 +74,57 @@ class OnlineNystrom:
|
|
75
74
|
self.Ahinv = self.Ahinv_UL @ self.Ahinv_VT # [n x n]
|
76
75
|
return U, L
|
77
76
|
|
78
|
-
def fit(self, features: torch.Tensor):
|
77
|
+
def fit(self, features: torch.Tensor) -> "OnlineNystrom":
|
79
78
|
OnlineNystrom.fit_transform(self, features)
|
80
79
|
return self
|
81
80
|
|
82
|
-
def fit_transform(self, features: torch.Tensor) ->
|
81
|
+
def fit_transform(self, features: torch.Tensor) -> torch.Tensor:
|
83
82
|
self.anchor_features = features
|
84
83
|
|
85
84
|
self.kernel.fit(self.anchor_features)
|
86
|
-
|
87
|
-
U, L = self._update_to_kernel() # [n x (? + 1)], [? + 1]
|
85
|
+
U, L = self._update_to_kernel(features.shape[-1]) # [n x (d + 1)], [d + 1]
|
88
86
|
|
89
87
|
self.transform_matrix = (U / L)[:, :self.n_components] # [n x n_components]
|
90
|
-
self.
|
91
|
-
return U[:, :self.n_components]
|
88
|
+
self.eigenvalues_ = L[:self.n_components] # [n_components]
|
89
|
+
return U[:, :self.n_components] # [n x n_components]
|
92
90
|
|
93
|
-
def update(self, features: torch.Tensor) ->
|
91
|
+
def update(self, features: torch.Tensor) -> torch.Tensor:
|
92
|
+
d = features.shape[-1]
|
94
93
|
n_chunks = ceildiv(len(features), self.chunk_size)
|
95
94
|
if n_chunks > 1:
|
96
95
|
""" Chunked version """
|
97
96
|
chunks = torch.chunk(features, n_chunks, dim=0)
|
98
97
|
for chunk in chunks:
|
99
98
|
self.kernel.update(chunk)
|
100
|
-
self._update_to_kernel()
|
99
|
+
self._update_to_kernel(d)
|
101
100
|
|
102
|
-
compressed_BBT =
|
103
|
-
for
|
104
|
-
_B = self.kernel.transform(chunk).mT
|
105
|
-
_compressed_B = self.Ahinv_VT @ _B
|
106
|
-
compressed_BBT = compressed_BBT + _compressed_B @ _compressed_B.mT
|
107
|
-
self.S = self.S + self.Ahinv_UL @ compressed_BBT @ self.Ahinv_UL.mT
|
108
|
-
US, self.
|
109
|
-
self.transform_matrix = self.Ahinv @ US * (self.
|
101
|
+
compressed_BBT = 0.0 # [(? + 1) x (? + 1))]
|
102
|
+
for chunk in chunks:
|
103
|
+
_B = self.kernel.transform(chunk).mT # [n x _m]
|
104
|
+
_compressed_B = self.Ahinv_VT @ _B # [(? + 1) x _m]
|
105
|
+
compressed_BBT = compressed_BBT + _compressed_B @ _compressed_B.mT # [(? + 1) x (? + 1)]
|
106
|
+
self.S = self.S + self.Ahinv_UL @ compressed_BBT @ self.Ahinv_UL.mT # [n x n]
|
107
|
+
US, self.eigenvalues_ = solve_eig(self.S, self.n_components, self.eig_solver) # [n x n_components], [n_components]
|
108
|
+
self.transform_matrix = self.Ahinv @ US * (self.eigenvalues_ ** -0.5) # [n x n_components]
|
110
109
|
|
111
110
|
VS = []
|
112
111
|
for chunk in chunks:
|
113
|
-
VS.append(self.kernel.transform(chunk) @ self.transform_matrix)
|
112
|
+
VS.append(self.kernel.transform(chunk) @ self.transform_matrix) # [_m x n_components]
|
114
113
|
VS = torch.cat(VS, dim=0)
|
115
|
-
return VS
|
114
|
+
return VS # [m x n_components]
|
116
115
|
else:
|
117
116
|
""" Unchunked version """
|
118
|
-
B = self.kernel.update(features).mT
|
119
|
-
self._update_to_kernel()
|
120
|
-
compressed_B = self.Ahinv_VT @ B
|
117
|
+
B = self.kernel.update(features).mT # [n x m]
|
118
|
+
self._update_to_kernel(d)
|
119
|
+
compressed_B = self.Ahinv_VT @ B # [indirect_pca_dim x m]
|
121
120
|
|
122
|
-
self.S = self.S + self.Ahinv_UL @ (compressed_B @ compressed_B.mT) @ self.Ahinv_UL.mT
|
123
|
-
US, self.
|
124
|
-
self.transform_matrix = self.Ahinv @ US * (self.
|
121
|
+
self.S = self.S + self.Ahinv_UL @ (compressed_B @ compressed_B.mT) @ self.Ahinv_UL.mT # [n x n]
|
122
|
+
US, self.eigenvalues_ = solve_eig(self.S, self.n_components, self.eig_solver) # [n x n_components], [n_components]
|
123
|
+
self.transform_matrix = self.Ahinv @ US * (self.eigenvalues_ ** -0.5) # [n x n_components]
|
125
124
|
|
126
|
-
return B.mT @ self.transform_matrix
|
125
|
+
return B.mT @ self.transform_matrix # [m x n_components]
|
127
126
|
|
128
|
-
def transform(self, features: torch.Tensor = None) ->
|
127
|
+
def transform(self, features: torch.Tensor = None) -> torch.Tensor:
|
129
128
|
if features is None:
|
130
129
|
VS = self.A @ self.transform_matrix # [n x n_components]
|
131
130
|
else:
|
@@ -135,12 +134,12 @@ class OnlineNystrom:
|
|
135
134
|
chunks = torch.chunk(features, n_chunks, dim=0)
|
136
135
|
VS = []
|
137
136
|
for chunk in chunks:
|
138
|
-
VS.append(self.kernel.transform(chunk) @ self.transform_matrix)
|
137
|
+
VS.append(self.kernel.transform(chunk) @ self.transform_matrix) # [_m x n_components]
|
139
138
|
VS = torch.cat(VS, dim=0)
|
140
139
|
else:
|
141
140
|
""" Unchunked version """
|
142
|
-
VS = self.kernel.transform(features) @ self.transform_matrix
|
143
|
-
return VS
|
141
|
+
VS = self.kernel.transform(features) @ self.transform_matrix # [m x n_components]
|
142
|
+
return VS # [m x n_components]
|
144
143
|
|
145
144
|
|
146
145
|
class OnlineNystromSubsampleFit(OnlineNystrom):
|
@@ -192,7 +191,7 @@ class OnlineNystromSubsampleFit(OnlineNystrom):
|
|
192
191
|
if _n_not_sampled > 0:
|
193
192
|
unsampled_indices = torch.full((_n,), True, device=features.device).scatter_(0, self.anchor_indices, False)
|
194
193
|
unsampled_features = features[unsampled_indices]
|
195
|
-
V_unsampled
|
194
|
+
V_unsampled = OnlineNystrom.update(self, unsampled_features)
|
196
195
|
else:
|
197
196
|
unsampled_indices = V_unsampled = None
|
198
197
|
return unsampled_indices, V_unsampled
|
@@ -201,7 +200,7 @@ class OnlineNystromSubsampleFit(OnlineNystrom):
|
|
201
200
|
self,
|
202
201
|
features: torch.Tensor,
|
203
202
|
precomputed_sampled_indices: torch.Tensor = None,
|
204
|
-
):
|
203
|
+
) -> "OnlineNystromSubsampleFit":
|
205
204
|
"""Fit Nystrom Normalized Cut on the input features.
|
206
205
|
Args:
|
207
206
|
features (torch.Tensor): input features, shape (n_samples, n_features)
|
@@ -217,7 +216,7 @@ class OnlineNystromSubsampleFit(OnlineNystrom):
|
|
217
216
|
self,
|
218
217
|
features: torch.Tensor,
|
219
218
|
precomputed_sampled_indices: torch.Tensor = None,
|
220
|
-
) ->
|
219
|
+
) -> torch.Tensor:
|
221
220
|
"""
|
222
221
|
Args:
|
223
222
|
features (torch.Tensor): input features, shape (n_samples, n_features)
|
@@ -229,7 +228,7 @@ class OnlineNystromSubsampleFit(OnlineNystrom):
|
|
229
228
|
(torch.Tensor): eigen_values, sorted in descending order, shape (num_eig,)
|
230
229
|
"""
|
231
230
|
unsampled_indices, V_unsampled = OnlineNystromSubsampleFit._fit_helper(self, features, precomputed_sampled_indices)
|
232
|
-
V_sampled
|
231
|
+
V_sampled = OnlineNystrom.transform(self)
|
233
232
|
|
234
233
|
if unsampled_indices is not None:
|
235
234
|
V = torch.zeros((len(unsampled_indices), self.n_components), device=features.device)
|
@@ -237,7 +236,7 @@ class OnlineNystromSubsampleFit(OnlineNystrom):
|
|
237
236
|
V[unsampled_indices] = V_unsampled
|
238
237
|
else:
|
239
238
|
V = V_sampled
|
240
|
-
return V
|
239
|
+
return V
|
241
240
|
|
242
241
|
|
243
242
|
def solve_eig(
|
nystrom_ncut/visualize_utils.py
CHANGED
@@ -179,14 +179,13 @@ def _rgb_with_dimensionality_reduction(
|
|
179
179
|
)
|
180
180
|
|
181
181
|
_inp = features[subgraph_indices].numpy(force=True)
|
182
|
-
_subgraph_embed = reduction(
|
182
|
+
_subgraph_embed = torch.tensor(reduction(
|
183
183
|
n_components=reduction_dim,
|
184
184
|
metric=disttype,
|
185
185
|
random_state=seed,
|
186
186
|
**reduction_kwargs
|
187
|
-
).fit_transform(_inp)
|
187
|
+
).fit_transform(_inp), device=features.device, dtype=features.dtype)
|
188
188
|
|
189
|
-
_subgraph_embed = torch.tensor(_subgraph_embed, dtype=torch.float32)
|
190
189
|
rgb = rgb_func(extrapolate_knn(
|
191
190
|
features[subgraph_indices],
|
192
191
|
_subgraph_embed,
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: nystrom_ncut
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.7
|
4
4
|
Summary: Normalized Cut and Nyström Approximation
|
5
5
|
Author-email: Huzheng Yang <huze.yann@gmail.com>, Wentinn Liao <wentinn.liao@gmail.com>
|
6
6
|
Project-URL: Documentation, https://github.com/JophiArcana/Nystrom-NCUT/
|
@@ -3,13 +3,13 @@ nystrom_ncut/__init__.py,sha256=HifrTcqX2-hYjBDe6xIThHvuIBYMPBA3EzjR8-qPMUM,512
|
|
3
3
|
nystrom_ncut/common.py,sha256=_PGJoImSk_Fb_5Ri-e_IsFoCcSfbGS8CxYUUHVoNM50,2036
|
4
4
|
nystrom_ncut/distance_utils.py,sha256=p-pYdpRrJsIhzxM_IxUqja7N8okngx52WGXD9pu_Aec,3129
|
5
5
|
nystrom_ncut/sampling_utils.py,sha256=oMmhFcd_N_D15Ht7F0rCGPSgLeitJszAKMD3ICKwHNU,3105
|
6
|
-
nystrom_ncut/visualize_utils.py,sha256=
|
6
|
+
nystrom_ncut/visualize_utils.py,sha256=_J6YjWUsBe0VqW6KXsQx_iPmRCcO-ie0g6t5mD289UI,22957
|
7
7
|
nystrom_ncut/nystrom/__init__.py,sha256=4EpxD3Cmc8Fif4vo8DG-6FpTfCnNanD5zCZxK3WrMwQ,121
|
8
|
-
nystrom_ncut/nystrom/distance_realization.py,sha256=
|
8
|
+
nystrom_ncut/nystrom/distance_realization.py,sha256=InajllGtRVnLVlZoipZNbHFTGHaTs3zxizKe3kI2Los,5815
|
9
9
|
nystrom_ncut/nystrom/normalized_cut.py,sha256=N-M5wkTo59vpbBfIx8evkSQBxlo4j80qCtuoifxQa_A,7578
|
10
|
-
nystrom_ncut/nystrom/nystrom_utils.py,sha256=
|
11
|
-
nystrom_ncut-0.1.
|
12
|
-
nystrom_ncut-0.1.
|
13
|
-
nystrom_ncut-0.1.
|
14
|
-
nystrom_ncut-0.1.
|
15
|
-
nystrom_ncut-0.1.
|
10
|
+
nystrom_ncut/nystrom/nystrom_utils.py,sha256=UVs1tC7vnVq2mWSTpcrP4C19x9wDJ77ACht0EltOO2E,12698
|
11
|
+
nystrom_ncut-0.1.7.dist-info/LICENSE,sha256=2bm9uFabQZ3Ykb_SaSU_uUbAj2-htc6WJQmS_65qD00,1073
|
12
|
+
nystrom_ncut-0.1.7.dist-info/METADATA,sha256=eb0Q6bwCKC4c5bcuJI_PnIaPW5qFYGSgwbPeuWI7EUk,6058
|
13
|
+
nystrom_ncut-0.1.7.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
14
|
+
nystrom_ncut-0.1.7.dist-info/top_level.txt,sha256=gM8IWWHYysIRTCvCTcdS4RShOyl9pxpylgSwPUZR2XM,22
|
15
|
+
nystrom_ncut-0.1.7.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|