Czy algorytmy znają gust muzyczny?

GZembrowski
Feb 14, 2019 · 6 min read

Zastanawialiście się może jak to się dzieje, że coś w piosence wam się podoba? Czy jest jakiś klucz przy pomocy którego oceniamy dźwięki, przecież każdy z nas ma swój własny gust. Przesłuchałem w życiu tysiące płyt i nadal nie wiem jaki jest mój. Z pomocą Data Science postanowiłem to sprawdzić.

Od dłuższego czasu zbieram utwory które prezentuje w audycjach, poukładane są w katalogi, co tydzień w specjalnym folderze ląduje 20–30 utworów. Jednak żeby je wybrać trzeba poświęcić bardzo dużo czasu. Wystarczy założyć, że co tydzień, w najbliższej okolicy, pojawia się od 300 do nawet 1000 nowych płyt - przesłuchanie ich wszystkich graniczy z cudem. Nawet gdyby były to tylko 30-sekundowe fragmenty…

Postanowiłem sprawdzić, czy algorytmy mogą mi w tym celu jakoś pomóc. Na początek zróbmy sobie listę ulubionych utworów:

Wyszło całkiem nieźle:

Mamy ponad 8 tyś. utworów (z kilku lat) — mam nadzieję, że wystarczy. Co możemy z tym robić? Tutaj z pomocą przychodzi Spotify oraz pakiet spotipy. Spotify oprócz algorytmu porównującego gusta użytkowników, analizuje również każdy z utworów osobno. Nie jestem specjalistą od dźwięku jednak myślę, że parametry generowane są automatycznie. Oto przykładowe dane jakie są gromadzone:

W takim razie, może zapytajmy Spotify o dane na temat moich upodobań? Zapytajmy najpierw Spotify czy zna utwory które należą do moich ulubionych, jeżeli zna to niech poda ‘id’:

W ten sposób dołożyliśmy do naszej ramki kolejną kolumnę:

Nie wszystkie utwory udało się znaleźć w Spotify. Z 8814 wierszy zostało nam 8546, to bardzo dobry wynik dla serwisu, gorszy dla moich upodobań — patrz hasło “I listen to the bands that don’t even exist yet”. Ok zapytajmy API jakie współczynniki mają moje ulubione utwory:

Tabela po pobraniu tych danych (czas pobierania ok 10 minut) wygląda mniej więcej tak:

Spotify zbiera również bardziej szczegółowe dane (dla dociekliwych: https://developer.spotify.com/documentation/web-api/reference/tracks/get-audio-analysis/ ). Z tej analizy wybrałem tylko te najprostsze do przetwarzania dane — ilości bars, sections, segments i wrzuciłem jako kolejne kolumny naszej ramki.

To by było na tyle jeśli chodzi o dane samych utworów, możemy jeszcze dorzucić informacje o samych artystach. Jeśli mamy id utworu, możemy zapytać o id artysty. Następnie dobieramy się do takich informacji:

Po dodaniu oddzielnych kolumn dla każdego gatunku sytuacja zaczyna się komplikować, tabela wygląda tak:

Po usunięciu duplikatów oraz dodaniu kolumn dla każdego gatunku uzbieraliśmy 898 kolumn. To wszystko przez to, że Spotify używa dodatkowo lokalizacji w nazwie gatunku np: scottish indie rock albo kombinuje ze sobą różne gatunki w jeden: retro electro lub deep space rock. To koniec zbierania danych dla moich ulubionych — teraz będzie trochę obrazków.

Tak w uproszczeniu kształtuje się mój gust muzyczny. Oczywiście można zrobić całą analizę tych histogramów: wolę raczej mniej żywe utwory, raczej durowe (choć stosunek mol do dur jest niepokojący), danceability wskazuje, że trochę bardziej lubię nie tańczyć niż tańczyć, valence już całkowicie mnie pogrąża…. Ale dość już o mnie.

Idea całego eksperymentu jest taka, by algorytm w jak największym stopniu pomógł mi odsiać utwory, które nie będą mi się podobały. Zatem potrzebujemy listy potencjalnych przyszłych ulubionych. Tu kłania się scrapowanie blogów. W tym przypadku użyłem oprogramowania Octoparse i po kilku minutach mamy tabelę z autorem i tytułem płyty. Jeśli przejdziemy analogiczną ścieżkę jak w przypadku ulubionych czyli: id_płyty-> id_utworu-> analiza utworów-> analiza autorów to kończymy z następującym wynikiem:

To zbiór z mniej więcej miesiąca, ciekawe, że kolumn jest mniej. Czyżbym miał szerszy gatunkowo gust muzyczny niż próbka z jednego miesiąca? Niekoniecznie, być może używane gatunki z czasem się zmieniały, i te przypisywane obecnie opisuje się używając np. mniejszej ilości kombinacji gatunków. Wyrównajmy zatem ilość kolumn:

Co jeszcze możemy zrobić? Dodam kolumnę ‘known’ tak, żeby artysta który już kiedyś pojawił się w zbiorze ulubionych miał jakieś fory:

Przy okazji kolumna mode została przygotowana pod OneHotEncoder.

Jest jeszcze jeden problem do rozwiązania. Kolumn dotyczących artist_genre jest bardzo dużo, być może nie mają wielkiego znaczenia, zmniejszam ich ilość przy pomocy PCA:

Powyżej otrzymany wynik, Explained Variance Ratio na zadowalającym poziomie. Pozostaje przyłączyć przekształcone kolumny.

Następnie skalujemy odpowiednie kolumny, a te które zawierają kategorie traktujmy OneHotEncoderem:

Ostateczny kształt naszych ramek:

Wyszło 134 kolumny — myślę, że komputer sobie poradzi w rozsądnym czasie. Pozostaje podział na train i test w proporcji 90:10, oraz przygotowanie funkcji oceniającej nasze wyniki. Wkładam do niej parametry takie jak:

  • proporcja inliers w train do wszystkich wierszy w train
  • proporcja inliers w test do wszystkich wierszy w test
  • proporcja outliers w nowych płytach do wszystkich utworów w nich. Ten parametr wydaje się najważniejszy — w końcu chcemy, żeby algorytm wykonał za nas jak najwięcej pracy. Im wyższy tym lepszy (prawdopodobnie).
  • Poniższe funkcje wydrukują kolejno — powyższe statystyki modelu, albumy o największej liczbie inliersów, utwory o największym pozytywnym prawdopodobieństwie:

Jeżeli chodzi o dobór algorytmów, to ogólnie problem ten nazywa się novelty detection i w przeciwieństwie do typowych metod klasyfikacji nadzorowanej kolumna y zawsze zawiera pozytywną informację. Dotyczy to wszystkich wierszy w ramce train i test, natomiast nasze X_out (płyty niewidziane przez algorytm) tej kolumny po prostu nie ma. Biblioteka Scikit-Learn posiada 3 algorytmy których możemy użyć, ale jak się okazało nie sprawdzają się zbyt dobrze. Głównym hyperparamatrem jest contamination, który informuje algorytm ile przypuszczalnie outliersów znajduje się w zbiorze train (od 0.0 do 1.0). Ten parametr trzeba określić arbitralnie. Ze zbioru Scikit najskuteczniejszy okazał się OneClassSVM, który przy contamination=0.1 odrzucał ok 30% ze zbioru X_out, przy contamination=0.2 odrzucał nawet 50%. Przy wzroście parametru powyżej 0.2 wzrost skuteczności zdecydowanie zmniejszał się. Należało znaleźć inna metodę. Okazuje się, że novelty detection można potraktować jako nienadzorowane outliers detection i tu z pomocą przychodzi pakiet PYOD.

Zadanie okazuje się banalnie proste:

Domyślnie ustawione mamy contamination na poziomie 0.1, a oto wynik:

I od razu wielki sukces:

  • błąd dla train i test w zasadzie identyczny.
  • Do przesłuchania wybrane 434 utwory, 9738 odrzuconych!
  • W czołówce co prawda albumy zawierające odpowiednio 42 i 32 utwory jednak są to albumy wg. algorytmu do przesłuchania w całości.
  • Jestem bardzo zadowolony, bo płyty wybrane przez algorytm są płytami które, patrząc na wykonawcę, wybrałbym do posłuchania w pierwszej kolejności.

Zmiana algorytmu na inny prowadzi do podobnych wyników, choć z reguły trochę gorszych i dziwniejszych. Poniżej wynik ze starego dobrego KNN który chyba uznał, że lubię oklaski w muzyce:

Trzeba pamiętać, że każdy z tych algorytmów pozwala na tuning hyperparametrów, zawsze też możemy operować contamination, aby lepiej dopasować wynik do naszych potrzeb.

Sprawdźmy jeszcze które utwory najbardziej mogą mi się podobać. Poniżej zestawienie wyników z kilku różnych algorytmów:

Czy będę co tydzień korzystał z tych algorytmów? Prawdopodobnie tak, jednak każdy z nich odrobinę inaczej dobiera wyniki i trzeba będzie wyciągnąć jakiś wspólny mianownik, dopasować hyperparametry (co w tym przypadku proste nie jest), być może głosowanie okaże się najskuteczniejsze.

PS Drodzy koledzy radiowcy, jako psycholog z zamiłowania, zachęcam do przesyłania listy ulubionych utworów, sprawdzimy co tam w środku siedzi;)

Grzegorz Zembrowski — Dziennikarz muzyczny radiowej Trójki, Specjalista ds. Infrastruktury medycznej, niedoszły inżynier materiałowy oraz poeta i aktor. Aktualnie skupiony głównie na projektach data science.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade