human
I am working on the file "Data Mining/Recommender Systems/Recommender-Engine_exercise.ipynb".
The first task is:
Cosine Similarity
Building a recommendation engine can be thought of as "filling in the holes" in the sparse matrix you made above.  For example, take a look at the MovieLense data.  You'll see that that matrix is mostly zeros.  Our task here is to predict what a given user will rate a given movie depending on the users tastes.  To determine a users taste, we can use cosine similarity which is given by $$s_u^{cos}(u_k,u_a)
 = \frac{ u_k \cdot u_a }{ \left \| u_k \right \| \left \| u_a \right \| }
 = \frac{ \sum x_{k,m}x_{a,m} }{ \sqrt{\sum x_{k,m}^2\sum x_{a,m}^2} }$$
for users $u_a$ and $u_k$ on ratings given by $x_{a,m}$ and $x_{b,m}$.  This is just the cosine of the angle between the two vectors.  Likewise, this can also be calculated for the similarity between two items, $i_a$ and $i_b$, given by $$s_u^{cos}(i_m,i_b)
 = \frac{ i_m \cdot i_b }{ \left \| i_m \right \| \left \| i_b \right \| }
 = \frac{ \sum x_{a,m} x_{a,b} }{ \sqrt{ \sum x_{a,m}^2 \sum x_{a,b}^2 } }$$
Then, the similarity between two users is given by $$\hat{x}{k,m} = \bar{x}{k} + \frac{\sum\limits_{u_a} s_u^{cos}(u_k,u_a) (x_{a,m})}{\sum\limits_{u_a}|s_u^{cos}(u_k,u_a)|}$$ and for items given by $$\hat{x}{k,m} = \frac{\sum\limits{i_b} s_u^{cos}(i_m,i_b) (x_{k,b}) }{\sum\limits_{i_b}|s_u^{cos}(i_m,i_b)|}$$
Use these ideas to construct a class cos_engine which can be used to recommend movies for a given user.  Be sure to also test your algorithm, reporting its accuracy.  Bonus: Use adjusted cosine similiarity.
Can you write Python code for it?
 Write me a Python code to determine a users taste, we can use cosine similarity which is given by $$s_u^{cos}(u_k,u_a)?
assistant
#Here is Python code to determine a users taste, we can use cosine similarity which is given by $$s_u^{cos}(u_k,u_a)
.

class cos_engine():
    def __init__(self, k, how='user'):
        self.k = k
        self.how = how
    
    def _cos_sim(self, x, y):
        num = np.sum(x * y)
        den = np.sum(x**2) * np.sum(y**2)
        return num / np.sqrt(den)
    
    def _user_based_filtering(self, user, X):
        sim = X.apply(lambda row: self._cos_sim(X.loc[user, :].values, row.values), axis=1)
        sim = sim.drop(user, axis=0)
        rec = sim.sort_values(ascending=False).head(self.k)
        return rec
    
    def _item_based_filtering(self, item, X):
        Xt = X.T
        sim = Xt.apply(lambda row: self._cos_sim(Xt.loc[item, :].values, row.values), axis=1)
        sim = sim.drop(item, axis=0)
        rec = sim.sort_values(ascending=False).head(self.k)
        return rec
    
    def fit(self, X):
        if self.how == 'user':
            Xfilled = []
            for user in X.index.values:
                ubf = self._user_based_filtering(user, X)
                weighted_sum = np.sum(X.loc[ubf.index, :].values * ubf.values.reshape(-1, 1), axis=0)
                Xfilled.append(weighted_sum / np.sum(np.abs(ubf.values)))
            self.Xfilled = pd.DataFrame(np.array(Xfilled), index=X.index, columns=X.columns)
        elif self.how == 'item':
            Xtfilled = []
            for item in X.columns.values:
                ibf = self._item_based_filtering(item, X)
                Xt = X.T
                weighted_sum = np.sum(Xt.loc[ibf.index, :].values * ibf.values.reshape(-1, 1), axis=0)
                Xtfilled.append(weighted_sum / np.sum(np.abs(ibf.values)))
            self.Xfilled = pd.DataFrame(np.array(Xtfilled).T, index=X.index, columns=X.columns)
        else:
            print('Use either "user" or "item" for the parameter "how".')
    
    def predict(self, user, X):
        try:
            ratings = self.Xfilled.loc[user, :]
            rated_items = X.loc[user, :] > 0
            ratings = ratings[~rated_items]
            return ratings.sort_values(ascending=False)
        except...