Skip to content

Commit

Permalink
Fix lint and test
Browse files Browse the repository at this point in the history
  • Loading branch information
chezou committed Dec 11, 2024
1 parent 3e09fcf commit 6430038
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 18 deletions.
2 changes: 1 addition & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ pytorch-lightning = {version = ">=1.6.0, <3.0.0", optional = true}
ipywidgets = {version = ">=7.7,<8.2", optional = true}
plotly = {version="^5.22.0", optional = true}
nbformat = {version = ">=4.2.0", optional = true}
cupy-cuda12x = {version = "^13.3.0", extras = ["cupy"], optional = true}
cupy-cuda12x = {version = "^13.3.0", python = "<3.13", extras = ["cupy"], optional = true}


[tool.poetry.extras]
Expand Down
10 changes: 7 additions & 3 deletions rectools/models/pure_svd.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,13 @@ def __init__(
self.tol = tol
self.maxiter = maxiter
self.random_state = random_state
if use_gpu and (not HAS_CUDA or cupy_svds is None): # pragma: no cover
warnings.warn("Forced to use CPU. CUDA is not available.")
use_gpu = False
if use_gpu: # pragma: no cover
if not HAS_CUDA:
warnings.warn("Forced to use CPU. CUDA is not available.")
use_gpu = False
if cp is None:
warnings.warn("Forced to use CPU. CuPy is not available.")
use_gpu = False

self.use_gpu = use_gpu

Expand Down
57 changes: 44 additions & 13 deletions tests/models/test_pure_svd.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import numpy as np
import pandas as pd
import pytest
from implicit.gpu import HAS_CUDA
from pytest_mock import MockerFixture

from rectools import Columns
from rectools.dataset import Dataset
Expand All @@ -33,7 +35,7 @@
)

try:
import cupy as cp
import cupy as cp # pylint: disable=import-error, unused-import
except ImportError: # pragma: no cover
cp = None

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

@pytest.mark.parametrize(
"filter_viewed,expected,use_gpu",
"filter_viewed,expected",
(
(
True,
Expand All @@ -56,7 +58,6 @@ def dataset(self) -> Dataset:
Columns.Rank: [1, 2, 1, 2],
}
),
False,
),
(
False,
Expand All @@ -67,8 +68,33 @@ def dataset(self) -> Dataset:
Columns.Rank: [1, 2, 1, 2],
}
),
False,
),
),
)
def test_basic(
self,
dataset: Dataset,
filter_viewed: bool,
expected: pd.DataFrame,
) -> None:
model = PureSVDModel(factors=2, use_gpu=False).fit(dataset)
actual = model.recommend(
users=np.array([10, 20]),
dataset=dataset,
k=2,
filter_viewed=filter_viewed,
)
pd.testing.assert_frame_equal(actual.drop(columns=Columns.Score), expected)
pd.testing.assert_frame_equal(
actual.sort_values([Columns.User, Columns.Score], ascending=[True, False]).reset_index(drop=True),
actual,
)

# SciPy's svds and cupy's svds results can be different and use_gpu fallback causes errors
@pytest.mark.skipif(HAS_CUDA is False, reason="CUDA is not available")
@pytest.mark.parametrize(
"filter_viewed,expected",
(
(
True,
pd.DataFrame(
Expand All @@ -78,7 +104,6 @@ def dataset(self) -> Dataset:
Columns.Rank: [1, 2, 1, 2],
}
),
True,
),
(
False,
Expand All @@ -89,18 +114,16 @@ def dataset(self) -> Dataset:
Columns.Rank: [1, 2, 1, 2],
}
),
True,
),
),
)
def test_basic(
def test_basic_gpu(
self,
dataset: Dataset,
filter_viewed: bool,
expected: pd.DataFrame,
use_gpu: bool,
) -> None:
model = PureSVDModel(factors=2, use_gpu=use_gpu).fit(dataset)
model = PureSVDModel(factors=2, use_gpu=True).fit(dataset)
actual = model.recommend(
users=np.array([10, 20]),
dataset=dataset,
Expand Down Expand Up @@ -297,12 +320,16 @@ def test_dumps_loads(self, dataset: Dataset) -> None:

class TestPureSVDModelConfiguration:

def test_from_config(self) -> None:
@pytest.mark.parametrize("use_gpu", (False, True))
def test_from_config(self, mocker: MockerFixture, use_gpu: bool) -> None:
mocker.patch("rectools.models.pure_svd.HAS_CUDA", return_value=True)
mocker.patch("rectools.models.pure_svd.cp", return_value=True)
config = {
"factors": 100,
"tol": 0,
"maxiter": 100,
"random_state": 32,
"use_gpu": use_gpu,
"verbose": 0,
}
model = PureSVDModel.from_config(config)
Expand All @@ -315,10 +342,14 @@ def test_from_config(self) -> None:
@pytest.mark.parametrize("random_state", (None, 42))
@pytest.mark.parametrize("simple_types", (False, True))
@pytest.mark.parametrize("use_gpu", (False, True))
def test_get_config(self, random_state: tp.Optional[int], simple_types: bool, use_gpu: bool) -> None:
def test_get_config(
self, mocker: MockerFixture, random_state: tp.Optional[int], simple_types: bool, use_gpu: bool
) -> None:
mocker.patch("rectools.models.pure_svd.HAS_CUDA", return_value=True)
mocker.patch("rectools.models.pure_svd.cp", return_value=True)
model = PureSVDModel(
factors=100,
tol=1,
tol=1.0,
maxiter=100,
random_state=random_state,
use_gpu=use_gpu,
Expand All @@ -328,7 +359,7 @@ def test_get_config(self, random_state: tp.Optional[int], simple_types: bool, us
expected = {
"cls": "PureSVDModel" if simple_types else PureSVDModel,
"factors": 100,
"tol": 1,
"tol": 1.0,
"maxiter": 100,
"random_state": random_state,
"use_gpu": use_gpu,
Expand Down

0 comments on commit 6430038

Please sign in to comment.