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.
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)
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.
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).
Cette fois, en supposant l'exemple 2, je voudrais mettre en œuvre une méthode pour recommander des documents sur la base du contenu.
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"
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).
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.
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.
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.
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)