Implementieren Sie die artikelbasierte Co-Filterung in Python unter Verwendung von MovieLens als Beispiel

Von der Co-Filterung habe ich die einfachste artikelbasierte Co-Filterung in Python implementiert, sodass ich sie Qiita zugänglich machen werde. (Dies ist wahrscheinlich die erste Implementierung. Wenn also Fehler auftreten, weisen Sie bitte auf mm hin.)

Verwenden Sie MovieLens 100K Dataset als empfohlenes Thema. Ich werde die detaillierte Erklärung dem Linkziel überlassen, aber grob gesagt sind es die Daten, die den Film mit einer Bewertung von 1 bis 5 bewertet haben.

Über das Co-Filtern

Co-Filtering ist im Englischen Collaborative Filtering, das als "Empfehlungssystem basierend auf Mundpropaganda basierend auf der Bewertung anderer" bezeichnet werden kann.

Die Co-Filterung kann wie folgt klassifiziert werden, und die artikelbasierte Co-Filterung wird als eine davon positioniert.

Weitere Informationen finden Sie unter Erklärung des Empfehlungssystems / Vorlesungsunterlagen von Professor Kamishima. Diese Klassifizierung basiert ebenfalls auf dem obigen Material.

Artikelbasierte Co-Filterung

Ich schrieb, dass die Co-Filterung ein Empfehlungssystem ist, das "die Bewertung anderer verwendet", aber die artikelbasierte Co-Filterung basiert auf den folgenden zwei Annahmen.

Annahme 1: Von den Punkten, die Herr A nicht bewertet hat (= empfohlene Kandidaten), ähneln diejenigen, die wahrscheinlich gemocht werden, denen, die Herr A hoch bewertet. </ i>

Annahme 2: Elemente können als ähnlich bezeichnet werden, wenn ihre Bewertungsmuster ähnlich sind. </ i>

Um ein Bild zu erhalten, ist die Erklärung auf Seite 36 von Aufbau eines Empfehlungssystems mithilfe kooperativer Filterung leicht zu verstehen.

Es wird durch eine mathematische Formel wie folgt ausgedrückt.

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}Ist die Bewertungsvorhersage für das Element y des Benutzers u\\
\scriptsize S_{y,j}Ist die Ähnlichkeit zwischen Punkt y und Punkt j\\
\scriptsize Y_{u}Ist eine Reihe von Elementen, die Benutzer u ausgewertet hat\\
\scriptsize r_{u,j}Ist die Bewertung des Benutzers u für Artikel j

Der Zähler ist die gewichtete Summe der nach Ähnlichkeit bewerteten Elemente, die Annahme 1 entspricht. Der Nenner ist die Normalisierung.

SCHRITT 1: Berechnen Sie die Ähnlichkeit von Elementen

Zunächst müssen wir die Ähnlichkeit der Elemente berechnen, die Annahme 2 entsprechen.

Konvertieren von CSV- und TsV-Daten in eine Matrix mit Python als Beispiel für MovieLens setzt voraus, dass sie bereits in die Matrix R geladen wurden.

>>> 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.]]

Dieses Mal verwenden wir Cosinus, um die Ähnlichkeit von Elementen zu berechnen. Es scheint, dass auch die Pearson-Korrelation verwendet wird.

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]Ist ein Spaltenvektor, der alle Benutzerbewertungen für Artikel i auflistet
                sim = similarity(R[:,i], R[:,j])

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

    return sims 

def similarity(item1, item2):
    #Eine Gruppe von Benutzern, die sowohl item1 als auch item2 bewertet haben
    common = np.logical_and(item1 != 0, item2 != 0)

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

    sim = 0.0
    #Die Anzahl der gemeinsamen Bewerter ist auf 2 oder mehr begrenzt.
    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.        ]]

SCHRITT 2: Bewertung vorhersagen

Da die Ähnlichkeit S der folgenden Formel in SCHRITT 1 erhalten wurde, kann der vorhergesagte Wert erhalten werden, indem die gewichtete Summe erhalten und normalisiert wird.

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):
    #Unrated ist 0,Bewertet wird ein Vektor, der 1 wird. Zur Berechnung von Normalisierern.
    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):
        #Der vorhergesagte Wert ist 0 für Fälle, in denen der Nenner 0 ist und ausgewertete Elemente
        if normalizers[i] == 0 or u[i] > 0:
            prediction[i] = 0
        else:
            prediction[i] = scores[i] / normalizers[i]

    #Vorhersage der Bewertung des Benutzers u für Punkt i
    return prediction

Zur Bestätigung habe ich es mit einem einfachen Beispiel versucht und das Ergebnis erhalten.


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.        ]

Zusammenfassung

Implementierte artikelbasierte Co-Filterung basierend auf MovieLens-Daten. Die Materialien, auf denen dieser Artikel basiert, sind wie folgt.

Recommended Posts