Aidemy Blog

株式会社アイデミーのブログです。機械学習・ディープラーニング関連技術の活用事例や実装方法をまとめる技術記事や、キャリア記事等を発信しています

Spotify APIで好きなアーティストの繋がりを可視化してディグる

初めまして、Aidemy研修生の照屋と申します。

突然ですが、皆さんは好きなアーティストのディグり方(探し方)ってどんな方法を使っていますか?

f:id:teruya6350:20180831000229j:plain

最近ではYouTubeや音楽発見サービス(Spotify、Apple Music…)、人によってはレコード店で物色という人もいると思います。私も色々な所にアンテナを立てて日々好きなジャンルのアーティスト達を探しています。

その中でも音楽発見サービスのSpotifyをよく利用するのですが、Spotifyが選んでくれるおすすめアーティストでたまに「えっこの人?」っていう人が入ってきたりします。実際に聞いてみても「うーん、好きなあのアーティストとテイストは似てるんだけど、違うんだよなあ」ってことがザラにあります。(笑)

そこで自分の好きなアーティストと繋がりのあるアーティストを可視化出来れば面白いディグりが出来るんじゃないかと思い、今回はSpotify APIというものを使って好きなアーティストの可視化したネットワークグラフを作っていきたいと思います。

0.Python使用環境

・Jupyter Notebook  1.0.0

・Spotipy 2.4.4
・pandas as pd  0.23.4
・matplotlib.pyplot as plt 2.2.3
・networkx as nx 2.1
・python_louvain 0.11

 

import部分ははこのようになっています。

import spotipy
import json
import pandas as pd
import matplotlib.pyplot as plt
import networkx as nx
from community import community_louvain
from spotipy.oauth2 import SpotifyClientCredentials

 

 

1.準備

まずはSpotify APIのspotipyを使用する準備をしていきます。

下記のサイトに飛んで、Spotifyのアカウントを登録して、

client_idとclient_secretを取得します。

https://developer.spotify.com/dashboard/login

# Spotify APIの準備
client_id = 'your id in here'
client_secret = 'your secret in here'
client_credentials_manager = spotipy.oauth2.SpotifyClientCredentials(client_id, client_secret)
spotify = spotipy.Spotify(client_credentials_manager=client_credentials_manager)

これでspotipyを使える状態になりました。

アーティストの情報をpandasのデータフレームにいれて処理していくので、まずデータフレームを定義します。

# アーティスト情報を格納するDataFrameを定義
artist_df = pd.DataFrame(columns=['artist_name','artist_ID','genre','popularity','related_artist_names'])

これで準備はできました、早速ディグっていきましょう。

2.最初のアーティストを検索する

アーティストをディグる方法として、自分の知っているアーティストに関連した(曲のテイストやルーツなど)アーティストを調べていくという方法があります。今回は、この方法に沿って、最初に知っているアーティストを一つ挙げて、そこから関連を調べていくことにします。

今回は、ここ数年巷を騒がせているSuchmosを入れてみました。Suchmosは茅ヶ崎生まれの横浜シティボーイな感じで、幅広い層におすすめできるアーティストなので、聞いたことない人はぜひ聞いてみて下さい。(笑)

open.spotify.com

知っているアーティストの名前をspotify上で検索すると、そのアーティストの固有IDを取得することができます。IDには、そのアーティストの名前のほかに、配信しているアルバムのタイトルや音楽ジャンル、認知度、関連するアーティストのIDなどが紐づけられています。

ここでは、その紐づいたデータを読み込んで、最初のアーティストのレコードとしてDataFrameに格納します。

# 最初のアーティストを取得
name = 'Suchmos'
spotapi_out = spotify.search(q='artist:' + name, type='artist')
artist_items = spotapi_out['artists']['items'][0]
artist_id = artist_items['id']
artid_list = [artist_id]
artname_related_list = []
spotapi_out_related = spotify.artist_related_artists(artist_id)
for artname_related in spotapi_out_related['artists']:
    artname_related_list.append(artname_related['name'])
s = pd.Series([artist_items['name'], artist_items['id'], artist_items['genres'],artist_items['popularity'],artname_related_list],index=artist_df.columns)
artist_df = artist_df.append(s,ignore_index=True)

これで最初のアーティストとそのアーティストに関連するアーティストの情報を取得できました。

3.関連アーティストの関連アーティストを探していく

次に、先ほど取得した最初のアーティストに関連するアーティストのIDを使って、さらに関連の関連…といったように調べていきます。家系図をたどるような作業で、とてもワクワクしますね。 このように、2章での処理と同様、DataFrameにアーティストの情報を格納していきます。

