Music Recommendation By Detecting Human Emotion 😁😥🥰😫
All About Music Recommendation by detecting Human.
- Creating Environnment with Python 3.7 and Installing Libreries.
- Performing basic preprocessing on the data.
- Applying KNN algorithm to the data.
- Data preparation for train test split and performing model training with Lightgbm Classifier to check the feature importace.
- Emotion Detection Starts.
Creating Environnment with Python 3.7 and Installing Libreries.
-
Create a conda environment :
conda create -n music python=3.7 -y
-
Activate the conda environment :
conda activate music
-
Now install following libraries :
pip install tensorflow
pip install sklearn
pip install matplotlib
pip install pandas
pip install numpy
pip install opencv-python
pip install lightgbm
-
After installing you are good to proceed further to importing required modules.
-
You can get the data for this project from here.
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import lightgbm
import time
import cv2
from sklearn.model_selection import train_test_split
from sklearn.cluster import KMeans
from sklearn.preprocessing import MinMaxScaler
from lightgbm import LGBMClassifier
from tensorflow.keras.utils import img_to_array
from keras.preprocessing import image
from keras.models import load_model
import os
import tensorflow as tf
import time
import imutils
import argparse
from imutils.video import VideoStream
df = pd.read_csv('./Spotify Dataset Analysis/data.csv')
df.drop_duplicates(inplace=True, subset=['name'])
name = df['name']
- We are choosing "danceability", "energy", "valence", "loudness" columns since they are the most important features for our model from data analysis.
column_feat = ["danceability", "energy", "valence", "loudness"]
scaler = MinMaxScaler().fit_transform(df[column_feat])
kmeans = KMeans(init="k-means++",
n_clusters=3, random_state=15).fit(scaler)
df['kmeans']= kmeans.labels_
# Setting up new column song_name
df['song_name'] = name
cluster = df.groupby(by=df['kmeans'])
X = df.drop(columns=['name','artists','id','release_date','song_name'])
Y = df.pop('kmeans')
X_train,X_test,y_train,y_test = train_test_split(X,
Y, test_size=0.25)
model = LGBMClassifier().fit(X_train,y_train)
model.score(X_train,y_train)
model.score(X_test,y_test)
-
We can see our training and testing score of the model is quite good.
-
Now visualizing feature importance of the model.
- We can see clearly that energy is the most important feature for our model.
ax = lightgbm.plot_importance(model,
max_num_features=10,
figsize=(15,10))
plt.show()
- Here we are sorting the cluster dataframe by papularity of the music and resetting the index.
data=cluster.apply(lambda x: x.sort_values(["popularity"],ascending=False))
data.reset_index(level=0, inplace=True)
Emotion Detection Starts.
- Loading Required model that is haarcascade_frontalface_default.xml for detecting face and epoch_75.hdf5 is for detecting emotion which I have already trained.
- Also giving the labels for different emotions.
- You can download a pretrained model from here
detector = cv2.CascadeClassifier(cv2.data.haarcascades + './haarcascade_frontalface_default.xml')
model = load_model("./epoch_75.hdf5")
EMOTIONS = ["Angry", "Scared", "Happy", "Sad", "Surprised", "Neutral"]
We are applying OpenCV to read a frame from a video and predicting using pre trained model.
def emotion_testing():
global label
cap = cv2.VideoCapture(0)
time.sleep(2.0)
while True:
# grab the current Frame.
_, frame = cap.read()
# resize the frame and convert it to grayscale
frame = imutils.resize(frame, width=300)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# initialize the canvas for the visualization, then clone
# the frame so we can draw on it.
canvas = np.zeros((220, 300, 3), dtype="uint8")
frameClone = frame.copy()
# Detect faces in the input frame, then clone the frame so that
# we can draw on it
rects = detector.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30), flags = cv2.CASCADE_SCALE_IMAGE)
# Ensure at least one face was found before continuing.
if len(rects) > 0:
# determine the largest face area
rect = sorted(rects, reverse=True,
key=lambda x: (x[2] - x[0]) * (x[3] - x[1]))[0]
(fX, fY, fW, fH) = rect
# extract the face ROI from the image, then preprocess
# it for the network
roi = gray[fY:fY + fH, fX:fX + fW]
roi = cv2.resize(roi, (48, 48))
roi = roi.astype("float") / 255.0
roi = tf.keras.preprocessing.image.img_to_array(roi)
roi = np.expand_dims(roi, axis=0)
# Make a prediction on the ROI,then lookup the class
# label
preds = model.predict(roi)[0]
label = EMOTIONS[preds.argmax()]
#print(label)
# Loop over the labels + probabilities and draw them
for (i, (emotion, prob)) in enumerate(zip(EMOTIONS, preds)):
# Construct the label text
text = "{}: {:.2f}%".format(emotion, prob * 100)
# Draw the label + probability bar on the canvas
w = int(prob * 300)
cv2.rectangle(canvas, (5, (i * 35) + 5),
(w, (i * 35) + 35), (0, 0, 255), -1)
cv2.putText(canvas, text, (10, (i * 35) + 23),
cv2.FONT_HERSHEY_SIMPLEX, 0.45,
(2, 180, 48), 2)
# draw the label on the frame
cv2.putText(frameClone, label, (fX, fY - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.45, (252, 247, 48), 2)
cv2.rectangle(frameClone, (fX, fY), (fX + fW, fY + fH),
(0, 0, 255), 2)
# show our classifications + probabilities
cv2.imshow("Face", frameClone)
# cv2.imshow("Probabilities", canvas)
# if the ’q’ key is pressed, stop the loop
if cv2.waitKey(1) & 0xFF == ord("q"):
break
return label
- Here following function generatesemotion code for each detected emotion. They are :
- 0 : Neutral
- 1 : Happy
- 2 : Sad
def code():
emotion_word = emotion_testing()
if emotion_word == 'Neutral':
emotion_code = 0
print("Neutral detected ")
elif emotion_word == 'Happy':
emotion_code = 1
print("Happy Detected..")
elif emotion_word == 'Sad':
emotion_code = 2
print("Sad Detected..")
else:
print("Hi Deep!!")
return emotion_code
- Following function is recommending songs according to the generated emotion code and kmeans labels.
def get_results():
emotion_code = code()
NUM_RECOMMEND=10
happy_set=[]
neutral_set=[]
sad_set=[]
if emotion_code==0:
happy_set.append(data[data['kmeans']==0]['song_name'].head(NUM_RECOMMEND))
return pd.DataFrame(happy_set).T
elif emotion_code == 1:
neutral_set.append(data[data['kmeans']==1]['song_name'].head(NUM_RECOMMEND))
return pd.DataFrame(neutral_set).T
else:
sad_set.append(data[data['kmeans']==2]['song_name'].head(NUM_RECOMMEND))
return pd.DataFrame(sad_set).T
- Here this function is to run whole model.
get_results()