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() |