1. Wstęp

Reguły asocjacyjne (association rules) dają możliwość odkrywania relacji między obserwacjami w bazach danych. Można to wykorzystać do przygotowywana rekomendacji kolejnych filmów dla klientów platform streamingowych. W tym projekcie została przeprowadzona przykładowa analiza z wykorzystaniem zbioru danych MovieLense, w którym znajdują się informacje odnośnie ocen obejrzanych filmów, wystawionych przez konkretnych użytkowników. Zostały przygotowane reguły asocjacyjne i ich wizualizacje, a także prosta rekomendacja kolejnego filmu na konkretnym przykładzie.

Zostały wykorzystane biblioteki arules (do przeprowadzenia analizy reguł asocjacyjnych), arulesViz (do wizualizacji reguł) i recommenderlab (do pobrania danych).

W projekcie sztuczna inteligencja została wykorzystana do pomocy w przygotowaniu kodu.

library(arules)
library(arulesViz)
library(recommenderlab)

2. Przygotowanie i eksploracja danych

Na początku dane zostały pobrane z internetowej bazy MovieLense. Mają one postać realRatingMatrix.

data("MovieLense")

Aby móc dalej wykorzystać pobrane dane, należy je przetworzyć na “transakcje”. W tym celu za “lubiane” filmy zostały uznane te, które uzyskały ocenę 4 lub 5 w skali 1-5. Pierwotny zbiór danych został przekształcony na typ binaryRatingMatrix przy pomocy funkcji binarize, a następnie z tego zbioru zostały uzyskane “koszyki” - zbiory filmów jednocześnie rekomendowanych przez konkretnych użytkowników.

movie_binary <- binarize(MovieLense, minRating = 4)
movie_trans <- as(as(movie_binary, "list"), "transactions")

Uzyskany zbiór składa się z 943 “koszyków”.

length(movie_trans)
## [1] 943

Zanim zostanie wykorzystany algorytm do przygotowania reguł asocjacyjnych, można zwizualizować przetworzony zbiór danych. Poniższy wykres prezentuje najczęściej lubiane w wybranym zbiorze danych filmy.

itemFrequencyPlot(movie_trans, topN = 10, col = 'steelblue', main = 'Najczęściej lubiane filmy', ylab = 'Częstość występowania (support)')

3. Reguły asocjacyjne

3.1. Przygotowanie reguł

Do przygotowania reguł została wykorzystana metoda apriori. Jako parametry zostały przyjęte minimalny support w wysokości 0.2 oraz minimalne confidence w wysokości 0.25. Ponadto, został wykorzystany parametr maxlen, aby znaleźć tylko reguły zawierające pojedyncze filmy po lewej stronie. Następnie reguły zostały oczyszczone z ewentualnej redundancji. W efekcie działania algorytmu zostały uzyskane 72 reguły.

rules <- apriori(movie_trans, parameter = list(supp = 0.2, conf = 0.25, minlen = 2, maxlen = 2))
## Apriori
## 
## Parameter specification:
##  confidence minval smax arem  aval originalSupport maxtime support minlen
##        0.25    0.1    1 none FALSE            TRUE       5     0.2      2
##  maxlen target  ext
##       2  rules TRUE
## 
## Algorithmic control:
##  filter tree heap memopt load sort verbose
##     0.1 TRUE TRUE  FALSE TRUE    2    TRUE
## 
## Absolute minimum support count: 188 
## 
## set item appearances ...[0 item(s)] done [0.00s].
## set transactions ...[1433 item(s), 943 transaction(s)] done [0.01s].
## sorting and recoding items ... [49 item(s)] done [0.00s].
## creating transaction tree ... done [0.00s].
## checking subsets of size 1 2
##  done [0.00s].
## writing ... [72 rule(s)] done [0.00s].
## creating S4 object  ... done [0.00s].
rules <- rules[!is.redundant(rules)]
summary(rules)
## set of 72 rules
## 
## rule length distribution (lhs + rhs):sizes
##  2 
## 72 
## 
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##       2       2       2       2       2       2 
## 
## summary of quality measures:
##     support         confidence        coverage           lift      
##  Min.   :0.2004   Min.   :0.3772   Min.   :0.2301   Min.   :1.138  
##  1st Qu.:0.2041   1st Qu.:0.5198   1st Qu.:0.3107   1st Qu.:1.399  
##  Median :0.2179   Median :0.6071   Median :0.3690   Median :1.584  
##  Mean   :0.2315   Mean   :0.6291   Mean   :0.3882   Mean   :1.651  
##  3rd Qu.:0.2450   3rd Qu.:0.7589   3rd Qu.:0.5313   3rd Qu.:1.857  
##  Max.   :0.3701   Max.   :0.9352   Max.   :0.5313   Max.   :2.385  
##      count      
##  Min.   :189.0  
##  1st Qu.:192.5  
##  Median :205.5  
##  Mean   :218.3  
##  3rd Qu.:231.0  
##  Max.   :349.0  
## 
## mining info:
##         data ntransactions support confidence
##  movie_trans           943     0.2       0.25
##                                                                                            call
##  apriori(data = movie_trans, parameter = list(supp = 0.2, conf = 0.25, minlen = 2, maxlen = 2))

