По умолчанию Spotify рекомендует одновременно 5 треков для создаваемого вами списка воспроизведения. Эта рекомендация в первую очередь выполняется путем обработки списка воспроизведения в целом, а также проверки сходства уникальных исполнителей / треков. При каждом обновлении вы получаете еще 5 рекомендаций по треку.

Для получения дополнительной информации о том, как Spotify рекомендует вам треки, вы можете посмотреть это видео здесь. Или вы можете посмотреть потрясающие слайды здесь и здесь.

В настоящее время пользователи получают различные рекомендации от Spotify. Рекомендации на основе треков и исполнителей могут быть вызваны из опций радио трека / исполнителя. Рекомендации по списку воспроизведения более сложны с точки зрения взаимосвязи между каждым исполнителем и дорожкой в ​​списке воспроизведения.

Теперь я расскажу вам, как я построил свой собственный способ создания списка воспроизведения наиболее подходящих треков для моих списков воспроизведения. Это также поможет вам создавать списки воспроизведения, похожие на уже существующие.

Для этого проекта я использовал Spotify web API, Spotipy library и некоторые алгоритмы машинного обучения из библиотек Scikit-Learn, все на Python 3. Вы можете проверить соответствующую записную книжку iPython в моем репозитории GitHub, если вы нравиться.

Итак, вот схема того, что делать (- это проще, чем может показаться!)

  • Создайте веб-приложение Spotify из Spotify for Developers и получите учетные данные приложения.

Вам необходимо сначала войти в систему и подключить Spotify Developer к своей учетной записи Spotify. На панели управления нажмите «Создать приложение». Появится такой экран;

Пока мы не заинтересованы в создании коммерческого приложения, просто выберите «Я не знаю», когда вас спросят, что вы создаете :) На последнем шаге вы должны согласиться с условиями, а затем ваше приложение. готов к использованию. Щелкните «Показать секрет клиента».

Скопируйте свой идентификатор клиента и секрет клиента, затем нажмите «Изменить настройки». Скопируйте адресную строку из браузера, вставьте ее в URI перенаправления, нажмите «ДОБАВИТЬ» и сохраните настройки.

Начать кодирование

  • Создайте записную книжку Jupyter или любую другую среду, в которой вы хотите запускать сценарии Python, и установите Spotipy;
!pip install Spotipy

Импортируйте библиотеку Spotipy - вы можете проверить документацию здесь. Авторизуйте токен в области, содержащей как минимум доступ playlist-modify-public (вы можете добавить больше в свою область действия. Доступные области см. Здесь).

Единственная информация, которую вам нужно предоставить в приведенном выше коде, - это ваш «Идентификатор клиента», «Секрет клиента» и «URI перенаправления», которые извлекаются с экрана вашего приложения.

  • После успешного получения авторизации Spotipy для использования веб-API Spotify вы можете начать «играть» со своими плейлистами Spotify.

Загрузите исходный плейлист как фрейм данных со звуковыми функциями, задав имена треков в качестве индексов. Вы привыкнете к тому, как Spotify хранит данные в плейлистах после множества экспериментов.

Вы можете получить свой sourcePlaylistID из последней части общедоступного URL-адреса вашего списка воспроизведения. Для этого примера я использовал мой публичный плейлист Bluest of Blues.

Один из важных шагов в приведенном выше коде - заставить его игнорировать локальные треки в исходном плейлисте, если таковые имеются. Можно добавить локальные треки в список воспроизведения с вашего локального компьютера, но эти треки не будут иметь идентификаторов треков или акустических функций, поэтому мы не сможем их использовать здесь.

Вы увидите, что есть некоторые функции, которые нам не понадобятся. Так что выбирайте только следующие;

playlist_df = playlist_df[["id", "acousticness", "danceability", "duration_ms", "energy", "instrumentalness",  "key", "liveness", "loudness", "mode", "speechiness", "tempo", "valence"]]
  • Оцените каждый трек в своем плейлисте с точки зрения его соответствия вашему плейлисту, чтобы наш проект превратился в задачу классификации на несколько классов. Добавьте этот рейтинг в качестве целевого столбца в фрейм данных исходного плейлиста. В моем примере я использовал рейтинг от 1 до 10;
playlist_df['ratings']=[10, 9, 9, 10, 8, 6, 8, 4, 3, 5, 7, 5, 5, 8, 8, 7, 8, 8, 10, 8, 10, 8, 4, 4, 4, 10, 10, 9, 8, 8, 4]

Создавая плейлист, вы можете почувствовать, что некоторые песни являются «характерными» для вашего плейлиста, поставив им самую высокую оценку. Некоторые могут остаться там просто ради гармонии, поэтому оставьте их по более низким ценам. Этот процесс оценки вручную может быть изменен в зависимости от вашего поведения при создании списка воспроизведения. Если вы склонны добавлять песни в зависимости от их соответствия вашему плейлисту (в первую очередь наиболее релевантные и т. Д.), Вы можете выставлять автоматические рейтинги в зависимости от порядка песен в вашем плейлисте.

  • С этого момента фрейм данных исходного плейлиста будет вашим обучающим набором.
X_train = playlist_df.drop(['id', 'ratings'], axis=1)
y_train = playlist_df['ratings']

Да, этот набор данных слишком мал для построения на нем модели машинного обучения! Вероятно, вы получите лучшие результаты, если у вас есть плейлист большего размера. Но не волнуйтесь, функция рекомендаций Spotipy позаботится о точных рекомендациях. Вы просто пытаетесь получить лучшие из них в соответствии с вашими оценками, используя вашу модель лучше, чем наихудшую для вашего набора тренировок. Так что не ожидайте высоких оценок перекрестной проверки.

Немного машинного обучения

Теперь мы попробуем некоторые алгоритмы машинного обучения на нашем обучающем наборе (фрейм данных исходного плейлиста). Я не буду вдаваться в подробности для каждого алгоритма здесь, поскольку это выходит за рамки этой истории, но для тех из вас, кто знаком с этими алгоритмами, будет интересно увидеть, как они работают для ваших плейлистов;)

Сначала я применяю PCA (анализ главных компонентов), чтобы немного уменьшить размерность. Вы также можете предпочесть применить t-SNE на этом этапе.

Я остановился на 8 компонентах, которые объяснили общую дисперсию 95%. Подгоните свой набор данных к PCA с оптимальным количеством компонентов для вашего случая.

# Fit your dataset to the optimal pca
pca = decomposition.PCA(n_components=8)
X_pca = pca.fit_transform(X_scaled)

Теперь при желании примените tf-idf vectorizer к названиям ваших треков. На самом деле, это необязательно, потому что Spotify уже сделает это для ваших треков с более продвинутыми методами, такими как Word2Vec и Annoy за кулисами, когда мы вызываем функцию рекомендации треков Spotipy.

from sklearn.feature_extraction.text import TfidfVectorizer

v = TfidfVectorizer(sublinear_tf=True, ngram_range=(1, 6), max_features=10000)
X_names_sparse = v.fit_transform(track_names)
X_names_sparse.shape

Теперь объедините два в один последний обучающий набор;

from scipy.sparse import csr_matrix, hstack

X_train_last = csr_matrix(hstack([X_pca, X_names_sparse]))

Инициализировать стратифицированную 5-кратную структуру для перекрестной проверки;

from sklearn.model_selection import StratifiedKFold, GridSearchCV

skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)

Давайте сначала обучим классификатор k-соседей и сохраним лучшие параметры после поиска по сетке через перекрестную проверку;

# kNN first
from sklearn.neighbors import KNeighborsClassifier

knn_params = {'n_neighbors': range(1, 10)}
knn = KNeighborsClassifier(n_jobs=-1)

knn_grid = GridSearchCV(knn, knn_params, cv=skf, n_jobs=-1, verbose=True)
knn_grid.fit(X_train_last, y_train)
knn_grid.best_params_, knn_grid.best_score_

Это дало 0,290 балла - хуже, чем мы могли ожидать :) Мы постараемся немного улучшить этот результат.

Далее попробуем Случайные леса;

# Random Forests second

parameters = {'max_features': [4, 7, 8, 10], 'min_samples_leaf': [1, 3, 5, 8], 'max_depth': [3, 5, 8]}
rfc = RandomForestClassifier(n_estimators=100, random_state=42, 
                             n_jobs=-1, oob_score=True)
forest_grid = GridSearchCV(rfc, parameters, n_jobs=-1, cv=skf, verbose=1)
forest_grid.fit(X_train_last, y_train)
forest_grid.best_estimator_, forest_grid.best_score_

Это дало 0,322 балла.

Наконец, давайте обучим классификатор дерева решений;

# Decision Trees third
from sklearn.tree import DecisionTreeClassifier

tree = DecisionTreeClassifier()

tree_params = {'max_depth': range(1,11), 'max_features': range(4,19)}

tree_grid = GridSearchCV(tree, tree_params, cv=skf, n_jobs=-1, verbose=True)

tree_grid.fit(X_train_last, y_train)
tree_grid.best_estimator_, tree_grid.best_score_

Это дало 0,452 балла за лучший оценщик. Лучшее из худших :)

Сборка набора тестов

Если вы зашли так далеко, молодец! Итак, позвольте нам теперь насладиться рекомендациями Spotipy.

  • Для тестового набора мы сначала получим ряд рекомендаций для каждого трека в нашем тренировочном наборе с помощью функции рекомендаций Spotipy. Установите ограничение на количество рекомендаций, которое вам нравится. Я предпочел рекомендовать (длина исходного плейлиста) / 2 трека на трек. Таким образом, в нашем тестовом наборе у нас есть фрейм данных не более ² / 2 треков (длина исходного плейлиста).

Сохраняйте только те же функции;

rec_playlist_df = rec_playlist_df[["acousticness", "danceability", "duration_ms", "energy", "instrumentalness",  "key", "liveness", "loudness", "mode", "speechiness", "tempo", "valence"]]
  • Делайте прогнозы с помощью своей лучшей модели
# Make predictions
tree_grid.best_estimator_.fit(X_train_last, y_train)
rec_playlist_df_scaled = StandardScaler().fit_transform(rec_playlist_df)
X_test_pca = pca.transform(rec_playlist_df_scaled)
X_test_names = v.transform(rec_track_names)
X_test_last = csr_matrix(hstack([X_test_pca, X_test_names]))
y_pred_class = tree_grid.best_estimator_.predict(X_test_last)
  • Получите треки с наивысшими рейтингами, чтобы добавить их в новый плейлист. (Вы также можете добавить их в исходный плейлист и продолжить с первого шага бесконечно много раз: D)
rec_playlist_df['ratings']=y_pred_class
rec_playlist_df = rec_playlist_df.sort_values('ratings', ascending = False)
rec_playlist_df = rec_playlist_df.reset_index()

# Pick the top ranking tracks to add your new playlist; 9 or 10 will work
recs_to_add = rec_playlist_df[rec_playlist_df['ratings']>=9]['index'].values.tolist()

Создайте новый пустой список воспроизведения, чтобы добавить эти треки;

# Create a new playlist for tracks to add
playlist_recs = sp.user_playlist_create(username, 
                                        name='PCA + tf-idf + DT - Recommended Songs for Playlist - {}'.format(sourcePlaylist['name']))

В моем примере будет создан новый список воспроизведения с именем «PCA + tf-idf + DT -Recommended Songs for Playlist -Bluest of Blues». При добавлении песен в список воспроизведения API позволяет добавлять не более 100 треков за один раз, поэтому вам может потребоваться изменить форму массива recs_to_add, если в нем более 100 треков.

# Add tracks to the new playlist
sp.user_playlist_add_tracks(username, playlist_recs['id'], recs_to_add);

Вот и все! У вас есть новый список воспроизведения, который включает лучшие рекомендации относительно оценок ваших песен для треков в исходном списке воспроизведения.

Итак, это мой собственный способ получить более релевантные рекомендации для моего плейлиста в качестве нового плейлиста. Не стесняйтесь задавать вопросы и комментировать.

В качестве примечания по созданию автоматических списков воспроизведения существует приложение с красивым пользовательским интерфейсом для создания более умных списков воспроизведения, принадлежащее автору библиотеки Spotipy. Вы можете проверить это здесь.

Если вам понравился мой рассказ, вы можете хлопать столько раз, сколько сможете, или подписывайтесь на меня в моем репозитории на GitHub - там вы найдете больше примеров :)

Вот мои аккаунты LinkedIn и Twitter, если хотите, свяжитесь с нами!

Счастливого спотипинга!