Введение

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

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

Набор данных

Мы будем использовать набор данных песен из Kaggle, который содержит тексты для 57650 песен. Набор данных можно скачать по этой ссылке: https://www.kaggle.com/mousehead/songlyrics

Набор данных содержит следующие столбцы:

Песня: Название песни

year: год выпуска песни

художник: Имя художника

Жанр: Жанр песни

текст: Текст песни

В этом уроке мы будем использовать только столбцы песни и текста.

Создание системы музыкальных рекомендаций

Шаг 1: очистка данных и предварительная обработка

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

Код модели

import pandas as pd
import numpy as np
df = pd.read_csv('songdata.csv')
df.head(3)
df.shape
(57650, 4)
df = df.sample(n=5000).drop('link', axis=1).reset_index(drop=True)
df.shape
(5000, 3)
df['text'] = df['text'].str.lower().replace(r'[^\w\s]','').replace(r'\n',' ', regex=True)
df['text'][0]
import nltk
from nltk.stem.porter import PorterStemmer
stemmer = PorterStemmer()

def tokenization(txt):
    tokens = nltk.word_tokenize(txt)
    stemming = [stemmer.stem(w) for w in tokens]
    return " ".join(stemming)
[12]
df['text'] = df['text'].apply(lambda x: tokenization(x))
[13]
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
[14]
tfidvector = TfidfVectorizer(analyzer='word',stop_words='english')
matrix = tfidvector.fit_transform(df['text'])
similarity = cosine_similarity(matrix)
[16]
similarity[0]
df[df['song']==''].index[0]
0
recommedation function
[39]
def recommendation(song_df):
    idx = df[df['song'] == song_df].index[0]
    distances = sorted(list(enumerate(similarity[idx])),reverse=True,key=lambda x:x[1])
    
    songs = []
    for m_id in distances[1:21]:
        songs.append(df.iloc[m_id[0]].song)
        
    return songs
[40]
recommendation('Alma Mater')
['O Love That Will Not Let Me Go',
 'Shall We Dance',
 'Churchill Speech',
 'Until Next Time',
 'The Lord Is My Sheperd',
 'God Bless The Child',
 'Mary Of Argyle',
 'O Little Town Of Bethlehem',
 'A Call To Harvest',
 'Christmas Secrets',
 'The Time Is Near',
 "All Tomorrow's Parties",
 'Fare Thee Well',
 'Dark Star',
 'As With Gladness Men Of Old',
 'As Much As Always',
 'From The Balcony',
 'May You Never Be Alone',
 'Alleluia! Sing To Jesus!',
 'America The Beautiful']
[41]
import pickle
pickle.dump(similarity,open('similarity.pkl','wb'))
pickle.dump(df,open('df.pkl','wb'))

Код приложения

from flask import Flask,request,render_template
import pandas as pd
import numpy as np
import pickle

df = pickle.load(open('df.pkl','rb'))
similarity = pickle.load(open('similarity.pkl','rb'))


def recommendation(song_df):
    idx = df[df['song'] == song_df].index[0]
    distances = sorted(list(enumerate(similarity[idx])), reverse=True, key=lambda x: x[1])
    # print(distances)
    songs = []
    for m_id in distances[1:21]:
        songs.append(df.iloc[m_id[0]].song)

    return songs

# flask app
app = Flask(__name__)
@app.route('/')
def index():
    songs = list(df['song'].values)
    return render_template('index.html', names=songs)

@app.route('/recom',methods=['POST'])
def recom():
    song = request.form['names']
    songs = recommendation(song)
    print(songs)
    return render_template('index.html',songs=songs)


# python main
if __name__ == "__main__":

HTML-код:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Music Recommendation System</title>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
  </head>
  <body style="background:black; color:white">

  <div class="container">
      <h2 class="text-center">Music Recommendation System</h2>

      <form action="/recom" method="post">
          <div class="form-group">
              <label for="text">Songs List</label>
              <select class="form-control" name="names" id="names">
                  {% for i in names %}
                  <option value="{{i}}">{{i}}</option>
                  {% endfor %}
              </select>
          </div>
          <button style="margin-top:20px;" type="submit" class="btn btn-primary btn-lg">get songs</button>
      </form>

      <div class="row">
          {% for i in songs %}
          <div class="card col-md-4" style="width: 18rem; margin-right:20px;margin-top:20px;">
              <img src="{{url_for('static',filename='img.png')}}" class="card-img-top" alt="...">
              <div class="card-body">
                <h5 class="card-title">{{i}}</h5>
              </div>
            </div>
          {% endfor %}
      </div>
  </div>


    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe" crossorigin="anonymous"></script>
  </body>
</html>