3.2. Wizualizacja reguł

Uzyskaną listę reguł można posortować po różnych parametrach: lift, confidence oraz support. Dla każdej z posortowanych list została przygotowana interaktywna wizualizacja dwudziestu pierwszych reguł. We wszystkich przypadkach można zauważyć dominację filmów z serii Star Wars i Indiana Jones.

3.2.1. Lift

Miara lift oznacza, ile razy polubienie filmu z lewej strony zwiększa szansę polubienia filmu z prawej strony.

rules_sorted_lift <- sort(rules, by = 'lift', decreasing = TRUE)
inspect(head(rules_sorted_lift, 20))
##      lhs                                            rhs                                           support confidence  coverage     lift count
## [1]  {Terminator, The (1984)}                    => {Raiders of the Lost Ark (1981)}            0.2025451  0.8801843 0.2301166 2.385097   191
## [2]  {Raiders of the Lost Ark (1981)}            => {Terminator, The (1984)}                    0.2025451  0.5488506 0.3690350 2.385097   191
## [3]  {Indiana Jones and the Last Crusade (1989)} => {Raiders of the Lost Ark (1981)}            0.2078473  0.8340426 0.2492047 2.260064   196
## [4]  {Raiders of the Lost Ark (1981)}            => {Indiana Jones and the Last Crusade (1989)} 0.2078473  0.5632184 0.3690350 2.260064   196
## [5]  {Empire Strikes Back, The (1980)}           => {Raiders of the Lost Ark (1981)}            0.2545069  0.8191126 0.3107105 2.219607   240
## [6]  {Raiders of the Lost Ark (1981)}            => {Empire Strikes Back, The (1980)}           0.2545069  0.6896552 0.3690350 2.219607   240
## [7]  {Back to the Future (1985)}                 => {Raiders of the Lost Ark (1981)}            0.2004242  0.8042553 0.2492047 2.179347   189
## [8]  {Raiders of the Lost Ark (1981)}            => {Back to the Future (1985)}                 0.2004242  0.5431034 0.3690350 2.179347   189
## [9]  {Fugitive, The (1993)}                      => {Raiders of the Lost Ark (1981)}            0.2184517  0.7803030 0.2799576 2.114442   206
## [10] {Raiders of the Lost Ark (1981)}            => {Fugitive, The (1993)}                      0.2184517  0.5919540 0.3690350 2.114442   206
## [11] {Princess Bride, The (1987)}                => {Raiders of the Lost Ark (1981)}            0.2004242  0.7620968 0.2629905 2.065107   189
## [12] {Raiders of the Lost Ark (1981)}            => {Princess Bride, The (1987)}                0.2004242  0.5431034 0.3690350 2.065107   189
## [13] {Pulp Fiction (1994)}                       => {Silence of the Lambs, The (1991)}          0.2195122  0.7040816 0.3117709 1.930084   207
## [14] {Silence of the Lambs, The (1991)}          => {Pulp Fiction (1994)}                       0.2195122  0.6017442 0.3647932 1.930084   207
## [15] {Empire Strikes Back, The (1980)}           => {Return of the Jedi (1983)}                 0.2396607  0.7713311 0.3107105 1.919169   226
## [16] {Return of the Jedi (1983)}                 => {Empire Strikes Back, The (1980)}           0.2396607  0.5963061 0.4019088 1.919169   226
## [17] {Raiders of the Lost Ark (1981)}            => {Pulp Fiction (1994)}                       0.2152704  0.5833333 0.3690350 1.871032   203
## [18] {Pulp Fiction (1994)}                       => {Raiders of the Lost Ark (1981)}            0.2152704  0.6904762 0.3117709 1.871032   203
## [19] {Silence of the Lambs, The (1991)}          => {Empire Strikes Back, The (1980)}           0.2099682  0.5755814 0.3647932 1.852468   198
## [20] {Empire Strikes Back, The (1980)}           => {Silence of the Lambs, The (1991)}          0.2099682  0.6757679 0.3107105 1.852468   198
plot(head(rules_sorted_lift, 20), method = 'graph', engine = 'htmlwidget')

