<p>Matrix factorization assumes that the "latent factors" such as the preference for italian food of a user and the italieness of the item food is implicated by the ratings in the matrix.</p>

<p>So the whole Problem kind of transforms into a matrix reconstruction problem for which a lot of different solutions exist. A simple, maybe slow, solution is (besides ALS and some other possibilities of Matrix reconstruction) approximating the matrix using a gradient descend algorithm. I recommend this short article <a href="http://www.columbia.edu/~jwp2128/Teaching/W4721/papers/ieeecomputer.pdf" rel="nofollow noreferrer">ieee article about recommender systems</a>.</p>

<p>Extracting the latent factors is a different problem.</p>

<p>So an implementation of GDM could look like:</p>

<pre><code>public void learnGDM(){
//traverse learnSet
for(int repeat = 0; repeat &lt; this.steps; repeat++){
    for (int i = 0; i &lt; this.learnSet.length; i++){
        for (int j = 0; j &lt; this.learnSet[0].length; j++){
            if(this.learnSet[i][j] &gt; 0.0d){
                double Rij = this.learnSet[i][j];

                for(int f = 0 ; f &lt;= latentFactors; f++){
                    double error = Rij - dotProduct(Q.getRow(i), P.getRow(j));/*estimated_Rij;*/
                    //ieee computer 1.pdf
                    double qif = Q.get(i, f);
                    double pif = P.get(j, f);
                    double Qvalue = qif + gradientGamma * (error * pif - gradientLambda * qif);
                    double Pvalue = pif + gradientGamma * (error * qif - gradientLambda * pif);
                    Q.set(i,f, Qvalue);
                    P.set(j, f, Pvalue);
                }
            }
        }
    }
    //check global error
    if(checkGlobalError() &lt; 0.001d){
        System.out.println("took" + repeat + "steps");
        break;
    }
}
</code></pre>

<p>Where the learnset is a two dimensional Array containing the Ratingmatrix as in the ieee article. The GDM algorithm changes the rating vectors P and Q a bit every iteration so that they approximate the ratings in the ratingmatrix. Then the "not given" ratings can be calculated by the dot product of P and Q. The highest estimations for the not given ratings will then be the recommendations.</p>

<p>So thats it for the start. There are a lot of optimizations and other algorithms or modified versions of GDM that can also be run in parallel.</p>

<p>Some good reads:</p>

<p><a href="http://www.prem-melville.com/publications/recommender-systems-eml2010.pdf" rel="nofollow noreferrer">recommender systems in the Encyclopedia of Machine Learning</a></p>

<p><a href="https://www.csie.ntu.edu.tw/~htlin/mooc/doc/215_present.pdf" rel="nofollow noreferrer">presentation on matrix factorization</a></p>

<p><a href="https://arxiv.org/pdf/1202.1112" rel="nofollow noreferrer">recommender systems</a> &lt;--- big one ^^</p>
Using matrix factorization for a recommender system
<p>I'm working on a recommender system for restaurants using an item-based collaborative filter in C# 6.0. I want to set up my algorithm to perform as well as possible, so I've done some research on different ways to predict ratings for restaurants the user hasn't reviewed yet.</p>

<p><strong>I'll start with the research I have done</strong></p>

<p>First I wanted to set up a user-based collaborative filter using a pearson correlation between users to be able to see which users fit well together.<br>
The main problem with this was the amount of data required to be able to calculate this correlation. First you needed 4 reviews per 2 users on the same restaurant. But my data is going to be very sparse. It wasn't likely that 2 users would have reviewed the exact same 4 restaurants. I wanted to fix this by widening the match terms (I.e. not matching users on same restaurants, but on a same type of restaurant), but this gave me the problem where it was hard to determine which reviews I would use in the correlation, since a user could have left 3 reviews on a restaurant with the type 'Fast food'. Which of these would fit best with the other user's review on a fast food restaurant?</p>

<p>After more research I concluded that an item-based collaborative filter outperforms an user-based collaborative filter. But again, I encountered the data sparsity issue. In my tests I was successfully able to calculate a prediction for a rating on a restaurant the user hasn't reviewed yet, but when I used the algorithm on a sparse dataset, the results weren't good enough. (Most of the time, a similarity wasn't possible between two restaurants, since no 2 users have rated the same restaurant).<br>
After even more research I found that using a matrix factorization method works well on sparse data.</p>

<p><strong>Now my problem</strong></p>

<p>I have been looking all over the internet for tutorials on using this method, but I don't have any experience in recommender systems and my knowledge on algebra is also limited. I understand the just of the method. You have a matrix where you have 1 side the users and the other side the restaurants. Each cell is the rating the user has given on the restaurant.<br>
The matrix factorization method creates two matrices of this, one with the weight between users and the type of the restaurant, and the other between restaurants and these types. </p>

<p>The thing I just can't figure out is how to calculate the weight between the type of restaurant and the restaurants/users (If I understand matrix factorization correctly). I found dozens of formulas which calculates these numbers, but I can't figure out how to break them down and apply them in my application.</p>

<p>I'll give you an example on how data looks in my application:<br>
In this table U1 stands for a user and R1 stands for a restaurant.
Each restaurant has their own tags (Type of restaurant). I.e. R1 has the tag 'Italian', R2 has 'Fast food', etc.</p>

<pre><code>   |  R1  |  R2  |  R3  |  R4  |
U1 |  3   |  1   |  2   |  -   |
U2 |  -   |  3   |  2   |  2   |
U3 |  5   |  4   |  -   |  4   |
U4 |  -   |  -   |  5   |  -   |
</code></pre>

<p>Is there anyone who can point me in the right direction or explain how I should use this method on my data? Any help would be greatly appreciated!</p>