0

Je souhaite créer une application de recommandation à l'aide de spark mllib et de l'algorithme ALS dans la technique de filtrage collaboratif. Mon jeu de données présente les caractéristiques de l'utilisateur et produit sous forme de chaîne comme:Spark mllib: comment convertir les entités catégorielles de chaînes en int pour Evaluation pour accepter

[{"user":"StringName1", "product":"StringProduct1", "rating":1}, 
{"user":"StringName2", "product":"StringProduct2", "rating":2}, 
{"user":"StringName1", "product":"StringProduct2", "rating":3},..] 

Mais la méthode Rating semble accepter que les valeurs int pour les utilisateurs et les caractéristiques du produit. Cela signifie-t-il que je devrai créer un dictionnaire séparé pour mapper chaque chaîne à un int? Mon ensemble de données aura des entrées en double pour l'utilisateur et le produit. Y a-t-il une solution intégrée pour cela dans la bibliothèque mllib elle-même?

Merci et toute aide appréciée! Edit: Non, ce n'est pas un doublon car la réponse à cette question ne semble pas correspondre à mon scénario. La bibliothèque spark.ml.recommendation.ALS.Rating ne semble pas prendre en charge les valeurs de chaîne pour user ou item. J'ai besoin de ce soutien.

+0

Quelle est la forme ou votre jeu de données? est-ce 'RDD [(String, String, Float)]'? – jtitusj

+0

@JohnTitusJungao oui. – void

+0

@ zero323 s'il vous plaît voir la modification. Aide appréciée! – void

Répondre

3

Laissez-moi essayer. En supposant que data: RDD[(String, String, Float)]

import org.apache.spark.mllib.recommendation.Rating 

val data = sc.parallelize(Array(("StringName1", "StringProduct1", 1.0), ("StringName2", "StringProduct2", 2.0), ("StringName3", "StringProduct3", 3.0))) 

//get distinct names and products and create maps from them 
val names = data.map(_._1).distinct.sortBy(x => x).zipWithIndex.collectAsMap 
val products = data.map(_._2).distinct.sortBy(x => x).zipWithIndex.collectAsMap 

//convert to Rating format 
val data_rating = data.map(r => Rating(names(r._1).toInt, products(r._2).toInt, r._3)) 

Cela devrait le faire. Fondamentalement, vous venez de créer un mappage à partir de chaîne à long, puis convertir long en int.

+0

Mais après cela, comment puis-je faire les prédictions après l'entraînement? Disons que j'ai un tuple de '(noms, produits)' pour prédire la note. Comment faire correspondre les noms à l'index correspondant dans l'ensemble d'apprentissage? – void

+1

si vous avez 'new_data: RDD [(String, String)]', vous devez créer 'val new_data_rating = new_data.map (r => (noms (r._1) .toInt, produits (r._2) .toInt)) 'puis le nourrir dans model.predict. – jtitusj

+0

Une dernière question. Alors, que se passe-t-il si dans mon 'new_data_rating', il y a un nom qui n'était pas présent dans l'ensemble d'entraînement. Ceci est censé être géré par l'algorithme ALS, mais ici je vais devoir le gérer? – void