jueves, 6 de junio de 2024

Recomendadores (quien compró este libro también compró...)

Hacer Recomendaciones

Introducción

Los sistemas de recomendación revolucionaron la forma en que se interactuaba con las páginas web, transformándolas de espacios pasivos en plataformas dinámicas y personalizadas. Estos sistemas, basados en el análisis de las acciones pasadas de los usuarios, ofrecen sugerencias de artículos, productos o contenido que podrían ser de su interés.

El pilar fundamental de los sistemas de recomendación radica en la comprensión del comportamiento de los usuarios. Al analizar sus interacciones previas, como compras, visualizaciones o búsquedas, estos sistemas identifican patrones y relaciones que permiten inferir sus preferencias. Por ejemplo, si un usuario "A" compra un producto "X" y luego otro usuario "C" adquiere el mismo producto, el sistema infiere que ambos usuarios comparten un gusto similar. En este escenario, el sistema podría recomendar el producto "Y", adquirido por el usuario "A", al usuario "C", basándose en su afinidad por el producto "X".

Algoritmos de recomendación:

Existen diversos algoritmos que sustentan los sistemas de recomendación, cada uno con sus propias ventajas y desventajas. Entre los más comunes destacan:

  1. Filtros colaborativos:
  2. Estos algoritmos se basan en la idea de que los usuarios con comportamientos similares tienden a tener preferencias similares. Para ello, se analiza la matriz de interacciones entre usuarios y productos, identificando grupos de usuarios con patrones de interacción semejantes. De esta manera, el sistema puede recomendar a un usuario productos que han sido valorados positivamente por otros usuarios del mismo grupo.
  3. Filtros basados en contenido:
  4. A diferencia de los filtros colaborativos, que se centran únicamente en las interacciones entre usuarios y productos, los filtros basados en contenido consideran atributos tanto de los usuarios como de los productos. Por ejemplo, se puede analizar la edad, sexo, intereses o historial de compras de un usuario para crear un perfil que lo caracterice. De igual manera, se pueden analizar las características de los productos, como su categoría, precio o descripción. Con base en esta información, el sistema puede recomendar productos que compartan características similares a aquellos que el usuario ha valorado previamente.

Tipos de sistemas de recomendación:

Los sistemas de recomendación pueden clasificarse en dos categorías principales:

  1. Sistemas basados en memoria:
  2. Estos sistemas almacenan un registro histórico de las interacciones entre usuarios y productos, utilizando esta información para generar recomendaciones. La ventaja de este enfoque radica en su simplicidad y eficiencia, sin embargo, puede presentar limitaciones en cuanto a la capacidad de procesar grandes volúmenes de datos.
  3. Sistemas basados en modelos:
  4. A diferencia de los sistemas basados en memoria, estos sistemas construyen modelos estadísticos o de aprendizaje automático a partir de las interacciones entre usuarios y productos. Estos modelos permiten realizar recomendaciones más precisas y personalizadas, adaptándose a las preferencias y comportamientos cambiantes de los usuarios. Sin embargo, su implementación puede ser más compleja y requerir mayor potencia de procesamiento.

    En la medida en que la tecnología ha avanzado tanto en capacidad de procesamiento como por el desarrollo o mejoramiento de nuevos algoritmos, conjuntamente con las huellas digitales que dejan las personas en la internet, estos sistemas se vuelvan aún más sofisticados y precisos, ofreciendo una experiencia de usuario cada vez más relevante y atractiva, pero al mismo tiempo, y de acuerdo con algunas voces críticas, una creciente invasión a la privacidad y una mayor capacidad de manipulación. Voy a reproducir un ejemplo del libro Collective Intelligence de Toby Segaran, elaborado originalmente en python. Correré el ejemplo usando R.

Recomendando películas

Supongamos que tengo un listado de personas que han calificado un grupo de películas:

persona Lady Snakes Just Superman You Night
Lisa 2.5 3.5 3.0 3.5 2.5 3.0
Gene 3.0 3.5 1.5 5.0 3.5 3.0
Michael 2.5 3.0 0.0 3.5 0.0 4.0
Claudia 0.0 3.5 3.0 4.0 2.5 4.5
Mick 3.0 4.0 2.0 3.0 2.0 3.0
Jack 3.0 4.0 0.0 5.0 3.5 3.5
Toby 0.0 4.5 0.0 4.0 1.0 0.0

Por las características de esta matriz, observo que no tengo variables adicionales ni sobre las películas ni sobre los críticos, por consiguiente, puedo construir un sistema de recomendación colaborativo basado en memoria. El sistema que construya, por un lado me debe indicar qué críticos son similares tomando como base las calificaciones que le asignaron a las películas que hayan visto en común. Con esta similitud se puede, entonces, recomendar una película a los críticos que no hayan visto o calificado alguna película.

Lo primero que debemos hacer es obtener una vía para obtener la similitud entre los críticos. En principio, si tomo en cuenta las puntuaciones básicas que cada uno de ellos ha asignado, puedo obtener un espacio de preferencia y tener una primera aproximación de la similitud entre ellos.

dispersion_gr <- function(x, y, palabras = NULL, 
                          ejex = "", ejey = "",
                          titulo = ""){
        plot(x, y, type = "n", 
             xlab= ejex, title = titulo,
             ylab = ejey)
        text(x, y, as.character(palabras),
             cex = 0.7)
        
                          }
dispersion_gr(criticos$You, 
              criticos$Snakes, 
              criticos$persona, 
              "You, Me, and Dupree", 
              "Snakes on the Plane", 
              "Puntuaciones")

El gráfico nos indica que Claudia y Lisa le dieron la misma puntuación a dos películas. Mick y Jack puntearon de forma similar a "Snakes on the Plane", pero diferente a "You, Me, and Dupree". Toby y Michael se parecen menos a cualquier otro de los cinéfilos. Toby puntean con la mayor calificación a "Snakes on the Plane", y sólo le otorga 1 a "You, Me, and Dupree". Michael no vió esta última, y le dió 3 puntos a la primera. Entre más cerca están las personas en este espacio, más similares son en sus preferencias.

Si quiero saber la distancia entre Toby y Mick, resto las puntuaciones que dieron a cada película, las elevo al cuadrado, sumo el resultado y obtengo la raíz cuadrada. Es decir, estoy aplicando la distancia euclídea:

# toby <- c(4.5, 1)
# Mick <- c(4, 2)

sqrt((4.5-4)^2 + (1-2)^2)
## [1] 1.118034

Entre más cercana son las personas, más pequeña es la distancia:

# Michael y Toby

sqrt((3-4.5)^2 + (0-1)^2)
## [1] 1.802776

El resultado indica que Toby y Mick están más cercanos entre sí en comparación con Toby y Michael. Algo que el espacio de preferencias indica con claridad.

Pero si quiero saber no tanto la distancia sino la similaridad, hay que darle valores altos a las personas que son más parecidas. Para ello se agrega 1 a la función y se la invierte:

# Toby y Mick
1/(1 +sqrt((4.5-4)^2 + (1-2)^2))
## [1] 0.472136
# Toby y Michael
1/(1+sqrt((3-4.5)^2 + (0-1)^2))
## [1] 0.3567892

El resultado indica que Toby y Mick son más similares entre sí que Toby y Michael al valorar las dos películas seleccionadas. El resultado de este modelo estará siempre entre 0 y 1. Con una función puedo acelar el proceso de inspección de similitud con base en toda la data.

Algunas distancias. Ejemplos

usuario_usuario <- function(matriz, personas = c(""))
        {
       # selecciono los usuarios
        seleccion <- matriz %>% 
                filter(persona %in% personas)
        
        productos <- select_if(seleccion, is.numeric)
        usuarios <- select_if(seleccion, is.character)
        
        distancia <- dist(productos, 
                          method = "euclidean")
        similitud <- round(1/(1+distancia), 4)
        
        paste("La similitud entre:", 
              personas[1], "y",
              personas[2],"es = ", similitud)
     
        
}

