{"id":16818425,"url":"https://github.com/gbolmier/funk-svd","last_synced_at":"2026-02-06T23:32:44.090Z","repository":{"id":43042763,"uuid":"179322874","full_name":"gbolmier/funk-svd","owner":"gbolmier","description":":zap: A python fast implementation of the famous SVD algorithm popularized by Simon Funk during Netflix Prize","archived":false,"fork":false,"pushed_at":"2022-07-04T09:00:20.000Z","size":48,"stargazers_count":224,"open_issues_count":7,"forks_count":68,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-07-22T17:48:05.023Z","etag":null,"topics":["numba","recommendation-algorithm"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gbolmier.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-04-03T15:53:33.000Z","updated_at":"2025-06-18T11:42:31.000Z","dependencies_parsed_at":"2022-07-14T19:30:44.117Z","dependency_job_id":null,"html_url":"https://github.com/gbolmier/funk-svd","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/gbolmier/funk-svd","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gbolmier%2Ffunk-svd","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gbolmier%2Ffunk-svd/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gbolmier%2Ffunk-svd/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gbolmier%2Ffunk-svd/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gbolmier","download_url":"https://codeload.github.com/gbolmier/funk-svd/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gbolmier%2Ffunk-svd/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29180422,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-06T23:15:33.022Z","status":"ssl_error","status_checked_at":"2026-02-06T23:15:09.128Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["numba","recommendation-algorithm"],"created_at":"2024-10-13T10:50:05.005Z","updated_at":"2026-02-06T23:32:44.058Z","avatar_url":"https://github.com/gbolmier.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# :zap: funk-svd [![Build Status](https://img.shields.io/travis/gbolmier/funk-svd/master.svg?style=flat)](https://travis-ci.com/gbolmier/funk-svd) [![License](https://img.shields.io/badge/License-MIT-blue.svg?style=flat)](https://opensource.org/licenses/MIT)\n\n`funk-svd` is a Python 3 library implementing a fast version of the famous SVD algorithm [popularized](http://sifter.org/simon/journal/20061211.html) by Simon Funk during the [Neflix Prize](http://en.wikipedia.org/wiki/Netflix_Prize) contest.\n\n[`Numba`](http://numba.pydata.org/) is used to speed up our algorithm, enabling us to run over 10 times faster than [`Surprise`](http://surpriselib.com)'s Cython implementation (cf. [benchmark notebook](http://nbviewer.jupyter.org/github/gbolmier/funk-svd/blob/master/benchmark.ipynb)).\n\n| Movielens 20M | RMSE   | MAE    | Time          |\n|:--------------|:------:|:------:|--------------:|\n| Surprise      |  0.88  |  0.68  | 10 min 40 sec |\n| Funk-svd      |  0.88  |  0.68  |        42 sec |\n\n## Installation\n\nRun `pip install git+https://github.com/gbolmier/funk-svd` in your terminal.\n\n## Contributing\n\nAll contributions, bug reports, bug fixes, enhancements, and ideas are welcome.\n\nA detailed overview on how to contribute can be found in the [contributor guide](CONTRIBUTING.md).\n\n## Quick example\n\n[run_experiment.py](run_experiment.py):\n\n```python\n\u003e\u003e\u003e from funk_svd.dataset import fetch_ml_ratings\n\u003e\u003e\u003e from funk_svd import SVD\n\n\u003e\u003e\u003e from sklearn.metrics import mean_absolute_error\n\n\n\u003e\u003e\u003e df = fetch_ml_ratings(variant='100k')\n\n\u003e\u003e\u003e train = df.sample(frac=0.8, random_state=7)\n\u003e\u003e\u003e val = df.drop(train.index.tolist()).sample(frac=0.5, random_state=8)\n\u003e\u003e\u003e test = df.drop(train.index.tolist()).drop(val.index.tolist())\n\n\u003e\u003e\u003e svd = SVD(lr=0.001, reg=0.005, n_epochs=100, n_factors=15,\n...           early_stopping=True, shuffle=False, min_rating=1, max_rating=5)\n\n\u003e\u003e\u003e svd.fit(X=train, X_val=val)\nPreprocessing data...\n\nEpoch 1/...\n\n\u003e\u003e\u003e pred = svd.predict(test)\n\u003e\u003e\u003e mae = mean_absolute_error(test['rating'], pred)\n\n\u003e\u003e\u003e print(f'Test MAE: {mae:.2f}')\nTest MAE: 0.75\n\n```\n\n## Funk SVD for recommendation in a nutshell\n\nWe have a huge sparse matrix:\n\n\u003ca href=\"https://www.codecogs.com/eqnedit.php?latex=R\u0026space;=\u0026space;\\begin{pmatrix}\u0026space;{\\color{Red}\u0026space;?}\u0026space;\u0026\u0026space;2\u0026space;\u0026\u0026space;\\cdots\u0026space;\u0026\u0026space;{\\color{Red}\u0026space;?}\u0026space;\u0026\u0026space;{\\color{Red}\u0026space;?}\u0026space;\\\\\u0026space;{\\color{Red}\u0026space;?}\u0026space;\u0026\u0026space;{\\color{Red}\u0026space;?}\u0026space;\u0026\u0026space;\\cdots\u0026space;\u0026\u0026space;{\\color{Red}\u0026space;?}\u0026space;\u0026\u0026space;4.5\u0026space;\\\\\u0026space;\\vdots\u0026space;\u0026\u0026space;\\ddots\u0026space;\u0026\u0026space;\\ddots\u0026space;\u0026\u0026space;\\ddots\u0026space;\u0026\u0026space;\\vdots\u0026space;\\\\\u0026space;3\u0026space;\u0026\u0026space;{\\color{Red}\u0026space;?}\u0026space;\u0026\u0026space;\\cdots\u0026space;\u0026\u0026space;{\\color{Red}\u0026space;?}\u0026space;\u0026\u0026space;{\\color{Red}\u0026space;?}\u0026space;\\\\\u0026space;{\\color{Red}\u0026space;?}\u0026space;\u0026\u0026space;{\\color{Red}\u0026space;?}\u0026space;\u0026\u0026space;\\cdots\u0026space;\u0026\u0026space;5\u0026space;\u0026\u0026space;{\\color{Red}\u0026space;?}\u0026space;\\end{pmatrix}\" target=\"_blank\"\u003e\u003cimg src=\"https://latex.codecogs.com/gif.latex?R\u0026space;=\u0026space;\\begin{pmatrix}\u0026space;{\\color{Red}\u0026space;?}\u0026space;\u0026\u0026space;2\u0026space;\u0026\u0026space;\\cdots\u0026space;\u0026\u0026space;{\\color{Red}\u0026space;?}\u0026space;\u0026\u0026space;{\\color{Red}\u0026space;?}\u0026space;\\\\\u0026space;{\\color{Red}\u0026space;?}\u0026space;\u0026\u0026space;{\\color{Red}\u0026space;?}\u0026space;\u0026\u0026space;\\cdots\u0026space;\u0026\u0026space;{\\color{Red}\u0026space;?}\u0026space;\u0026\u0026space;4.5\u0026space;\\\\\u0026space;\\vdots\u0026space;\u0026\u0026space;\\ddots\u0026space;\u0026\u0026space;\\ddots\u0026space;\u0026\u0026space;\\ddots\u0026space;\u0026\u0026space;\\vdots\u0026space;\\\\\u0026space;3\u0026space;\u0026\u0026space;{\\color{Red}\u0026space;?}\u0026space;\u0026\u0026space;\\cdots\u0026space;\u0026\u0026space;{\\color{Red}\u0026space;?}\u0026space;\u0026\u0026space;{\\color{Red}\u0026space;?}\u0026space;\\\\\u0026space;{\\color{Red}\u0026space;?}\u0026space;\u0026\u0026space;{\\color{Red}\u0026space;?}\u0026space;\u0026\u0026space;\\cdots\u0026space;\u0026\u0026space;5\u0026space;\u0026\u0026space;{\\color{Red}\u0026space;?}\u0026space;\\end{pmatrix}\" title=\"R = \\begin{pmatrix} {\\color{Red} ?} \u0026 2 \u0026 \\cdots \u0026 {\\color{Red} ?} \u0026 {\\color{Red} ?} \\\\ {\\color{Red} ?} \u0026 {\\color{Red} ?} \u0026 \\cdots \u0026 {\\color{Red} ?} \u0026 4.5 \\\\ \\vdots \u0026 \\ddots \u0026 \\ddots \u0026 \\ddots \u0026 \\vdots \\\\ 3 \u0026 {\\color{Red} ?} \u0026 \\cdots \u0026 {\\color{Red} ?} \u0026 {\\color{Red} ?} \\\\ {\\color{Red} ?} \u0026 {\\color{Red} ?} \u0026 \\cdots \u0026 5 \u0026 {\\color{Red} ?} \\end{pmatrix}\" /\u003e\u003c/a\u003e\n\nstoring known ratings for a set of users and items:\n\n\u003ca href=\"https://www.codecogs.com/eqnedit.php?latex=\\inline\u0026space;u\u0026space;=\u0026space;1,\u0026space;...,\u0026space;U\" target=\"_blank\"\u003e\u003cimg src=\"https://latex.codecogs.com/gif.latex?\\inline\u0026space;u\u0026space;=\u0026space;1,\u0026space;...,\u0026space;U\" title=\"u = 1, ..., U\" /\u003e\u003c/a\u003e\n\n\u003ca href=\"https://www.codecogs.com/eqnedit.php?latex=\\inline\u0026space;i\u0026space;=\u0026space;1,\u0026space;...,\u0026space;I\" target=\"_blank\"\u003e\u003cimg src=\"https://latex.codecogs.com/gif.latex?\\inline\u0026space;i\u0026space;=\u0026space;1,\u0026space;...,\u0026space;I\" title=\"i = 1, ..., I\" /\u003e\u003c/a\u003e\n\nThe idea is to estimate unknown ratings by factorizing the rating matrix into two smaller matrices representing user and item characteristics:\n\n\u003ca href=\"https://www.codecogs.com/eqnedit.php?latex=P\u0026space;=\u0026space;\\begin{pmatrix}\u0026space;0.37\u0026space;\u0026\u0026space;\\cdots\u0026space;\u0026\u0026space;0.69\u0026space;\\\\\u0026space;\\vdots\u0026space;\u0026\u0026space;\\ddots\u0026space;\u0026\u0026space;\\vdots\u0026space;\\\\\u0026space;\\vdots\u0026space;\u0026\u0026space;\\ddots\u0026space;\u0026\u0026space;\\vdots\u0026space;\\\\\u0026space;\\vdots\u0026space;\u0026\u0026space;\\ddots\u0026space;\u0026\u0026space;\\vdots\u0026space;\\\\\u0026space;1.08\u0026space;\u0026\u0026space;\\cdots\u0026space;\u0026\u0026space;0.24\u0026space;\\end{pmatrix}\u0026space;,\u0026space;Q\u0026space;=\u0026space;\\begin{pmatrix}\u0026space;0.09\u0026space;\u0026\u0026space;\\cdots\u0026space;\u0026\u0026space;\\cdots\u0026space;\u0026\u0026space;\\cdots\u0026space;\u0026\u0026space;0.46\u0026space;\\\\\u0026space;\\vdots\u0026space;\u0026\u0026space;\\ddots\u0026space;\u0026\u0026space;\\ddots\u0026space;\u0026\u0026space;\\ddots\u0026space;\u0026\u0026space;\\vdots\u0026space;\\\\\u0026space;0.51\u0026space;\u0026\u0026space;\\cdots\u0026space;\u0026\u0026space;\\cdots\u0026space;\u0026\u0026space;\\cdots\u0026space;\u0026\u0026space;0.72\u0026space;\\end{pmatrix}\" target=\"_blank\"\u003e\u003cimg src=\"https://latex.codecogs.com/gif.latex?P\u0026space;=\u0026space;\\begin{pmatrix}\u0026space;0.37\u0026space;\u0026\u0026space;\\cdots\u0026space;\u0026\u0026space;0.69\u0026space;\\\\\u0026space;\\vdots\u0026space;\u0026\u0026space;\\ddots\u0026space;\u0026\u0026space;\\vdots\u0026space;\\\\\u0026space;\\vdots\u0026space;\u0026\u0026space;\\ddots\u0026space;\u0026\u0026space;\\vdots\u0026space;\\\\\u0026space;\\vdots\u0026space;\u0026\u0026space;\\ddots\u0026space;\u0026\u0026space;\\vdots\u0026space;\\\\\u0026space;1.08\u0026space;\u0026\u0026space;\\cdots\u0026space;\u0026\u0026space;0.24\u0026space;\\end{pmatrix}\u0026space;,\u0026space;Q\u0026space;=\u0026space;\\begin{pmatrix}\u0026space;0.09\u0026space;\u0026\u0026space;\\cdots\u0026space;\u0026\u0026space;\\cdots\u0026space;\u0026\u0026space;\\cdots\u0026space;\u0026\u0026space;0.46\u0026space;\\\\\u0026space;\\vdots\u0026space;\u0026\u0026space;\\ddots\u0026space;\u0026\u0026space;\\ddots\u0026space;\u0026\u0026space;\\ddots\u0026space;\u0026\u0026space;\\vdots\u0026space;\\\\\u0026space;0.51\u0026space;\u0026\u0026space;\\cdots\u0026space;\u0026\u0026space;\\cdots\u0026space;\u0026\u0026space;\\cdots\u0026space;\u0026\u0026space;0.72\u0026space;\\end{pmatrix}\" title=\"P = \\begin{pmatrix} 0.37 \u0026 \\cdots \u0026 0.69 \\\\ \\vdots \u0026 \\ddots \u0026 \\vdots \\\\ \\vdots \u0026 \\ddots \u0026 \\vdots \\\\ \\vdots \u0026 \\ddots \u0026 \\vdots \\\\ 1.08 \u0026 \\cdots \u0026 0.24 \\end{pmatrix} , Q = \\begin{pmatrix} 0.09 \u0026 \\cdots \u0026 \\cdots \u0026 \\cdots \u0026 0.46 \\\\ \\vdots \u0026 \\ddots \u0026 \\ddots \u0026 \\ddots \u0026 \\vdots \\\\ 0.51 \u0026 \\cdots \u0026 \\cdots \u0026 \\cdots \u0026 0.72 \\end{pmatrix}\" /\u003e\u003c/a\u003e\n\nWe call these two matrices users and items latent factors. Then, by applying the dot product between both matrices we can reconstruct our rating matrix. The trick is that the empty values will now contain estimated ratings.\n\nIn order to get more accurate results, the global average rating as well as the user and item biases are used in addition:\n\n\u003ca href=\"https://www.codecogs.com/eqnedit.php?latex=\\bar{r}\u0026space;=\u0026space;\\frac{1}{N}\u0026space;\\sum_{i=1}^{N}\u0026space;K_{i}\" target=\"_blank\"\u003e\u003cimg src=\"https://latex.codecogs.com/gif.latex?\\bar{r}\u0026space;=\u0026space;\\frac{1}{N}\u0026space;\\sum_{i=1}^{N}\u0026space;K_{i}\" title=\"\\bar{r} = \\frac{1}{N} \\sum_{i=1}^{N} K_{i}\" /\u003e\u003c/a\u003e\n\nwhere K stands for known ratings.\n\n\u003ca href=\"https://www.codecogs.com/eqnedit.php?latex=bu\u0026space;=\u0026space;\\begin{pmatrix}\u0026space;0.35\u0026space;\u0026\u0026space;\\cdots\u0026space;\u0026\u0026space;0.07\u0026space;\\end{pmatrix}\" target=\"_blank\"\u003e\u003cimg src=\"https://latex.codecogs.com/gif.latex?bu\u0026space;=\u0026space;\\begin{pmatrix}\u0026space;0.35\u0026space;\u0026\u0026space;\\cdots\u0026space;\u0026\u0026space;0.07\u0026space;\\end{pmatrix}\" title=\"bu = \\begin{pmatrix} 0.35 \u0026 \\cdots \u0026 0.07 \\end{pmatrix}\" /\u003e\u003c/a\u003e\n\n\u003ca href=\"https://www.codecogs.com/eqnedit.php?latex=bi\u0026space;=\u0026space;\\begin{pmatrix}\u0026space;0.16\u0026space;\u0026\u0026space;\\cdots\u0026space;\u0026\u0026space;0.40\u0026space;\\end{pmatrix}\" target=\"_blank\"\u003e\u003cimg src=\"https://latex.codecogs.com/gif.latex?bi\u0026space;=\u0026space;\\begin{pmatrix}\u0026space;0.16\u0026space;\u0026\u0026space;\\cdots\u0026space;\u0026\u0026space;0.40\u0026space;\\end{pmatrix}\" title=\"bi = \\begin{pmatrix} 0.16 \u0026 \\cdots \u0026 0.40 \\end{pmatrix}\" /\u003e\u003c/a\u003e\n\nThen, we can estimate any rating by applying:\n\n\u003ca href=\"https://www.codecogs.com/eqnedit.php?latex=\\hat{r}_{u,\u0026space;i}\u0026space;=\u0026space;\\bar{r}\u0026space;\u0026plus;\u0026space;bu_{u}\u0026space;\u0026plus;\u0026space;bi_{i}\u0026space;\u0026plus;\u0026space;\\sum_{f=1}^{F}\u0026space;P_{u,\u0026space;f}\u0026space;*\u0026space;Q_{i,\u0026space;f}\" target=\"_blank\"\u003e\u003cimg src=\"https://latex.codecogs.com/gif.latex?\\hat{r}_{u,\u0026space;i}\u0026space;=\u0026space;\\bar{r}\u0026space;\u0026plus;\u0026space;bu_{u}\u0026space;\u0026plus;\u0026space;bi_{i}\u0026space;\u0026plus;\u0026space;\\sum_{f=1}^{F}\u0026space;P_{u,\u0026space;f}\u0026space;*\u0026space;Q_{i,\u0026space;f}\" title=\"\\hat{r}_{u, i} = \\bar{r} + bu_{u} + bi_{i} + \\sum_{f=1}^{F} P_{u, f} * Q_{i, f}\" /\u003e\u003c/a\u003e\n\nThe learning step consists in performing the SGD algorithm where for each known rating the biases and latent factors are updated as follows:\n\n\u003ca href=\"https://www.codecogs.com/eqnedit.php?latex=err\u0026space;=\u0026space;r\u0026space;-\u0026space;\\hat{r}\" target=\"_blank\"\u003e\u003cimg src=\"https://latex.codecogs.com/gif.latex?err\u0026space;=\u0026space;r\u0026space;-\u0026space;\\hat{r}\" title=\"err = r - \\hat{r}\" /\u003e\u003c/a\u003e\n\n\u003ca href=\"https://www.codecogs.com/eqnedit.php?latex=bu_{u}\u0026space;=\u0026space;bu_{u}\u0026space;\u0026plus;\u0026space;\\alpha\u0026space;*\u0026space;(err\u0026space;-\u0026space;\\lambda\u0026space;*\u0026space;bu_{u})\" target=\"_blank\"\u003e\u003cimg src=\"https://latex.codecogs.com/gif.latex?bu_{u}\u0026space;=\u0026space;bu_{u}\u0026space;\u0026plus;\u0026space;\\alpha\u0026space;*\u0026space;(err\u0026space;-\u0026space;\\lambda\u0026space;*\u0026space;bu_{u})\" title=\"bu_{u} = bu_{u} + \\alpha * (err - \\lambda * bu_{u})\" /\u003e\u003c/a\u003e\n\n\u003ca href=\"https://www.codecogs.com/eqnedit.php?latex=bi_{i}\u0026space;=\u0026space;bi_{i}\u0026space;\u0026plus;\u0026space;\\alpha\u0026space;*\u0026space;(err\u0026space;-\u0026space;\\lambda\u0026space;*\u0026space;bi_{i})\" target=\"_blank\"\u003e\u003cimg src=\"https://latex.codecogs.com/gif.latex?bi_{i}\u0026space;=\u0026space;bi_{i}\u0026space;\u0026plus;\u0026space;\\alpha\u0026space;*\u0026space;(err\u0026space;-\u0026space;\\lambda\u0026space;*\u0026space;bi_{i})\" title=\"bi_{i} = bi_{i} + \\alpha * (err - \\lambda * bi_{i})\" /\u003e\u003c/a\u003e\n\n\u003ca href=\"https://www.codecogs.com/eqnedit.php?latex=P_{u,\u0026space;f}\u0026space;=\u0026space;P_{u,\u0026space;f}\u0026space;\u0026plus;\u0026space;\\alpha\u0026space;*\u0026space;(err\u0026space;*\u0026space;Q_{i,\u0026space;f}\u0026space;-\u0026space;\\lambda\u0026space;*\u0026space;P_{u,\u0026space;f})\" target=\"_blank\"\u003e\u003cimg src=\"https://latex.codecogs.com/gif.latex?P_{u,\u0026space;f}\u0026space;=\u0026space;P_{u,\u0026space;f}\u0026space;\u0026plus;\u0026space;\\alpha\u0026space;*\u0026space;(err\u0026space;*\u0026space;Q_{i,\u0026space;f}\u0026space;-\u0026space;\\lambda\u0026space;*\u0026space;P_{u,\u0026space;f})\" title=\"P_{u, f} = P_{u, f} + \\alpha * (err * Q_{i, f} - \\lambda * P_{u, f})\" /\u003e\u003c/a\u003e\n\n\u003ca href=\"https://www.codecogs.com/eqnedit.php?latex=Q_{i,\u0026space;f}\u0026space;=\u0026space;Q_{i,\u0026space;f}\u0026space;\u0026plus;\u0026space;\\alpha\u0026space;*\u0026space;(err\u0026space;*\u0026space;P_{u,\u0026space;f}\u0026space;-\u0026space;\\lambda\u0026space;*\u0026space;Q_{i,\u0026space;f})\" target=\"_blank\"\u003e\u003cimg src=\"https://latex.codecogs.com/gif.latex?Q_{i,\u0026space;f}\u0026space;=\u0026space;Q_{i,\u0026space;f}\u0026space;\u0026plus;\u0026space;\\alpha\u0026space;*\u0026space;(err\u0026space;*\u0026space;P_{u,\u0026space;f}\u0026space;-\u0026space;\\lambda\u0026space;*\u0026space;Q_{i,\u0026space;f})\" title=\"Q_{i, f} = Q_{i, f} + \\alpha * (err * P_{u, f} - \\lambda * Q_{i, f})\" /\u003e\u003c/a\u003e\n\nwhere alpha is the learning rate and lambda is the regularization term.\n\n## References\n\n- [Collaborative filtering](https://en.wikipedia.org/wiki/Collaborative_filtering)\n- [Matrix completion](https://en.wikipedia.org/wiki/Matrix_completion)\n- [Matrix factorization (recommender systems)](https://en.wikipedia.org/wiki/Matrix_factorization_(recommender_systems))\n- [Recommender Systems Handbook](https://www.cse.iitk.ac.in/users/nsrivast/HCC/Recommender_systems_handbook.pdf)\n- [Singular value decomposition](https://en.wikipedia.org/wiki/Singular_value_decomposition)\n- [Surprise library for recommender systems](http://surpriselib.com/)\n\n## License\n\nMIT license, [see here](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgbolmier%2Ffunk-svd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgbolmier%2Ffunk-svd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgbolmier%2Ffunk-svd/lists"}