Przewidywanie polubień: w algorytmach prostego silnika rekomendacji

Opublikowany: 2022-03-11

Silnik rekomendacji (czasami określany jako system rekomendacji) to narzędzie, które pozwala twórcom algorytmów przewidzieć, co może lub nie spodoba się użytkownikowi na liście danych elementów. Silniki rekomendacji są dość interesującą alternatywą dla pól wyszukiwania, ponieważ silniki rekomendacji pomagają użytkownikom odkrywać produkty lub treści, na które w inny sposób mogliby nie natknąć się. To sprawia, że ​​silniki rekomendacji są świetną częścią witryn internetowych i usług, takich jak Facebook, YouTube, Amazon i nie tylko.

Silniki rekomendacji działają idealnie na dwa sposoby. Może polegać na właściwościach przedmiotów, które użytkownik lubi, które są analizowane w celu określenia, co jeszcze może podobać się użytkownikowi; lub może polegać na upodobaniach i niechęciach innych użytkowników, które silnik rekomendacji wykorzystuje następnie do obliczania indeksu podobieństwa między użytkownikami i odpowiedniego polecania im elementów. Możliwe jest również połączenie obu tych metod w celu zbudowania znacznie solidniejszego silnika rekomendacji. Jednak, podobnie jak w przypadku wszystkich innych problemów związanych z informacją, konieczne jest wybranie algorytmu odpowiedniego dla rozwiązywanego problemu.

Budowanie silnika rekomendacji

W tym samouczku przeprowadzimy Cię przez proces tworzenia silnika rekomendacji, który jest oparty na współpracy i pamięci. Ten silnik rekomendacji będzie polecał filmy użytkownikom na podstawie tego, co lubią, a czego nie, i będzie działał jak drugi przykład, o którym wspomniano wcześniej. W tym projekcie będziemy używać podstawowych operacji na zbiorach, trochę matematyki i Node.js/CoffeeScript. Cały kod źródłowy dotyczący tego samouczka można znaleźć tutaj.

Zbiory i równania

Przed wdrożeniem mechanizmu rekomendacji opartego na pamięci współpracy musimy najpierw zrozumieć podstawową ideę takiego systemu. Dla tego silnika każdy element i każdy użytkownik to tylko identyfikatory. Dlatego podczas generowania rekomendacji nie będziemy brać pod uwagę żadnych innych atrybutów filmu (na przykład obsady, reżysera, gatunku itp.). Podobieństwo między dwoma użytkownikami jest reprezentowane za pomocą liczby dziesiętnej z zakresu od -1,0 do 1,0. Nazwiemy tę liczbę indeksem podobieństwa. Wreszcie, możliwość polubienia filmu przez użytkownika zostanie przedstawiona za pomocą innej liczby dziesiętnej z zakresu od -1,0 do 1,0. Teraz, kiedy modelowaliśmy świat wokół tego systemu za pomocą prostych terminów, możemy uwolnić garść eleganckich równań matematycznych, aby zdefiniować związek między tymi identyfikatorami a liczbami.

W naszym algorytmie rekomendacji zachowamy pewną liczbę zestawów. Każdy użytkownik będzie miał dwa zestawy: zestaw filmów, które użytkownik lubi, oraz zestaw filmów, których użytkownik nie lubi. Z każdym filmem będą również powiązane dwa zestawy: zestaw użytkowników, którym film się podobał, oraz zestaw użytkowników, którym film się nie spodobał. Podczas etapów, na których generowane są rekomendacje, tworzonych jest szereg zestawów - głównie połączenia lub przecięcia innych zestawów. Dla każdego użytkownika będziemy mieć również uporządkowane listy sugestii i podobnych użytkowników.

Aby obliczyć wskaźnik podobieństwa, użyjemy odmiany wzoru na indeks Jaccarda. Formuła ta, znana pierwotnie jako „współczynnik wspólnotowy” (ukuta przez Paula Jaccarda), porównuje dwa zestawy i tworzy prostą statystykę dziesiętną od 0 do 1,0:

wskaźnik podobieństwa

