Implémenter le co-filtrage basé sur les éléments dans Python en utilisant MovieLens comme exemple

Du co-filtrage, j'ai implémenté le co-filtrage basé sur les éléments le plus simple en python, alors exposons-le à Qiita. (Il s'agit probablement de la première implémentation, donc s'il y a des erreurs, veuillez préciser mm)

Utilisez MovieLens 100K Dataset comme sujet recommandé. Je laisserai l'explication détaillée à la destination du lien, mais en gros, ce sont les données qui ont évalué le film avec une note de 1 à 5.

À propos du co-filtrage

En anglais, le co-filtrage est un filtrage collaboratif, que l'on peut appeler un «système de recommandation basé sur le bouche-à-oreille basé sur l'évaluation des autres».

Le co-filtrage peut être classé comme suit, et le co-filtrage basé sur les éléments est positionné comme l'un d'entre eux.

Pour plus de détails, veuillez lire Commentaire du système de recommandation / matériel de conférence du professeur Kamishima. Cette classification est également basée sur le matériau ci-dessus.

Co-filtrage basé sur les articles

J'ai écrit que le co-filtrage est un système de recommandation qui "utilise l'évaluation des autres", mais le co-filtrage basé sur les éléments est basé sur les deux hypothèses suivantes.

Hypothèse 1: Parmi les éléments que M. A n'a pas évalués (= candidats recommandés), ceux qui sont susceptibles d'être appréciés sont similaires aux éléments que M. A évalue fortement. </ i>

Hypothèse 2: Les éléments peuvent être considérés comme similaires si leurs modèles d'évaluation sont similaires. </ i>

Pour obtenir une image, l'explication à la page 36 ~ de Construction d'un système de recommandation utilisant le filtrage coopératif est facile à comprendre.

Il est exprimé par une formule mathématique comme suit.

r'_{u,y} = \frac{\sum _{j \in Y_u} {s_{y,j}r_{u,j}}}{\sum _{j \in Y_u} {\mid s_{y,j} \mid}}
\scriptsize r'_{u,y}La prédiction d'évaluation pour l'élément y de l'utilisateur u\\
\scriptsize S_{y,j}La similitude entre l'élément y et l'élément j\\
\scriptsize Y_{u}Est un ensemble d'éléments que l'utilisateur u a évalué\\
\scriptsize r_{u,j}La note de l'utilisateur u pour l'élément j

Le numérateur est la somme pondérée des items évalués par similarité, ce qui correspond à l'hypothèse 1. Le dénominateur est la normalisation.

ÉTAPE 1: Calculez la similitude des éléments

Premièrement, nous devons calculer la similitude des éléments qui correspondent à l'hypothèse 2.

Convertir les données csv et tsv en une matrice avec MovieLens utilisant python comme exemple suppose qu'elle a déjà été chargée dans la matrice R.

>>> print(R)
[[ 5.  3.  4. ...,  0.  0.  0.]
 [ 4.  0.  0. ...,  0.  0.  0.]
 [ 0.  0.  0. ...,  0.  0.  0.]
 ...,
 [ 5.  0.  0. ...,  0.  0.  0.]
 [ 0.  0.  0. ...,  0.  0.  0.]
 [ 0.  5.  0. ...,  0.  0.  0.]]

Cette fois, nous utiliserons le cosinus pour calculer la similitude des éléments. Il semble que la corrélation de Pearson soit également utilisée.

def compute_item_similarities(R):
    # n: movie counts
    n = R.shape[1]
    sims = np.zeros((n,n))

    for i in range(n):
        for j in range(i, n):
            if i == j:
                sim = 1.0
            else:
                # R[:, i]Est un vecteur de colonne répertoriant toutes les évaluations utilisateur pour l'élément i
                sim = similarity(R[:,i], R[:,j])

            sims[i][j] = sim 
            sims[j][i] = sim 

    return sims 

def similarity(item1, item2):
    #Un ensemble d'utilisateurs qui ont évalué à la fois item1 et item2
    common = np.logical_and(item1 != 0, item2 != 0)

    v1 = item1[common]
    v2 = item2[common]

    sim = 0.0
    #Le nombre d'évaluateurs communs est limité à 2 ou plus.
    if v1.size > 1:
        sim = 1.0 - cosine(v1, v2)

    return sim

sims = compute_item_similarities(R)
>>> print(sims)
[[ 1.          0.94873739  0.91329972 ...,  0.          0.          0.        ]
 [ 0.94873739  1.          0.90887971 ...,  0.          0.          0.        ]
 [ 0.91329972  0.90887971  1.         ...,  0.          0.          0.        ]
 ...,
 [ 0.          0.          0.         ...,  1.          0.          0.        ]
 [ 0.          0.          0.         ...,  0.          1.          0.        ]
 [ 0.          0.          0.         ...,  0.          0.          1.        ]]

ÉTAPE 2: Évaluation des prédictions

Puisque la similitude S de la formule suivante a été obtenue à l'ÉTAPE 1, la valeur prédite peut être obtenue en obtenant la somme pondérée et en la normalisant.

r'_{u,y} = \frac{\sum _{j \in Y_u} {s_{y,j}r_{u,j}}}{\sum _{j \in Y_u} {\mid s_{y,j} \mid}}
def predict(u, sims):
    #Non classé est 0,Evalué est un vecteur qui devient 1. Pour le calcul des normalisateurs.
    x = np.zeros(u.size) 
    x[u > 0] = 1

    scores      = sims.dot(u)
    normalizers = sims.dot(x)

    prediction = np.zeros(u.size)
    for i in range(u.size):
        #La valeur prédite est 0 pour les cas où le dénominateur est 0 et les éléments évalués
        if normalizers[i] == 0 or u[i] > 0:
            prediction[i] = 0
        else:
            prediction[i] = scores[i] / normalizers[i]

    #Prédiction de l'évaluation de l'utilisateur u pour l'élément i
    return prediction

Pour confirmation, je l'ai essayé avec un exemple simple et j'ai obtenu le résultat.


u = np.array([5, 0, 1])
sims = np.array([ [1, 0.2, 0], [0.2, 1, 0.1], [0, 0.1, 1] ])

>> print(predict(u, sims))
[ 0.          3.66666667  0.        ]

Résumé

Implémentation d'un co-filtrage basé sur les éléments basé sur les données MovieLens Les matériaux à partir desquels cet article est basé sont les suivants.

Recommended Posts