108 lines
5.5 KiB
Python
108 lines
5.5 KiB
Python
|
"""
|
|||
|
Использовать регрессию по варианту для своих данных по варианту, самостоятельно сформулировав задачу.
|
|||
|
Оценить, насколько хорошо она подходит для решения сформулированной вами задачи.
|
|||
|
|
|||
|
"""
|
|||
|
|
|||
|
"""
|
|||
|
Задача, решаемая регрессией:
|
|||
|
Предсказание популярности нового музыкального трека на основе его определённых характеристик.
|
|||
|
Регрессионная модель может предсказывать числовую оценку популярности трека,
|
|||
|
что может быть полезно для музыкальных платформ по типу Spotify.
|
|||
|
"""
|
|||
|
|
|||
|
# 12 вариант
|
|||
|
# Набор данных по курсовой: "Prediction of music genre"
|
|||
|
# Тип регрессии: Логистическая регрессия
|
|||
|
|
|||
|
import pandas as pd
|
|||
|
import warnings
|
|||
|
import sklearn.exceptions
|
|||
|
from sklearn.linear_model import LogisticRegression
|
|||
|
from sklearn.model_selection import train_test_split
|
|||
|
from sklearn.metrics import classification_report, confusion_matrix, f1_score
|
|||
|
from sklearn.feature_selection import RFE
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DATASET_FILE = 'music_genre.csv'
|
|||
|
|
|||
|
|
|||
|
def main():
|
|||
|
df = open_dataset(DATASET_FILE)
|
|||
|
df = df.sample(frac=.5) # отбираем 50% рандомных строк с набора данных, т.к. он большой
|
|||
|
print("\033[92m[----------> Набор данных <----------]\033[00m")
|
|||
|
print(df)
|
|||
|
|
|||
|
# Перевод ладов (минор/мажор) в числовые признаки
|
|||
|
df_music = df.copy()
|
|||
|
df_music['mode'] = df_music['mode'].apply(lambda x: 1 if x == 'Major' else 0)
|
|||
|
|
|||
|
# разделим проценты популярности на 4 уровня (от 0 до 3)
|
|||
|
df_music['popularity'] = df_music['popularity'].apply(lambda x: int(x // 25))
|
|||
|
|
|||
|
X = df_music.drop(columns=['popularity']) # характеристики музыкального трека
|
|||
|
y = df_music['popularity'] # уровень популярности
|
|||
|
|
|||
|
# Разделение датасета на тренировочные (95%) и тестовые данные (5%)
|
|||
|
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.05)
|
|||
|
|
|||
|
# Создание и обучение модели логистической регрессии
|
|||
|
model = LogisticRegression(solver='lbfgs', max_iter=2000)
|
|||
|
model.fit(X_train.values, y_train)
|
|||
|
|
|||
|
# Поиск 5 важных признаков
|
|||
|
rfe = RFE(estimator=model, n_features_to_select=5)
|
|||
|
rfe = rfe.fit(X_train.values, y_train)
|
|||
|
features_ranks = pd.DataFrame({'Признак': X.columns.values, 'Выбор': rfe.support_, 'Ранг': rfe.ranking_})
|
|||
|
print("\033[92m\n[----------> Оценка признаков, влияющих на популярность трека <----------]\033[00m")
|
|||
|
print(features_ranks.sort_values(by=['Ранг']))
|
|||
|
|
|||
|
# Убираем незначительные признаки из датасета
|
|||
|
del_features = features_ranks['Признак'][features_ranks['Ранг'] == True]
|
|||
|
X_train = X_train[del_features]
|
|||
|
X_test = X_test[del_features]
|
|||
|
|
|||
|
# Переобучаем на них модель
|
|||
|
model.fit(X_train.values, y_train)
|
|||
|
|
|||
|
# Предсказание на тестовых данных уровня популярности трека
|
|||
|
y_pred = model.predict(X_test.values)
|
|||
|
|
|||
|
# Формирование матрицы путаницы
|
|||
|
cm = confusion_matrix(y_test, y_pred)
|
|||
|
print("\033[92m\n[----------> Матрица путаницы <----------]\033[00m")
|
|||
|
print(cm)
|
|||
|
pred_true = sum(cm[i][i] for i in range(len(cm))) # верные прогнозы
|
|||
|
pred_false = cm.sum() - pred_true # неверные прогнозы
|
|||
|
print("\033[94mКол-во правильных предсказаний (главная диагональ) = {}\033[00m" .format(pred_true))
|
|||
|
print("\033[91mКол-во неправильных предсказаний (остальное) = {}\033[00m".format(pred_false))
|
|||
|
|
|||
|
print("\033[92m\n[----------> Оценка модели <----------]\033[00m")
|
|||
|
print('Точность модели на тестовых данных: {:.2f}'.format(model.score(X_test.values, y_test)))
|
|||
|
|
|||
|
print("\033[92m\n[----------> Отчёт о классификации по уровням <----------]\033[00m")
|
|||
|
# игнор ошибки отсутствия некоторых классах при прогнозе (в данном случае 0 и 3)
|
|||
|
warnings.filterwarnings("ignore", category=sklearn.exceptions.UndefinedMetricWarning)
|
|||
|
print(classification_report(y_test, y_pred))
|
|||
|
print("\033[95mМаксимально предсказанный уровень: {}\033[00m".format(y_pred.max()))
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
# Функция считывания и очищения csv-файла
|
|||
|
def open_dataset(csv_file):
|
|||
|
# открываем файл с указанием знака-отделителя
|
|||
|
df = pd.read_csv(csv_file, delimiter=',')
|
|||
|
# выбираем необходимые признаки
|
|||
|
df = df[['duration_ms', 'mode', 'tempo', 'instrumentalness', 'acousticness', 'speechiness',
|
|||
|
'danceability', 'energy', 'liveness', 'valence', 'loudness', 'popularity']]
|
|||
|
# очищаем набор данных от пустых и неподходящих значений
|
|||
|
df = df[df['tempo'] != '?']
|
|||
|
df = df.dropna()
|
|||
|
return df
|
|||
|
|
|||
|
|
|||
|
|
|||
|
if __name__ == "__main__":
|
|||
|
main()
|