En praktisk implementation av ett rekommendationssystem

Relevanta dokument
Rekommendationer på nätet

Rekommendationssystem. med fördjupning på collaborative filtering

SÅ BLIR DIN NETFLIX- UPPLEVELSE BÄTTRE. En litteraturstudie om Netflixs rekommendationssystem

Effekten av varierande datamängd vid filmbetygsprediktion

Lösningsförslag till tentamen i EDA011, lördagen den 16 december 2006

LINKÖPINGS UNIVERSITET. Rekommendationssystem

Colloborative filtering ett rekommendationssystem

Sätt att skriva ut binärträd

Kodexempel från Programmering 2 Tobias Wrigstad, Ph.D.

729G04 Programmering och diskret matematik. Föreläsning 7

Några inbyggda funktioner (med resultat!) Introduktion till programmering D0009E. Föreläsning 4: Villkor och rekursion. Modulus-operatorn.

Inom datalogin brukar man använda träd för att beskriva vissa typer av problem. Om man begränsar sig till träd där varje nod förgrenar sig högst två

Lektion 2: Sökagenter. Robin Keskisärkkä

VILKET REKOMMENDATIONSSYTEM SKA EN INTERAKTIV MEDIETJÄNST VÄLJA?

Institutionen för datavetenskap Department of Computer and Information Science

Grundläggande datalogi - Övning 2

TiVo ett rekommendationssystem. TiVo ett rekommendationssystem

Introduktion till programmering SMD180. Föreläsning 4: Villkor och rekursion

Föreläsning 13 och 14: Binära träd

Regression med Genetiska Algoritmer

Tentamen i Introduktion till programmering

Föreläsning 8 Programmeringsteknik och Matlab DD1312. Klassmetod. Egen modul

Instruktioner - Datortentamen TDDD73 Funktionell och imperativ programmering i Python TDDE24 Funktionell och imperativ programmering del 2

kl Tentaupplägg

729G04 Programmering och diskret matematik

Föreläsning 8 SLUMPTAL, SIMULERING + INTRODUKTION TILL VEKTORER

Det finns en referensbok (Java) hos vakten som du får gå fram och läsa men inte ta tillbaka till bänken.

Innehåll Introduktion... 3 InteractiveScene.config... 3 Scener <scenes>... 3 Typsnitt <fonts>... 3 Övergångar <transitions>...

Python. Python är, som Scheme, ett interpreterat språk men det finns kompilatorer för Python.

Johan Karlsson Datavetenskap för teknisk kemi, 10p, moment 1 Datavetenskap Umeå Universitet. Tentamen

Personifierad Netflix

Uppgifter till tenta i 729G04 Programmering och diskret matematik. 17 december 2015, kl 14:00-18:00

Python. Python är, som Scheme, ett interpreterat språk men det finns kompilatorer för Python.

Föreläsning 10 Datalogi 1 DA2001. Utskrift på skärmen. Syntax. print( Hej ) Hur är det? Hej. print( Hej,end= ) print( Hur är det? ) HejHur är det?

Programmering grundkurs

729G04 Programmering och diskret matematik

Tentamen Datastrukturer (DAT037)

Dugga Datastrukturer (DAT036)

Grundläggande datalogi - Övning 4

Övning 1 - Abstrakta datatyper

TDP Regler

Introduktion till programmering SMD180. Föreläsning 9: Tupler

Tentamen Datastrukturer (DAT036)

Anmälningskod: Lägg uppgifterna i ordning. Skriv uppgiftsnummer (gäller B-delen) och din kod överst i högra hörnet på alla papper

Rekommendationssystem för livestreamingtjänster

TDDE10 TDDE11, 725G90/1. Objektorienterad programmering i Java, Föreläsning 2 Erik Nilsson, Institutionen för Datavetenskap, LiU

Föreläsning 2 Programmeringsteknik DD1310. Programmering. Programspråk

Introduktion till programmering D0009E. Föreläsning 5: Fruktbara funktioner

Namn Stil Dokumentation Objekt-orienterad programmering OBS OBS OBS OBS OBS OBS OBS OBS