usuario_usuario(criticos, c("Toby", "Michael"))
## [1] "La similitud entre: Toby y Michael es =  0.1646"
usuario_usuario(criticos, c("Toby", "Lisa"))
## [1] "La similitud entre: Toby y Lisa es =  0.1595"

El resultado nos indica que hay mayor similitud entre Toby y Michael en sus forma de calificar las películas que entre Toby y Lisa en la valoración de todas las películas.

Además de la distancia euclìdea puedo usar muchas otras mejor adaptada el tipo de data de la matriz de incidencia. Por ejemplo la correlación de Pearson ha demostrado ser una mejor medida de distancia en casos en los que las puntuaciones varían sustancialmente: algunos críticos son mucho más estrictos que otros en su puntuación.

usuario_pearson <- function(matriz, personas = c(""))
{
        # extraigo las persona que han evaluado
        seleccion <- matriz %>% 
                filter(persona %in% personas)
        
        # obtengo las peliculas 
        
        productos <- seleccion %>% 
                gather(pelicula, puntuacion, -persona) %>% 
                filter(puntuacion > 0) %>% 
                group_by(pelicula) %>% 
                count(pelicula) %>% 
                filter(n > 1)
                #spread(pelicula, puntuacion)
        # encontrar la correlacion de Pearson entre los
        # criticos
        
        a <- unname(unlist(productos$pelicula))
        
        b <-  seleccion[, a]
        c <- t(b)
        n <- ncol(c)
        sumx <-  sum(c[,1])
        sumy <-  sum(c[,2])
        
        xy <-  sum(c[,1]*c[,2])
        x2 <- sum(c[,1]^2)
        y2 <-  sum(c[,2]^2)
        
        sumx2 <- sumx^2
        sumy2 <- sumy^2
        
        
        num <- (n*xy) - (sumx*sumy)
        denx <- (n*x2-sumx2)
        deny <-  (n*y2-sumy2)
        denxy <- denx * deny
        raiz <- sqrt(denxy)
        
        
        r = num/raiz
        
        #usuarios <- select_if(seleccion, is.character)
        
        
       
        return(r)
        
        
}


usuario_pearson(criticos, c("Toby", "Lisa"))
## [1] -1.210091

Ahora busco la forma de poder obtenercon un crítico dado, de modo que, si éste está interesado, pueda revisar en primer lugar las opiniones que emiten aquellos que han punteado las pelìculas de manera similar a como las ha evaluado él

criticos_recomendados <-  function(matriz, critico,
                                  n= 3){
        # hallar la correlacion entre los criticos
        a <- cor(t(criticos[,2:7]))
        diag(a)<-0
        colnames(a) <- criticos$persona
        rownames(a) <- criticos$persona 
        a <- data.frame(a)
        # seleccionar el critico de interes
        sort(a[critico,], decreasing = T)[1:n]
        # obtener los tres que mas se le parecen
        
 
}

Aplico la funcion para tres criticos

criticos_recomendados(criticos, "Toby")
##           Lisa      Gene      Mick
## Toby 0.7957438 0.7038607 0.6408284
criticos_recomendados(criticos, "Gene")
##           Jack      Toby   Michael
## Gene 0.9415184 0.7038607 0.5310078

Toby debería leer las opiniones de Lisa, Gene y Mick; Gene, de Jack, Toby y Michael.

A continuación, habría que recomendarle películas a quien no las haya visto. Creo la función para medir la similitud entre las películas

evaluar_tambien <-  function(similares, matriz){
       buscar <-  c(rownames(similares), 
                    colnames(similares)) 
       
       criticos %>% 
               filter(persona %in% buscar) %>% 
               gather(pelicula, puntuacion, 
                      -persona) -> pa_recomendar
       
       recomendar <- pa_recomendar %>% 
               filter(puntuacion == 0)
       
       recomendar %<>% 
               group_by(pelicula) %>% 
               count(pelicula) 
       
       vio <- pa_recomendar %>% 
               filter(puntuacion > 0,
                      persona %in% rownames(similares))
       
       paste("Las personas que evaluaron:", vio$pelicula, 
             "tambien evaluaron:", recomendar$pelicula)
}

