miércoles, 23 de abril de 2014

Laboratorio: Sistema de Recomendación con Mahout

Tutorial de creación de sistema de Recomendación

   En la pagina web de Apache Mahout se proporciona un pequeño tutorial de cómo crear un sistema de recomendación (filtrado colaborativo entre usuarios):

https://mahout.apache.org/users/recommender/userbased-5-minutes.html

Pasos seguidos: 
  1. Integración de Eclipse con Maven.
  2. Creación de un Proyecto Maven.
  3. Añadir dependencias en "pom.xml". En mi caso tengo instalado la versión de mahout de la distribución CDH5 de cloudera.
        <dependency>                                                  
            <groupId>org.apache.mahout</groupId> 
            <artifactId>mahout-core</artifactId>          
            <version>0.8-cdh5.0.0</version>              
        </dependency>                                                 
     
     
Recomendación de 3 items al usuario 2
Evaluación del sistema de recomendación











Aplicación del sistema de recomendación en un dataset real

   El grupo de investigación GroupLense proporciona a través de su pagina web diversos datasets de puntuaciones de películas proporcionadas por diferentes usuarios extraídos de la página MovieLens. He utilizado el dataset MovieLens 1M, que proporciona 1 millón de puntuaciones proporcionadas por 6000 usuarios sobre 4000 películas.

Ejemplo de recomendación de películas.


/** Sistema de recomendación: User-Based
* Dataset: GroupLens (http://grouplens.org/datasets/movielens/)
*
* Autor: Antonio Soriano
*/
public class App{
// Rutas de ficheros de entrada y salida para la conversion
static final String inputFile = "data/ratings.dat" ;
static final String outputFile = "data/ratings.csv" ;
static final String movieFile = "data/movies.dat" ;
public static void main( String[] args ) throws IOException, TasteException{
// Conversión del fichero de entrada a csv
CreateCsvRatingsFile();
// Obtenermos la lista de películas
ArrayList<String> movieList = ObtainMovie();
// Creamos el modelo de datos para el recomendador
File ratingsFile = new File(outputFile);
DataModel model = new FileDataModel(ratingsFile);
// Creamos un recomendador basado en similitud entre usuarios
UserSimilarity similarity = new PearsonCorrelationSimilarity(model);
UserNeighborhood neighborhood = new ThresholdUserNeighborhood(0.1, similarity, model);
UserBasedRecommender recommender = new GenericUserBasedRecommender(model, neighborhood, similarity);
// Escogemos un usuario, mostramos sus votos y las peliculas recomendadas
int userId = 20 ; // Uno al azar
int numMovieRec = 3 ; // Recomendamos 3 peliculas
// Primero mostramos las peliculas votadas
System.out.println("El usuario con Id: " + userId + " ha votado:" );
LongPrimitiveIterator items = model.getItemIDsFromUser(userId).iterator();
for(;items.hasNext();){
long movieId = items.nextLong();
System.out.println(" - Pelicula votada: " + movieList.get((int)movieId - 1) + " - Voto: " + model.getPreferenceValue(userId, movieId));
}
System.out.println("");
System.out.println("Las películas recomendadas son:");
List<RecommendedItem> recommendations = recommender.recommend(userId, numMovieRec);
for(RecommendedItem recommendedItem : recommendations){
System.out.println(" - Recomendamos: " + movieList.get((int) recommendedItem.getItemID()));
}
/*
// Recorremos todos los usuarios y recomendamos 3 peliculas
for (LongPrimitiveIterator it = model.getUserIDs();it.hasNext();){
long userId = it.nextLong();
List<RecommendedItem> recommendations = recommender.recommend(userId, 3);
// Si está vacio
if(recommendations.size() == 0){
System.out.println("User " + userId + ": no recommendations");
}
for(RecommendedItem recommendedItem : recommendations){
System.out.println("User " + userId + ": " + recommendedItem);
}
}*/
}
private static ArrayList<String> ObtainMovie() throws IOException{
BufferedReader br = new BufferedReader(new FileReader(movieFile)) ;
ArrayList<String> movies = new ArrayList<String>();
String line ;
String[] temp;
int i = 1;
while( (line = br.readLine())!= null ){
temp = line.split("::");
if( i != Integer.parseInt(temp[0])){
for (; i < Integer.parseInt(temp[0]);i++)
movies.add("Null");
movies.add(temp[1]);
i = Integer.parseInt(temp[0])+1;
}else{
movies.add(temp[1]);
i++;
}
}
br.close();
return movies;
}
private static void CreateCsvRatingsFile() throws IOException{
// Descriptores de ficheros de lectura y escritura
BufferedReader br = new BufferedReader(new FileReader(inputFile)) ;
BufferedWriter bw = new BufferedWriter(new FileWriter(outputFile)) ;
// Leemos linea a linea, la procesamos y escribimos linea a linea
String line = null;
String line2write = null;
String[] temp;
while( (line = br.readLine())!= null){
temp = line.split("::"); // linea = 4 strings --> s1::s2::s3::s4
line2write = temp[0] + "," + temp[1] + "," + temp[2]; // nuevo formato: s1,s2,23
bw.write(line2write);
bw.newLine();
bw.flush();
}
// Cerramos descriptores
bw.close();
br.close();
}
}

1 comentario:

  1. Buenas Tardes quisiera saber como implementar este codigo para Map/Reduce, podrias ayudarme por favor

    ResponderEliminar