¿Cómo sabe una biblioteca qué libro te gustará?
Un sistema de recomendación sugiere a una persona cosas que le pueden gustar, a partir de lo que han valorado otras personas parecidas. Es el método que usan las bibliotecas, las tiendas y las plataformas de música.
Una biblioteca universitaria tiene las notas que cuatro lectores dieron a cinco libros. Quiere decirle a Lucas qué libro leer ahora.
Al final de esta lección
Nota
Puedo recomendar un libro a partir de lo que valoraron los lectores más parecidos.
Palabras clave
| Palabra | Qué significa | Ejemplo |
|---|---|---|
| Valoración | la nota que una persona da a un libro | 4 de 5 |
| Similitud | cuánto se parecen dos personas | |
| Lector similar | una persona que valoró igual que tú | |
| Media ponderada | una media en la que unos valores pesan más | |
| Arranque en frío | no recomendar bien porque aún no hay valoraciones |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Dos lectores son parecidos si valoran igual
Para recomendar, primero se mide cuánto se parecen dos lectores. Se miran solo los libros que valoraron los dos.
Se suman las diferencias entre sus notas, sin signo. Una similitud sencilla es 1 / (1 + esa suma). Si no hay diferencias vale 1. Cuanto mayor es la diferencia, más baja.
Ejemplo resuelto: las notas de cuatro lectores
| Lector | faro | ciudad | mapa | cielo |
|---|---|---|---|---|
| Lucas | 5 | 3 | 4 | sin leer |
| Mateo | 5 | 2 | 4 | 5 |
| Carmen | 1 | 5 | 2 | 2 |
| Pablo | 4 | 3 | 5 | 4 |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Mide la similitud de Lucas
docker exec jupyter python3 -c "R={'Lucas': {'faro': 5, 'ciudad': 3, 'mapa': 4}, 'Mateo': {'faro': 5, 'ciudad': 2, 'mapa': 4, 'cielo': 5}, 'Carmen': {'faro': 1, 'ciudad': 5, 'mapa': 2, 'cielo': 2}, 'Pablo': {'faro': 4, 'ciudad': 3, 'mapa': 5, 'cielo': 4}}; s=lambda a, b: 1/(1+sum(abs(R[a][i]-R[b][i]) for i in R[a] if i in R[b])); print([(u, round(s('Lucas', u), 2)) for u in ('Mateo', 'Carmen', 'Pablo')])"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
La puntuación es una media ponderada
Lucas no ha leído «cielo». Se miran los lectores que sí lo valoraron. Cada nota se multiplica por la similitud de ese lector con Lucas.
Se suman los resultados y se divide entre la suma de las similitudes. Es una media ponderada: la opinión de quien se parece más pesa más. La tabla redondea las similitudes; el programa no, y por eso da 4,29.
Ejemplo resuelto: la puntuación de «cielo» para Lucas
| Lector | Similitud | Nota a «cielo» | Similitud × nota |
|---|---|---|---|
| Mateo | 0,50 | 5 | 2,50 |
| Carmen | 0,11 | 2 | 0,22 |
| Pablo | 0,33 | 4 | 1,33 |
| Suma | 0,94 | 4,05 |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Calcula la puntuación de «cielo» para Lucas
docker exec jupyter python3 -c "R={'Lucas': {'faro': 5, 'ciudad': 3, 'mapa': 4}, 'Mateo': {'faro': 5, 'ciudad': 2, 'mapa': 4, 'cielo': 5}, 'Carmen': {'faro': 1, 'ciudad': 5, 'mapa': 2, 'cielo': 2}, 'Pablo': {'faro': 4, 'ciudad': 3, 'mapa': 5, 'cielo': 4}}; s=lambda a, b: 1/(1+sum(abs(R[a][i]-R[b][i]) for i in R[a] if i in R[b])); u=('Mateo', 'Carmen', 'Pablo'); print(round(sum(s('Lucas', x) * R[x]['cielo'] for x in u) / sum(s('Lucas', x) for x in u), 2))"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Calcula la puntuación con un programa
# Cada lector valora libros de 1 a 5. Lucas no ha leído «cielo».
ratings = {
"Lucas": {"faro": 5, "ciudad": 3, "mapa": 4},
"Mateo": {"faro": 5, "ciudad": 2, "mapa": 4, "cielo": 5},
"Carmen": {"faro": 1, "ciudad": 5, "mapa": 2, "cielo": 2},
"Pablo": {"faro": 4, "ciudad": 3, "mapa": 5, "cielo": 4},
}
def similarity(a, b):
gap = 0
for book in a:
if book in b:
gap = gap + abs(a[book] - b[book])
return 1 / (1 + gap)
top = 0.0
bottom = 0.0
for other in ratings:
if other != "Lucas" and "cielo" in ratings[other]:
weight = similarity(ratings["Lucas"], ratings[other])
top = top + weight * ratings[other]["cielo"]
bottom = bottom + weight
print("puntuación de cielo para Lucas:", round(top / bottom, 2))
# Cambia la valoración de Carmen a 5 en "cielo" y vuelve a ejecutar.
Un error muy común
Advertencia
Mucha gente cree que un lector con la similitud más alta es el más fiable. Si solo han leído un libro en común y lo valoraron igual, la similitud es 1. Eso no demuestra nada. Pide un mínimo de libros en común antes de fiarte.
También se pueden comparar los libros entre sí
Hasta aquí se comparaban lectores. También se pueden comparar libros: dos libros son parecidos si los mismos lectores los valoran alto.
Para un lector nuevo sin notas no hay lectores parecidos. Es el arranque en frío. Se resuelve con los libros más populares hasta que haya datos.
Cuenta qué libros gustan a quien amó «cielo»
docker exec jupyter python3 -c "R={'Lucas': {'faro': 5, 'ciudad': 3, 'mapa': 4}, 'Mateo': {'faro': 5, 'ciudad': 2, 'mapa': 4, 'cielo': 5}, 'Carmen': {'faro': 1, 'ciudad': 5, 'mapa': 2, 'cielo': 2}, 'Pablo': {'faro': 4, 'ciudad': 3, 'mapa': 5, 'cielo': 4}}; s=lambda a, b: 1/(1+sum(abs(R[a][i]-R[b][i]) for i in R[a] if i in R[b])); print([(j, sum(1 for u in R if R[u].get('cielo', 0)>=4 and R[u].get(j, 0)>=4)) for j in ('faro', 'ciudad', 'mapa')])"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Para ir más lejos: elige entre varios libros
Con la puntuación de cada libro sin leer, ordena los libros de mayor a menor y recomienda el primero. Después piensa: ¿qué pasa si un libro solo lo ha valorado un lector?