”Spotify Radio е функция, която създава плейлист въз основа на която и да е песен, албум, плейлист или изпълнител, които изберете. Плейлистът също се актуализира извънредно, за да бъде свеж. Представете си, че не сте наистина сигурни какво конкретно да слушате в момента, но знаете в какво настроение сте. Просто изберете, да речем, песен, която представя това настроение най-добре и стартирайте радиото оттам!“

Това определение за радио Spotify идва от блога на общността на Spotify и обобщава концепцията доста добре. Идеята тук е да се намери начин да се генерира цял плейлист от една песен и от спомагателни данни, които можем да намерим навсякъде другаде.

Нека рамкираме този проблем.

Проблем

Spotify има 82 милиона песни и 365 милиона потребители.

Тъй като искаме да изградим радио и потребителят ще слуша куп песни от него (може би на случаен принцип), подреждането не е от решаващо значение. В този случай един добър начин за препоръчване на съдържание е да се предвиди вероятността за ангажиране с потребителите. За това можем да разглеждаме това като проблем с двоична класификация и да формулираме проблема, както следва.

При даден потребител, песен и контекст (време, местоположение и сезон), предвидете вероятността за ангажиране за всяка песен и подредете песните, като използвате този резултат.

Обща архитектура:

По отношение на архитектурата, най-добрият вариант за нас е да използваме подход на фуния. Изпълнението на сложен алгоритъм за класиране над 82 милиона песни не би било достатъчно ефективно във времето. Така трябва да изпълним по-малко сложен алгоритъм, за да отхвърлим неуместните елементи от списъка с песни. Нека настроим много прост алгоритъм за намиране на песни, които изглеждат близки до текущата песен (т.е. песента от който искаме да направим плейлиста).

Разбира се, ще ни е необходим алгоритъм за класиране, за да изберем най-подходящите песни за нашата продукция. Този компонент ще бъде много по-сложен от първия и ще използва много повече функции, за да осигури персонализиране. Ще обсъдим тази стъпка в дълбочина по-късно.

Добавянето на стъпка за филтриране може да е интересно. Не искаме да показваме плейлист, съставен само от един изпълнител или един албум, например. Добавянето на разнообразие към нашите резултати може да бъде интересно за бизнеса, тъй като може да увеличи откритията за потребителите, което всъщност очакваме от Spotify Radio. Или може би не, вижте частта за AB тестване за това.

Вече установихме, че ще ни трябва компонент за избор на потенциални препоръки, като компонент за класиране и компонент за филтриране. Ще трябва да помислим за друг компонент, за да генерираме етикети от нашите живи данни. Този компонент ще захранва както нашите модели за класиране, така и модели за предварителен подбор.

Модел за генериране на кандидат

За тази стъпка искаме да отхвърлим неподходящите песни от нашето търсене. В обикновена система за препоръки, ние просто бихме обучили базирана на дърво система или логистична регресия, за да предвидим вероятност за ангажиране и да запазим най-високо класираните песни (топ 500 или така). Тук трябва да покажем песни, които по някакъв начин са близки до първоначалната песен (тази, от която изграждаме радиото).

Вместо да обучаваме контролиран модел, ще използваме KNN модел.

Инженеринг на функции:

Ако искаме да изчислим най-близките съседи на писта, чудесно е да можем лесно да изчислим разстоянието между тази писта и останалите. Това разстояние може да бъде изчислено в различни векторни пространства и можем да получим проекция на нашата песен в различни векторни пространства, използвайки вграждания.

За този прост модел нека просто се съсредоточим върху самата песен и някои метаданни.

Относно самата песен, използването на дълбока невронна мрежаможе да е начинът за генериране на вграждания. Разбира се, всички вграждания на песни ще бъдат предварително генерирани (не забравяйте, че поддържаме тази стъпка проста).

Забележка: Песента няма да се промени, генерирането й веднъж е добре. Все още можем да актуализираме вгражданията от време на време, тъй като нови данни ще бъдат добавени към нашия каталог с песни

Един удивителен начин за генериране на вграждания от метаданните е чрез графики. По-специално, графиките на свойствата ще се представят много добре тук. Ето пример за много опростена графика, свързана с песните на Spotify. (Съжалявам за липсващите ръбове).