Instruktioner - Datortentamen TDDD73 Funktionell och imperativ programmering i Python

Mer grafik. Jan Erik Moström

TDDC74 Programmering: Abstraktion och modellering Tentamen, lördag 29 augusti 2015, kl 8 12

Tentamen i Programmeringsteknik I

Abstrakta datatyper Laboration 2 GruDat, DD1344

729G04 Programmering och diskret matematik TEN kl 8-12

TNK046 GIS - Databaser Laborationsuppgift 2

Artificiell intelligens En agent som spelar Black Jack Andreas Perjons [andpe813]

Övningar Dag 2 En första klass

Introduktion till programmering SMD180. Föreläsning 5: Fruktbara funktioner

Tentamen, EDA501/EDAA20 Programmering M MD W BK L

TENTAMEN PROGRAMMERINGSMETODIK MOMENT 2 - JAVA, 4P

Grundläggande datalogi - Övning 3

Tentamen Datastrukturer, DAT037 (DAT036)

TDDI TDDI22 Tentaregler

EnKlass. Instans 3 av EnKlass. Instans 2 av EnKlass

TDDC74 Programmering: Abstraktion och modellering Dugga 3, kl 14 16, 25 mars 2015

Föreläsning 5 Programmeringsteknik DD1310. Modulen doctest. Exempel. Doctest Dictionary Filhantering

Laboration 1: Figurer i hierarki

PROV. 12 Egenskaper (provavsnitt)

Datalogi för E Övning 3

Lägg uppgifterna i ordning. Skriv uppgiftsnummer och din kod överst i högra hörnet på alla papper.

729G74 - IT och programmering, grundkurs. Dugga.

Instruktioner - Datortentamen TDDD73 Funktionell och imperativ programmering i Python

DI-institutionen Sid 1 av 6 Hans-Edy Mårtensson Sten Sundin

Tentamen, EDAA20/EDA501 Programmering

Systems for automatic recommendations of news and events

Introduktion till algoritmer - Lektion 4 Matematikgymnasiet, Läsåret Lektion 4

Det finns en referensbok (Java) hos tentavakten som du får gå fram och läsa men inte ta tillbaka till bänken.

Föreläsning 4: Poster

Bankkonto - övning. Övning 2 Skriv en metod, geträntan, som returnerar räntan.

729G75: Programmering och algoritmiskt tänkande. Tema 1. Föreläsning 1 Jody Foo

OOP Tentamen

Tentamen Datastrukturer (DAT036)

Python. Vi har ofta behov av att behandla datastrukturer på ett enhetligt sätt så att vi kan göra samma sak i flera olika program.

Fältnamn /Rubrik Fältnamn /Rubrik Fältnamn /Rubrik Fältnamn /Rubrik Data Data Data Data Data Data Data Data

Inlämningsuppgift : Finn. 2D1418 Språkteknologi. Christoffer Sabel E-post: csabel@kth.se 1

TENTAMEN I PROGRAMMERING. På tentamen ges graderade betyg:. 3:a 24 poäng, 4:a 36 poäng och 5:a 48 poäng

TDDC30. Kursledning Kursledare: Jonas Lindgren. Labassistent: Jonas Lindgren Labassistent: Niklas Holma Labassistent: Erik Nilsson

v. 42 Python HT17 En introduktion Oscar Bergqvist

Föreläsning 8 - del 2: Objektorienterad programmering - avancerat

Programmering för språkteknologer II, HT2014. Rum

Introduktion till programmering SMD180. Föreläsning 2: Variabler, uttryck och satser

TDDD92 Artificiell intelligens -- projekt

Grunderna i SQL del 1

Deklarativ programmering

Introduktion till programmering SMD180. Föreläsning 8: Listor

Selektion och iteration

v. 43 Python HT17 En introduktion Oscar Bergqvist

Alla datorprogram har en sak gemensam; alla processerar indata för att producera något slags resultat, utdata.

Services + REST och OAuth

Transkript:

Konsten att välja En praktisk implementation av ett rekommendationssystem Projektarbete Artificiell intelligens Patricia Lindblad 729G43 729G43 patli010!1

1. Introduktion 3 1.1. Vad är ett rekommendationssystem? 3 1.2. Kollaborativ filtrering 3 1.3. Innehållsbaserad filtrering 4 2. Implementation 5 2.1. Kollaborativa rekommendationer 5 2.2. Innehållsbaserade rekommendationer 6 2.3. Kombinerade rekommendationer 6 3. Reflektioner 6 3.1. Resultat 6 3.2. Betygsskalor 7 3.3. Attribut 7 3.4. Grannskapets rekommendationer 8 3.5. Hybridsystem 8 4. Källor 9 5. Bilagor 10 5.1. Bilaga A - Exempel på rekommendation 10 5.2. Bilaga B - Kod för rekommendationssystemen 11 5.3. Bilaga C - Kod för Movie-klassen 15 5.4. Bilaga D - Kod för User-klassen 16 729G43 patli010!2

1. Introduktion I dagsläget finns så mycket material (eng. content) tillgängligt för varje internetanvändare att det är omöjligt att tillgodogöra sig allt. Bara på YouTube i juni 2015 laddades det upp 400 timmar material varje minut, och antalet uppladdat material har ökat exponentiellt de senaste 10 åren ( Hours of video, 2018). När det finns mycket material att välja på för användaren finns det en valfrihet, men för mycket material kan tvärtom vara begränsande. Det material användaren egentligen är intresserad av drunknar i mängderna av annat material, eller så uppstår det en Too much choice - effekt. Där användaren blir så överväldigad av antalet alternativ att den inte väljer någonting alls (Scwartz, 2006). Till exempel om Netflix utbud hade varit en lång lista med alla tillgängliga filmer, eller om Amazon.com listade sina produkter i alfabetisk ordning skulle själva akten att göra ett val kunna bli för betungande för användaren, som då istället skulle avstå från att göra ett val över huvud taget. För att hjälpa användarna att sålla denna enorma mängd tillgängligt material, och för att eventuellt öka försäljningen med ett uppskattat 10-25% (Recommender Systems, 2015) konstruerades rekommendationssystem, som systematiskt sållar det tillgängliga materialet åt användaren, och parar ihop användare med material eller artiklar. 1.1. Vad är ett rekommendationssystem? Rekommendationssystem används inom industrin för att koppla samman användare (eng. users) med artiklar (eng. items). Systemet kan antingen föreslå ett topantal artiklar för en specifik användare, eller för varje artikel föreslå ett top-antal användare som kan vara intresserade av artikeln. Att föreslå top-antal artiklar är dock vanligare, trots att algoritmerna är spegelvänt identiska (Aggarwal, 2016). Det finns många olika sätt att bygga rekommendationssystem. Två av de enklaste är kollaborativ (eng. collaborative) och innehållsbaserad (eng. content-based) filtrering. 1.2. Kollaborativ filtrering En kollaborativ filtreringsmetod kan också kallas för en grannskapsbaserad filtrering (eng. neighbourhood-based filtering). Metoden bygger på att användare som tidigare betygsatt artiklar med samma betyg med stor sannolikhet också kommer tycka samma 729G43 patli010!3

sak om icke betygsatta artiklar. De användare som ingår i samma kluster ingår då i varandras grannskap. Exempel: Anna har sett filmerna X, Y och Z. Bo har också sett filmerna X och Y, men inte Z. Anna och Bo har betygsatt filmerna X och Y likadant, se tabellen nedan. X Y Z Anna 3 1 5 Bo 3 1? Vi vet inte vad Bo tycker om film Z eftersom han inte betygsatt den. Däremot vet vi att Anna tyckte mycket om film Z då hon gav den högsta betyg (5). Eftersom att Anna om Bo har betygsatt filmer likadant tidigare är det hög sannolikhet att de kommer tycka likadant om film Z också. Eftersom Anna tyckte mycket om film Z rekommenderas film Z till Bo. 1.3. Innehållsbaserad filtrering Den innehållsbaserade filtreringen utgår från användarens egna betygsättningar. Artiklar som fått högt betyg av användaren har en uppsättning attribut. Andra artiklar som har samma attribut rekommenderas till användaren. Ju fler likadana attribut artiklarna har, desto starkare blir rekommendationen. Ett till filmexempel: I exemplet nedan har Bo sett filmen Shrek och gett den högsta betyg. Alla de tre andra filmerna i biblioteket får en uppsättning attribut med binära värden för att enkelt kunna jämföra filmerna. Animerad Musik Barn OK IMDB > 8 Shrek JA JA JA NEJ Ex Machina NEJ NEJ NEJ NEJ Blues Brothers NEJ JA JA NEJ Hitta Nemo JA NEJ JA JA Eftersom Bo satte högsta betyg på Shrek är det relevant att hitta filmer som liknar Shrek att rekommendera till Bo. Därför jämförs attributen från olika filmer för att se vilken film som mest liknar Shrek. 729G43 patli010!4

Shrek och Ex Machina har 1 gemensamt attribut Shrek och Blues Brothers har 3 gemensamma attribut Shrek och Hitta Nemo har 2 gemensamma attribut Den film som bäst liknar användarens tidigare uttryckta preferens och kommer att rekommenderas är alltså Blues Brothers. 2. Implementation Jag byggde två enkla varianter på rekommendationssystem, som rekommenderar filmer utifrån ett dataset kallat MovieLens. MovieLens finns tillgängligt på internet tack vare forskargruppen GroupLens vid University of Minnesota. Datasetet innehåller 100 000 betygssättningar på 9 000 filmer av 700 användare, och filmerna är annoterade med 1 300 attribut. Datasetet består av två separata csv-filer. Den första innehåller [FilmId, FilmTitel, Attribut], den andra [AnvändarId, FilmId, Betyg, Tidstämpel]. Mina rekomendationssystem består av två delar, en kollaborativ och en innehållsbaserad som presenteras nedan. 2.1. Kollaborativa rekommendationer För att skapa en given användares grannskap jämfördes användaren med alla andra användare, och fick matchningspoäng för varje film de gett samma betyg. De 10 användare som fick högst matchningspoäng ansågs vara samma typ av användare som den givna användaren, och ingick då i den givna användarens grannskap. Alla betygsättningar dessa tio gjort räknades samman med de andra betygssättningarna för samma film av de andra användarna i grannskapet och sedan dividerades summan på antalet som betygsatt filmen. Detta gav ett genomsnittsbetyg för varje film. Exempel: om film A fått högsta betyg (5) av 1 användare i grannskapet får film A 5 totala poäng (5 1). Om film B har setts av alla de andra i grannskapet och fått betyg 1 av alla i grannskapet får film B 1 poäng totalt ((1 10) 10). Om film C får blandade omdömen av hälften av grannskapet kan det se ut som följer: 2 + 4 +5 + 3 +3 = 17, 17 5 = 3. 4 poäng totalt. Funktionen returnerade de 10 filmer med högst genomsnittsbetyg. 729G43 patli010!5

2.2. Innehållsbaserade rekommendationer För en given användare sparas de filmer som fått betyg 4.0 eller högre av användaren. Dessa anses vara användarens favoritfilmer. Alla filmer är sedan tidigare annoterade med genrer, vilket här är filmens attribut. För alla favoritfilmer viktas alla attribut efter hur många gånger de förekom totalt bland alla favoritfilmer. Alla filmer i filmbiblioteket får ett totalbetyg baserat på vikterna av sina attribut. Till exempel: om 5 av Annas favoritfilmer är annoterade med "Action", och två är annoterade med "Comedy" så får en film annoterad med "Action" +5 poäng, en film med "Comedy"+2 poäng och en film med både "Action" och "Comedy"+7 poäng. Om attributet Romance inte förekom alls bland Annas favoritfilmer får en film annoterad med Romance +0 för det attributet. Funktionen returnerade de 10 filmer med högst betyg. 2.3. Kombinerade rekommendationer Slutligen anropades de båda funktionerna ovan, och rekommenderade en slutgiltig lista på filmer baserat på användarens uttryckta preferenser och kollaborativa grannskap i en och samma rekommendation. Ett exempel på en retur från systemen finns i bilaga A - Exempel på rekommendation. 3. Reflektioner Nedan följer några reflektioner kring hur arbetet skulle kunna utvecklas i ett framtida projekt. 3.1. Resultat Resultatet är svårt för mig personligen att bedöma, eftersom en bra rekommendation är kvalitativ snarare än kvantitativ. Rekommendationssystemen levererar ofelbart titeln på 20 filmer varje gång koden körs. Dock har jag inte sett alla filmer, och inte heller vet jag vem användaren är, och vilka filmer av de rekommenderade denna skulle tycka om. Rent matematiskt och logiskt gör koden det den ska. Hur bra 729G43 patli010!6

rekommendationerna sedan är beror också på om de grundantaganden som gjordes i början är korrekta. Till exempel att användare som har satt samma betyg tidigare kommer göra det i fortsättningen. För en utveckling av det här projektet skulle det kunna implementeras en funktion som specificerar vad rekommendationen baseras på. Någonting i stil med Du såg The Hunger Games, då kanske du gillar. En sådan funktion skulle förbättra användarupplevelsen (Aggarwal, 2016) och göra det lättare att bedöma rekommendationens rimlighet. 3.2. Betygsskalor Det finns olika varianter på möjliga betygsskalor rekommendationssystem kan använda sig av. I MovieLens uttrycks betygen på en 10-gradig skala från 0 till 5.0. Användarens betyg behöver alltså inte vara ett heltal, utan betyg som 3.5 är godkända värden. Min tolkning är att den här skalan enbart uttrycker grader av gillande, och att det inte finns någon metod för användaren att uttrycka sitt specifika ogillande för en artikel. Dock hade man kunnat tolka betyg 3.0 som neutralt, 5.0 som starkt gillande och 1.0 som starkt ogillande. Då hade rekommenderaren kunnat aktivt undvika att rekommendera attribut associerade med ogillade filmer. I den nuvarande koden är betyg 1.0 fortfarande en form utav gillande. 3.3. Attribut I det här fallet var en films attribut enbart en lista på genrer. Dock finns det många aspekter av en film som kan avgöra vad användaren tycker om filmen, och som skulle kunna avgöra huruvida användaren vill se en film eller inte. Attribut som Favoritskådespelare, Lyckligt slut eller Bra filmmusik skulle behövas hållas i åtanke för att göra ännu bättre rekommendationer. Mer detaljerade attribut skulle ge mer skräddarsydda rekommendationer baserat på användarens tidigare betygsättningar, men inte heller vill man ha för homogena rekommendationer. En som bara hittar varianter på filmen man precis såg är inte ett bra alternativ. Helst vill man basera rekommendationerna på vad användaren sett, och samtidigt rekommendera många olika varianter på artiklar 729G43 patli010!7

