[PYTHON] Essayez de mettre en œuvre un filtrage basé sur le contenu ou des recommandations de documents

Poursuivant l'article précédent Implémentation du co-filtrage basé sur les éléments dans MovieLens en utilisant python comme exemple, considérons le filtrage basé sur le contenu.

À propos du filtrage basé sur le contenu

C'est un terme général pour un système qui recommande des articles en faisant correspondre les goûts des utilisateurs avec les caractéristiques des articles.

Si vous regardez les caractéristiques du contenu, vous pouvez dire qu'il s'agit d'un filtrage basé sur le contenu, donc il n'y a pas d'algorithme fixe. (Et je comprends)

Techniques de filtrage basées sur le contenu

Exemple 1: utilisation des métadonnées d'article

Par exemple, dans le cas d'un film, la quantité de fonctionnalités de l'élément peut être {acteur, genre, réalisateur, pays}, et la quantité de fonctionnalités de l'utilisateur peut être exprimée par la valeur moyenne des éléments préférés.

Exemple 2: utilisation de mots apparaissant dans des documents

Lors de la recommandation d'articles sur des sites d'actualités, il est possible d'utiliser des mots qui apparaissent dans le document. Par exemple, la quantité de fonctionnalités d'un élément est exprimée par la valeur TF / IDF d'un mot, et la quantité de fonctionnalités d'un utilisateur est exprimée par la valeur moyenne des éléments favoris (= articles).

Recommandation de documents basée sur le contenu

Cette fois, en supposant l'exemple 2, je voudrais mettre en œuvre une méthode pour recommander des documents sur la base du contenu.

La source de données

Utilisez le jeu de données scikit-learn Le jeu de données texte des 20 groupes de discussion.

Contient des données pour 20 catégories de groupes de discussion tels que "comp.graphics" et "rec.sport.baseball".

>>> from sklearn.datasets import fetch_20newsgroups
>>> newsgroups_train = fetch_20newsgroups(subset='train')
>>> newsgroups_train.data[0]
"From: [email protected] (where's my thing)\nSubject: WHAT car is this!?\nNntp-Posting-Host: rac3.wam.umd.edu\nOrganization: University of Maryland, College Park\nLines: 15\n\n I was wondering if anyone out there could enlighten me on this car I saw\nthe other day. It was a 2-door sports car, looked to be from the late 60s/\nearly 70s. It was called a Bricklin. The doors were really small. In addition,\nthe front bumper was separate from the rest of the body. This is \nall I know. If anyone can tellme a model name, engine specs, years\nof production, where this car is made, history, or whatever info you\nhave on this funky looking car, please e-mail.\n\nThanks,\n- IL\n   ---- brought to you by your neighborhood Lerxst ----\n\n\n\n\n"

Système de recommandation de documents à construire

Nous allons construire un système qui saisit la fréquence d'occurrence des mots (sac de mots) et renvoie des documents avec une forte similitude (dans ce cas, publication dans un groupe de discussion).

1. Construire un corpus

from gensim import corpora, models, similarities
from sklearn.datasets import fetch_20newsgroups
from collections import defaultdict
import nltk
import re

def create_dictionary_and_corpus(documents):
    texts = [tokens(document) for document in documents]

    frequency = defaultdict(int)
    for text in texts:
        for token in text:
            frequency[token] += 1

    #Supprimer les jetons avec 1 occurrence sur tous les documents
    texts = [[token for token in text if frequency[token] > 1] for text in texts]

    dictionary = corpora.Dictionary(texts)
    corpus = [dictionary.doc2bow(text) for text in texts]
    
    return dictionary, corpus

def tokens(document):
    symbols = ["'", '"', '`', '.', ',', '-', '!', '?', ':', ';', '(', ')', '*', '--', '\\']
    stopwords = nltk.corpus.stopwords.words('english')

    #Supprimer les mots vides et les symboles
    tokens = [re.sub(r'[,\.]$', '', word) for word in document.lower().split() if word not in stopwords + symbols]
    
    return tokens

#Télécharger les données de 20 groupes de discussion
newsgroups_train = fetch_20newsgroups(subset='train',remove=('headers', 'footers', 'quotes'))

#Créez un dictionnaire et un corpus en utilisant les 100 premiers
dictionary, corpus = create_dictionary_and_corpus(newsgroups_train.data[0:100])

Pour plus d'informations sur dictonary et corpus, voir tutoriel gensim.

2. Construisez un modèle

def create_model_and_index(corpus):
    tfidf = models.TfidfModel(corpus)
    index = similarities.MatrixSimilarity(tfidf[corpus])
    return tfidf, index

model, index = create_model_and_index(corpus)

Construisez un modèle Tfidf à partir de corpus. Pour plus d'informations, accédez à Thèmes et transformations.

3. Recommander des documents

Essayez d'utiliser les premières données d'entraînement (index: 0) pour la saisie. Si le système de recommandation est construit correctement, vous devriez être recommandé comme document similaire.

bow = dictionary.doc2bow(tokens(newsgroups_train.data[0]))
vec_tfidf = model[bow]
sims = index[vec_tfidf] 

sims = sorted(enumerate(sims), key=lambda item: item[1], reverse=True)

for i in range(3):
    doc_id     = sims[i][0]
    simirarity = round(sims[i][1] * 100, 0)
    print(doc_id, simirarity)

Comme prévu, doc_id: 0 a été recommandé avec 100% de similitude.

0 100.0
17 12.0
84 11.0

Il faut noter que

sims = index[vec_tfidf] 

La similitude est calculée dans la partie de, mais vous voudrez peut-être voir le tutoriel Requêtes de similarité pour plus de détails.

Résumé

Cette fois, nous avons utilisé les données de formation comme données d'entrée, mais si vous exprimez le document préféré de l'utilisateur dans un sac de mots et que vous le saisissez, je pense que ce sera un système de recommandation de document personnalisé. (Bien que cela demandera probablement une certaine ingéniosité dans la pratique)

Je vais également coller le code combiné.


from gensim import corpora, models, similarities
from sklearn.datasets import fetch_20newsgroups
from collections import defaultdict
import nltk
import re

def create_dictionary_and_corpus(documents):
    texts = [tokens(document) for document in documents]

    frequency = defaultdict(int)
    for text in texts:
        for token in text:
            frequency[token] += 1

    texts = [[token for token in text if frequency[token] > 1] for text in texts]

    dictionary = corpora.Dictionary(texts)
    corpus = [dictionary.doc2bow(text) for text in texts]
    
    return dictionary, corpus

def tokens(document):
    symbols = ["'", '"', '`', '.', ',', '-', '!', '?', ':', ';', '(', ')', '*', '--', '\\']
    stopwords = nltk.corpus.stopwords.words('english')
    tokens = [re.sub(r'[,\.]$', '', word) for word in document.lower().split() if word not in stopwords + symbols]
    
    return tokens

def create_model_and_index(corpus):
    tfidf = models.TfidfModel(corpus)
    index = similarities.MatrixSimilarity(tfidf[corpus])
    return tfidf, index

# Use 100 samples to build dictionary and corpus
newsgroups_train = fetch_20newsgroups(subset='train',remove=('headers', 'footers', 'quotes'))
dictionary, corpus = create_dictionary_and_corpus(newsgroups_train.data[0:100])

# Create TfIdf Model and its index
model, index = create_model_and_index(corpus)

# System Evaluation
bow = dictionary.doc2bow(tokens(newsgroups_train.data[0]))
vec_tfidf = model[bow]
sims = index[vec_tfidf] 

sims = sorted(enumerate(sims), key=lambda item: item[1], reverse=True)

for i in range(3):
    doc_id     = sims[i][0]
    simirarity = round(sims[i][1] * 100, 0)
    print(doc_id, simirarity)

Recommended Posts

Essayez de mettre en œuvre un filtrage basé sur le contenu ou des recommandations de documents
[Recommandation] Filtrage basé sur le contenu et filtrage coopératif