Formuła polega na podzieleniu liczby wspólnych elementów w każdym zestawie przez liczbę wszystkich elementów (liczonych tylko raz) w obu zestawach. Indeks Jaccarda dwóch identycznych zestawów zawsze będzie wynosił 1, podczas gdy indeks Jaccarda dwóch zestawów bez elementów wspólnych zawsze da 0. Teraz, gdy wiemy, jak porównać dwa zestawy, zastanówmy się nad strategią, której możemy użyć do porównania dwóch użytkowników. Jak wspomniano wcześniej, użytkownicy, z punktu widzenia systemu, to trzy rzeczy: identyfikator, zestaw lubianych filmów i zestaw nielubianych filmów. Gdybyśmy mieli zdefiniować indeks podobieństwa naszych użytkowników wyłącznie na podstawie zestawu ich lubianych przez nich filmów, moglibyśmy bezpośrednio użyć formuły indeksu Jaccarda:

formuła indeksu jaccarda

Tutaj U1 i U2 to dwaj użytkownicy, których porównujemy, a L1 i L2 to zestawy filmów, które podobały się odpowiednio U1 i U2. Teraz, jeśli się nad tym zastanowić, dwóch użytkowników lubiących te same filmy jest podobnych, to dwóch użytkowników, którzy nie lubią tych samych filmów, również powinni być podobni. Tutaj trochę modyfikujemy równanie:

zmodyfikowane równanie

Zamiast uwzględniać tylko powszechne polubienia w liczniku formuły, teraz dodajemy również liczbę powszechnych polubień. W mianowniku bierzemy liczbę wszystkich przedmiotów, które spodobały się lub nie spodobały się użytkownikowi. Teraz, gdy rozważyliśmy zarówno upodobania, jak i antypatie w niezależny sposób, powinniśmy również pomyśleć o przypadku, w którym preferencje dwóch użytkowników są przeciwstawne. Wskaźnik podobieństwa dwóch użytkowników, z których jeden lubi film, a drugi go nie lubi, nie powinien wynosić 0:

wskaźnik podobieństwa dwóch użytkowników

To jedna długa formuła! Ale to proste, obiecuję. Jest podobny do naszego poprzedniego wzoru z niewielką różnicą w liczniku. Odejmujemy teraz liczbę sprzecznych upodobań i upodobań tych dwóch użytkowników od liczby ich wspólnych upodobań i upodobań. Powoduje to, że formuła indeksu podobieństwa ma zakres wartości od -1,0 do 1,0. Dwóch użytkowników o identycznych gustach będzie miało wskaźnik podobieństwa równy 1,0, podczas gdy dwóch użytkowników o całkowicie sprzecznych gustach w filmach będzie mieć wskaźnik podobieństwa równy -1,0.

Teraz, gdy wiemy, jak porównać dwóch użytkowników na podstawie ich gustów filmowych, musimy zbadać jeszcze jedną formułę, zanim zaczniemy wdrażać nasz algorytm silnika rekomendacji domowej produkcji:

algorytm silnika rekomendacji

Rozłóżmy trochę to równanie. Przez P(U,M) rozumiemy możliwość, że użytkownik U polubi film M . ZL i ZD to suma wskaźników podobieństwa użytkownika U do wszystkich użytkowników, którym odpowiednio podobał się lub nie podobał film M . |ML|+|MD| reprezentuje całkowitą liczbę użytkowników, którym podobał się lub nie podobał film M . Wynik P(U,M) daje liczbę od -1,0 do 1,0.

O to chodzi. W następnej sekcji możemy użyć tych formuł, aby rozpocząć wdrażanie naszego mechanizmu rekomendacji opartego na pamięci współpracy.

Budowanie silnika rekomendacji

Zbudujemy ten silnik rekomendacji jako bardzo prostą aplikację Node.js. Będzie też bardzo mało pracy nad interfejsem, głównie niektóre strony HTML i formularze (będziemy używać Bootstrap, aby strony wyglądały schludnie). Po stronie serwera użyjemy CoffeeScript. Aplikacja będzie miała kilka tras GET i POST. Choć w aplikacji będziemy mieli pojęcie użytkowników, nie będziemy mieli rozbudowanego mechanizmu rejestracji/logowania. Dla trwałości użyjemy pakietu Bourne dostępnego przez NPM, który umożliwia aplikacji przechowywanie danych w czystych plikach JSON i wykonywanie na nich podstawowych zapytań do bazy danych. Wykorzystamy Express.js, aby ułatwić proces zarządzania trasami i handlerami.

W tym momencie, jeśli jesteś nowy w programowaniu Node.js, możesz sklonować repozytorium GitHub, aby łatwiej było śledzić ten samouczek. Jak w przypadku każdego innego projektu Node.js, zaczniemy od utworzenia pliku package.json i zainstalowania zestawu pakietów zależności wymaganych dla tego projektu. Jeśli korzystasz ze sklonowanego repozytorium, plik package.json powinien już tam być, skąd instalacja zależności będzie wymagać wykonania „$ npm install”. Spowoduje to zainstalowanie wszystkich pakietów wymienionych w pliku package.json.

Pakiety Node.js, których potrzebujemy do tego projektu, to:

  • asynchroniczny
  • granica
  • kawa-skrypt
  • wyrazić
  • jadeit
  • podkreślać

Zbudujemy silnik rekomendacji, dzieląc wszystkie odpowiednie metody na cztery oddzielne klasy CoffeeScript, z których każda będzie przechowywana w „lib/engine”: Silnik, Ocena, Podobne i Sugestie. Klasa Engine będzie odpowiedzialna za dostarczenie prostego interfejsu API dla silnika rekomendacji i powiąże ze sobą pozostałe trzy klasy. Rater będzie odpowiedzialny za śledzenie polubień i antypatii (jako dwie oddzielne instancje klasy Rater). Podobne i Sugestie będą odpowiedzialne odpowiednio za określanie i śledzenie podobnych użytkowników i polecanych przedmiotów dla użytkowników.

Śledzenie polubień i niechęci

Zacznijmy najpierw od naszej klasy Oceniający. To jest proste:

 class Rater constructor: (@engine, @kind) -> add: (user, item, done) -> remove: (user, item, done) -> itemsByUser: (user, done) -> usersByItem: (item, done) ->

Jak wskazano wcześniej w tym samouczku, będziemy mieć jedną instancję Ratera dla polubień, a drugą dla niechęci. Aby zarejestrować, że użytkownik lubi dany przedmiot, przekażemy go do „Rater#add()”. Podobnie, aby usunąć ocenę, przekażemy je do „Rater#remove()”.

Ponieważ używamy Bourne'a jako rozwiązania bazodanowego bez serwera, będziemy przechowywać te oceny w pliku o nazwie „./db-#{@kind}.json”, gdzie rodzaj to „lubię” lub „nie lubię”. Otworzymy bazę danych wewnątrz konstruktora instancji Rater:

 constructor: (@engine, @kind) -> @db = new Bourne "./db-#{@kind}.json"

Dzięki temu dodawanie rekordów ocen będzie tak proste, jak wywołanie metody bazy danych Bourne w naszej metodzie „Rater#add()”:

 @db.insert user: user, item: item, (err) =>

Podobnie jest z ich usunięciem („db.delete” zamiast „db.insert”). Zanim jednak coś dodamy lub usuniemy, musimy upewnić się, że nie istnieje już w bazie danych. Idealnie, z prawdziwą bazą danych, moglibyśmy to zrobić jako pojedynczą operację. W przypadku Bourne'a musimy najpierw przeprowadzić kontrolę ręczną; a po zakończeniu wstawiania lub usuwania musimy upewnić się, że ponownie obliczyliśmy wskaźniki podobieństwa dla tego użytkownika, a następnie wygenerować zestaw nowych sugestii. Metody „Rater#add()” i „Rater#remove()” będą wyglądać mniej więcej tak:

 add: (user, item, done) -> @db.find user: user, item: item, (err, res) => if res.length > 0 return done() @db.insert user: user, item: item, (err) => async.series [ (done) => @engine.similars.update user, done (done) => @engine.suggestions.update user, done ], done remove: (user, item, done) -> @db.delete user: user, item: item, (err) => async.series [ (done) => @engine.similars.update user, done (done) => @engine.suggestions.update user, done ], done

