Skip to content

Instantly share code, notes, and snippets.

@Auax
Created June 19, 2021 10:28
Show Gist options
  • Select an option

  • Save Auax/a80e19cf3e57c0bbf4177ac3b8fd4502 to your computer and use it in GitHub Desktop.

Select an option

Save Auax/a80e19cf3e57c0bbf4177ac3b8fd4502 to your computer and use it in GitHub Desktop.
Predict a Spotify song genre
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"import numpy as np"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **Requesting Access Token from Spotify Web API**"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'{\"access_token\":\"BQCREIj2YaT4AUwMJWDs9-kwTY_EFHqXpghZp4TX-Tamglzl-ICc72mnQ0kKi-ZL5K_Ms3Gn-d9lWwP8DXU\",\"token_type\":\"Bearer\",\"expires_in\":3600,\"scope\":\"\"}'"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import requests\n",
"import json\n",
"client_id = your_client_id\n",
"client_secret = your_client_secret\n",
"\n",
"grant_type = 'client_credentials'\n",
"\n",
"#Request body parameter: grant_type Value: Required. Set it to client_credentials\n",
"body_params = {'grant_type' : grant_type}\n",
"\n",
"url='https://accounts.spotify.com/api/token'\n",
"\n",
"response=requests.post(url, data=body_params, auth = (client_id, client_secret)) \n",
"response.text"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import ast \n",
"response_dict = ast.literal_eval(response.text)"
]
},
{
"cell_type": "code",
"execution_count": 220,
"metadata": {},
"outputs": [],
"source": [
"access_token = response_dict['access_token']\n",
"headers = {'Authorization': 'Bearer '+ access_token}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **Get Playlist Tracks IDs**"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"def get_id(songs):\n",
" out = []\n",
" for song in songs['items']:\n",
" out.append(song['track']['id'])\n",
" return out"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **Getting Hip-Hop Playlist Track IDs**"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"r = requests.get(\"https://api.spotify.com/v1/playlists/37i9dQZF1DX2RxBh64BHjQ/tracks\", headers=headers)"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [],
"source": [
"hip_hop_songs = r.json()"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"hip_hop_ids = get_id(hip_hop_songs)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **Getting Classical Playlist Track IDs**"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"r = requests.get(\"https://api.spotify.com/v1/playlists/37i9dQZF1DWWEJlAGA9gs0/tracks\", headers=headers)"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"classical_songs = r.json()"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"classical_ids = get_id(classical_songs)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **Getting Techno Playlist Track IDs**"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"r = requests.get(\"https://api.spotify.com/v1/playlists/37i9dQZF1DX6J5NfMJS675/tracks\", headers=headers)"
]
},
{
"cell_type": "code",
"execution_count": 52,
"metadata": {},
"outputs": [],
"source": [
"techno_songs = r.json()"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"techno_ids = get_id(techno_songs)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **Requesting Track Features and inserting into Pandas DataFrame**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"***Hip-Hop***"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"hip_hop_ids_test = \",\".join(hip_hop_ids)"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"r = requests.get(f\"https://api.spotify.com/v1/audio-features/?ids={hip_hop_ids_test}\", headers=headers)"
]
},
{
"cell_type": "code",
"execution_count": 100,
"metadata": {},
"outputs": [],
"source": [
"hip_hop_features = r.json()"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"# Delete None values (avoid errors with the DataFrame)\n",
"def remove_none(features):\n",
" for element in features['audio_features']:\n",
" if element == None:\n",
" index_pos = features['audio_features'].index(element)\n",
" features['audio_features'].pop(index_pos)\n",
" return features"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"# Remove None values from the list\n",
"hip_hop_features = remove_none(hip_hop_features)"
]
},
{
"cell_type": "code",
"execution_count": 104,
"metadata": {},
"outputs": [],
"source": [
"# Create a DataFrame\n",
"df_hip_hop = pd.DataFrame(hip_hop_features['audio_features'])"
]
},
{
"cell_type": "code",
"execution_count": 105,
"metadata": {},
"outputs": [],
"source": [
"# Create a new column\n",
"df_hip_hop['target'] = 'Hip-Hop'"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>danceability</th>\n",
" <th>energy</th>\n",
" <th>key</th>\n",
" <th>loudness</th>\n",
" <th>mode</th>\n",
" <th>speechiness</th>\n",
" <th>acousticness</th>\n",
" <th>instrumentalness</th>\n",
" <th>liveness</th>\n",
" <th>valence</th>\n",
" <th>tempo</th>\n",
" <th>type</th>\n",
" <th>id</th>\n",
" <th>uri</th>\n",
" <th>track_href</th>\n",
" <th>analysis_url</th>\n",
" <th>duration_ms</th>\n",
" <th>time_signature</th>\n",
" <th>target</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>0.794</td>\n",
" <td>0.756</td>\n",
" <td>5</td>\n",
" <td>-7.160</td>\n",
" <td>0</td>\n",
" <td>0.136</td>\n",
" <td>0.11000</td>\n",
" <td>0.0</td>\n",
" <td>0.247</td>\n",
" <td>0.775</td>\n",
" <td>123.066</td>\n",
" <td>audio_features</td>\n",
" <td>4DuUwzP4ALMqpquHU0ltAB</td>\n",
" <td>spotify:track:4DuUwzP4ALMqpquHU0ltAB</td>\n",
" <td>https://api.spotify.com/v1/tracks/4DuUwzP4ALMq...</td>\n",
" <td>https://api.spotify.com/v1/audio-analysis/4DuU...</td>\n",
" <td>156498</td>\n",
" <td>4</td>\n",
" <td>Hip-Hop</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>0.836</td>\n",
" <td>0.611</td>\n",
" <td>4</td>\n",
" <td>-6.737</td>\n",
" <td>1</td>\n",
" <td>0.247</td>\n",
" <td>0.00406</td>\n",
" <td>0.0</td>\n",
" <td>0.101</td>\n",
" <td>0.787</td>\n",
" <td>160.000</td>\n",
" <td>audio_features</td>\n",
" <td>2No8W4sLebINx3pdRUeMnl</td>\n",
" <td>spotify:track:2No8W4sLebINx3pdRUeMnl</td>\n",
" <td>https://api.spotify.com/v1/tracks/2No8W4sLebIN...</td>\n",
" <td>https://api.spotify.com/v1/audio-analysis/2No8...</td>\n",
" <td>145125</td>\n",
" <td>4</td>\n",
" <td>Hip-Hop</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" danceability energy key loudness mode speechiness acousticness \\\n",
"0 0.794 0.756 5 -7.160 0 0.136 0.11000 \n",
"1 0.836 0.611 4 -6.737 1 0.247 0.00406 \n",
"\n",
" instrumentalness liveness valence tempo type \\\n",
"0 0.0 0.247 0.775 123.066 audio_features \n",
"1 0.0 0.101 0.787 160.000 audio_features \n",
"\n",
" id uri \\\n",
"0 4DuUwzP4ALMqpquHU0ltAB spotify:track:4DuUwzP4ALMqpquHU0ltAB \n",
"1 2No8W4sLebINx3pdRUeMnl spotify:track:2No8W4sLebINx3pdRUeMnl \n",
"\n",
" track_href \\\n",
"0 https://api.spotify.com/v1/tracks/4DuUwzP4ALMq... \n",
"1 https://api.spotify.com/v1/tracks/2No8W4sLebIN... \n",
"\n",
" analysis_url duration_ms \\\n",
"0 https://api.spotify.com/v1/audio-analysis/4DuU... 156498 \n",
"1 https://api.spotify.com/v1/audio-analysis/2No8... 145125 \n",
"\n",
" time_signature target \n",
"0 4 Hip-Hop \n",
"1 4 Hip-Hop "
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df_hip_hop.head(2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"***Classical***"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"classical_ids = \",\".join(classical_ids)"
]
},
{
"cell_type": "code",
"execution_count": 109,
"metadata": {},
"outputs": [],
"source": [
"r = requests.get(f\"https://api.spotify.com/v1/audio-features/?ids={classical_ids}\", headers=headers)"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"classical_features = r.json()"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"df_classical = pd.DataFrame(classical_features['audio_features'])"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"df_classical['target'] = \"Classical\""
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>danceability</th>\n",
" <th>energy</th>\n",
" <th>key</th>\n",
" <th>loudness</th>\n",
" <th>mode</th>\n",
" <th>speechiness</th>\n",
" <th>acousticness</th>\n",
" <th>instrumentalness</th>\n",
" <th>liveness</th>\n",
" <th>valence</th>\n",
" <th>tempo</th>\n",
" <th>type</th>\n",
" <th>id</th>\n",
" <th>uri</th>\n",
" <th>track_href</th>\n",
" <th>analysis_url</th>\n",
" <th>duration_ms</th>\n",
" <th>time_signature</th>\n",
" <th>target</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>0.2210</td>\n",
" <td>0.1260</td>\n",
" <td>0</td>\n",
" <td>-25.427</td>\n",
" <td>1</td>\n",
" <td>0.0447</td>\n",
" <td>0.989</td>\n",
" <td>0.897</td>\n",
" <td>0.1020</td>\n",
" <td>0.2160</td>\n",
" <td>133.630</td>\n",
" <td>audio_features</td>\n",
" <td>4SFBV7SRNG2e2kyL1F6kjU</td>\n",
" <td>spotify:track:4SFBV7SRNG2e2kyL1F6kjU</td>\n",
" <td>https://api.spotify.com/v1/tracks/4SFBV7SRNG2e...</td>\n",
" <td>https://api.spotify.com/v1/audio-analysis/4SFB...</td>\n",
" <td>139307</td>\n",
" <td>4</td>\n",
" <td>Classical</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>0.0811</td>\n",
" <td>0.0122</td>\n",
" <td>4</td>\n",
" <td>-32.654</td>\n",
" <td>0</td>\n",
" <td>0.0511</td>\n",
" <td>0.902</td>\n",
" <td>0.308</td>\n",
" <td>0.0648</td>\n",
" <td>0.0384</td>\n",
" <td>74.554</td>\n",
" <td>audio_features</td>\n",
" <td>2kAgCRZPG3YQR2VMqRvLmb</td>\n",
" <td>spotify:track:2kAgCRZPG3YQR2VMqRvLmb</td>\n",
" <td>https://api.spotify.com/v1/tracks/2kAgCRZPG3YQ...</td>\n",
" <td>https://api.spotify.com/v1/audio-analysis/2kAg...</td>\n",
" <td>935360</td>\n",
" <td>4</td>\n",
" <td>Classical</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" danceability energy key loudness mode speechiness acousticness \\\n",
"0 0.2210 0.1260 0 -25.427 1 0.0447 0.989 \n",
"1 0.0811 0.0122 4 -32.654 0 0.0511 0.902 \n",
"\n",
" instrumentalness liveness valence tempo type \\\n",
"0 0.897 0.1020 0.2160 133.630 audio_features \n",
"1 0.308 0.0648 0.0384 74.554 audio_features \n",
"\n",
" id uri \\\n",
"0 4SFBV7SRNG2e2kyL1F6kjU spotify:track:4SFBV7SRNG2e2kyL1F6kjU \n",
"1 2kAgCRZPG3YQR2VMqRvLmb spotify:track:2kAgCRZPG3YQR2VMqRvLmb \n",
"\n",
" track_href \\\n",
"0 https://api.spotify.com/v1/tracks/4SFBV7SRNG2e... \n",
"1 https://api.spotify.com/v1/tracks/2kAgCRZPG3YQ... \n",
"\n",
" analysis_url duration_ms \\\n",
"0 https://api.spotify.com/v1/audio-analysis/4SFB... 139307 \n",
"1 https://api.spotify.com/v1/audio-analysis/2kAg... 935360 \n",
"\n",
" time_signature target \n",
"0 4 Classical \n",
"1 4 Classical "
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df_classical.head(2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"***Techno***"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"techno_ids = \",\".join(techno_ids)"
]
},
{
"cell_type": "code",
"execution_count": 117,
"metadata": {},
"outputs": [],
"source": [
"r = requests.get(f\"https://api.spotify.com/v1/audio-features/?ids={techno_ids}\", headers=headers)"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"techno_features = r.json()"
]
},
{
"cell_type": "code",
"execution_count": 119,
"metadata": {},
"outputs": [],
"source": [
"df_techno = pd.DataFrame(techno_features['audio_features'])"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"df_techno['target'] = 'Techno'"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>danceability</th>\n",
" <th>energy</th>\n",
" <th>key</th>\n",
" <th>loudness</th>\n",
" <th>mode</th>\n",
" <th>speechiness</th>\n",
" <th>acousticness</th>\n",
" <th>instrumentalness</th>\n",
" <th>liveness</th>\n",
" <th>valence</th>\n",
" <th>tempo</th>\n",
" <th>type</th>\n",
" <th>id</th>\n",
" <th>uri</th>\n",
" <th>track_href</th>\n",
" <th>analysis_url</th>\n",
" <th>duration_ms</th>\n",
" <th>time_signature</th>\n",
" <th>target</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>0.652</td>\n",
" <td>0.859</td>\n",
" <td>11</td>\n",
" <td>-7.757</td>\n",
" <td>1</td>\n",
" <td>0.0519</td>\n",
" <td>0.000315</td>\n",
" <td>0.908</td>\n",
" <td>0.0752</td>\n",
" <td>0.0348</td>\n",
" <td>129.984</td>\n",
" <td>audio_features</td>\n",
" <td>0M07XMvl0ylY9VVt69LsJu</td>\n",
" <td>spotify:track:0M07XMvl0ylY9VVt69LsJu</td>\n",
" <td>https://api.spotify.com/v1/tracks/0M07XMvl0ylY...</td>\n",
" <td>https://api.spotify.com/v1/audio-analysis/0M07...</td>\n",
" <td>391385</td>\n",
" <td>3</td>\n",
" <td>Techno</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>0.798</td>\n",
" <td>0.870</td>\n",
" <td>7</td>\n",
" <td>-6.337</td>\n",
" <td>1</td>\n",
" <td>0.0818</td>\n",
" <td>0.001160</td>\n",
" <td>0.830</td>\n",
" <td>0.0582</td>\n",
" <td>0.2760</td>\n",
" <td>129.999</td>\n",
" <td>audio_features</td>\n",
" <td>5weOq4YmiAgStu1cmSZQuB</td>\n",
" <td>spotify:track:5weOq4YmiAgStu1cmSZQuB</td>\n",
" <td>https://api.spotify.com/v1/tracks/5weOq4YmiAgS...</td>\n",
" <td>https://api.spotify.com/v1/audio-analysis/5weO...</td>\n",
" <td>451044</td>\n",
" <td>4</td>\n",
" <td>Techno</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" danceability energy key loudness mode speechiness acousticness \\\n",
"0 0.652 0.859 11 -7.757 1 0.0519 0.000315 \n",
"1 0.798 0.870 7 -6.337 1 0.0818 0.001160 \n",
"\n",
" instrumentalness liveness valence tempo type \\\n",
"0 0.908 0.0752 0.0348 129.984 audio_features \n",
"1 0.830 0.0582 0.2760 129.999 audio_features \n",
"\n",
" id uri \\\n",
"0 0M07XMvl0ylY9VVt69LsJu spotify:track:0M07XMvl0ylY9VVt69LsJu \n",
"1 5weOq4YmiAgStu1cmSZQuB spotify:track:5weOq4YmiAgStu1cmSZQuB \n",
"\n",
" track_href \\\n",
"0 https://api.spotify.com/v1/tracks/0M07XMvl0ylY... \n",
"1 https://api.spotify.com/v1/tracks/5weOq4YmiAgS... \n",
"\n",
" analysis_url duration_ms \\\n",
"0 https://api.spotify.com/v1/audio-analysis/0M07... 391385 \n",
"1 https://api.spotify.com/v1/audio-analysis/5weO... 451044 \n",
"\n",
" time_signature target \n",
"0 3 Techno \n",
"1 4 Techno "
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df_techno.head(2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **Combining DataFrames**"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"main_df = pd.concat([df_hip_hop,df_classical,df_techno])"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>danceability</th>\n",
" <th>energy</th>\n",
" <th>key</th>\n",
" <th>loudness</th>\n",
" <th>mode</th>\n",
" <th>speechiness</th>\n",
" <th>acousticness</th>\n",
" <th>instrumentalness</th>\n",
" <th>liveness</th>\n",
" <th>valence</th>\n",
" <th>tempo</th>\n",
" <th>type</th>\n",
" <th>id</th>\n",
" <th>uri</th>\n",
" <th>track_href</th>\n",
" <th>analysis_url</th>\n",
" <th>duration_ms</th>\n",
" <th>time_signature</th>\n",
" <th>target</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>0.794</td>\n",
" <td>0.756</td>\n",
" <td>5</td>\n",
" <td>-7.160</td>\n",
" <td>0</td>\n",
" <td>0.136</td>\n",
" <td>0.11000</td>\n",
" <td>0.0</td>\n",
" <td>0.247</td>\n",
" <td>0.775</td>\n",
" <td>123.066</td>\n",
" <td>audio_features</td>\n",
" <td>4DuUwzP4ALMqpquHU0ltAB</td>\n",
" <td>spotify:track:4DuUwzP4ALMqpquHU0ltAB</td>\n",
" <td>https://api.spotify.com/v1/tracks/4DuUwzP4ALMq...</td>\n",
" <td>https://api.spotify.com/v1/audio-analysis/4DuU...</td>\n",
" <td>156498</td>\n",
" <td>4</td>\n",
" <td>Hip-Hop</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>0.836</td>\n",
" <td>0.611</td>\n",
" <td>4</td>\n",
" <td>-6.737</td>\n",
" <td>1</td>\n",
" <td>0.247</td>\n",
" <td>0.00406</td>\n",
" <td>0.0</td>\n",
" <td>0.101</td>\n",
" <td>0.787</td>\n",
" <td>160.000</td>\n",
" <td>audio_features</td>\n",
" <td>2No8W4sLebINx3pdRUeMnl</td>\n",
" <td>spotify:track:2No8W4sLebINx3pdRUeMnl</td>\n",
" <td>https://api.spotify.com/v1/tracks/2No8W4sLebIN...</td>\n",
" <td>https://api.spotify.com/v1/audio-analysis/2No8...</td>\n",
" <td>145125</td>\n",
" <td>4</td>\n",
" <td>Hip-Hop</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" danceability energy key loudness mode speechiness acousticness \\\n",
"0 0.794 0.756 5 -7.160 0 0.136 0.11000 \n",
"1 0.836 0.611 4 -6.737 1 0.247 0.00406 \n",
"\n",
" instrumentalness liveness valence tempo type \\\n",
"0 0.0 0.247 0.775 123.066 audio_features \n",
"1 0.0 0.101 0.787 160.000 audio_features \n",
"\n",
" id uri \\\n",
"0 4DuUwzP4ALMqpquHU0ltAB spotify:track:4DuUwzP4ALMqpquHU0ltAB \n",
"1 2No8W4sLebINx3pdRUeMnl spotify:track:2No8W4sLebINx3pdRUeMnl \n",
"\n",
" track_href \\\n",
"0 https://api.spotify.com/v1/tracks/4DuUwzP4ALMq... \n",
"1 https://api.spotify.com/v1/tracks/2No8W4sLebIN... \n",
"\n",
" analysis_url duration_ms \\\n",
"0 https://api.spotify.com/v1/audio-analysis/4DuU... 156498 \n",
"1 https://api.spotify.com/v1/audio-analysis/2No8... 145125 \n",
"\n",
" time_signature target \n",
"0 4 Hip-Hop \n",
"1 4 Hip-Hop "
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"main_df.head(2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **Selecting features for algorithm**"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"X = main_df[['danceability', 'energy', 'key', 'loudness', 'speechiness', \n",
" 'acousticness', 'instrumentalness', 'liveness', 'valence', \n",
" 'tempo', 'time_signature']]"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"y = main_df.target"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Stored 'X' (DataFrame)\n",
"Stored 'y' (Series)\n"
]
}
],
"source": [
"# Save variables in JupyterNotebook\n",
"%store X\n",
"%store y"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **Scaling Features**"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>danceability</th>\n",
" <th>energy</th>\n",
" <th>key</th>\n",
" <th>loudness</th>\n",
" <th>speechiness</th>\n",
" <th>acousticness</th>\n",
" <th>instrumentalness</th>\n",
" <th>liveness</th>\n",
" <th>valence</th>\n",
" <th>tempo</th>\n",
" <th>time_signature</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>0.794</td>\n",
" <td>0.756</td>\n",
" <td>5</td>\n",
" <td>-7.160</td>\n",
" <td>0.1360</td>\n",
" <td>0.11000</td>\n",
" <td>0.000000</td>\n",
" <td>0.2470</td>\n",
" <td>0.775</td>\n",
" <td>123.066</td>\n",
" <td>4</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>0.836</td>\n",
" <td>0.611</td>\n",
" <td>4</td>\n",
" <td>-6.737</td>\n",
" <td>0.2470</td>\n",
" <td>0.00406</td>\n",
" <td>0.000000</td>\n",
" <td>0.1010</td>\n",
" <td>0.787</td>\n",
" <td>160.000</td>\n",
" <td>4</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>0.902</td>\n",
" <td>0.462</td>\n",
" <td>7</td>\n",
" <td>-7.945</td>\n",
" <td>0.0979</td>\n",
" <td>0.19000</td>\n",
" <td>0.000002</td>\n",
" <td>0.0940</td>\n",
" <td>0.646</td>\n",
" <td>103.984</td>\n",
" <td>4</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>0.900</td>\n",
" <td>0.521</td>\n",
" <td>4</td>\n",
" <td>-7.286</td>\n",
" <td>0.1470</td>\n",
" <td>0.01350</td>\n",
" <td>0.000000</td>\n",
" <td>0.0951</td>\n",
" <td>0.213</td>\n",
" <td>132.007</td>\n",
" <td>4</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>0.868</td>\n",
" <td>0.474</td>\n",
" <td>2</td>\n",
" <td>-8.252</td>\n",
" <td>0.3390</td>\n",
" <td>0.02580</td>\n",
" <td>0.000000</td>\n",
" <td>0.1010</td>\n",
" <td>0.189</td>\n",
" <td>130.000</td>\n",
" <td>4</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" danceability energy key loudness speechiness acousticness \\\n",
"0 0.794 0.756 5 -7.160 0.1360 0.11000 \n",
"1 0.836 0.611 4 -6.737 0.2470 0.00406 \n",
"2 0.902 0.462 7 -7.945 0.0979 0.19000 \n",
"3 0.900 0.521 4 -7.286 0.1470 0.01350 \n",
"4 0.868 0.474 2 -8.252 0.3390 0.02580 \n",
"\n",
" instrumentalness liveness valence tempo time_signature \n",
"0 0.000000 0.2470 0.775 123.066 4 \n",
"1 0.000000 0.1010 0.787 160.000 4 \n",
"2 0.000002 0.0940 0.646 103.984 4 \n",
"3 0.000000 0.0951 0.213 132.007 4 \n",
"4 0.000000 0.1010 0.189 130.000 4 "
]
},
"execution_count": 135,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from sklearn.preprocessing import StandardScaler\n",
"\n",
"scaler = StandardScaler()\n",
"scaled_data = scaler.fit_transform(X)\n",
"\n",
"scaled_df = pd.DataFrame(X, columns=X.columns)\n",
"scaled_df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **Training**"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from sklearn.model_selection import train_test_split\n",
"\n",
"X_train, X_test, y_train, y_test = train_test_split(scaled_df, y, test_size=0.2, random_state=3)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **Attempting multiple K values for K Nearest Neighbors**"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from sklearn.neighbors import KNeighborsClassifier"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from sklearn.metrics import precision_score, recall_score, accuracy_score, f1_score"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"# Find best K value\n",
"def find_best_k(X_train, y_train, X_test, y_test, min_k=1, max_k=25):\n",
" best_k = 0\n",
" best_score = 0.0\n",
" \n",
" for k in range(min_k, max_k+1, 2):\n",
" knn = KNeighborsClassifier(n_neighbors=k)\n",
" knn.fit(X_train, y_train)\n",
" preds = knn.predict(X_test)\n",
" f1 = f1_score(y_test, preds, average='micro')\n",
" if f1 > best_score:\n",
" best_k = k\n",
" best_score = f1\n",
" \n",
" print(\"Best Value for k: {}\".format(best_k))\n",
" print(\"F1-Score: {}\".format(best_score))"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Best Value for k: 3\n",
"F1-Score: 0.9423076923076923\n"
]
}
],
"source": [
"find_best_k(X_train, y_train, X_test, y_test)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"***The best K value is 3***"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"knn = KNeighborsClassifier(n_neighbors=3) # n_neighbors = best K value\n",
"knn.fit(X_train, y_train)\n",
"preds = knn.predict(X_test)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **Classification Scores on Test Set**"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from sklearn.metrics import classification_report"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"def print_metrics(labels, preds):\n",
" print(\"Precision Score: {}\".format(precision_score(labels, preds, average='micro')))\n",
" print(\"Recall Score: {}\".format(recall_score(labels, preds, average='micro')))\n",
" print(\"Accuracy Score: {}\".format(accuracy_score(labels, preds)))\n",
" print(\"F1 Score: {}\".format(f1_score(labels, preds, average='micro')))"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Precision Score: 0.9423076923076923\n",
"Recall Score: 0.9423076923076923\n",
"Accuracy Score: 0.9423076923076923\n",
"F1 Score: 0.9423076923076923\n"
]
}
],
"source": [
"print_metrics(y_test, preds)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **Predicting a Song**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Our model is completed. We can now predict the type of music**"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"def song_by_id(id):\n",
" r = requests.get(f\"https://api.spotify.com/v1/audio-features/?ids={id}\", headers=headers)\n",
" song_features = r.json()\n",
" \n",
" song_df = pd.DataFrame(song_features['audio_features'])\n",
"\n",
" return song_df[['danceability', 'energy', 'key', 'loudness', 'speechiness', \n",
" 'acousticness', 'instrumentalness', 'liveness', 'valence', \n",
" 'tempo', 'time_signature']]"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"scrolled": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Hip-Hop\n"
]
}
],
"source": [
"id = '1mea3bSkSGXuIRvnydlB5b'\n",
"preds = knn.predict(song_by_id(id))\n",
"print(preds[0])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.5"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment