-
-
Notifications
You must be signed in to change notification settings - Fork 183
/
Copy pathtest_svd.py
81 lines (71 loc) · 2.71 KB
/
test_svd.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
from __future__ import annotations
import numpy as np
import pytest
import rpy2.robjects as robjects
from rpy2.robjects import numpy2ri
from prince import svd
from tests import load_df_from_R
@pytest.mark.parametrize(
"n_components, are_rows_weighted, are_columns_weighted",
[
pytest.param(
n_components,
are_rows_weighted,
are_columns_weighted,
id=f"{n_components=}:{are_rows_weighted=}:{are_columns_weighted=}",
)
for n_components in [1, 3, 10]
for are_rows_weighted in [False, True]
for are_columns_weighted in [False, True]
],
)
class TestSVD:
@pytest.fixture(autouse=True)
def _prepare(self, n_components, are_rows_weighted, are_columns_weighted):
self.n_components = n_components
self.are_rows_weighted = are_rows_weighted
self.are_columns_weighted = are_columns_weighted
self.dataset = np.random.rand(100, 10)
self.row_weights = np.random.rand(100)
self.row_weights /= self.row_weights.sum()
self.column_weights = np.random.rand(10)
# Fit Prince
self.svd = svd.compute_svd(
X=self.dataset,
row_weights=self.row_weights if are_rows_weighted else None,
column_weights=self.column_weights if are_columns_weighted else None,
n_components=n_components,
n_iter=3,
random_state=42,
engine="scipy",
)
# Fit FactoMineR
robjects.r("library('FactoMineR')")
robjects.r.assign("X", numpy2ri.py2rpy(self.dataset))
robjects.r.assign("row.w", numpy2ri.py2rpy(self.row_weights))
robjects.r.assign("col.w", numpy2ri.py2rpy(self.column_weights))
robjects.r("row.w <- as.vector(row.w)")
robjects.r("col.w <- as.vector(col.w)")
args = f"X, ncp={n_components}"
if are_rows_weighted:
args += ", row.w=row.w"
if are_columns_weighted:
args += ", col.w=col.w"
robjects.r(f"svd = svd.triplet({args})")
def test_U(self):
assert self.svd.U.shape == (100, self.n_components)
if self.are_rows_weighted:
P = self.svd.U
F = load_df_from_R("svd$U")
np.testing.assert_allclose(np.abs(F), np.abs(P))
def test_s(self):
assert self.svd.s.shape == (self.n_components,)
if self.are_rows_weighted:
P = self.svd.s
F = robjects.r("svd$vs")[: self.n_components]
np.testing.assert_allclose(np.abs(F), np.abs(P))
def test_V(self):
assert self.svd.V.shape == (self.n_components, 10)
P = self.svd.V
F = load_df_from_R("svd$V").T
np.testing.assert_allclose(np.abs(F), np.abs(P))