Dla zwięzłości pominiemy części, w których sprawdzamy błędy. To może być rozsądna rzecz do zrobienia w artykule, ale nie jest wymówką dla ignorowania błędów w prawdziwym kodzie.

Pozostałe dwie metody, „Rater#itemsByUser()” i „Rater#usersByItem()” z tej klasy, będą polegać na wykonywaniu tego, na co wskazują ich nazwy — wyszukiwaniu elementów ocenionych odpowiednio przez użytkownika i użytkowników, którzy ocenili element. Na przykład, jeśli instancja Ratera zostanie utworzona z kind = “likes” , „Rater#itemsByUser()” znajdzie wszystkie elementy ocenione przez użytkownika.

Znajdowanie podobnych użytkowników

Przechodząc do naszej następnej klasy: Podobne. Ta klasa pomoże nam obliczyć i śledzić wskaźniki podobieństwa między użytkownikami. Jak omówiono wcześniej, obliczenie podobieństwa między dwoma użytkownikami obejmuje analizę zestawów przedmiotów, które lubią i nie lubią. Aby to zrobić, będziemy polegać na instancjach Rater, aby pobrać zestawy odpowiednich elementów, a następnie określić indeks podobieństwa dla niektórych par użytkowników za pomocą formuły indeksu podobieństwa.

Znajdowanie podobnych użytkowników

Podobnie jak nasza poprzednia klasa, Rater, umieścimy wszystko w bazie danych Bourne o nazwie „./db-similars.json”, którą otworzymy w konstruktorze Rater. Klasa będzie posiadała metodę „Similars#byUser()”, która pozwoli nam wyszukać użytkowników podobnych do danego użytkownika poprzez proste wyszukiwanie w bazie danych:

 @db.findOne user: user, (err, {others}) =>

Jednak najważniejszą metodą tej klasy jest „Similars#update()”, która działa poprzez pobranie użytkownika i obliczenie listy innych użytkowników, którzy są podobni, oraz zapisanie listy w bazie danych, wraz z ich wskaźnikami podobieństwa. Zaczyna się od znalezienia upodobań i niechęci użytkownika:

 async.auto userLikes: (done) => @engine.likes.itemsByUser user, done userDislikes: (done) => @engine.dislikes.itemsByUser user, done , (err, {userLikes, userDislikes}) => items = _.flatten([userLikes, userDislikes])

Znajdujemy również wszystkich użytkowników, którzy ocenili te pozycje:

 async.map items, (item, done) => async.map [ @engine.likes @engine.dislikes ], (rater, done) => rater.usersByItem item, done , done , (err, others) =>

Następnie dla każdego z tych innych użytkowników obliczamy indeks podobieństwa i przechowujemy go w bazie danych:

 async.map others, (other, done) => async.auto otherLikes: (done) => @engine.likes.itemsByUser other, done otherDislikes: (done) => @engine.dislikes.itemsByUser other, done , (err, {otherLikes, otherDislikes}) => done null, user: other similarity: (_.intersection(userLikes, otherLikes).length+_.intersection(userDislikes, otherDislikes).length-_.intersection(userLikes, otherDislikes).length-_.intersection(userDislikes, otherLikes).length) / _.union(userLikes, otherLikes, userDislikes, otherDislikes).length , (err, others) => @db.insert user: user others: others , done

W powyższym fragmencie można zauważyć, że mamy wyrażenie identyczne z naszą formułą indeksu podobieństwa, odmianą formuły indeksu Jaccarda.

Generowanie rekomendacji

Nasze następne zajęcia, Sugestie, to miejsce, w którym odbywają się wszystkie przewidywania. Podobnie jak klasa Podobne, opieramy się na innej bazie danych Bourne o nazwie „./db-suggestions.json”, otwartej w konstruktorze.

Generowanie rekomendacji i sugestii