Pruebo la funcion

a <-  criticos_recomendados(criticos, "Gene")
evaluar_tambien(a, criticos)

## [1] "Las personas que evaluaron: Lady tambien evaluaron: Just"   
## [2] "Las personas que evaluaron: Snakes tambien evaluaron: Lady" 
## [3] "Las personas que evaluaron: Just tambien evaluaron: Night"  
## [4] "Las personas que evaluaron: Superman tambien evaluaron: You"
## [5] "Las personas que evaluaron: You tambien evaluaron: Just"    
## [6] "Las personas que evaluaron: Night tambien evaluaron: Lady"

a <-  criticos_recomendados(criticos, "Toby")

recomienda_producto <- function(criticosRecomendados, df){
        # extraigo al deseado
        mi_critico <- rownames(criticosRecomendados)
        
        # obtengo los criticos similares a mi_critico
        buscar <-  c(colnames(a))
        
        # elimino el nombre de mi_critico de la data
        rownames(buscar) <- NULL
        
        # selecciono las recomendaciones hechas por los criticos
        # similares
        recomendaciones  <-  criticos %>% 
                filter(persona %in% buscar)
        
        
        numericas <- select_if(recomendaciones, is.numeric)
        # eliminar valores ceros
        
        numericas * t(criticosRecomendados) -> pesos
        total <- rowSums(criticosRecomendados)
        
        columnas <- colSums(numericas)
        sim.sum <- total/columnas[columnas != 0]
        
        
        sim.sum<-sort(sim.sum, decreasing = T)
        
        return(sim.sum)
        
}

recomienda_producto(a, criticos)
##      Just       You      Lady     Night    Snakes  Superman 
## 0.3292974 0.2675541 0.2518156 0.2378259 0.1945848 0.1861246

Ahora mezclo todos los conceptos vistos y elaboro una función que me permita recomendar productos, tomando en cuenta, en este caso, al crítico más parecido a un crítico pre-seleccionado

obtener_recomendacion <-  function(matriz, miPersona, n = nrow(matriz)){
        
        #extraer el critico deseado
        mi_critico <- matriz %>% 
                filter(persona %in% miPersona)
        
        # veo que peliculas no ha evaluado
        no_vistas <- mi_critico %>% 
                gather(pelicula, puntuacion, -persona) %>% 
                filter(puntuacion == 0) %>% 
                spread(pelicula, puntuacion)
        
        # si el critico ha punteado todo,no hay nada que recomendar
        mensaje <- "Por ahora no hay recomendacion"
        if(ncol(no_vistas) == 1){
                return(mensaje)
        } else {
        
        
        # busco las personas mas similares a mi_critico
        criticos.sim <- criticos_recomendados(matriz, miPersona,
                                              n = n)
        # busco los criticos que no son mi_critico
        seleccion <- matriz %>% 
                filter(!persona %in% miPersona)
        
        # selecciono de ese df las que mi_critico no ha visto
        para_ver <- seleccion[, colnames(no_vistas)] 
        
        # anulo nombre de filas
        rownames(criticos.sim) <- NULL
        
        # elimino de los criticos el nombre del critico seleccionado
        score <- t(criticos.sim)
        score <-score[which(rownames(score)!= miPersona),]
        
        # elimino caracteres
        numericas <- select_if(seleccion, is.numeric)
        # obtengo los pesos
        numericas * t(score) -> pesos
        
        # Obtengo la sumatoria de las similitudes
        total <- sum(score)
        
        # Obtengo la sumatoria de las peliculas
        columnas <- colSums(numericas)
        
        # obtengo los valores de la pelicula de acuerdo con los 
        # criticos mas parecidos al critico seleccinado
        sim.sum <- total/columnas[columnas != 0]
        
        # ordeno de mayor a menor y obtengo las dos primeras 
        # recomendaciones mas altos
        sim.sum<-sort(sim.sum, decreasing = T)[1:2]
        
        return(sim.sum)
        
        }  
}

