Что, если бы был способ заставить ваш компьютер сказать, хотите ли вы песню или нет, основываясь на конкретных особенностях этой песни? Большинство приложений для потоковой передачи музыки используют алгоритмы, которые рекомендуют песни на основе исполнителя и жанра, но что, если бы мы могли рекомендовать песню на основе ее сложных атрибутов, таких как темп или «танцевальность» песни? Просто может случиться так, что песни, подобранные с точностью, будут более привлекательными для конкретных вкусов слушателя.

Здесь я исследую различные алгоритмы машинного обучения в наборе данных Kaggle «Атрибуты песни Spotify» и пытаюсь сформировать модель, которая может решить, нужна ли песня пользователю.



Этот набор данных содержит 2017 различных песен, каждая из которых имеет связанные атрибуты и ярлык. Атрибуты песни включают в себя такие функции, как «энергия», «громкость» и «валентность», которые используются в приведенных ниже алгоритмах для классификации. Каждая песня имеет класс «1» (что означает, что песня понравилась пользователю) или «0» (что означает, что она не понравилась пользователю). Наша цель — иметь возможность предсказать, нравится или не нравится пользователю песня, основываясь на ее атрибутах. Я тестирую четыре разных алгоритма, приведенных ниже: k-ближайших соседей, логистическую регрессию, лассо-регрессию и повышение градиента — и сравниваю их результаты на тестовых данных.

Обучающие данные определяются как имеющие векторы признаков x1, x2, …, xN ∈ R13 и соответствующие целевые значения y1, y2, …, yN ∈ {0, 1}. Чтобы подготовить данные, я удалил столбцы «название песни», «исполнитель» и идентификатор, нормализовал оставшиеся данные и преобразовал их в массив. Я разделил данные на 80% обучающий набор и 20% проверочный набор для тестирования. В каждом приведенном ниже методе я проверяю свои прогнозы с нуля, разделив количество правильных прогнозов на общее количество прогнозов.

Первый используемый алгоритм классификации — K ближайших соседей. K-ближайшие соседи — это алгоритм классификации и регрессии, используемый для прогнозирования целевого значения тестового наблюдения простым и интуитивно понятным способом. Алгоритм работает, беря тестовое наблюдение x0 и определяя K точек в обучающих данных, которые наиболее близки к x0. В задаче регрессии среднее значение y этих K точек становится предсказанным значением x0. В задаче классификации значения y K ближайших соседей получают голосование, так что x0 относится к классу с наибольшим количеством голосов.

Здесь я реализую K-ближайших соседей с нуля, используя K = 10. Алгоритм начинает с последовательного просмотра тестовых данных песни, затем он вычисляет евклидово расстояние между этим тестовым примером и каждой песней в обучающих данных, затем сортирует эти расстояния от наименьшего к наибольшему с точки зрения их индекса в данных обучения, и, наконец, первые 10 голосуют, чтобы решить, к какому классу принадлежит тестовый пример. Прогнозы для всех текстовых примеров хранятся в списке.

Алгоритм дал показатель точности 69,8 %, что не так уж и плохо, но этот показатель, безусловно, можно было бы улучшить по крайней мере с помощью одного из приведенных ниже алгоритмов. После тестирования нескольких значений K лучшим оказалось значение 10; все, что выше или ниже, приводит к более низкому баллу.

Второй используемый алгоритм классификации — это бинарная логистическая регрессия со стохастическим градиентным спуском. В логистической регрессии мы моделируем взаимосвязь между двумя качественными переменными, используя логистическую модель для выполнения классификации между двумя классами (0 и 1). Мы определяем:

где x^i — расширенный вектор признаков. В отличие от K ближайших соседей, логистическая модель выводит вероятность того, что тестовый пример принадлежит классу 1. Для вектора признаков xi мы называем его прогнозируемой вероятностью f(xi) и определить его как:

σ(u) — наша логистическая функция, используемая для преобразования скаляра в вероятность. Мы надеемся, что f(xi) согласуется с истинной вероятностью yi для i = 1, 2,…, N. Для этого мы должны найти β, для которого

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

В этом случае мы минимизируем L(β), используя стохастический градиентный спуск, который постепенно перемещает β в направлении наискорейшего спуска (направление, противоположное градиенту L(β)). Стохастический градиентный спуск начинается с инициализации значения для β, называемого β0 . Затем для каждого прохода по обучающему набору данных или эпохе мы случайным образом выбираем i и обновляем β следующим образом:

для t = 1, 2, 3,… вплоть до того количества эпох, которое мы хотели бы выполнить. Здесь α — наша скорость обучения, а градиент Li(β) — это просто градиент l(yi,f(xi)) . Использование ∇Li(β) вместо ∇L(β) снижает нагрузку на наш алгоритм по сравнению с обычным градиентным спуском и привносит в модель случайность. Это помогает предотвратить переоснащение, поскольку оно ограничивает способность модели слишком близко следовать за шумом в наших обучающих данных.

Когда мы достигли нашего окончательного значения β, теперь мы можем классифицировать наши тестовые данные следующим образом: для каждого тестового примера xi, если наша прогнозируемая вероятность f(xi) ≥ 12, то мы классифицируем его как класс 1, в противном случае мы классифицируем xi как класс 0.

В коде я использую реализацию scikit-learn для логистической регрессии с использованием как нормального, так и стохастического градиентного спуска, а также свою собственную реализацию с нуля. β инициализируется нулями, альфа — 0,001, и число эпох должно быть 150. Код также вычисляет функцию стоимости на каждой итерации и отображает полученные значения. Чтобы сравнить различия в точности по количеству эпох, я тестирую алгоритм, используя от 50 до 500 эпох, и строю график зависимости каждой оценки точности от количества итераций.

В моем сравнении точности с количеством итераций SGD вы можете видеть, как большее количество итераций приводит к снижению точности на рисунке 1 ниже. Снижение точности является признаком переобучения — с большим количеством итераций наша модель была более склонна к следующим ошибкам, таким образом создавая подгонку только для обучающих данных, а не для тестовых данных. Чтобы обуздать это, модель останавливается после 150 итераций, так как это, по-видимому, и точка сходимости на рисунке 2, и точка высокой точности на рисунке 1.

Неожиданно ни реализация scikit-learn, ни моя собственная не превзошли показатель K-ближайших соседей. Моя реализация SGD также получила более высокий балл, чем реализация scikit-learn (😊). Обычный алгоритм логистической регрессии Sci-kitlearn дал точность 53,8 %, их алгоритм SGD — точность 51,2 %, а мой — точность 58,5 %.

В этом разделе мы представляем метод сокращения под названием Lasso, который прикрепляет член регуляризации или штраф к исходной модели логистической регрессии, чтобы еще больше уменьшить переоснащение. Раньше мы выбирали β с целью минимизировать L(β). Теперь мы выберем β, чтобы минимизировать L(β) + λβ1. Этот второй член называется l1-членом регуляризации R(β) и представляет количество ненулевых коэффициентов β. Мы хотим, чтобы это число было небольшим, чтобы у нас было очень мало ненулевых коэффициентов β, чтобы обеспечить разреженность, и позволить модели сосредоточиться на функциях, которые действительно полезны для выполнения точных прогнозов. естественным образом уменьшает переоснащение.

Однако добавление R(β) требует новой процедуры минимизации, поскольку член не дифференцируем. Градиентный спуск здесь не сработает, поэтому обратимся к методу проксимального градиента. В этом методе мы инициализируем β, как и раньше, но обновляем бета-версию следующим образом:

для t = 0, 1, 2, …, где проксимальный оператор нормы l1 определяется как

Функция clip обрезает β^ до αλ, если оно выходит за пределы диапазона |αλ|.
В противном случае β остается без изменений. Как и при градиентном спуске, β постоянно обновляется до тех пор, пока приведенное выше уравнение не сойдется к минимуму.

Я реализую алгоритм с нуля, установив λ = 20, α = 0,0001 и количество итераций до 60. На каждой итерации β составляет обновляется, как описано выше, а значения функции стоимости L(β) на каждой итерации рассчитываются и сохраняются в списке для последующего построения графика.

Точность улучшается до 67,3% после выполнения лассо, но это ненамного. На рисунке 3 ниже показано, как L(β) сходится примерно после 30 итераций, но на всякий случай я позволил алгоритму пройти 60 итераций. На рисунке 4 видно, что около 7 коэффициентов β имеют значения, почти равные 0, что демонстрирует его разреженность. β можно сделать более разреженным, увеличив λ, но слишком большое значение λ может привести к недостаточной подгонке модели и, следовательно, к снижению точности. . Однако мы можем видеть, что модель считает танцевальность, продолжительность, энергию, тональность, режим, темп и валентность песни наиболее важными характеристиками для классификации того, нравится она человеку или нет.

Последняя модель, которую мы используем, называется повышение градиента. Повышение градиента — это метод регрессии и классификации, который принимает форму ансамбля деревьев решений. Дерево решений само по себе является моделью прогнозирования, которая принимает входную переменную, делает наблюдения над ней (представленные ветвями) и делает вывод о ее целевом значении (представленном листьями) в структуре, подобной блок-схеме. Ансамбль деревьев решений представляет собой просто комбинацию всех этих моделей, так что конечное целевое значение входной переменной представляет собой среднее значение ее целевого значения в каждом дереве. Дерево решений представлено как T(xi), где xi — входная переменная.

Повышение градиента для бинарной классификации начинается с определения обучающего набора, состоящего из векторов признаков x1, x2, …, xN ∈ R13 и целевых значений y1, y2, …, yN ∈ {0,1}. . Наше прогнозируемое целевое значение для наблюдения равно

где Tj — дерево регрессии. Как и в случае с логистической регрессией, наша цель — выбрать Tm(xi), который минимизирует функцию потерь.

Далее это можно переписать, используя приближение Ньютона:

Если установить невязку ri = α(yi − σ(fm−1(xi))), можно заметить, что алгоритм просто находит Tm путем подгонки регрессии дерева к остаткам ri.

Для простоты я использую алгоритм повышения градиента для классификации, предоставленный XGBoost. XGBoost включает в свои вычисления член регуляризации для контроля переобучения и, как известно, превосходит машину повышения градиента как по скорости, так и по точности. После тестирования нескольких скоростей обучения и нескольких значений для n_estimators (количество деревьев в модели) скорость обучения 0,01 и n_estimators 1500 работали лучше всего.

XGBoost оказался лучшим алгоритмом для этого примера, что неудивительно, поскольку он известен как особенно отличный алгоритм классификации и регрессии. Самый высокий показатель точности для этой модели на данный момент составляет 80,4%.

В целом, если бы мне нужно было ранжировать алгоритмы, которые лучше всего предсказывают музыкальные предпочтения человека в этом наборе данных, это было бы:

(1) Повышение градиента:80,4%
(2) K-ближайшие соседи:
69,8%
(3) Логистическая регрессия с лассо :
67,3%
(4) Моя логистическая регрессия с SGD:
58,5%
(5) Логистическая регрессия Sci-Kit Learn с GD:
53,8%
(6) Логистическая регрессия Sci-Kit Learn с SGD:
51,2%

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