Skip to content

Commit 6788d67

Browse files
committed
Fix lint and test
1 parent 3e09fcf commit 6788d67

4 files changed

Lines changed: 52 additions & 18 deletions

File tree

‎poetry.lock‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎pyproject.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ pytorch-lightning = {version = ">=1.6.0, <3.0.0", optional = true}
8484
ipywidgets = {version = ">=7.7,<8.2", optional = true}
8585
plotly = {version="^5.22.0", optional = true}
8686
nbformat = {version = ">=4.2.0", optional = true}
87-
cupy-cuda12x = {version = "^13.3.0", extras = ["cupy"], optional = true}
87+
cupy-cuda12x = {version = "^13.3.0", python = "<3.13", extras = ["cupy"], optional = true}
8888

8989

9090
[tool.poetry.extras]

‎rectools/models/pure_svd.py‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,13 @@ def __init__(
9191
self.tol = tol
9292
self.maxiter = maxiter
9393
self.random_state = random_state
94-
if use_gpu and (not HAS_CUDA or cupy_svds is None): # pragma: no cover
95-
warnings.warn("Forced to use CPU. CUDA is not available.")
96-
use_gpu = False
94+
if use_gpu: # pragma: no cover
95+
if not HAS_CUDA:
96+
warnings.warn("Forced to use CPU. CUDA is not available.")
97+
use_gpu = False
98+
if cp is None:
99+
warnings.warn("Forced to use CPU. CuPy is not available.")
100+
use_gpu = False
97101

98102
self.use_gpu = use_gpu
99103

‎tests/models/test_pure_svd.py‎

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414

1515
import typing as tp
1616

17+
import implicit.gpu
1718
import numpy as np
1819
import pandas as pd
1920
import pytest
21+
from implicit.gpu import HAS_CUDA
2022

2123
from rectools import Columns
2224
from rectools.dataset import Dataset
@@ -33,7 +35,7 @@
3335
)
3436

3537
try:
36-
import cupy as cp
38+
import cupy as cp # pylint: disable=import-error, unused-import
3739
except ImportError: # pragma: no cover
3840
cp = None
3941

@@ -45,7 +47,7 @@ def dataset(self) -> Dataset:
4547
return DATASET
4648

4749
@pytest.mark.parametrize(
48-
"filter_viewed,expected,use_gpu",
50+
"filter_viewed,expected",
4951
(
5052
(
5153
True,
@@ -56,7 +58,6 @@ def dataset(self) -> Dataset:
5658
Columns.Rank: [1, 2, 1, 2],
5759
}
5860
),
59-
False,
6061
),
6162
(
6263
False,
@@ -67,8 +68,33 @@ def dataset(self) -> Dataset:
6768
Columns.Rank: [1, 2, 1, 2],
6869
}
6970
),
70-
False,
7171
),
72+
),
73+
)
74+
def test_basic(
75+
self,
76+
dataset: Dataset,
77+
filter_viewed: bool,
78+
expected: pd.DataFrame,
79+
) -> None:
80+
model = PureSVDModel(factors=2, use_gpu=False).fit(dataset)
81+
actual = model.recommend(
82+
users=np.array([10, 20]),
83+
dataset=dataset,
84+
k=2,
85+
filter_viewed=filter_viewed,
86+
)
87+
pd.testing.assert_frame_equal(actual.drop(columns=Columns.Score), expected)
88+
pd.testing.assert_frame_equal(
89+
actual.sort_values([Columns.User, Columns.Score], ascending=[True, False]).reset_index(drop=True),
90+
actual,
91+
)
92+
93+
# SciPy's svds and cupy's svds results can be different and use_gpu fallback causes errors
94+
@pytest.mark.skipif(HAS_CUDA is False, reason="CUDA is not available")
95+
@pytest.mark.parametrize(
96+
"filter_viewed,expected",
97+
(
7298
(
7399
True,
74100
pd.DataFrame(
@@ -78,7 +104,6 @@ def dataset(self) -> Dataset:
78104
Columns.Rank: [1, 2, 1, 2],
79105
}
80106
),
81-
True,
82107
),
83108
(
84109
False,
@@ -89,18 +114,16 @@ def dataset(self) -> Dataset:
89114
Columns.Rank: [1, 2, 1, 2],
90115
}
91116
),
92-
True,
93117
),
94118
),
95119
)
96-
def test_basic(
120+
def test_basic_gpu(
97121
self,
98122
dataset: Dataset,
99123
filter_viewed: bool,
100124
expected: pd.DataFrame,
101-
use_gpu: bool,
102125
) -> None:
103-
model = PureSVDModel(factors=2, use_gpu=use_gpu).fit(dataset)
126+
model = PureSVDModel(factors=2, use_gpu=True).fit(dataset)
104127
actual = model.recommend(
105128
users=np.array([10, 20]),
106129
dataset=dataset,
@@ -297,12 +320,18 @@ def test_dumps_loads(self, dataset: Dataset) -> None:
297320

298321
class TestPureSVDModelConfiguration:
299322

300-
def test_from_config(self) -> None:
323+
def setup_method(self) -> None:
324+
implicit.gpu.HAS_CUDA = True # To avoid errors when test without cuda
325+
326+
@pytest.mark.parametrize("use_gpu", (False, True))
327+
def test_from_config(self, mocker, use_gpu: bool) -> None:
328+
mocker.patch("rectools.models.pure_svd.cp", return_value=True)
301329
config = {
302330
"factors": 100,
303331
"tol": 0,
304332
"maxiter": 100,
305333
"random_state": 32,
334+
"use_gpu": use_gpu,
306335
"verbose": 0,
307336
}
308337
model = PureSVDModel.from_config(config)
@@ -315,10 +344,11 @@ def test_from_config(self) -> None:
315344
@pytest.mark.parametrize("random_state", (None, 42))
316345
@pytest.mark.parametrize("simple_types", (False, True))
317346
@pytest.mark.parametrize("use_gpu", (False, True))
318-
def test_get_config(self, random_state: tp.Optional[int], simple_types: bool, use_gpu: bool) -> None:
347+
def test_get_config(self, mocker, random_state: tp.Optional[int], simple_types: bool, use_gpu: bool) -> None:
348+
mocker.patch("rectools.models.pure_svd.cp", return_value=True)
319349
model = PureSVDModel(
320350
factors=100,
321-
tol=1,
351+
tol=1.0,
322352
maxiter=100,
323353
random_state=random_state,
324354
use_gpu=use_gpu,
@@ -328,7 +358,7 @@ def test_get_config(self, random_state: tp.Optional[int], simple_types: bool, us
328358
expected = {
329359
"cls": "PureSVDModel" if simple_types else PureSVDModel,
330360
"factors": 100,
331-
"tol": 1,
361+
"tol": 1.0,
332362
"maxiter": 100,
333363
"random_state": random_state,
334364
"use_gpu": use_gpu,

0 commit comments

Comments
 (0)