till användaren (Aggarwal, 2016). Om alla rekommendationer är mer eller mindre identiska föreligger risken att användaren inte skulle tycka om en enda av artiklarna. En ännu mer avancerad variant skulle vara ett försök till att klustra attribut, för att avgöra om vissa attribut exklusivt förekommer med varandra. Så att användare som till exempel enbart tycker om Skräck-komedier inte får rekommendationer på filmer som bara har attributet Skräck eller Komedi. 3.4. Grannskapets rekommendationer Tyvärr finns det en rent matematisk aspekt av grannskapsrekommendationerna som antagligen gör att den slutgiltiga rekommendationen inte blir så bra som den kunde varit. För att räkna ut vad grannskapet gav för genomsnittsbetyg adderas betyget från alla i grannskapet som sett den aktuella filmen. Summan divideras med antalet som sett filmen får att få deras genomsnittsbetyg, och de med högst betyg rekommenderas till den givna användaren. Dock får detta effekten att om film X fått högsta betyg av en enda användare i grannskapet får film X högre genomsnittsbetyg (5.0) än en film Y som setts av alla 10 användarna i grannskapet och som fått högsta betyg av alla utom en användare. Även om den 10de användaren ger betyg 4.5 blir snittbetyget 4.95, och systemet kommer rekommendera film X. Algoritmen för hur genomsnittsbetyget bör förbättras, genom att vikta filmernas genomsnittsbetyg så att de filmer fler har sett får en starkare rekommendation än i nuläget. 3.5. Hybridsystem En filtreringsmetod som tar hänsyn till flera olika filtreringsmetoder, till exempel kollaborativa och innehållsbaserade kallas för ett hybrid(rekommendations)system (eng. hybrid system). En klar förbättring till det nuvarande systemet och en eventuell framtida variant skulle vara ett implementerat hybridsystem, som förutsäger användarens betyg baserat på grannskapets genomsnittliga betyg samt vilka uttalade preferenser av attribut användaren har. 729G43 patli010!8

4. Källor Aggarwal, C. C. (2016). Recommender Systems: The textbook. Cham: Springer International Publishing. Hours of video uploaded to YouTube every minute as of July 2015. (2018). Hämtad från: https://www.statista.com/statistics/259477/hours-of-video-uploaded-to-youtubeevery-minute/ Recommender Systems. (2015-10-10). Hämtad 2018-01-02, från https:// www.youtube.com/watch?v=eeg1deewuja Scwartz, B. (2006-06). More isn t always better. Harvard Business Review. Hämtad 2018-01-09 från: https://hbr.org/2006/06/more-isnt-always-better 729G43 patli010!9

5. Bilagor 5.1. Bilaga A - Exempel på rekommendation 729G43 patli010!10

5.2. Bilaga B - Kod för rekommendationssystemen """ Två rekommendationssystem. Bygger på MovieLens-biblioteket av användare och betygsättningar.""" import ML_User_class as uc import MovieLens_attr as ma import csv import operator # Dictionary med 'UserId': '{ratings}' user_data = uc.user.users(uc.user.get_all_data()) # Slumpmässigt valt User-objekt my_user = uc.user.pick_random_user() # Anropar funktionen som uppdaterar användarens top 10 matchande användare uc.user.match_users(my_user, user_data) # Lista med alla Movie-objekt movie_data = ma.movie.give_attributes_and_ids(ma.movie.get_all_data()) # COLLABORATIVE FILTERING # baseras på användare som har liknande ratings # returnerar lista med de 10 starkaste rekomendationerna def collaborative_filtering(user): # Hämtar användarens top 10 matchande användare # Returnerar en nästlad lista på formatet: [användaren, en lista med 10 dictionarys]. # I varje dictionary finns alla ratings gjorda av en utav de 10 bäst matchande användarna def get_other_users_ratings(user): other_users_ratings = [] for each_user in user.top_10_users: other_users_id = each_user[0] #print(other_users_id) for userid, ratings in uc.user.users(uc.user.get_all_data()).items(): if userid == other_users_id: other_users_ratings.append(ratings) elif userid == user.id: user.ratings = ratings return [user, other_users_ratings] # Tar in en nästlad lista med [användaren, en lista med dictionarys] # För varje film som de top 10 matchande användarna sett, men användaren själv inte sett # summeras alla ratings till en rekommendationssumma. De filmer med högst rekommenadtionssumma # är de starkast rekommenderade filmerna. # Reutrnerar de 10 starkast rekommenderade Movie-objekten 729G43 patli010!11