Чудесен подход за използване на тези свързани данни е вграждането на възлите с алгоритми като Node2Vec или GraphSAGE. Идеята е съвсем същата като Word2vec, но тук характеристиките на контекста се генерират от произволни разходки в графиката от началния възел (т.е. нашата следа).

Още веднъж, тези вграждания трябва да се изчисляват предварително редовно (с AirFlow например). Искаме само да изчислим проста KNN в производствената среда.

Модел за класиране

Нашият използван преди това модел силно намали набора от кандидати за нашето радио. Това е страхотно, защото означава, че можем да използваме по-сложни модели, тъй като ще трябва да го изпълняваме с по-малко данни. Тук искаме да предвидим вероятността за ангажиране. За това можем да използваме логистична регресия, дърво-базирано решение или дълбока невронна мрежа.

Добър начин да продължите е да изпробвате списък с модели и да запазите най-добрите. Може да искате да ги подредите след това или да запазите само един от тях.

За този проблем бих избрал някои подсилени дървовидни модели (XGBoost, lightgbm, Catboost), логистичен регресионен модел и DNN.

Инженеринг на функции:

Тук ще можем да използваме всички данни на нашия потребител (при условие, че той е влязъл, в противен случай можем да направим друг модел, който би бил агностик на потребителските данни), много допълнителни оскъдни данни, кръстосано генерирани данни, потребителско проследяване генерирани данни и разбира се контекстни данни. Има безкрайност от допълнителни функции, които можем да добавим. Не се колебайте да коментирате всякакви допълнителни идеи (така че алгоритъмът за класиране на Medium поставя моята статия по-високо 👊).

Потребителски функции:

Това са функции, свързани директно с потребителя. Статистически, хората на определени възрасти и определен пол може да са по-склонни да слушат конкретни песни. Те могат да предизвикат пристрастия в нашия алгоритъм, така че трябва да внимаваме с тях.

Потребител за проследяване на функции:

Това са характеристиките, които свързват потребителя с входната песен. Те са тук главно, за да изчислят приликата между слушателските навици на потребителя и входната песен.

Характеристики на проследяване:

Тук можем да използваме повторно изчислените преди това вграждания, които обсъдихме преди. Можем също изрично да зададем жанра, някои тагове и свързаните с тенденциите функции на песента. Може да се добави и преди колко време излезе песента например. Ще използваме същите функции за началната песен

Функции за проследяване:

Тук можем да изясним всички подобни характеристики, които можем да си представим. Идеята е да имате ясна представа колко далеч е входната писта от началната писта.

Характеристики на контекста:

Аз лично наистина харесвам поп-пънк музиката, когато дойде лятото. Бих се интересувал и от кънтри музика, ако бях на пътешествие в САЩ. Е, затова контекстните функции са тук. За да даде контекст на модела, той може да препоръча точните песни в точния момент.

Това биха били входните характеристики на нашия модел за класиране. Сега трябва да можем да генерираме етикетите за тези точки от данни. Това е, което ще разгледаме в следващата точка.

Генериране на данни

Изрична обратна връзка:

Изричната обратна връзка съответства на обратната връзка, предоставена директно от потребителя.

Можем да визуализираме ангажираността със съдържанието като двоичен вектор, където 1 съответства на песен, с която потребителят се е ангажирал. Ангажимент тук може да бъде харесване на песен или добавяне на песен към плейлист.

Можем също да дефинираме един вектор за харесванията и един вектор за допълненията към плейлистите. Това би позволило на бизнеса да придаде по-голямо значение на определен вид взаимодействие. Да кажем, че бизнесът иска песните да се разпространяват лесно, тогава ние ще искаме ангажираността да бъде по-фокусирана върху хората, които добавят песните към своите плейлисти, така че техните роднини също да слушат тези песни.

По отношение на данните, ще бъде предизвикателство да се определи ангажираността на потребител с песен, тъй като през повечето време потребителите просто ще слушат песента, а не ще се ангажират с нея. Същият проблем може да възникне, когато се опитвате да препоръчате съдържание като филми. Ето защо ще се съсредоточим и върху имплицитната обратна връзка

Използване на имплицитна обратна връзка:

Неявната обратна връзка се извлича директно от взаимодействията на потребителя с платформата. Тук можем да изчислим резултат според нормализираното време за слушане на песен. Добавянето на този нов вид обратна връзка ще ни позволи да съберем много повече данни и да се справим с проблема с MNAR (потребителят най-вече взаимодейства с неща, които харесва, и променя набора от данни). В този обхват трябва да изберем произволни стойности за времето за слушане за валидиране и анулиране на песен. Ето пример за комбиниране на явна и скрита обратна връзка за генериране на етикети.

Забележка: Също така е по-добре да не вземаме под внимание нито една игнорирана песен, която всъщност не е била видяна от потребителя, ще считаме, че дадена песен е била игнорирана, ако потребителят я е пропуснал, докато е трябвало да бъде следващата един. По същия начин ще считаме за положителна обратна връзка потребител, който щракне върху песен преди времето й.

Разбира се, не забравяйте да балансирате своя набор от данни (от гледна точка на етикети) и да разделите наборите от влак, стойност и тестове по стратифициран начин, така че да не тествате в период, който алгоритъмът никога не е виждал .

Показатели

Досега имаме архитектура, набор от компоненти за препоръчване на песни и ефективна система за генериране на етикети за тяхното обучение. Сега как можем да потвърдим качеството на нашата система? Трябва да дефинираме набор от показатели, за да оценим независимо нашите компоненти, но също и да оценим цялата система.

Офлайн показатели:

Нашите офлайн показатели ще бъдат доста ясни.

За нашия KNN модел RMSE може да бъде правилният начин. Ще го наблюдаваме, за да проверим дали текущата ни писта е много далеч от нещо друго или не. Това ще ни даде представа за това как една следа е свързана с други следи в нашия набор от данни. Друг важен показател за този компонент ще бъде Recall. Не искаме да пропуснем нито един възможен кандидат, който може да е подходящ за плейлиста, който изграждаме.

За нашия класатор ще извършим двоична класификация. Искаме да имаме възможно най-малко лоши съвпадения и колкото е възможно повече добри съвпадения. F-резултатът изглежда като добър тип показател тук. Ние ще искаме да претеглим прецизността и припомнянето в израза му, за да отговаря възможно най-много на нуждите на бизнеса.

Онлайн показатели:

Както бе споменато по-горе, потребителят не се ангажира толкова изрично със съдържание на стрийминг платформи. Трябва да намерим по-добър начин да разберем дали потребителят оценява съдържанието, което предлагаме. В противен случай можем да измерим имплицитната ангажираност, която сме дефинирали преди, или да добавим някои други показатели като средно време на сесия (колко време прекарва потребителят на нашата платформа по време на една сесия).

Филтриране:

Тук бихме могли да дефинираме индекс за излишък, пряко свързан с нашия алгоритъм за филтриране, което би позволило ограничаване на цялостното излишък на плейлист. Това излишък може да бъде изчислено чрез близостта между вгражданията на възлите на графиката, която изградихме преди. Или просто като преброите общите възли между две песни, има много начини да го направите.

Ако си спомняте добре, когато говорихме за филтриращия компонент, споменахме, че добавянето на разнообразие към нашите резултати е това, което клиентите очакват от Spotify Radio. Но кои сме ние, за да казваме какво наистина искат клиентите? Поведението на клиентите не е лесно за предвиждане, а още по-малко за предвиждане. При този сценарий A/B тестването изглежда като нещо, което наистина искаме да направим.

Тук ще внедрим различни версии на алгоритъма в подмножества от сървъри, които ще работят за хомогенни проби от потребители и ще наблюдаваме нашите онлайн показатели, за да изберем най-подходящия.

Ако искате да научите повече за A/B тестването, мога само да ви насърча да разгледате тази статия от Netflix Tech Blog в Medium.

Заключение и следващи стъпки:

Създадохме конвейер, който би паснал доста добре на двигател за препоръки, базиран на подобни песни. Не сме обсъждали много от точките на дизайна. Някои други точки биха били обсъждането на опциите за база данни, опциите за внедряване и много други инфраструктурни въпроси. Ако искате конкретна публикация за внедряването на този вид тръбопровод, просто ме уведомете в коментарите 😄