3.2.2. Confidence

Miara confidence oznacza, jakiemu odsetkowi oglądających, którym podobał się film po lewej stronie, podobał się także film po prawej stronie.

rules_sorted_conf <- sort(rules, by = 'confidence', decreasing = TRUE)
inspect(head(rules_sorted_conf, 20))
##      lhs                                            rhs                                support confidence  coverage     lift count
## [1]  {Empire Strikes Back, The (1980)}           => {Star Wars (1977)}               0.2905620  0.9351536 0.3107105 1.760179   274
## [2]  {Return of the Jedi (1983)}                 => {Star Wars (1977)}               0.3700954  0.9208443 0.4019088 1.733246   349
## [3]  {Terminator, The (1984)}                    => {Raiders of the Lost Ark (1981)} 0.2025451  0.8801843 0.2301166 2.385097   191
## [4]  {Indiana Jones and the Last Crusade (1989)} => {Star Wars (1977)}               0.2163309  0.8680851 0.2492047 1.633941   204
## [5]  {Alien (1979)}                              => {Star Wars (1977)}               0.2025451  0.8565022 0.2364793 1.612139   191
## [6]  {Princess Bride, The (1987)}                => {Star Wars (1977)}               0.2216331  0.8427419 0.2629905 1.586239   209
## [7]  {Raiders of the Lost Ark (1981)}            => {Star Wars (1977)}               0.3107105  0.8419540 0.3690350 1.584756   293
## [8]  {Terminator 2: Judgment Day (1991)}         => {Star Wars (1977)}               0.2014846  0.8407080 0.2396607 1.582410   190
## [9]  {Indiana Jones and the Last Crusade (1989)} => {Raiders of the Lost Ark (1981)} 0.2078473  0.8340426 0.2492047 2.260064   196
## [10] {Back to the Future (1985)}                 => {Star Wars (1977)}               0.2046660  0.8212766 0.2492047 1.545836   193
## [11] {Empire Strikes Back, The (1980)}           => {Raiders of the Lost Ark (1981)} 0.2545069  0.8191126 0.3107105 2.219607   240
## [12] {Fugitive, The (1993)}                      => {Star Wars (1977)}               0.2279958  0.8143939 0.2799576 1.532881   215
## [13] {Monty Python and the Holy Grail (1974)}    => {Star Wars (1977)}               0.2078473  0.8099174 0.2566278 1.524455   196
## [14] {Back to the Future (1985)}                 => {Raiders of the Lost Ark (1981)} 0.2004242  0.8042553 0.2492047 2.179347   189
## [15] {Fugitive, The (1993)}                      => {Raiders of the Lost Ark (1981)} 0.2184517  0.7803030 0.2799576 2.114442   206
## [16] {Empire Strikes Back, The (1980)}           => {Return of the Jedi (1983)}      0.2396607  0.7713311 0.3107105 1.919169   226
## [17] {Toy Story (1995)}                          => {Star Wars (1977)}               0.2619300  0.7694704 0.3404030 1.448325   247
## [18] {Princess Bride, The (1987)}                => {Raiders of the Lost Ark (1981)} 0.2004242  0.7620968 0.2629905 2.065107   189
## [19] {Godfather, The (1972)}                     => {Star Wars (1977)}               0.2820785  0.7578348 0.3722163 1.426424   266
## [20] {Silence of the Lambs, The (1991)}          => {Star Wars (1977)}               0.2714740  0.7441860 0.3647932 1.400733   256
plot(head(rules_sorted_conf, 20), method = 'graph', engine = 'htmlwidget')

3.2.3. Support

Miara support oznacza, jaki odsetek wszystkich oglądających polubił jednocześnie oba filmy.