def my_top_10_rec(user_and_other_users_ratings): user = user_and_other_users_ratings[0] others_ratings = user_and_other_users_ratings[1] not_viewed_movies = {} for each_rating in others_ratings: for movie, score in each_rating.items(): if movie not in not_viewed_movies: if movie not in user.ratings.keys(): not_viewed_movies[movie] = [float(score)] elif movie in not_viewed_movies: not_viewed_movies[movie] += [float(score)] dictionary_total_scores = compute_scores(not_viewed_movies) sorted_recommended_movies = sorted(dictionary_total_scores.items(), key=operator.itemgetter(1), reverse=true) top_10_recommended_movies = sorted_recommended_movies[:10] return top_10_recommended_movies # Tar in ett dictionary med 'MovieId': [alla betyg] # Returnerar dictionary med 'MovieId': total score def compute_scores(all_scores): total_dict = {} for movie, ratings in all_scores.items(): sum_scores = 0 total_score = 0 for score in ratings: sum_scores += score total_score = sum_scores/len(ratings) total_dict[movie] = total_score return total_dict # Tar in en lista med Movie-objekt # Returnerar en lista med titlarna på dessa Movie-objekt def get_titles(top_10_recommended_movies): top_10_titles = [] for each_rating in top_10_recommended_movies: movie = each_rating[0] top_10_titles.append(ma.movie.get_a_movie_title(movie, ma.movie.get_all_data())) return top_10_titles return get_titles(my_top_10_rec(get_other_users_ratings(my_user))) # CONTENT BASED FILTERING # baseras på användarens egna ratings # returnerar lista med de 10 starkaste rekomendationerna def content_based_filtering(user, movie_data): # Tar in ett User-objekt och en lista med Movie-objekt 729G43 patli010!12

# Returnerar ett dictionary med attributen för filmerna hade som användaren satte # betyg 4 eller högre på, och många andra filmer som användaren gillade som hade samma attribut. # Format: 'Attribut': 'förekomster' # Exempelvis betyder "('Action': 5)" att användaren tyckte om 5 olika filmer som hade Attributet 'Action' # Returnerar också lista med alla Movie-objekt def attributes_user_liked(user, movie_data): liked_movies = [] liked_attributes = {} for movie_id, rating in user.ratings.items(): if float(rating) >= 4.0: liked_movies.append(movie_id) for movie_id in liked_movies: for each_movie in movie_data: if movie_id == each_movie.id: for attribute in each_movie.attr: if attribute not in liked_attributes: liked_attributes[attribute] = 1 if attribute in liked_attributes: liked_attributes[attribute] += 1 return [liked_attributes, movie_data] # Tar in en nästlad lista med [attribut, lista med alla Movie-objekt] # Anropar matching_score som räknar ut hur stark rekommenationen för en specifik film är # Returnerar titlarna på 10 starkast rekommenderade filmerna def match_movies(attributes_user_liked_and_movie_data): liked_attributes = attributes_user_liked_and_movie_data[0] movie_data = attributes_user_liked_and_movie_data[1] every_movie_score = {} potential_matches = [] titles = [] for movie in movie_data: for attribute in movie.attr: if attribute in liked_attributes.keys(): potential_matches.append(movie) for movie in potential_matches: every_movie_score[movie.title] = matching_score(liked_attributes, movie) sorted_recommendations = sorted(every_movie_score.items(), key=operator.itemgetter(1), reverse=true) top_10 = sorted_recommendations[:10] for movie in top_10: titles.append(movie[0]) return titles # Tar in ett dictionary med de attribut associerade med filmer som användaren gillat, samt ett Movie-objekt 729G43 patli010!13

# Returnerar ett rekommenadtionsvärde för en film baserat på # hur många gånger attributet förekom hos användaren def matching_score(liked_attributes, movie): total_score = 0 for attribute in movie.attr: if attribute in liked_attributes.keys(): total_score += liked_attributes[attribute] return total_score return match_movies(attributes_user_liked(user, movie_data)) # Tar in rekomendationerna från collaborative filtering och content-based filtering # Returnerar en lista med en kombinerad rekomendation def hybrid(content, collaborative): hybrid_recommendations = [] for movie in content: if movie not in hybrid_recommendations: hybrid_recommendations.append(movie) for movie in collaborative: if movie not in hybrid_recommendations: hybrid_recommendations.append(movie) print('recommended FOR YOU:' + '\n') for movie in hybrid_recommendations: print(str(movie) + '\n') return hybrid_recommendations hybrid(content_based_filtering(my_user, movie_data), collaborative_filtering(my_user)) 729G43 patli010!14