Pruebo

obtener_recomendacion(criticos, "Gene")
## [1] "Por ahora no hay recomendacion"
obtener_recomendacion(criticos, "Toby")
##      Just      Lady 
## 0.3731090 0.2531811
obtener_recomendacion(criticos, "Mick")
## [1] "Por ahora no hay recomendacion"
obtener_recomendacion(criticos, "Jack")
##      Just      Lady 
## 0.3556534 0.3071552

Hay un defecto en este recomendador y es que las películas más populares reciben siempre el primer lugar de recomendacion. Si le agrego un elemento de aleatoriedad mediante sample(1:6,1) puedo introducir la posiblidad de que no sea la película más popular la que se recomiende siempre.

Ejemplos adicionales

Trabajo un ejemplo proveniente de la página http://www.salemmarafi.com/code/collaborative-filtering-r/. Sigo el mismo procedimiento, pero empleo la data que he venido trabajando.

El primer paso consiste en crear la función para medir la distancia, En este caso, la distancia coseno.

 getCosine <- function(x,y) 
  {
    this.cosine <- sum(x*y) / (sqrt(sum(x*x)) * sqrt(sum(y*y)))
    return(this.cosine)
 }

Para observar qué películas son similares entre ellas, me quedo sólo con los valores de las películas, sin los usuarios

peliculas <-  criticos[, 2:7]

Creo una matriz vacía que llenaré posteriormente cuando calcule la distancia coseno ya definida:

peliculas_sim <- matrix(NA,
                nrow=ncol(peliculas),
                ncol=ncol(peliculas),
                dimnames=list(colnames(peliculas),
                              colnames(peliculas)))

knitr::kable(peliculas_sim,
                       row.names = FALSE
                       )     
Lady Snakes Just Superman You Night
NA NA NA NA NA NA
NA NA NA NA NA NA
NA NA NA NA NA NA
NA NA NA NA NA NA
NA NA NA NA NA NA
NA NA NA NA NA NA

Itero en las películas originales para aplicar la distancia a las columnas:

# Lets fill in those empty spaces with cosine similarities
# Itero entre las columnas
for(i in 1:ncol(peliculas)) {
        # itero por cada culumna
        for(j in 1:ncol(peliculas)) {
                # relleno con la distancia coseno
                peliculas_sim[i,j] <- getCosine(as.matrix(peliculas[i]),as.matrix(peliculas[j]))
        }
}

# Transformo la matriz en data.frame
peliculas_sim <- as.data.frame(peliculas_sim)

knitr::kable(peliculas_sim)    
Lady Snakes Just Superman You Night
Lady 1.0000000 0.8156887 0.5815915 0.8364864 0.8163351 0.8423369
Snakes 0.8156887 1.0000000 0.7025733 0.9798781 0.8767683 0.8690098
Just 0.5815915 0.7025733 1.0000000 0.6802298 0.7598559 0.7712312
Superman 0.8364864 0.9798781 0.6802298 1.0000000 0.9153023 0.8995283
You 0.8163351 0.8767683 0.7598559 0.9153023 1.0000000 0.8435202
Night 0.8423369 0.8690098 0.7712312 0.8995283 0.8435202 1.0000000

Para seleccionar las películas, de acuerdo con la similitud, ordeno los vecinos más próximos de cada película. Para ello creo una matriz en la que luego se coloca la información

pelis <- peliculas_sim

diag(peliculas_sim) <- 0

peliculas_vec <- matrix(NA,
                        nrow=ncol(peliculas_sim),                        ncol= 6,                   dimnames=list(colnames(peliculas_sim)))

Itero, para obtener la data

for(i in 1:ncol(peliculas_sim)) 
{
       peliculas_vec[i,] <- t(rownames(peliculas_sim[order(
                                            peliculas_sim[,i],
                                            decreasing=TRUE),][i]))
}

