recommend() method for ImplicitALSWrapperModel
Your Question
Hello! I see that here is no usage of ImplicitALSWrapperModel's recommend() method. I see that rectools' recommend() fallbacks to something underlying called ImplicitRanker with custom implementation by RecTools. I wonder why is this behaviour used instead of the native implicit's recommend(). Also this implementation works a way longer than implicit's.
Operating System
No response
Python Version
No response
RecTools version
No response
Hi! ImplicitRanker uses exactly the same method for scoring items as in implicit library, we are calling it directly: https://github.com/MobileTeleSystems/RecTools/blob/0be5e1592e06022109faf1d446c7aee82fbd9dfb/rectools/models/rank.py#L194
In implicit framework recommend just returns the results directly without any processing. Items in recommendations can still include already-seen items and repeated items. They will get neginf scores, but they are still present.
In our wrapper we process those results, apply filtering based on scores here: https://github.com/MobileTeleSystems/RecTools/blob/0be5e1592e06022109faf1d446c7aee82fbd9dfb/rectools/models/rank.py#L106 And after that we convert results to pandas.
So this is why our recommend is slower: we do some post-processing.
If the difference in speed is extraordinary then please check your version of rectools package. You might be using older version where we didn't use ImplicitRanker
Yes, thank you. I see it works the same way and the speed should be the same. My speed problem(10 s vs 5 min for context) was because the RecTools' ImplicitRanker implementation does not use the GPU. I was able to run predictions on the GPU with the patch:
--- a/rank.py 2024-10-30 16:03:51.376808529 +0300
+++ b/rank.py 2024-10-30 16:07:06.556808606 +0300
@@ -18,6 +18,7 @@
from enum import Enum
import implicit.cpu
+import implicit.gpu
import numpy as np
from implicit.cpu.matrix_factorization_base import _filter_items_from_sparse_matrix as filter_items_from_sparse_matrix
from scipy import sparse
@@ -191,14 +192,22 @@
real_k = min(k, object_factors.shape[0])
- ids, scores = implicit.cpu.topk.topk( # pylint: disable=c-extension-no-member
- items=object_factors,
- query=subject_factors,
- k=real_k,
+ object_factors = implicit.gpu.Matrix(object_factors)
+ subject_factors = implicit.gpu.Matrix(subject_factors)
+ if object_norms is not None:
+ object_norms = implicit.gpu.Matrix(object_norms)
+ if filter_query_items is not None:
+ filter_query_items = implicit.gpu.COOMatrix(filter_query_items.tocoo())
+
+
+ ids, scores = implicit.gpu.KnnQuery().topk( # pylint: disable=c-extension-no-member
+ object_factors,
+ subject_factors,
+ real_k,
item_norms=object_norms, # query norms for COSINE distance are applied afterwards
- filter_query_items=filter_query_items, # queries x objects csr matrix for getting neginf scores
- filter_items=None, # rectools doesn't support blacklist for now
- num_threads=num_threads,
+ query_filter=filter_query_items, # queries x objects csr matrix for getting neginf scores
+ item_filter=None, # rectools doesn't support blacklist for now
+ # num_threads=num_threads,
)
if sorted_object_whitelist is not None:
@Waujito Thank you for sharing. It would be nice to have it out of the box so I've added this to our backlog. If you feel like contributing - it would also be great. Please let me know :)
Yeah, I want to try to propose a draft implementation of this.
That's great. In case of any questions the fastest way for a reply is in our Telegram channel https://t.me/RecTools_Support
Hi! @Waujito we're still working on gpu support for all models. Found another thing: gpu ranking scores may significantly differ from cpu ranking scores in some cases. This is especially true for PureSVDModel. We are still researching the cause so decided to add models support for use_gpu in ImplicitRanker to the next release, not the current one. We hope will be quite soon.