Введение

Spotify, одна из самых известных платформ для потоковой передачи музыки, является моим самым часто используемым приложением в повседневной жизни. Будучи меломаном, я создал более десяти плейлистов в таких жанрах, как поп-музыка, хип-хоп, рок и джаз. Тем не менее, я всегда оказывался со своим плейлистом на мандаринском языке, когда мне больше всего нужна была музыка. Однажды я случайно наткнулся на документы Spotify Web API и был очарован функциями звука, которые отслеживает Spotify. На следующем изображении показан ответ аудиофункций при вызове Get /audio-features.

Подробнее о каждом параметре см. Справочник по API.

Мое внимание привлек еще один параметр — популярность.

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

Прежде чем начать этот эксперимент, я просмотрела Интернет, чтобы узнать, выполнял ли кто-нибудь еще подобное упражнение. Есть и другие эксперименты по предсказанию популярности песни по звуковым характеристикам, например, эта статья. Набор данных, использованный в этой статье, был взят из Kaggle. Тем не менее, я хотел бы сосредоточиться на песнях на китайском языке, а у Kaggle нет набора данных о популярности песен на китайском языке. Поэтому я извлек набор данных Spotify вручную из веб-API Spotify.

Извлечение/исследование данных

В качестве набора данных я собрал 3000 атрибутов песен в жанре «мандо-поп» с 2019 по 2022 год. Сначала я получаю токен Bearer из консоли Spotify Web API для целей аутентификации.

auth_token = "BQAbNoApNP48x6r_2G5qfAUFXzgEUIqpUxhYZx7WpETfpg77wXdzpxgkXYdQaIx9MqmnfKzGq3o0Om3O4F2JwBRORPJK-GwxbswcKg66Wf-7x5blrDWKy8CUmC-_eDZ4BjQTFZDV2Z9W1rsNbj1zlmK179d8SyuyXzkyAMFP96n3J2Nc"
headers = {
    'Authorization': 'Bearer {token}'.format(token=auth_token)
}

Затем я создал список из 3000 идентификаторов песен, по 1000 в год, с помощью веб-API Spotify. Затем я извлекаю атрибуты песен из этого списка с помощью Spotify Web API.

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

Для данных информация о песне, которые я извлек:

  • Идентификатор песни (идентификатор дорожки в Spotify) Название дорожки (название дорожки)
  • ID основного исполнителя (ID основного исполнителя Spotify)
  • Имя исполнителя (имя главного исполнителя)
  • Название альбома (Альбом, в котором появляется трек)

Для данных атрибутов песни, которые я извлек:

  • Популярность трека (популярность трека. Значение будет от 0 до 100, где 100 — самый популярный)
  • танцевальность (значение 0,0 соответствует наименее танцевальной способности, а 1,0 — наиболее танцевальной)
  • энергия (Энергия представляет собой меру от 0,0 до 1,0 и представляет перцептивную меру интенсивности и активности)
  • ключ (тональность, в которой находится дорожка. Целые числа сопоставляются с высотой звука с использованием стандартной нотации класса высоты тона. Например, 0 = C, 1 = C♯/D♭, 2 = D и т. д. Если тональность не обнаружена, значение равно - 1)
  • громкость (общая громкость дорожки в децибелах (дБ). Обычно значения находятся в диапазоне от -60 до 0 дБ)
  • режим (режим указывает модальность (основной или второстепенный) дорожки. мажор представлен 1, а минор - 0)
  • Речевость (Речь определяет присутствие произнесенных слов в дорожке. 1.0 — наиболее речеподобный, 0.0 — наиболее неречевой)
  • акустика (1,0 означает высокую степень уверенности в том, что трек является акустическим, а 0,0 означает высокую уверенность в том, что трек не является акустическим)
  • инструментальность (предсказывает, не содержит ли трек вокала. 1.0 означает, что трек не содержит вокала)
  • Живость (Обнаруживает присутствие аудитории в записи. Более высокие значения живости представляют собой повышенную вероятность того, что трек был исполнен вживую)
  • валентность (показатель от 0,0 до 1,0, описывающий музыкальную позитивность, передаваемую треком. Треки с высокой валентностью звучат более позитивно (например, счастливый, веселый, эйфорический), а треки с низкой валентностью звучат более негативно (например, грустный, подавленный, злой))
  • темп (общий предполагаемый темп трека в ударах в минуту (BPM))
  • duration_ms (длительность трека в миллисекундах)
  • time_signature (Предполагаемый тактовый размер. Размер варьируется от 3 до 7, что указывает размер от «3/4» до «7/4»)

Как я упоминал ранее, мы сосредоточены только на том, как атрибуты песни (сгенерированные алгоритмом Spotify) взаимодействуют с ее популярностью. Поэтому информация о песне для этого проекта будет удалена.

df = df.drop(columns=['track_id','track_name','artist_id','artist_name','album'])

Хотя все остальные столбцы являются числовыми значениями, некоторые из них являются непрерывными переменными, такими как энергия, которая представляет собой меру от 0,0 до 1,0 и представляет перцептивную меру интенсивности и активности. Некоторые из них представляют собой дискретные переменные, такие как клавиши, с целыми числами, сопоставленными с высотой тона с использованием стандартной нотации класса высоты тона. Есть одна категориальная переменная — mode. Для этого проекта я решил использовать регрессионные модели. Другими словами, непрерывные и дискретные переменные не нуждаются в дополнительной предварительной обработке. Для mode,который содержит только 0 и 1, его не нужно фиктивировать.

Я использовал StandardScaler, чтобы удалить среднее значение и масштабировать каждую переменную до единичной дисперсии для track_popularity, key и mode из-за их значительной дисперсии.

need_scale_df = df.drop(columns=['track_popularity', 'key', 'mode'])
scale = StandardScaler()
df_scaled = pd.DataFrame(scale.fit_transform(need_scale_df),
                                columns=need_scale_df.keys())

Давайте проведем небольшое исследование данных! Сначала я нарисовал и описал распределение нашего значения Y — track_popularity.

sns.displot(data=final_data['track_popularity'],  kind='kde',
            palette='cool', height=5, aspect=1.4).set(title='Track Popularity Distribution')

Распределение пика track_popularity составляет около 20 и смещено вправо. Другими словами, набор данных несбалансирован.

final_data['track_popularity'].describe()

Затем я построил тепловую карту корреляций между переменными.

plt.figure(figsize=(20, 10))
sns.heatmap(final_data.corr(),annot = True)

На этой тепловой карте мы не видим каких-либо четких указаний на сильную корреляцию между track_popularity и другими переменными. Давайте лучше посмотрим на значение корреляции каждой переменной с помощью track_popularity.

abs(final_data.corr()['track_popularity']).sort_values()

Я решил отбросить переменные со значением абсолютной корреляции ниже 0,05, чтобы убрать шум и повысить точность моделей.

Теперь, когда исследование данных и разработка признаков завершены, я продолжу обучение моделированию в Части 2.

Вот блокнот Python для этого проекта.