knitr::kable(peliculas_vec)  
Lady Night Superman You Snakes Just Lady
Snakes Superman You Night Lady Just Snakes
Just Night You Snakes Superman Lady Just
Superman Snakes You Night Lady Just Superman
You Superman Snakes Night Lady Just You
Night Superman Snakes You Lady Just Night

Quien vea la película Lady, se le puede recomendar las peliculas Night y Superman; a quien le guste la película Snakes, se le puede recomendar las películas Superman y You, y así sucesivamente.

Puedo crear una funcion con todo el procedimiento y obtener así un rcomendador para productos:

productos <- function(dato, n = 5){
        
        getCosine <- function(x,y) 
        {
                this.cosine <- sum(x*y) / (sqrt(sum(x*x)) * 
                                                   sqrt(sum(y*y)))
                return(this.cosine)
        }
        
        peliculas_sim <- matrix(NA,
                                nrow=ncol(dato),
                                ncol=ncol(dato),
                                dimnames=list(colnames(dato),
                                              colnames(dato)))
        
        for(i in 1:ncol(dato)) {
                # Loop through the columns for each column
                for(j in 1:ncol(dato)) {
                        # Fill in placeholder with cosine similarities
                        peliculas_sim[i,j] <- getCosine(as.matrix(dato[i]),
                                                        as.matrix(dato[j]))
                }
        }
        
        diag(peliculas_sim)<-0
        peliculas_sim <- as.data.frame(peliculas_sim)
        
        peliculas_vec <- matrix(NA,
                                nrow=ncol(peliculas_sim), 
                                ncol= n,
                                dimnames=list(colnames(peliculas_sim)))
        
        for(i in 1:ncol(peliculas_sim)) 
        {
                peliculas_vec[i,] <- t(head(n = n, 
                                            rownames(peliculas_sim[order(
                        peliculas_sim[,i],
                        decreasing=TRUE),][i])))
        }
        colnames(peliculas_vec) <- paste0("opcion_", 1:n)
        peliculas_vec <- as.data.frame(peliculas_vec)
        return( peliculas_vec)
        
        
}

Fue necesario refinar el procedimiento para evitar que una película que ya he visto me sean recomendadas. Esto ocurría porque la diagonal no se había llevado a 0, por tanto, la primera opción eran la mismas películas, puesto que la mayor similitud es 1.

Aplico

productos(criticos[,2:7])
##          opcion_1 opcion_2 opcion_3 opcion_4 opcion_5
## Lady        Night Superman      You   Snakes     Just
## Snakes   Superman      You    Night     Lady     Just
## Just        Night      You   Snakes Superman     Lady
## Superman   Snakes      You    Night     Lady     Just
## You      Superman   Snakes    Night     Lady     Just
## Night    Superman   Snakes      You     Lady     Just

Analizo ahora las recomendaciones para quienes no hayan analizado alguna película

# Funcion para calcular las puntuaciones
 
 getScore <- function(history, similarities)
  {
    x <- sum(history * similarities)/sum(similarities)
    x
  }

Genero una matriz para ingresar luego las puntuaciones

peliculas_sim <-  pelis
# A placeholder matrix
 holder <- matrix(NA, nrow = nrow(criticos),
                  ncol = ncol(criticos)-1,
                  dimnames=list((criticos$persona),
                                colnames(criticos[-1])))
