Le deuxième de la série Spark. Cette fois, nous utiliserons MLlib pour implémenter les recommandations en utilisant le co-filtrage.
Premier coup [Apprentissage automatique] Démarrez Spark avec iPython Notebook et essayez MLlib http://qiita.com/kenmatsu4/items/00ad151e857d546a97c3
environnement
Veuillez noter que cet article décrit ce qui a été fait dans l'environnement ci-dessus, de sorte que les paramètres peuvent différer dans d'autres environnements. En outre, il est fondamentalement censé exécuter Spark sur iPython Notebook. Veuillez consulter ce qui précède pour savoir comment procéder.
Commencez par démarrer Spark.
#Démarrer Spark
import os, sys
import pandas as pd
import numpy as np
from datetime import datetime as dt
print "loading PySpark setting..."
spark_home = os.environ.get('SPARK_HOME', None)
print spark_home
if not spark_home:
raise ValueError('SPARK_HOME environment variable is not set')
sys.path.insert(0, os.path.join(spark_home, 'python'))
sys.path.insert(0, os.path.join(spark_home, 'python/lib/py4j-0.8.2.1-src.zip'))
execfile(os.path.join(spark_home, 'python/pyspark/shell.py'))
Voici les exemples de données inclus avec Spark, et il existe des données sur les informations de critique de film appelées MovieLens, alors utilisez-les. Lisez les données dans SPARK_HOME comme indiqué ci-dessous.
#Exemple de lecture de données
df = pd.read_csv(os.path.join(spark_home, 'data/mllib/als/sample_movielens_ratings.txt'),
delimiter='::', names=('uid', 'iid', 'rating','time'),engine='python')
pv_rating = df.pivot(index='uid', columns='iid', values='rating').fillna(0)
print pv_rating
Les données ressemblent à ceci. uid est l'ID utilisateur, iid est l'ID d'élément (film), et les données à l'intérieur sont la note du film pour chaque utilisateur.
uid\iid | 0 | 1 | 2 | 3 | 4 | ... | 95 | 96 | 97 | 98 | 99 |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 0 | 3 | 1 | 0 | ... | 2 | 1 | 0 | 1 | 1 |
1 | 0 | 0 | 2 | 1 | 2 | ... | 0 | 1 | 1 | 0 | 0 |
2 | 0 | 0 | 0 | 0 | 3 | ... | 0 | 0 | 0 | 0 | 0 |
3 | 1 | 1 | 1 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 |
... | |||||||||||
27 | 1 | 0 | 0 | 0 | 0 | ... | 1 | 0 | 0 | 1 | 0 |
28 | 3 | 1 | 4 | 1 | 0 | ... | 2 | 0 | 0 | 1 | 1 |
29 | 0 | 0 | 0 | 1 | 1 | ... | 0 | 0 | 1 | 0 | 1 |
Tout d'abord, visualisons de quel type de données il s'agit.
#Visualisation des notes
%matplotlib inline
import matplotlib.pyplot as plt
import matplotlib.cm as cm
n_y, n_x = pv_rating.shape
X, Y = np.meshgrid(range(n_x+1), range(n_y+1))
Z = pv_rating.as_matrix()
Z.astype(np.float32)
Z = Z[::-1,:]
print Z.shape
fig = plt.figure(figsize=(19,5))
ax = plt.subplot(111)
plt.ylim(0,30)
plt.xlim(0,99)
ax.set_xticks([])
ax.set_yticks([])
cax = ax.pcolor(X, Y, Z, cmap=cm.get_cmap('ocean_r'), alpha=0.6)
cbar = fig.colorbar(cax, ticks=range(6))
#cbar.ax.set_yticklabels(['5', '4', '3', '2', '1', '0'])# vertically oriented colorbar
plt.show()
L'axe vertical est l'utilisateur et l'axe horizontal est le film. Les zones blanches sont celles où il n'y a pas d'évaluation. Lorsqu'il y a une couleur, il y a des informations de classement et les numéros sont codés par couleur comme indiqué par la barre sur la droite.
Le sujet principal est d'ici. Les recommandations sont faites en utilisant la méthode appelée ALS (Alternating Least Squares) dans MLlib fournie avec Spark. Il s'agit d'une technique appelée co-filtrage, qui fait des inférences en utilisant les informations d'un utilisateur et d'un autre utilisateur ayant des goûts similaires (ici, la classification des films). L'une des caractéristiques est que le contenu du film est ignoré dans un sens et déduit du comportement de l'utilisateur.
Nous commencerons à apprendre des données.
from pyspark.mllib.recommendation import ALS, MatrixFactorizationModel, Rating
#Préparation des données d'entraînement
sc_rating = sc.parallelize(df.as_matrix())
ratings = sc_rating.map(lambda l: Rating(int(l[0]), int(l[1]), float(l[2])))
# ALS(Alternating Least Squares)Générer des recommandations avec
rank = 10
numIterations = 10
model = ALS.train(ratings, rank, numIterations)
#Donnez une note à la partie où il n'y avait pas de données à partir des données apprises
n_y, n_x = pv_rating.shape
X, Y = np.meshgrid(range(n_x+1), range(n_y+1))
f_XY = np.c_[Y.flatten(), X.flatten()]
predictions_all = model.predictAll(sc.parallelize(f_XY)).map(lambda r: ((r[0], r[1]), limitter(r[2]) ))
def selector(x, y):
if x is None:
return y
elif x != 0:
return x
else:
return y
#Restez là où il y a déjà une note et remplacez la valeur calculée par ALS là où il n'y a pas de note
ratesAndPreds = ratings.map(lambda r: ((r[0], r[1]), r[2])).rightOuterJoin(predictions_all).map(lambda r: ((r[0][0], r[0][1]), selector(r[1][0], r[1][1])) )
result = np.array(ratesAndPreds.sortBy(lambda x: (x[0], x[1])).collect())
Z = result[:,1]
Z = Z.astype(np.float32).reshape(pv_rating.shape)[::-1,:]
Visualisez les résultats déduits. Dans le graphique précédent, il y avait de nombreuses parties blanches (parties sans cote), mais elles ont presque disparu! L'endroit où la valeur numérique est entrée dans cet espace vide est l'information de recommandation. Vous pouvez définir un certain seuil pour cela et dire "Recommander s'il est supérieur à cela": smile:
fig = plt.figure(figsize=(19,5))
ax = plt.subplot(111)
plt.ylim(0,29)
plt.xlim(0,99)
ax.set_xticks([])
ax.set_yticks([])
cax = ax.pcolor(X, Y, Z, cmap=cm.get_cmap('ocean_r'), alpha=0.6)
cbar = fig.colorbar(cax, ticks=range(6))
plt.show()
Enfin, regardons l'exactitude de cet apprentissage. Mesurez la distance entre la valeur prédite et l'endroit où il y a à l'origine une note par l'erreur quadratique moyenne.
#Calcul de la précision
testdata = ratings.map(lambda p: (p[0], p[1]))
predictions = model.predictAll(testdata).map(lambda r: ((r[0], r[1]), limitter(r[2]) ))
ratesAndPreds = ratings.map(lambda r: ((r[0], r[1]), r[2])).join(predictions)
MSE = ratesAndPreds.map(lambda r: (r[1][0] - r[1][1])**2).mean()
print("Mean Squared Error = " + str(MSE))
out
#Erreur quadratique moyenne
Mean Squared Error = 0.0558736464582
De plus, les résultats sont les suivants lorsqu'ils sont visualisés numériquement. Lorsqu'il y a une note, les chiffres sont proches, et s'il n'y en a aucun, la note prévue est incluse.
out
((uid, iid), (rating, predict))
[((29, 17), (3.0, 2.9547048179008057)),
((23, 51), (None, 1.421916504776083)),
((11, 7), (None, 1.9669319580489901)),
((28, 10), (None, 0.06769150007295854)),
((9, 93), (None, 2.349846935916598)),
((23, 91), (None, 2.597452490149535)),
((17, 13), (2.0, 2.0700773308441507)),
((16, 38), (1.0, 0.8512992797830536)),
((22, 12), (None, 3.331810711043588)),
((12, 50), (4.0, 4.095528922729588)),
((11, 15), (None, 1.1874705514088135)),
((22, 52), (None, 3.4707062021048283)),
((0, 14), (None, 0.503229802782621)),
((8, 94), (None, 1.0007500227764983)),
((29, 89), (None, 0.4272431835442813)),
((5, 1), (1.0, 1.2148556310982808)),
((4, 42), (None, 1.030942641195369)),
((25, 13), (None, 1.5033919417064503)),
((3, 55), (None, 2.50649511105159))]
Spark 1.5.0 Machine Learning Library (MLlib) Guide http://spark.apache.org/docs/latest/mllib-guide.html
MLlib - Collaborative Filtering http://spark.apache.org/docs/latest/mllib-collaborative-filtering.html
Movie Recommendation with MLlib https://databricks-training.s3.amazonaws.com/movie-recommendation-with-mllib.html
Code de cet article (GitHub) https://github.com/matsuken92/Qiita_Contents/blob/master/MLlib_recommendation/Spark_MLlib-recommendation.ipynb