NicolasHug / Surprise

A Python scikit for building and analyzing recommender systems
http://surpriselib.com
BSD 3-Clause "New" or "Revised" License
6.34k stars 1.01k forks source link

Significantly improve performance of SVD and SVDpp (cleaner) #401

Closed ProfHercules closed 2 years ago

ProfHercules commented 2 years ago

All changes are documented more clearly in the commits. Before starting to make changes, I ran all tests using Python 3.9, they all passed. After all changes, all the tests still pass.

Initially, on my M1 MacBook Air, examples/bench_mf.py produced the following:

Movielens 100k RMSE MAE Time
SVD 0.936 0.738 0:00:12
SVD++ 0.922 0.723 0:07:08
NMF 0.964 0.758 0:00:11

After all changes, the run time looks like this:

Movielens 100k RMSE MAE Time
SVD 0.936 0.738 0:00:02
SVD++ 0.922 0.723 0:00:32
NMF 0.964 0.758 0:00:11

Which is a 6x improvement in speed for SVD and a 13.38x improvement for SVDpp.

I also ran the same benchmark using the MovieLens 1M dataset, and got the following:

Movielens 1M RMSE MAE Time
SVD 0.874 0.686 0:00:25
SVD++ 0.862 0.672 0:10:37
NMF 0.917 0.725 0:01:49

The primary differences between this PR and #400 is

Note: I documented the process here, feel free to give it a read!

NicolasHug commented 2 years ago

@ProfHercules Thank you so much for your dedication and for taking the time to submit a PR. I'm sorry I couldn't get to it sooner.

Since you submitted, I've made a bunch of modifications on the master branch. In master I have removed some old code relying on six, which is where a bunch of Python interaction were coming from when using range() in Cython. Also I enabled by default a bunch of compiler directive like the ones you were using here (bouncheck=False, etc.). I also updated the CI so that it can run small benchmarks when submitting a PR (it's the "Benchmark / build (3.9) (pull_request)" below).

Before changes on master: https://github.com/NicolasHug/Surprise/pull/422

Movielens 100k RMSE MAE Time
SVD 0.936 0.738 0:00:30
SVD++ 0.922 0.723 0:16:16
NMF 0.964 0.758 0:00:30
After changes on master https://github.com/NicolasHug/Surprise/pull/421 Movielens 100k RMSE MAE Time
SVD 0.936 0.738 0:00:07
SVD++ 0.922 0.723 0:05:24
NMF 0.964 0.758 0:00:09

This PR:

Movielens 100k RMSE MAE Time
SVD 0.936 0.738 0:00:05
SVD++ cache_ratings=False 0.922 0.723 0:01:54
SVD++ cache_ratings=True 0.921 0.722 0:01:38
NMF 0.965 0.759 0:00:08

I've also made a bunch of changes to this PR. Some of them are cosmetic, some of them are maybe more relevant:

On the benchmark above we observe similar speedups as you did: 6X for SVD and ~10X for SVDpp.

NicolasHug commented 2 years ago

Merging now, thanks a lot again for your PR @ProfHercules , this is a very nice improvement!