Klasa będzie miała metodę „Suggestions#forUser()” do wyszukiwania obliczonych sugestii dla danego użytkownika:

 forUser: (user, done) -> @db.findOne user: user, (err, {suggestions}={suggestion: []}) -> done null, suggestions

Metodą, która obliczy te wyniki, jest „Suggestions#update()”. Ta metoda, taka jak „Similars#update()”, przyjmie użytkownika jako argument. Metoda rozpoczyna się od wypisania wszystkich użytkowników podobnych do danego użytkownika oraz wszystkich pozycji, których dany użytkownik nie ocenił:

 @engine.similars.byUser user, (err, others) => async.auto likes: (done) => @engine.likes.itemsByUser user, done dislikes: (done) => @engine.dislikes.itemsByUser user, done items: (done) => async.map others, (other, done) => async.map [ @engine.likes @engine.dislikes ], (rater, done) => rater.itemsByUser other.user, done , done , done , (err, {likes, dislikes, items}) => items = _.difference _.unique(_.flatten items), likes, dislikes

Gdy mamy wszystkich pozostałych użytkowników i pozycje bez oceny, możemy rozpocząć obliczanie nowego zestawu rekomendacji, usuwając wszystkie poprzednie zestawy rekomendacji, iterując każdy element i obliczając możliwość polubienia go przez użytkownika na podstawie dostępnych informacji:

 @db.delete user: user, (err) => async.map items, (item, done) => async.auto likers: (done) => @engine.likes.usersByItem item, done dislikers: (done) => @engine.dislikes.usersByItem item, done , (err, {likers, dislikers}) => numerator = 0 for other in _.without _.flatten([likers, dislikers]), user other = _.findWhere(others, user: other) if other? numerator += other.similarity done null, item: item weight: numerator / _.union(likers, dislikers).length , (err, suggestions) =>

Po wykonaniu tej czynności zapisujemy go z powrotem w bazie danych:

 @db.insert user: user suggestions: suggestions , done

Udostępnianie Library API

Wewnątrz klasy Engine łączymy wszystko w schludną strukturę podobną do interfejsu API, aby zapewnić łatwy dostęp ze świata zewnętrznego:

 class Engine constructor: -> @likes = new Rater @, 'likes' @dislikes = new Rater @, 'dislikes' @similars = new Similars @ @suggestions = new Suggestions @

Po utworzeniu instancji obiektu Engine:

 e = new Engine

Możemy łatwo dodawać lub usuwać polubienia i antypatie:

 e.likes.add user, item, (err) -> e.dislikes.add user, item, (err) ->

Możemy również rozpocząć aktualizację wskaźników podobieństwa i sugestii użytkowników:

 e.similars.update user, (err) -> e.suggestions.update user, (err) ->

Na koniec ważne jest, aby wyeksportować tę klasę silnika (i wszystkie inne klasy) z odpowiednich plików „.coffee”:

 module.exports = Engine

Następnie wyeksportuj silnik z pakietu, tworząc plik „index.coffee” w jednej linii:

 module.exports = require './engine'

Tworzenie interfejsu użytkownika

Aby móc korzystać z algorytmu silnika rekomendacji w tym samouczku, chcemy zapewnić prosty interfejs użytkownika w Internecie. Aby to zrobić, tworzymy aplikację Express w naszym pliku „web.iced” i obsługujemy kilka tras:

 movies = require './data/movies.json' Engine = require './lib/engine' e = new Eengine app = express() app.set 'views', "#{__dirname}/views" app.set 'view engine', 'jade' app.route('/refresh') .post(({query}, res, next) -> async.series [ (done) => e.similars.update query.user, done (done) => e.suggestions.update query.user, done ], (err) => res.redirect "/?user=#{query.user}" ) app.route('/like') .post(({query}, res, next) -> if query.unset is 'yes' e.likes.remove query.user, query.movie, (err) => res.redirect "/?user=#{query.user}" else e.dislikes.remove query.user, query.movie, (err) => e.likes.add query.user, query.movie, (err) => if err? return next err res.redirect "/?user=#{query.user}" ) app.route('/dislike') .post(({query}, res, next) -> if query.unset is 'yes' e.dislikes.remove query.user, query.movie, (err) => res.redirect "/?user=#{query.user}" else e.likes.remove query.user, query.movie, (err) => e.dislikes.add query.user, query.movie, (err) => res.redirect "/?user=#{query.user}" ) app.route('/') .get(({query}, res, next) -> async.auto likes: (done) => e.likes.itemsByUser query.user, done dislikes: (done) => e.dislikes.itemsByUser query.user, done suggestions: (done) => e.suggestions.forUser query.user, (err, suggestions) => done null, _.map _.sortBy(suggestions, (suggestion) -> -suggestion.weight), (suggestion) => _.findWhere movies, id: suggestion.item , (err, {likes, dislikes, suggestions}) => res.render 'index', movies: movies user: query.user likes: likes dislikes: dislikes suggestions: suggestions[...4] )

