曲の特徴からアーティスト分類の概要
Spotify APIを使うと,曲の特徴を簡単に取得することができます。
例えば,曲調やテンポ(BPM)などが得られます。
そこで,これらの曲の特徴からアーティストを分類するモデルを作る方法をご紹介します。
分類には,機械学習モデルのランダムフォレストを使用します。
アーティスト分類する方法
準備するもの
今回は,Pythonを使って分類をしてみました。
使用するモジュールは以下の通りです。
- pandas(データ分析用)
- spotipy(Spotify連携)
- scikit-learn(ランダムフォレスト)
また,Spotify APIの連携が済んでいない方は連携をしてください。
モジュールのインストールとAPIの設定
まずは,データ取得のためのモジュールやAPIの設定をします。
import pandas as pd
import spotipy
from spotipy.oauth2 import SpotifyClientCredentials
import time
# spotify developerから取得したclient_idとclient_secretを入力
client_id = '自分のclient_idを入力'
client_secret = '自分のclient_secretを入力'
client_credentials_manager = spotipy.oauth2.SpotifyClientCredentials(client_id, client_secret)
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
データを取得するための関数を定義(コピペ可)
データを簡単に取得するための関数を定義します。
プレイリスト内の曲IDを取得する関数
# プレイリスト内の曲IDを取得
def getTrackIDs(playlist_ids):
track_ids = []
for playlist_id in playlist_ids:
playlist = sp.playlist(playlist_id)
while playlist['tracks']['next']:
for item in playlist['tracks']['items']:
track = item['track']
if not track['id'] in track_ids:
track_ids.append(track['id'])
playlist['tracks'] = sp.next(playlist['tracks'])
else:
for item in playlist['tracks']['items']:
track = item['track']
if not track['id'] in track_ids:
track_ids.append(track['id'])
return track_ids
曲IDを入れると特徴量を取得する関数
# 曲IDを入れると,特徴を取得
def getTrackFeatures(id):
meta = sp.track(id)
features = sp.audio_features(id)
name = meta['name']
album = meta['album']['name']
artist = meta['album']['artists'][0]['name']
release_date = meta['album']['release_date']
length = meta['duration_ms']
popularity = meta['popularity']
key = features[0]['key']
mode = features[0]['mode']
danceability = features[0]['danceability']
acousticness = features[0]['acousticness']
energy = features[0]['energy']
instrumentalness = features[0]['instrumentalness']
liveness = features[0]['liveness']
loudness = features[0]['loudness']
speechiness = features[0]['speechiness']
tempo = features[0]['tempo']
time_signature = features[0]['time_signature']
valence = features[0]['valence']
track = [name, album, artist, release_date, length, popularity, key, mode, danceability, acousticness, energy, instrumentalness, liveness, loudness, speechiness, tempo, time_signature, valence]
return track
dataframeにまとめる関数
# プレリストIDを入れるとdataframeを作成
def make_artist_df(ID):
playlist = ID
track_ids = getTrackIDs(playlist)
tracks = []
for track_id in track_ids:
time.sleep(0.3)
track = getTrackFeatures(track_id)
tracks.append(track)
df = pd.DataFrame(tracks, columns = ['name', 'album', 'artist', 'release_date', 'length', 'popularity', 'key', 'mode', 'danceability', 'acousticness', 'energy', 'instrumentalness', 'liveness', 'loudness', 'speechiness', 'tempo', 'time_signature', 'valence'])
return df
アーティストの曲データの取得
今回は,「あいみょん」と「椎名林檎」の曲を分類するモデルを作成します。
学習データには「本人名義の楽曲」,テストデータには「他のアーティストに提供している楽曲」としています。
まずは,「あいみょん」の楽曲が入っているプレイリストを検索してURLを取得します。
URLはhttps://open.spotify.com/playlist/ABCDEFG
のようになっていると思いますが,ABCDEFGが必要となります。
例えば,あいみょんのプレリストのURLがhttps://open.spotify.com/playlist/ABCDEFG
のときに,
df_aimyon = make_artist_df(['ABCDEFG'])
とすると,このプレイリストの曲を取得することができます。
「あいみょん」と「椎名林檎」の楽曲一覧を取得し,整理するコードは以下の通りです。
# プレイリストの取得
df_aimyon = make_artist_df(['2OeC2Zk6PArga135rOoRf2'])
df_ringo = make_artist_df(['0TVkEpBwbo5YYVvNAvjq7c'])
# 提供曲だけ除く
df_ringo_cut = df_ringo[df_ringo["album"] != "逆輸入 〜航空局〜"]
# 必要な特徴量だけ抽出
df_r = df_ringo_cut[['artist', 'length', 'popularity',
'key', 'mode', 'danceability', 'acousticness', 'energy',
'instrumentalness', 'liveness', 'loudness', 'speechiness', 'tempo',
'time_signature', 'valence']]
df_a = df_aimyon[['artist', 'length', 'popularity',
'key', 'mode', 'danceability', 'acousticness', 'energy',
'instrumentalness', 'liveness', 'loudness', 'speechiness', 'tempo',
'time_signature', 'valence']]
# 本人名義だけ抽出
df_a = df_a[df_a["artist"] == "Aimyon"]
df_r = df_r[df_r["artist"] == "Sheena Ringo"]
次に,テストデータとなる「他のアーティストに提供している楽曲」を同じ方法で取得します。
# 提供曲リスト
df_a_supply = make_artist_df(['1DHx4I1yaelFYhDgsTiRAr'])
df_r_supply = make_artist_df(['6MZGHZDQSSZBytE5wQr1WX'])
df_a_test = df_a_supply[['artist', 'length', 'popularity',
'key', 'mode', 'danceability', 'acousticness', 'energy',
'instrumentalness', 'liveness', 'loudness', 'speechiness', 'tempo',
'time_signature', 'valence']]
df_r_test = df_r_supply[['artist', 'length', 'popularity',
'key', 'mode', 'danceability', 'acousticness', 'energy',
'instrumentalness', 'liveness', 'loudness', 'speechiness', 'tempo',
'time_signature', 'valence']]
df_a_test["artist"] = "Aimyon"
df_r_test["artist"] = "Sheena Ringo"
学習データとテストデータを整理する
ここまでで,使うデータを全て取得できましたのでデータを整理します。
df_train
に学習データ,df_test
にテストデータが格納されるように整理します。
ここで,「あいみょん」の学習データ数が79,「椎名林檎」の学習データ数が195となっており,データ不均衡であるため,椎名林檎のデータ数を減らして同じデータ数にしています。
df_train = pd.concat([df_a,df_r.sample(79)],ignore_index=True)
df_test = pd.concat([df_a_test, df_r_test],ignore_index=True)
X_train = df_train.drop("artist", axis=1)
y_train = df_train["artist"]
X_test = df_test.drop("artist", axis=1)
y_test = df_test["artist"]
予測モデルの作成
今回は,ランダムフォレストで予測を行います。
精度は追求しないのでパラメータは初期設定にしています。
# 学習
from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier()
model.fit(X_train, y_train) # モデルの学習
結果の確認
それでは,結果を確認してみましょう。
# 予測値と実値との比較
df_result = pd.DataFrame()
df_result["true"] = y_test
df_result["Pred"] = model.predict(X_test)
以下のような出力になると思います。
print(df_result) ------------------------------------------- true Pred 0 Aimyon Sheena Ringo 1 Aimyon Sheena Ringo 2 Aimyon Sheena Ringo 3 Aimyon Sheena Ringo 4 Aimyon Aimyon 5 Aimyon Aimyon 6 Aimyon Aimyon 7 Sheena Ringo Sheena Ringo 8 Sheena Ringo Aimyon 9 Sheena Ringo Sheena Ringo
これでは,分かりにくいので混同行列で結果を見てみましょう。
![](https://icochan1.net/wp-content/uploads/2023/03/5f63f49b6b7d98988e1002a4a4f2d6d5-1024x576.png)
今回は椎名林檎の提供楽曲が多かったため,極端になっていますが,Accurateは77%(20/26)でした。
![](http://image.moshimo.com/af-img/2817/000000054171.png)
コード全文
今回使用したコードはこちらです。
import pandas as pd
import spotipy
from spotipy.oauth2 import SpotifyClientCredentials
import time
# spotify developerから取得したclient_idとclient_secretを入力
client_id = '自分のclient_idを入力'
client_secret = '自分のclient_secretを入力'
client_credentials_manager = spotipy.oauth2.SpotifyClientCredentials(client_id, client_secret)
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
# プレイリスト内の曲IDを取得
def getTrackIDs(playlist_ids):
track_ids = []
for playlist_id in playlist_ids:
playlist = sp.playlist(playlist_id)
while playlist['tracks']['next']:
for item in playlist['tracks']['items']:
track = item['track']
if not track['id'] in track_ids:
track_ids.append(track['id'])
playlist['tracks'] = sp.next(playlist['tracks'])
else:
for item in playlist['tracks']['items']:
track = item['track']
if not track['id'] in track_ids:
track_ids.append(track['id'])
return track_ids
# 曲IDを入れると,特徴を取得
def getTrackFeatures(id):
meta = sp.track(id)
features = sp.audio_features(id)
name = meta['name']
album = meta['album']['name']
artist = meta['album']['artists'][0]['name']
release_date = meta['album']['release_date']
length = meta['duration_ms']
popularity = meta['popularity']
key = features[0]['key']
mode = features[0]['mode']
danceability = features[0]['danceability']
acousticness = features[0]['acousticness']
energy = features[0]['energy']
instrumentalness = features[0]['instrumentalness']
liveness = features[0]['liveness']
loudness = features[0]['loudness']
speechiness = features[0]['speechiness']
tempo = features[0]['tempo']
time_signature = features[0]['time_signature']
valence = features[0]['valence']
track = [name, album, artist, release_date, length, popularity, key, mode, danceability, acousticness, energy, instrumentalness, liveness, loudness, speechiness, tempo, time_signature, valence]
return track
# プレリストIDを入れるとdataframeを作成
def make_artist_df(ID):
playlist = ID
track_ids = getTrackIDs(playlist)
tracks = []
for track_id in track_ids:
time.sleep(0.3)
track = getTrackFeatures(track_id)
tracks.append(track)
df = pd.DataFrame(tracks, columns = ['name', 'album', 'artist', 'release_date', 'length', 'popularity', 'key', 'mode', 'danceability', 'acousticness', 'energy', 'instrumentalness', 'liveness', 'loudness', 'speechiness', 'tempo', 'time_signature', 'valence'])
return df
# プレイリストの取得
df_aimyon = make_artist_df(['2OeC2Zk6PArga135rOoRf2'])
df_ringo = make_artist_df(['0TVkEpBwbo5YYVvNAvjq7c'])
# 提供曲だけ除く
df_ringo_cut = df_ringo[df_ringo["album"] != "逆輸入 〜航空局〜"]
# 必要な特徴量だけ抽出
df_r = df_ringo_cut[['artist', 'length', 'popularity',
'key', 'mode', 'danceability', 'acousticness', 'energy',
'instrumentalness', 'liveness', 'loudness', 'speechiness', 'tempo',
'time_signature', 'valence']]
df_a = df_aimyon[['artist', 'length', 'popularity',
'key', 'mode', 'danceability', 'acousticness', 'energy',
'instrumentalness', 'liveness', 'loudness', 'speechiness', 'tempo',
'time_signature', 'valence']]
# 本人名義だけ抽出
df_a = df_a[df_a["artist"] == "Aimyon"]
df_r = df_r[df_r["artist"] == "Sheena Ringo"]
# 提供曲リスト
df_a_supply = make_artist_df(['1DHx4I1yaelFYhDgsTiRAr'])
df_r_supply = make_artist_df(['6MZGHZDQSSZBytE5wQr1WX'])
df_a_test = df_a_supply[['artist', 'length', 'popularity',
'key', 'mode', 'danceability', 'acousticness', 'energy',
'instrumentalness', 'liveness', 'loudness', 'speechiness', 'tempo',
'time_signature', 'valence']]
df_r_test = df_r_supply[['artist', 'length', 'popularity',
'key', 'mode', 'danceability', 'acousticness', 'energy',
'instrumentalness', 'liveness', 'loudness', 'speechiness', 'tempo',
'time_signature', 'valence']]
df_a_test["artist"] = "Aimyon"
df_r_test["artist"] = "Sheena Ringo"
df_train = pd.concat([df_a,df_r.sample(79)],ignore_index=True)
df_test = pd.concat([df_a_test, df_r_test],ignore_index=True)
X_train = df_train.drop("artist", axis=1)
y_train = df_train["artist"]
X_test = df_test.drop("artist", axis=1)
y_test = df_test["artist"]
# 学習
from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier()
model.fit(X_train, y_train) # モデルの学習
# 予測値と実値との比較
df_result = pd.DataFrame()
df_result["true"] = y_test
df_result["Pred"] = model.predict(X_test)
まとめ
楽曲の特徴からアーティストを分類する方法についてご紹介しました。
Spotify APIは楽曲分析には最強のツールだと思います。
データ数を増やしたり特徴量をチューニングするとさらに精度も上がると思います。
ぜひ,いろんな使い方を試してみてください!
↓参考にさせていただいたサイト
コメント