Skip to content

Commit a3b2112

Browse files
author
Daria Tikhonovich
committed
Merge branch 'main' of https://github.com/MobileTeleSystems/RecTools into release/0.10.0
2 parents 814b63f + ac11874 commit a3b2112

File tree

2 files changed

+14
-11
lines changed

2 files changed

+14
-11
lines changed

rectools/models/implicit_bpr.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@ class ImplicitBPRWrapperModel(VectorModel[ImplicitBPRWrapperModelConfig]):
101101
102102
See https://benfred.github.io/implicit/api/models/cpu/bpr.html for details of the base model.
103103
104+
Please note that implicit BPR model training is not deterministic with num_threads > 1 or use_gpu=True.
105+
https://github.com/benfred/implicit/issues/710
106+
104107
Parameters
105108
----------
106109
model : BayesianPersonalizedRanking

tests/models/test_implicit_bpr.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@
4040
assert_second_fit_refits_model,
4141
)
4242

43+
# Note that num_threads > 1 for BayesianPersonalizedRanking CPU training will make model training undeterministic
44+
# https://github.com/benfred/implicit/issues/710
45+
# GPU training is always underministic
46+
4347

4448
@pytest.mark.parametrize("use_gpu", (False, True) if HAS_CUDA else (False,))
4549
class TestImplicitBPRWrapperModel:
@@ -71,7 +75,7 @@ def dataset(self) -> Dataset:
7175
pd.DataFrame(
7276
{
7377
Columns.User: [10, 10, 20, 20],
74-
Columns.Item: [17, 15, 17, 15],
78+
Columns.Item: [17, 13, 17, 15],
7579
Columns.Rank: [1, 2, 1, 2],
7680
}
7781
),
@@ -111,7 +115,7 @@ def test_basic(
111115
use_gpu: bool,
112116
) -> None:
113117
base_model = BayesianPersonalizedRanking(
114-
factors=2, num_threads=2, iterations=100, use_gpu=use_gpu, random_state=42
118+
factors=2, num_threads=1, iterations=100, use_gpu=use_gpu, random_state=42
115119
)
116120
self._init_model_factors_inplace(base_model, dataset)
117121
model = ImplicitBPRWrapperModel(model=base_model).fit(dataset)
@@ -130,7 +134,7 @@ def test_basic(
130134

131135
def test_consistent_with_pure_implicit(self, dataset: Dataset, use_gpu: bool) -> None:
132136
base_model = BayesianPersonalizedRanking(
133-
factors=2, num_threads=2, iterations=100, use_gpu=use_gpu, random_state=42
137+
factors=2, num_threads=1, iterations=100, use_gpu=use_gpu, random_state=42
134138
)
135139
self._init_model_factors_inplace(base_model, dataset)
136140
users = np.array([10, 20, 30, 40])
@@ -164,7 +168,7 @@ def test_gpu_ranking_consistent_with_pure_implicit(
164168
use_gpu: bool,
165169
) -> None:
166170
base_model = BayesianPersonalizedRanking(
167-
factors=2, num_threads=2, iterations=100, use_gpu=False, random_state=42
171+
factors=2, num_threads=1, iterations=100, use_gpu=False, random_state=42
168172
)
169173
self._init_model_factors_inplace(base_model, dataset)
170174
users = np.array([10, 20, 30, 40])
@@ -219,7 +223,7 @@ def test_with_whitelist(
219223
use_gpu: bool,
220224
) -> None:
221225
base_model = BayesianPersonalizedRanking(
222-
factors=32, num_threads=2, iterations=100, use_gpu=use_gpu, random_state=42
226+
factors=32, num_threads=1, iterations=100, use_gpu=use_gpu, random_state=42
223227
)
224228
model = ImplicitBPRWrapperModel(model=base_model).fit(dataset)
225229
actual = model.recommend(
@@ -279,7 +283,7 @@ def test_i2i(
279283
use_gpu: bool,
280284
) -> None:
281285
base_model = BayesianPersonalizedRanking(
282-
factors=2, num_threads=2, iterations=100, use_gpu=use_gpu, random_state=1
286+
factors=2, num_threads=1, iterations=100, use_gpu=use_gpu, random_state=1
283287
)
284288
self._init_model_factors_inplace(base_model, dataset)
285289
model = ImplicitBPRWrapperModel(model=base_model).fit(dataset)
@@ -297,8 +301,6 @@ def test_i2i(
297301
)
298302

299303
def test_second_fit_refits_model(self, dataset: Dataset, use_gpu: bool) -> None:
300-
# note that num_threads > 1 will make model training undeterministic
301-
# https://github.com/benfred/implicit/issues/710
302304
# GPU training is always nondeterministic so we only test for CPU training
303305
if use_gpu:
304306
pytest.skip("BPR is nondeterministic on GPU")
@@ -312,7 +314,7 @@ def set_random_state() -> None:
312314
assert_second_fit_refits_model(model, dataset, set_random_state)
313315

314316
def test_dumps_loads(self, dataset: Dataset, use_gpu: bool) -> None:
315-
base_model = BayesianPersonalizedRanking(factors=8, num_threads=2, use_gpu=use_gpu, random_state=1)
317+
base_model = BayesianPersonalizedRanking(factors=8, num_threads=1, use_gpu=use_gpu, random_state=1)
316318
model = ImplicitBPRWrapperModel(model=base_model).fit(dataset)
317319
assert_dumps_loads_do_not_change_model(model, dataset)
318320

@@ -503,8 +505,6 @@ def test_custom_model_class(self) -> None:
503505
def test_get_config_and_from_config_compatibility(
504506
self, simple_types: bool, recommend_use_gpu: tp.Optional[bool], recommend_n_threads: tp.Optional[int]
505507
) -> None:
506-
# note that num_threads > 1 will make model training undeterministic
507-
# https://github.com/benfred/implicit/issues/710
508508
initial_config = {
509509
"model": {"factors": 4, "num_threads": 1, "iterations": 2, "random_state": 42},
510510
"verbose": 1,

0 commit comments

Comments
 (0)