W ramach aplikacji obsługujemy cztery trasy. Ścieżka indeksu „/” to miejsce, w którym obsługujemy frontendowy kod HTML, renderując szablon Jade. Generowanie szablonu wymaga listy filmów, nazwy użytkownika bieżącego użytkownika, upodobań i upodobań użytkownika oraz czterech najlepszych sugestii dla użytkownika. Kod źródłowy szablonu Jade jest pomijany w artykule, ale jest dostępny w repozytorium GitHub.

Trasy „/lubię” i „/nie lubię” to miejsca, w których akceptujemy żądania POST w celu rejestrowania upodobań i niechęci użytkownika. Obie trasy dodają ocenę, najpierw usuwając wszelkie sprzeczne oceny, jeśli to konieczne. Na przykład użytkownik polubiący coś, czego wcześniej nie lubił, spowoduje, że program obsługi najpierw usunie ocenę „nielubienie”. Trasy te pozwalają również użytkownikowi na „nielubienie” lub „nielubienie” przedmiotu, jeśli jest to pożądane.

Wreszcie trasa „/odśwież” pozwala użytkownikowi na ponowne generowanie zestawu rekomendacji na żądanie. Chociaż ta akcja jest wykonywana automatycznie za każdym razem, gdy użytkownik dokona jakiejkolwiek oceny elementu.

Jazda testowa

