diff --git a/dmoj/decorators.py b/dmoj/decorators.py new file mode 100644 index 0000000..b6c6d0d --- /dev/null +++ b/dmoj/decorators.py @@ -0,0 +1,12 @@ +import time + +def timeit(method): + def timed(*args, **kw): + ts = time.time() + result = method(*args, **kw) + te = time.time() + if 'log_time' in kw: + name = kw.get('log_name', method.__name__.upper()) + kw['log_time'][name] = int((te - ts) * 1000) + return result + return timed \ No newline at end of file diff --git a/judge/ml/collab_filter.py b/judge/ml/collab_filter.py index 511cebc..2a8171f 100644 --- a/judge/ml/collab_filter.py +++ b/judge/ml/collab_filter.py @@ -1,6 +1,7 @@ import numpy as np from django.conf import settings import os +from dmoj.decorators import timeit class CollabFilter: @@ -8,7 +9,8 @@ class CollabFilter: COSINE = 'cosine' # name = 'collab_filter' or 'collab_filter_time' - def __init__(self, name): + @timeit + def __init__(self, name, **kwargs): embeddings = np.load(os.path.join(settings.ML_OUTPUT_PATH, name + '/embeddings.npz'), allow_pickle=True) arr0, arr1 = embeddings.files @@ -34,7 +36,8 @@ class CollabFilter: scores = u.dot(V.T) return scores - def user_recommendations(self, user, problems, measure=DOT, limit=None): + @timeit + def user_recommendations(self, user, problems, measure=DOT, limit=None, **kwargs): uid = user.id if uid >= len(self.user_embeddings): uid = 0 diff --git a/judge/views/problem.py b/judge/views/problem.py index ddb83c5..5d7e331 100644 --- a/judge/views/problem.py +++ b/judge/views/problem.py @@ -591,6 +591,8 @@ class ProblemList(QueryStringSortMixin, TitleMixin, SolvedProblemMixin, ListView return HttpResponseRedirect(request.get_full_path()) +cf_logger = logging.getLogger('judge.ml.collab_filter') + class ProblemFeed(ProblemList): model = Problem context_object_name = 'problems' @@ -645,20 +647,39 @@ class ProblemFeed(ProblemList): if not settings.ML_OUTPUT_PATH or not user: return queryset.order_by('?') - cf_model = CollabFilter('collab_filter') - cf_time_model = CollabFilter('collab_filter_time') + # Logging + log_data = { + 'user': self.request.user.username, + 'cf': { + 'dot': {}, + 'cosine': {}, + }, + 'cf_time': { + 'dot': {}, + 'cosine': {} + }, + } + + cf_model = CollabFilter('collab_filter', log_time=log_data['cf']) + cf_time_model = CollabFilter('collab_filter_time', log_time=log_data['cf_time']) hot_problems_recommendations = [ problem for problem in hot_problems(timedelta(days=7), 20) if problem in queryset ] q = self.merge_recommendation([ - cf_model.user_recommendations(user, queryset, cf_model.DOT, 100), - cf_model.user_recommendations(user, queryset, cf_model.COSINE, 100), - cf_time_model.user_recommendations(user, queryset, cf_time_model.COSINE, 100), - cf_time_model.user_recommendations(user, queryset, cf_time_model.DOT, 100), + cf_model.user_recommendations(user, queryset, cf_model.DOT, 100, + log_time=log_data['cf']['dot']), + cf_model.user_recommendations(user, queryset, cf_model.COSINE, 100, + log_time=log_data['cf']['cosine']), + cf_time_model.user_recommendations(user, queryset, cf_time_model.COSINE, 100, + log_time=log_data['cf_time']['cosine']), + cf_time_model.user_recommendations(user, queryset, cf_time_model.DOT, 100, + log_time=log_data['cf_time']['dot']), hot_problems_recommendations ]) + + cf_logger.info(log_data) return q def get_context_data(self, **kwargs):