rules_sorted_supp <- sort(rules, by = 'support', decreasing = TRUE)
inspect(head(rules_sorted_supp, 20))
##      lhs                                   rhs                                  support confidence  coverage     lift count
## [1]  {Return of the Jedi (1983)}        => {Star Wars (1977)}                 0.3700954  0.9208443 0.4019088 1.733246   349
## [2]  {Star Wars (1977)}                 => {Return of the Jedi (1983)}        0.3700954  0.6966068 0.5312831 1.733246   349
## [3]  {Raiders of the Lost Ark (1981)}   => {Star Wars (1977)}                 0.3107105  0.8419540 0.3690350 1.584756   293
## [4]  {Star Wars (1977)}                 => {Raiders of the Lost Ark (1981)}   0.3107105  0.5848303 0.5312831 1.584756   293
## [5]  {Empire Strikes Back, The (1980)}  => {Star Wars (1977)}                 0.2905620  0.9351536 0.3107105 1.760179   274
## [6]  {Star Wars (1977)}                 => {Empire Strikes Back, The (1980)}  0.2905620  0.5469062 0.5312831 1.760179   274
## [7]  {Fargo (1996)}                     => {Star Wars (1977)}                 0.2831389  0.6576355 0.4305408 1.237825   267
## [8]  {Star Wars (1977)}                 => {Fargo (1996)}                     0.2831389  0.5329341 0.5312831 1.237825   267
## [9]  {Godfather, The (1972)}            => {Star Wars (1977)}                 0.2820785  0.7578348 0.3722163 1.426424   266
## [10] {Star Wars (1977)}                 => {Godfather, The (1972)}            0.2820785  0.5309381 0.5312831 1.426424   266
## [11] {Silence of the Lambs, The (1991)} => {Star Wars (1977)}                 0.2714740  0.7441860 0.3647932 1.400733   256
## [12] {Star Wars (1977)}                 => {Silence of the Lambs, The (1991)} 0.2714740  0.5109780 0.5312831 1.400733   256
## [13] {Toy Story (1995)}                 => {Star Wars (1977)}                 0.2619300  0.7694704 0.3404030 1.448325   247
## [14] {Star Wars (1977)}                 => {Toy Story (1995)}                 0.2619300  0.4930140 0.5312831 1.448325   247
## [15] {Empire Strikes Back, The (1980)}  => {Raiders of the Lost Ark (1981)}   0.2545069  0.8191126 0.3107105 2.219607   240
## [16] {Raiders of the Lost Ark (1981)}   => {Empire Strikes Back, The (1980)}  0.2545069  0.6896552 0.3690350 2.219607   240
## [17] {Return of the Jedi (1983)}        => {Raiders of the Lost Ark (1981)}   0.2449629  0.6094987 0.4019088 1.651601   231
## [18] {Raiders of the Lost Ark (1981)}   => {Return of the Jedi (1983)}        0.2449629  0.6637931 0.3690350 1.651601   231
## [19] {Silence of the Lambs, The (1991)} => {Raiders of the Lost Ark (1981)}   0.2449629  0.6715116 0.3647932 1.819642   231
## [20] {Raiders of the Lost Ark (1981)}   => {Silence of the Lambs, The (1991)} 0.2449629  0.6637931 0.3690350 1.819642   231
plot(head(rules_sorted_supp, 20), method = 'graph', engine = 'htmlwidget')

3.3. Zastosowanie reguł

Przygotowane i oczyszczone reguły asocjacyjne można wykorzystać do stworzenia rekomendacji dalszych filmów do oglądania dla osób, które polubiły konkretne filmy. Jako przykład został wzięty film Star Wars (1977), dla którego zostało przygotowane 5 rekomendacji posortowanych po mierze confidence. Są to więc filmy, dla których jest największe prawdopodobieństwo, że oglądający je polubi, jeżeli podobał mu się też oryginalny film.

star_wars_rules <- subset(rules, lhs %in% 'Star Wars (1977)')
star_wars_rules <- sort(star_wars_rules, by = 'confidence', decreasing = TRUE)
inspect(head(star_wars_rules, 5))
##     lhs                   rhs                               support  
## [1] {Star Wars (1977)} => {Return of the Jedi (1983)}       0.3700954
## [2] {Star Wars (1977)} => {Raiders of the Lost Ark (1981)}  0.3107105
## [3] {Star Wars (1977)} => {Empire Strikes Back, The (1980)} 0.2905620
## [4] {Star Wars (1977)} => {Fargo (1996)}                    0.2831389
## [5] {Star Wars (1977)} => {Godfather, The (1972)}           0.2820785
##     confidence coverage  lift     count
## [1] 0.6966068  0.5312831 1.733246 349  
## [2] 0.5848303  0.5312831 1.584756 293  
## [3] 0.5469062  0.5312831 1.760179 274  
## [4] 0.5329341  0.5312831 1.237825 267  
## [5] 0.5309381  0.5312831 1.426424 266

Na pierwszym miejscu znalazł się sequel tego filmu, czyli Return of the Jedi (1983). 70% osób, którym podobał się oryginalny film, podobał się też ten sequel. Ponadto, szansa polubienia sequela wzrasta około 1.73 razy, jeżeli wiadomo, że dana osoba polubiła oryginalny film. Można też odczytać, że 37% wszystkich osób polubiło oba filmy jednocześnie.