4

Les données d'entrée que j'ai pour recommandation ressemble à:convertissons les données d'entrée pour la SLA dans pyspark

[(u'97990079', u'18_34', 2), 
(u'585853655', u'11_8', 1), 
(u'1398696913', u'6_20', 1), 
(u'612168869', u'7_16', 1), 
(u'2272846159', u'11_17', 2)] 

qui suit le format que (user_id, item_id, score). Si je comprends bien, ALS en étincelle doit convertir user_id, item_id en nombre entier avant l'entraînement? Dans ce cas, les seules solutions que je peux penser est maintenant d'utiliser des dictionnaires et la carte tous les user_id et item_id en entier comme

dictionary for item_id : {'18_34': 1, '18_35':2, ...} 
dictionary for user_id : {'97990079':1, '585853655':2, ...} 

Mais je me demandais s'il y a d'autres façon élégante de le faire? Merci!

Répondre

4

Une façon de gérer cela est d'utiliser des transformateurs ML. Tout d'abord permet de convertir vos données en une trame de données:

ratings_df = sqlContext.createDataFrame([ 
    (u'97990079', u'18_34', 2), (u'585853655', u'11_8', 1), 
    (u'1398696913', u'6_20', 1), (u'612168869', u'7_16', 1), 
    (u'2272846159', u'11_17', 2)], 
    ("user_id", "item_id_str", "rating")) 

Ensuite, nous aurons besoin d'un StringIndexer

from pyspark.ml.feature import StringIndexer 

indexer = StringIndexer(inputCol="item_id_str", outputCol="item_id") 

permet enfin de transformer dataframe en utilisant indexeur:

from pyspark.sql.functions import col 

transformed = (indexer 
    .fit(ratings_df) 
    .transform(ratings_df) 
    .withColumn("user_id", col("user_id").cast("integer")) 
    .select("user_id", "item_id", "rating")) 

et convertir en RDD[Rating]:

from pyspark.mllib.recommendation import Rating 

ratings_rdd = transformed.map(lambda r: Rating(r.user_id, r.item_id, r.rating)) 

Dans les nouvelles versions de Spark, vous pouvez sauter les conversions et les utiliser directement ml.recommendation.ALS:

from pyspark.ml.recommendation import ALS 

als = (ALS(userCol="user_id", itemCol="item_id", ratingCol="rating") 
    .fit(transformed))