5.3. Bilaga C - Kod för Movie-klassen """ Tar in csv-fil på formatet MovieId, MovieTitle, MovieAttributes.""" import csv class Movie: def init (self): self.id = '' self.title = '' self.attr = {} # Hämtar data från csv-filen # Returnerar datan som en nästlad lista, där varje lista: # [MovieId, MovieTitle, Attribute1 Attribute2] def get_all_data(): all_data = [] with open('movies.csv', newline='') as dataset: reader = csv.reader(dataset) next(reader, None) for row in reader: all_data.append(row) return all_data # Tar in ett movieid, och den nästlade listan med all data ovan # Returnerar titeln på filmen som tillhör movieid def get_a_movie_title(movie_id, all_data): for movie in all_data: if movie[0] == movie_id: return movie[1] # Tar den nästlade listan med all data ovan # Returnerar en lista med alla filmer som Movie-objekt # Varje movie-objekt har uppdaterats med sina tillhörande id, titlar och attribut def give_attributes_and_ids(all_data): movie_obj = [] for each_movie in all_data: movie_id = each_movie[0] movie_title = each_movie[1] movie_attr = each_movie[2] each_movie = Movie() movie_obj.append(each_movie) each_movie.id = movie_id each_movie.title = movie_title each_movie.attr = movie_attr.split(' ') return movie_obj 729G43 patli010!15

5.4. Bilaga D - Kod för User-klassen """ Tar in csv-fil på formatet UserId, MovieId, Rating, Timestamp.""" import csv import random import operator class User: def init (self): self.id = '' self.ratings = {} self.top_10_users = [] # format {'FilmId': 'rating'} # Hämtar data från csv-filen # Returnerar datan som en nästlad lista, där varje lista: # [UserId, MovieId, Rating, Timestamp] def get_all_data(): all_data = [] with open('ratings.csv', newline='') as dataset: reader = csv.reader(dataset) next(reader, None) for row in reader: all_data.append(row) return all_data # Tar den nästlade listan med all data ovan # Returnerar en lista med alla användare som User-objekt # Varje User-objekt har uppdaterats med sina tillhörande id och ratings def give_users_id_and_ratings(all_data): all_user_ids = [] users_with_id = [] for each_rating in all_data: user_id = each_rating[0] if user_id not in all_user_ids: all_user_ids.append(user_id) for user in all_user_ids: user_id = user user = User() #user.all_inst.append(user) user.id = user_id users_with_id.append(user) for user in users_with_id: for rating in all_data: if rating[0] == user.id: user.ratings[rating[1]] = rating[2] return users_with_id # Tar in den nästlade listan med all data ovan 729G43 patli010!16

# Returnerar dict med 'UserId': {ratings} def users(all_data): all_user_ratings = {} users = User.give_users_id_and_ratings(all_data) for user in users: all_user_ratings[user.id] = user.ratings return all_user_ratings # Tar in ett User-objekt och den nästlade listan med all data ovan # Uppdaterar User-objektets.top_10_users # Returnerar en lista med User-objektets top 10 matchande användare def match_users(input_user, all_data): my_matching_scores = {} my_seen_movies = [] input_ratings = all_data[input_user.id] for movie, rating in input_ratings.items(): my_seen_movies.append(movie) for movie in my_seen_movies: for user, ratings in all_data.items(): for title, score in ratings.items(): if movie == title and input_ratings[movie] == ratings[movie] and user!= input_user.id: if user not in my_matching_scores: my_matching_scores[user] = 1 else: my_matching_scores[user] += 1 sorted_my_matching_scores = sorted(my_matching_scores.items(), key=operator.itemgetter(1), reverse=true) input_user.top_10_users = sorted_my_matching_scores[:10] return input_user.top_10_users # Returnerar ett slumpmässigt User-objekt def pick_random_user(): rand_user = random.choice(user.give_users_id_and_ratings(user.get_all_data())) return rand_user 729G43 patli010!17