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:
- Integración de Eclipse con Maven.
- Creación de un Proyecto Maven.
- 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. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** 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(); | |
} | |
} |