Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion tensorly/decomposition/_constrained_cp.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ def initialize_constrained_parafac(
elif init == "svd":
factors = []
for mode in range(tl.ndim(tensor)):
U, S, _ = svd_interface(unfold(tensor, mode), n_eigenvecs=rank, method=svd)
U, S, _ = svd_interface(unfold(tensor, mode), n_eigenvecs=rank, method=svd, random_state=rng)

# Put SVD initialization on the same scaling as the tensor in case normalize_factors=False
if mode == 0:
Expand Down
1 change: 1 addition & 0 deletions tensorly/decomposition/_cp.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ def initialize_cp(
non_negative=non_negative,
mask=mask_unfold,
n_iter_mask_imputation=svd_mask_repeats,
random_state=rng,
)

# Put SVD initialization on the same scaling as the tensor in case normalize_factors=False
Expand Down
8 changes: 4 additions & 4 deletions tensorly/decomposition/_parafac2.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,10 @@ def initialize_decomposition(
else:
unfolded_mode_2 = tl.transpose(tl.concatenate(list(tensor_slices), axis=0))

C = svd_interface(unfolded_mode_2, n_eigenvecs=rank, method=svd)[0]
C = svd_interface(unfolded_mode_2, n_eigenvecs=rank, method=svd, random_state=random_state)[0]

B = tl.eye(rank, **context)
projections = _compute_projections(tensor_slices, (A, B, C), svd)
projections = _compute_projections(tensor_slices, (A, B, C), svd, random_state)
return Parafac2Tensor((None, [A, B, C], projections))

elif isinstance(init, (tuple, list, Parafac2Tensor, CPTensor)):
Expand All @@ -155,15 +155,15 @@ def initialize_decomposition(
raise ValueError(f'Initialization method "{init}" not recognized')


def _compute_projections(tensor_slices, factors, svd):
def _compute_projections(tensor_slices, factors, svd, random_state=None):
n_eig = factors[0].shape[1]
out = []

for A, tensor_slice in zip(factors[0], tensor_slices):
lhs = T.dot(factors[1], T.transpose(A * factors[2]))
rhs = T.transpose(tensor_slice)
U, _, Vh = svd_interface(
T.dot(lhs, rhs), n_eigenvecs=n_eig, method=svd, flip_sign=False
T.dot(lhs, rhs), n_eigenvecs=n_eig, method=svd, flip_sign=False, random_state=random_state
)

out.append(T.transpose(T.dot(U, Vh)))
Expand Down
6 changes: 3 additions & 3 deletions tensorly/decomposition/_tr_svd.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from ..tenalg.svd import svd_interface


def tensor_ring(input_tensor, rank, mode=0, svd="truncated_svd", verbose=False):
def tensor_ring(input_tensor, rank, mode=0, svd="truncated_svd", verbose=False, random_state=None):
"""Tensor Ring decomposition via recursive SVD

Decomposes `input_tensor` into a sequence of order-3 tensors (factors) [1]_.
Expand Down Expand Up @@ -58,7 +58,7 @@ def tensor_ring(input_tensor, rank, mode=0, svd="truncated_svd", verbose=False):
)

# SVD of unfolding matrix
U, S, V = svd_interface(unfolding, n_eigenvecs=rank[0] * rank[1], method=svd)
U, S, V = svd_interface(unfolding, n_eigenvecs=rank[0] * rank[1], method=svd, random_state=random_state)

# Get first TR factor
factor = tl.reshape(U, (tensor_size[0], rank[0], rank[1]))
Expand All @@ -80,7 +80,7 @@ def tensor_ring(input_tensor, rank, mode=0, svd="truncated_svd", verbose=False):
# SVD of unfolding matrix
n_row, n_column = unfolding.shape
current_rank = min(n_row, n_column, rank[k + 1])
U, S, V = svd_interface(unfolding, n_eigenvecs=current_rank, method=svd)
U, S, V = svd_interface(unfolding, n_eigenvecs=current_rank, method=svd, random_state=random_state)
rank[k + 1] = current_rank

# Get kth TR factor
Expand Down
4 changes: 2 additions & 2 deletions tensorly/decomposition/_tt.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from ..tenalg.svd import svd_interface


def tensor_train(input_tensor, rank, svd="truncated_svd", verbose=False):
def tensor_train(input_tensor, rank, svd="truncated_svd", verbose=False, random_state=None):
"""TT decomposition via recursive SVD

Decomposes `input_tensor` into a sequence of order-3 tensors (factors)
Expand Down Expand Up @@ -48,7 +48,7 @@ def tensor_train(input_tensor, rank, svd="truncated_svd", verbose=False):
# SVD of unfolding matrix
(n_row, n_column) = unfolding.shape
current_rank = min(n_row, n_column, rank[k + 1])
U, S, V = svd_interface(unfolding, n_eigenvecs=current_rank, method=svd)
U, S, V = svd_interface(unfolding, n_eigenvecs=current_rank, method=svd, random_state=random_state)

rank[k + 1] = current_rank

Expand Down
4 changes: 2 additions & 2 deletions tensorly/preprocessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@


def svd_compress_tensor_slices(
tensor_slices, compression_threshold=0.0, max_rank=None, svd="truncated_svd"
tensor_slices, compression_threshold=0.0, max_rank=None, svd="truncated_svd", random_state=None
):
r"""Compress data with the SVD for running PARAFAC2.

Expand Down Expand Up @@ -88,7 +88,7 @@ def svd_compress_tensor_slices(
score_matrices[i] = tensor_slice
continue

U, s, Vh = svd_interface(tensor_slice, n_eigenvecs=rank_limit, method=svd)
U, s, Vh = svd_interface(tensor_slice, n_eigenvecs=rank_limit, method=svd, random_state=random_state)

# Threshold SVD, keeping only singular values that satisfy s_i >= s_0 * epsilon
# where epsilon is the compression threshold
Expand Down
5 changes: 3 additions & 2 deletions tensorly/tests/test_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ def test_svd():
for svd in SVD_FUNS:
if svd == "randomized_svd":
decimal = 2
rng = tl.check_random_state(1234)
else:
decimal = 3
sizes = [(100, 100), (100, 5), (10, 10), (10, 4), (5, 100)]
Expand All @@ -199,7 +200,7 @@ def test_svd():
for s, n in zip(sizes, n_eigenvecs):
matrix = np.random.random(s)
matrix_backend = T.tensor(matrix)
fU, fS, fV = svd_interface(matrix_backend, n_eigenvecs=n, method=svd)
fU, fS, fV = svd_interface(matrix_backend, n_eigenvecs=n, method=svd, random_state=rng)
U, S, V = np.linalg.svd(matrix, full_matrices=True)
U, S, V = U[:, :n], S[:n], V[:n, :]

Expand Down Expand Up @@ -237,7 +238,7 @@ def test_svd():
# Should fail on non-matrices
with assert_raises(ValueError):
tensor = T.tensor(np.random.random((3, 3, 3)))
svd_interface(tensor, n_eigenvecs=n, method=svd)
svd_interface(tensor, n_eigenvecs=n, method=svd, random_state=rng)

# Test for singular matrices (some eigenvals will be zero)
# Rank at most 5
Expand Down
Loading