# Loop through the users (rows)
   for(i in 1:nrow(holder)) 
   {
       # itero  (columns)
       for(j in 1:ncol(holder)) 
       {
           # Obtengo el nombre de la película y del crítico
           
		   
             user <- rownames(holder)[i]
             product <- colnames(holder)[j]
 
           # para no recomendar una película ya vista por ambas parte
           # creo una cadena vacía en la que guardo el nombre de la pelicula vista
             if(as.integer(criticos[criticos$persona==user,
                                   product]) == 1)
             { 
                 holder[i,j]<-""
              } else {
 
           # Obtengo las películas con mayor similaridad
             topN<-((head(n=3,(peliculas_sim[order(peliculas_sim[,
                                                          product],decreasing=TRUE),][product]))))
             topN.names <- as.character(rownames(topN))
             topN.similarities <- as.numeric(topN[,1])
 
           # elimino filas 
             topN.similarities<-topN.similarities[-1]
             topN.names<-topN.names[-1]
 
           # obtengo el historial de las peliculas
             topN.purchases<- criticos[,
                                       c("persona",
                                         topN.names)]
             topN.userPurchases<-topN.purchases[topN.purchases$user==user,]
             topN.userPurchases <- as.numeric(topN.userPurchases[!(names(topN.userPurchases) %in% c("user"))])
 
            # calculo la puntuación del usuario y de la pelicula
             holder[i,j]<-getScore(similarities=topN.similarities,history=topN.userPurchases)
 
         } # cierre de else
       } # cierre del loop for  
   } # cierre for loop para los usuarios
 
criticos.scores <- holder
# 10 vecinos en orden de acuerdo con la similaridad
topN<-((head(n=6,(peliculas_sim[order(
        peliculas_sim[,product],decreasing=TRUE),
        ][product]))))

topN
##              Night
## Night    1.0000000
## Superman 0.8995283
## Snakes   0.8690098
## You      0.8435202
## Lady     0.8423369
## Just     0.7712312

topN.names <- as.character(rownames(topN))

topN.similarities <- as.numeric(topN[,1])

topN.similarities
## [1] 1.0000000 0.8995283 0.8690098 0.8435202 0.8423369 0.7712312

# topN.similarities<-topN.similarities[-1]
 #topN.names<-topN.names[-1]
# We then get the user's purchase history for those 10 items
topN.purchases<- criticos[,c("persona",topN.names)]

topN.purchases
## # A tibble: 7 x 7
##   persona Night Superman Snakes   You  Lady  Just
##   <chr>   <dbl>    <dbl>  <dbl> <dbl> <dbl> <dbl>
## 1 Lisa      3        3.5    3.5   2.5   2.5   3  
## 2 Gene      3        5      3.5   3.5   3     1.5
## 3 Michael   4        3.5    3     0     2.5   0  
## 4 Claudia   4.5      4      3.5   2.5   0     3  
## 5 Mick      3        3      4     2     3     2  
## 6 Jack      3.5      5      4     3.5   3     0  
## 7 Toby      0        4      4.5   1     0     0

topN.userPurchases<-topN.purchases[topN.purchases$persona==user,]

topN.userPurchases
## # A tibble: 1 x 7
##   persona Night Superman Snakes   You  Lady  Just
##   <chr>   <dbl>    <dbl>  <dbl> <dbl> <dbl> <dbl>
## 1 Toby        0        4    4.5     1     0     0

topN.userPurchases <- as.numeric(topN.userPurchases[!(names(topN.userPurchases) %in% c("user"))])
 
topN.userPurchases 
## [1]  NA 0.0 4.0 4.5 1.0 0.0 0.0
 holder[i,j]<-getScore(similarities=topN.similarities,
                       history=topN.userPurchases)
# Lets make our recommendations pretty

criticos.scores.holder <- matrix(NA,
                                 nrow=nrow(criticos.scores),
                                 ncol=6,
                                 dimnames=list(
                                         rownames(                                                 criticos.scores)
                                         ))
  
for(i in 1:nrow(criticos.scores)) 
  {
    criticos.scores.holder[i,] <- names(head(n=6,
                      (criticos.scores[,                                      order(criticos.scores.holder[i,],                                  
					  decreasing=TRUE)])[i,]))
  }

Medidas de similitud

x1 <- rnorm(30)
x2 <- rnorm(30)
Euc_dist = dist(rbind(x1,x2) ,method="euclidean")
vec1 = c( 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 )
vec2 = c( 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0 )
library(lsa)
cosine(vec1,vec2)
##           [,1]
## [1,] 0.2357023
Coef = cor(mtcars, method="pearson")

R cuenta con el paquete recommenderlab para analizar y hacer recomendaciones. Nos ahorramos todos estos pasos que hemos seguido hasta aquí.

No hay comentarios.: