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

Выбор модели

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

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

Статистические модели с одним участником:

  • Регрессия автоматического определения релевантности (ARD)
  • Регрессия байесовского хребта

Модели статистического ансамбля:

  • Повышение градиента для регрессии
  • AdaBoost регрессор
  • Дерево регрессии с усилением градиента на основе гистограммы
  • Эпсилон-регрессия опорных векторов (SVR)
  • Регрессия дополнительных деревьев

Нейронные сети:

  • Многоуровневый регрессор персептрона (MLPRegressor)

Обучение модели

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

def evaluate(X_train, X_test, y_train, y_test):
    # Names of models
    model_name_list = ['ARDRegression', 
                      'BayesianRidge', 'Extra Trees', 'SVM',
                       'Gradient Boosted', 'AdaBoostRegressor', 'HistGradientBoostingRegressor', 'MLPRegressor', 'Baseline']
    
    # Instantiate the models
    model1 = ARDRegression(compute_score=True, n_iter=50)
    model2 = BayesianRidge(compute_score=True, n_iter=50)
    model3 = ExtraTreesRegressor(n_estimators=50)
    model4 = SVR(kernel='rbf', degree=3, C=1.0, gamma='auto')
    model5 = GradientBoostingRegressor(n_estimators=20)
    model6 = AdaBoostRegressor(random_state=0, n_estimators=50)
    model7 = HistGradientBoostingRegressor()
    model8 = MLPRegressor(random_state=1, max_iter=100)
    
    # Dataframe for results
    results = pd.DataFrame(columns=['mae', 'rmse', 'r_square'], index = model_name_list)

    # Train and predict with each model
    for i, model in enumerate([model1, model2, model3, model4, model5, model6, model7, model8]):
        model.fit(X_train, y_train)
        predictions = model.predict(X_test)
        
        # Metrics
        mae = np.mean(abs(predictions - y_test))
        rmse = np.sqrt(np.mean((predictions - y_test) ** 2))
        Adj_R_square = 1 - (1-r2_score(y_test, predictions)) * (len(y_test)-1)/(len(y_test)-X_test.shape[1]-1)
        
        # Insert results into the dataframe
        model_name = model_name_list[i]
        results.loc[model_name, :] = [mae, rmse, Adj_R_square]
        
        #plot prediction
        plt.plot(predictions[:100])
        plt.plot(y_test.reset_index(drop=True)[:100])
        plt.figure(figsize=(400, 150))
        plt.show()
    
    # Median Value Baseline Metrics
    baseline = np.median(y_train)
    baseline_mae = np.mean(abs(baseline - y_test))
    baseline_rmse = np.sqrt(np.mean((baseline - y_test) ** 2))
    baseline_R_square = Adj_R_square
    
    results.loc['Baseline', :] = [baseline_mae, baseline_rmse, baseline_R_square]
    
    return results

Полученные результаты

Следующие изображения представляют собой прогнозируемые результаты в сравнении с фактическими результатами.

Давайте распечатаем MAE, RMSE и R_Square каждого результата.

Как видите, результаты ужасны! Все модели имеют баллы MAE выше 8,2 и RMSE выше 10,1. Также редко можно увидеть результаты прогнозирования с отрицательным значением R в квадрате. Отрицательное значение R Squared означает, что выбранная модель не соответствует тренду данных, и ее соответствие хуже, чем у горизонтальной линии. Судя по графикам, только Дополнительные деревья, Градиентная повышающая регрессия на основе гистограммы Дерево и MLPRegressor в какой-то мере следуют тренду данных.

Почему такой плохой результат?

Так почему именно такой плохой результат? Я пришел к выводу, что две важные причины, вызвавшие неудачу этих моделей, — это низкая корреляция переменных и несбалансированные данные.

  1. Низкая переменная корреляция

Я нарисовал тепловую карту в части 1 этого проекта, чтобы увидеть корреляции между переменными. Переменная с самым высоким значением корреляции с track_popularity — это живость, которая равна -0,118. Объективно говоря, даже живость считается слабо или не связанной с track_popularity. Хотя корреляции переменных не полностью определяют результаты прогнозирования/прогнозирования регрессионными моделями, все переменные, используемые в этом проекте, плохо коррелируют и, несомненно, играют значительную роль в плохих результатах прогнозирования.

2. Несбалансированные данные

Я также заметил, что набор данных, который я использовал, очень несбалансирован. Давайте вспомним график распределения track_popularity и детали.

Из этого графика видно, что большинство наших наборов данных имеют значение track_popularity от 7 до 57, при этом минимальное значение равно 10, а максимальное значение равно 70. График имеет положительную асимметрию. Другими словами, неравное распределение повлияло на результаты нашего прогноза. Я просмотрел наборы данных, используемые другими проектами прогнозирования популярности Spotify от Kaggle, и они распределены гораздо более равномерно: минимум равен 0, а максимум равен 100.

Я тоже нашел кое-что интересное. Вместо того, чтобы предсказывать числовое значение track_popularity с помощью моделей машинного обучения, некоторые люди делят track_popularity на разделы, такие как непопулярные (оценка от 0 до 25), менее популярные (оценка от 25 до 50), более популярный (от 50 до 75) и очень популярный (от 75 до 100). Это превращает проблему регрессии в проблему классификации. Я бы использовал этот подход, если бы не эти неравномерно распределенные данные.

Что я могу сделать, чтобы улучшить результат?

  1. Обогащение данных

Одним из способов, который может улучшить результат, является обогащение данных. Это означает, что нужно собирать более ценные данные (более высокая корреляция с track_popularity). Мы можем получить различные данные о треке из веб-API Spotify. Например, можно получить количество подписчиков артиста на Spotify и популярность артиста. Несмотря на то, что я не проводил корреляционный анализ этих переменных, нетрудно предсказать, что популярность исполнителя играет значительную роль в популярности трека.

Другой пример — переменная — доступные_рынки. Список стран, в которых можно проигрывать трек. Даже если у трека есть атрибуты, которые, по прогнозам, будут популярными, с ограниченными доступными рынками, трек может получить более низкую, чем ожидалось, track_popularity. Подобные переменные следует учитывать при прогнозировании.

2. Передискретизация

Хотя избыточная выборка в теме регрессии встречается редко, выборка набора данных слишком мала, чтобы охватить крайние случаи. Мы можем использовать метод избыточной выборки, чтобы получить более равномерное распределение track_popularity. Он дублирует или создает новые синтетические примеры в классах меньшинства. В схеме этого проекта мы будем передискретизировать данные с track_popularity выше 50 и ниже 10.

Заключение

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

Спасибо, что нашли время прочитать эту статью. Если вы считаете это полезным, пожалуйста, оставьте лайк и комментарий!

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