artid_list_tail = 0

for i in range(relation_size):
    artid_list_head = artid_list_tail
    artid_list_tail = len(artid_list)
    for artid in artid_list[artid_list_head:artid_list_tail]:
        spotapi_out = spotify.artist_related_artists(artid)
        for artid_related in spotapi_out['artists']:
            artist_df_bool = artist_df['artist_ID']==artid_related['id']
            if artist_df_bool.sum()==0 and artid_related['popularity']>=Threshold:
                # 類似のアーティストリストを作成
                spotapi_out_related = spotify.artist_related_artists(artid_related['id'])
                artname_related2_list = []
                for artname_related2 in spotapi_out_related['artists']:
                    artname_related2_list.append(artname_related2['name'])
                artid_list.append(artid_related['id'])
                s = pd.Series([artid_related['name'], artid_related['id'], artid_related['genres'], 
                               artid_related['popularity'], artname_related2_list], index=artist_df.columns)
                artist_df = artist_df.append(s,ignore_index=True)

ただし、関連の関連の…と続けていくとアーティストの数は指数的に増大していくので、繰り返し数を決定するrelation_sizeはあまり大きい値にしないほうがいいです。最初のアーティストの認知度にもよりますが、5以上では処理が全然終わらなくなることが多い印象でした。

4.アーティスト同士の関連情報を辞書に格納

 ここでは、取得した大量のアーティスト情報をネットワークグラフに表すためにアーティスト同士の関係を作らないといけないので、その準備をしていきます。

まず、どのアーティストが誰と関連しているかを表す辞書を作ります。

アーティスト関連辞書={アーティストの名前:[関連アーティストの名前1,関連アーティストの名前2,.....] }となるようにデータを格納していきます。

# アーティストの関係の辞書を作る
plt.figure(figsize = (50, 50))
artdic = {}
for i in range(len(artid_list)):
    artdic[artist_df.iloc[i,0]] = []
for i in range(len(artid_list)):
    for artname_related in artist_df.iloc[i,4]:
        artdic[artist_df.iloc[i,0]].append(artname_related)

 

5.アーティスト間ネットワークを可視化する

最後に取得したアーティスト同士の関連情報を、ネットワークとして可視化します。可視化にはnetworkxというライブラリを使います。各アーティストを、その媒介中心性に比例した大きさを持つノードとし、エッジをつないでネットワークを描きます。

# グルーピング してグラフを表示
G = nx.Graph(artdic)
pos = nx.spring_layout(G)
partition = community_louvain.best_partition(G)
betcent = nx.communicability_betweenness_centrality(G)
node_size = [10000 * size for size in list(betcent.values())]
nx.draw_networkx(G, pos ,node_color=[partition[node] for node in G.nodes()], node_size=node_size, cmap=plt.cm.RdYlBu)
plt.axis('off') 
plt.show()

 

では、可視化したネットワークの全体をご覧ください!

 

f:id:teruya6350:20180831132730j:plain

 みっ、見えない(笑)。

数が多すぎて、細かいところはわかりませんが、アーティスト同士がクラスタとしてグルーピングされていることがわかりますね。

では最初のアーティストにしたSuchmosの周囲のネットワークを見てみます。

f:id:teruya6350:20180831132042j:plain

ターゲットのSuchmosの周りには今のシティポップ界隈を賑やかすNulbarichやYogee New Wavesなどがいます。

その中でもHouse Popに寄ったIriやChelmicoといったアーティストを介することでtofuBeatsやPUNPEEといったPopsの面々に繋がります。

f:id:teruya6350:20180831131854j:plain

Suchmosからくるりを介することでエレファントカシマシやチャットモンチー、ELLEGARDEN、アジカンといったJ-pop,J-rockに繋がっていくことが分かりますね。

f:id:teruya6350:20180831132353j:plain

 

まとめ

今回は、見た目のわかりやすさとグラフの描画限界などを考慮して邦楽で関連アーティストの取得量にも制限を掛けていますが、本当にSpotifyの全力を出して制限を掛けずにグラフを描画出来たら、音楽体系のネットワークをグラフに出来るのでもっと面白いものが見れると思います。

今後はアーティストごとのジャンル情報や楽曲の音データの特徴量などの要素も考慮したネットワークを可視化してさらに、ディグりツールとしての性能を追求していきたいと思います。

ここまでご覧くださってありがとうございました。