Jeśli próbowałeś zaimplementować tę aplikację od podstaw, postępując zgodnie z tym artykułem, musisz wykonać ostatni krok, zanim będziesz mógł ją przetestować. Będziesz musiał utworzyć plik „.json” w „data/movies.json” i wypełnić go danymi filmu, takimi jak:

 [ { "id": "1", "name": "Transformers: Age of Extinction", "thumb": { "url": "//upload.wikimedia.org/wikipedia/en/7/7f/Inception_ver3.jpg" } }, // … ]

Możesz skopiować ten dostępny w repozytorium GitHub, które jest wstępnie wypełnione kilkoma nazwami filmów i adresami URL miniatur.

Gdy cały kod źródłowy jest gotowy i połączony ze sobą, uruchomienie procesu serwera wymaga wywołania następującego polecenia:

 $ npm start

Zakładając, że wszystko poszło gładko, powinieneś zobaczyć następujący tekst na terminalu:

 Listening on 5000

Ponieważ nie wdrożyliśmy żadnego prawdziwego systemu uwierzytelniania użytkowników, prototypowa aplikacja opiera się tylko na nazwie użytkownika wybranej po odwiedzeniu „http://localhost:5000”. Po wprowadzeniu nazwy użytkownika i przesłaniu formularza należy przejść do innej strony z dwiema sekcjami: „Polecane filmy” i „Wszystkie filmy”. Ponieważ brakuje nam najważniejszego elementu opartego na pamięci współpracującej silnika rekomendacji (danych), nie będziemy w stanie polecić żadnych filmów temu nowemu użytkownikowi.

W tym momencie powinieneś otworzyć inne okno przeglądarki na „http://localhost:5000” i zalogować się tam jako inny użytkownik. Lubię i nie lubię niektórych filmów jako ten drugi użytkownik. Wróć do okna przeglądarki pierwszego użytkownika i oceń także niektóre filmy. Upewnij się, że oceniasz co najmniej kilka popularnych filmów dla obu użytkowników. Powinieneś natychmiast zacząć widzieć rekomendacje.

Ulepszenia

W tym samouczku dotyczącym algorytmów zbudowaliśmy prototypowy silnik rekomendacji. Z pewnością istnieją sposoby na ulepszenie tego silnika. W tej sekcji pokrótce omówimy niektóre obszary, w których niezbędne są ulepszenia, aby można było je stosować na dużą skalę. Jednak w przypadkach, w których wymagana jest skalowalność, stabilność i inne tego typu właściwości, zawsze należy uciekać się do dobrego, sprawdzonego rozwiązania. Podobnie jak w pozostałej części artykułu, tutaj chodzi o zapewnienie wglądu w działanie silnika rekomendacji. Zamiast omawiać oczywiste wady obecnej metody (takie jak stan wyścigu w niektórych wdrożonych przez nas metodach), ulepszenia zostaną omówione na wyższym poziomie.

Jednym z bardzo oczywistych ulepszeń jest użycie prawdziwej bazy danych zamiast naszego rozwiązania opartego na plikach. Rozwiązanie oparte na plikach może działać dobrze w prototypie na małą skalę, ale nie jest to wcale rozsądny wybór do rzeczywistego użytku. Jedną z wielu opcji jest Redis. Redis jest szybki i ma specjalne możliwości, które są przydatne w przypadku struktur danych podobnych do zestawu.

Inną kwestią, którą możemy po prostu obejść, jest fakt, że obliczamy nowe rekomendacje za każdym razem, gdy użytkownik tworzy lub zmienia swoje oceny filmów. Zamiast wykonywać ponowne obliczenia w locie w czasie rzeczywistym, powinniśmy kolejkować te żądania aktualizacji rekomendacji dla użytkowników i wykonywać je za kulisami – być może ustawiając określony czas odświeżania.

Poza tymi „technicznymi” wyborami, istnieje również kilka strategicznych wyborów, których można dokonać w celu ulepszenia zaleceń. Wraz ze wzrostem liczby elementów i użytkowników generowanie rekomendacji będzie coraz bardziej kosztowne (pod względem czasu i zasobów systemowych). Można to przyspieszyć, wybierając tylko podzbiór użytkowników do generowania rekomendacji, zamiast za każdym razem przetwarzać całą bazę danych. Na przykład, jeśli był to silnik rekomendacji dla restauracji, możesz ograniczyć podobny zestaw użytkowników, aby zawierał tylko tych użytkowników, którzy mieszkają w tym samym mieście lub stanie.

Inne ulepszenia mogą obejmować przyjęcie podejścia hybrydowego, w którym zalecenia są generowane na podstawie zarówno filtrowania zespołowego, jak i filtrowania opartego na treści. Byłoby to szczególnie dobre w przypadku treści, takich jak filmy, gdzie właściwości treści są dobrze zdefiniowane. Na przykład Netflix idzie tą drogą, polecając filmy w oparciu zarówno o działania innych użytkowników, jak i atrybuty filmów.

Wniosek

Oparte na pamięci algorytmy oparte na współpracy silnika rekomendacji mogą być dość potężną rzeczą. Ten, z którym eksperymentowaliśmy w tym artykule, może być prymitywny, ale jest też prosty: łatwy do zrozumienia i prosty do zbudowania. Może nie jest to idealne, ale solidne implementacje silników rekomendacji, takich jak Recommendable, opierają się na podobnych fundamentalnych założeniach.

Podobnie jak w przypadku większości innych problemów informatycznych, które wiążą się z dużą ilością danych, uzyskanie prawidłowych rekomendacji wiąże się z wyborem odpowiedniego algorytmu i odpowiednich atrybutów treści, nad którymi będziemy pracować. Mam nadzieję, że ten artykuł dał ci wgląd w to, co dzieje się w silniku rekomendacji opartym na pamięci współpracy, gdy go używasz.