作者 | John Koh
来源 | Medium
编辑 | 代码医生团队
感谢Spotify API,能够提取和探索喜欢听的歌曲 - 那些让我点击那个心形图标的歌曲。
建立
要从Spotify API获取数据,需要使用以下步骤进行初始设置:
1.登录Spotify for Developers并创建一个应用程序。
https://developer.spotify.com/dashboard/
2.从应用程序仪表板页面中,选择编辑设置并将重定向URI设置为
http:// localhost:8888
3.记下客户端ID和客户端密钥。
收集数据
可以使用Spotpy Web API的Spotipy来获取相关数据。要获取歌曲,需要生成授权令牌。
https://spotipy.readthedocs.io/en/latest/
import spotipy
import spotipy.util as util
from spotipy.oauth2 import SpotifyClientCredentials
cid = '<INSERT CLIENT ID>'
secret = '<INSERT CLIENT SECRET>'
username = ""
client_credentials_manager = SpotifyClientCredentials(client_id=cid, client_secret=secret)
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
# Get read access to your library
scope = 'user-library-read'
token = util.prompt_for_user_token(username, scope)
if token:
sp = spotipy.Spotify(auth=token)
else:
print("Can't get token for", username)
有两个API,current_user_saved_tracks和audio_features,用于获取标题,艺术家,时间歌曲以及声学,舞蹈和乐器等功能。这些功能将帮助更好地理解播放列表。
这些功能的一些描述如下表所示:
要查看歌曲的完整功能,您可以查看此链接。
https://developer.spotify.com/documentation/web-api/reference/tracks/get-audio-features/
#include timestamp added, title and artists of a song
df_saved_tracks['added_at'] = added_ts_list
df_saved_tracks['song_title'] = title_list
df_saved_tracks['artists'] = artist_list
df_saved_tracks = pd.DataFrame()
track_list = ''
added_ts_list = []
artist_list = []
title_list = []
more_songs = True
offset_index = 0
while more_songs:
songs = sp.current_user_saved_tracks(offset=offset_index)
for song in songs['items']:
#join track ids to a string for audio_features function
track_list += song['track']['id'] +','
#get the time when the song was added
added_ts_list.append(song['added_at'])
#get the title of the song
title_list.append(song['track']['name'])
#get all the artists in the song
artists = song['track']['artists']
artists_name = ''
for artist in artists:
artists_name += artist['name'] + ','
artist_list.append(artists_name[:-1])
#get the track features and append into a dataframe
track_features = sp.audio_features(track_list[:-1])
df_temp = pd.DataFrame(track_features)
df_saved_tracks = df_saved_tracks.append(df_temp)
track_list = ''
if songs['next'] == None:
# no more songs in playlist
more_songs = False
else:
# get the next n songs
offset_index += songs['limit']
#include timestamp added, title and artists of a song
df_saved_tracks['added_at'] = added_ts_list
df_saved_tracks['song_title'] = title_list
df_saved_tracks['artists'] = artist_list
以下是获得的数据集的示例。
我对音乐的品味有所改变吗?
获取数据后,是时候了解功能如何随时间变化。可以按照添加的年份和月份对歌曲进行分组,获取每个功能随时间的平均值并将其可视化。
线图按年份分隔,以使其更具一口大小。多年来,语气(紫罗兰色)最接近0。这表明我一般都会听那些不那么说唱的歌。声学(蓝色)是波动的,这意味着我随着时间的推移混合了声学和非声学歌曲。
我最感兴趣的是工具性(绿色)。2015年和2016年,它稳定接近0.然而,从2017年开始,工具性开始波动。这可能表明我的音乐品味从2017年开始改变。可以将数据过滤为2017年添加的歌曲。
我在听什么类型的歌?
聚类
根据上面的图表,我知道我正在听更多的乐器歌曲。但它是有助于舞蹈的那种歌曲吗?还是更古典的歌曲?其他人怎么样?我目前对音乐的品味是什么?可以将具有相似特征的歌曲组合在一起,并分析每个群集。一种类型的聚类方法是K-means Clustering,我将用它来分析我的歌曲。
https://en.wikipedia.org/wiki/K-means_clustering
对于群集,希望同一群集中的点尽可能接近。还希望群集之间的距离尽可能远离彼此。这使得每个群集看起来紧凑,同时彼此间隔开。
以下是4个集群的聚类情况的可视化。绿点表示每个群集质心(群集的中心)。
K-means聚类
由于聚类依赖于距离,因此数据规模将影响结果。例如如果想按高度聚集,从1.5米到1.9米,重量从60公斤到80公斤。因此这些点在高度轴上扩展0.4,权重在20上扩散。这意味着权重将在确定集群时占主导地位。
可以标准化数据范围,使特征影响结果。
cluster_features = ['acousticness', 'danceability', 'instrumentalness', 'energy', 'speechiness']
df_cluster = df_recent[cluster_features]
X = np.array(df_cluster)
scaler = StandardScaler()
scaler.fit(X)
X = scaler.transform(X)
在了解了群集的功能之后,会听到多少种类型/群组的歌曲?一种方法是根据自己的知识进行有根据的猜测。如果你聆听从edm到hip hop到爵士乐等所有类型的音乐,你可以提供更高的数字,比如... 7也许吧?因为K-means聚类需要指定想要的聚类数量,可以设置k = 7,其中k是聚类的数量。
另一种方法是使用肘方法的帮助来确定簇的数量。在弯头方法中,可以对一系列设定的簇数进行聚类,例如k = 1,k = 2,...,k = 9,k = 10。对于每个k,将获取每个点并测量其与群集质心的平方距离,并将它们相加。这称为平方距离之和(SSD)。SSD测量每个点与群集质心的接近程度。因此SSD越小,相同群集中的点越近。
ss_dist = []
K = range(1, 11)
for k in K:
km = KMeans(n_clusters=k, init='k-means++', random_state=123)
km = km.fit(X)
ss_dist.append(km.inertia_)
plt.plot(K, ss_dist, 'bx-')
plt.xlabel('k')
plt.ylabel('Sum of squared distances')
plt.title('Elbow Method For Optimal k')
plt.show()
因此如果为每个k绘制SSD,将得到如下所示的曲线:
从上图可以看出,随着k的增加,SSD减少了。这是有意义的,因为点可能具有更近的群集,从而导致SSD更低。
早些时候,我提到希望每个集群中的点尽可能接近。但是不能选择k = 10,因为它是最低的。想象一下。如果选择k = N,其中N是歌曲的数量,将每首歌曲作为自己的群集,因此SSD将为0.这是因为每个点的群集质心是该点本身。
相反将选择k,这样如果添加另一个集群,SSD会略有下降。这被称为肘法。如果将曲线看作我们的手臂,会在开始时获得一个陡峭的斜坡,中间突然变得温和。这使它具有“肘部”形状。
基于肘法,推荐的簇数为4,因为从k = 4到k = 5,线条变得平缓。然而,我也玩了k = 5,发现我喜欢给出的簇。因此,在这篇文章中,我将分享我得到的k = 5的结果。
集群可视化
那集群怎么样?不幸的是,在此还无法查看它。这是因为簇使用5个特征形成。如果您将每个要素视为维度,则可获得5-D。由于可以查看高达3-D的图像,需要执行一种称为降维的技术。这使可以从5-D减少到更低的任何尺寸。
为了尽可能直观地尝试解释它,降维旨在从较高维度制作低维度的特征集,同时保留尽可能多的信息。如果您希望更好地了解它的作用,您可以观看有关主成分分析(PCA)的视频,这是降维的方法之一。
如果使用PCA来减少维度,让我们看看保留了多少数据。
蓝色条显示每个主要组件(PC)对数据的贡献量。第一台PC贡献了40%的数据信息。第二个和第三个每个贡献20%。红线显示PC的数据累积信息。通过从5维减少到2,保留了60%的数据信息。同样,如果我们要减少到3维,则保留80%的数据信息。
现在看看聚类在二维和三维散点图上的样子。
二维散点图中的点彼此重叠,看起来可能看起来没有很好地完成聚类。但是如果从三维视角来看它,可以更好地看到这些集群。
尝试另一种叫做t-Distributed Stochastic Neighbor Embedding(t-SNE)的方法。t-SNE在可视化高维数据方面表现良好。
在这种情况下,2-D t-SNE散点图能够很好地可视化5个簇。还可以粗略地告诉群集3是最大的群集,群集0或1是最小的群集。看看如何使用条形图分布集群。
群集分析
现在可以了解不同集群的特征。比较群集中的要素分布。
# set binning intervals of 0.1
bins = np.linspace(0,1,10)
# create subplots for number of clusters(Rows) and features(Cols)
num_features = len(cluster_features)
f, axes = plt.subplots(num_clusters, num_features,
figsize=(20, 10), sharex='col'
row = 0
for cluster in np.sort(df_recent['cluster'].unique()):
df_cluster = df_recent[df_recent['cluster'] == cluster]
col = 0
for feature in cluster_features:
rec_grp = df_recent.groupby(pd.cut(df_recent[feature], bins)).size().reset_index(name='count')
cluster_grp = df_cluster.groupby(pd.cut(df_cluster[feature], bins)).size().reset_index(name='count')
sns.barplot(data=rec_grp, x=feature, y='count',
color='grey', ax=axes[row, col])
sns.barplot(data=cluster_grp, x=feature, y='count',
color='red', ax=axes[row, col])
axes[row, col].set_xlabel('')
axes[row, col].set_xticklabels(range(1,10))
if col > 0:
axes[row, col].set_ylabel('')
if row == 0:
axes[row, col].set_title(feature)
col += 1
row += 1
f.suptitle('Profile for each clusters')
plt.show()
每行代表集群,0到4,每列代表特征。灰色条表示要素的分布。这使可以大致了解该功能的分布。红色条表示该群集中要素的分布,用于与其他群集进行比较。
当查看每个群集的分布时,可以看到每个群集在某些特征中是高还是低。这是通过红色条相对于灰色条位于右侧(高侧)还是左侧(低侧)来识别的。从这些特征中,可以对它们进行分析,甚至可以提出一个集群标识。
Cluster 0 (Instrumental): Highinstrumentalness. Low speechiness.
Cluster 1 (Lyrical): High danceability, energy, speechiness. Low acousticness, instrumentalness.
Cluster 2 (Chill vibes): High danceability. Low energy, instrumentalness, speechiness.
Cluster 3 (Dance): High danceability, energy. Low acousticness, instrumentalness, speechiness.
Cluster 4 (Wind down): Highacousticness. Low danceability, instrumnetalness, energy, speechiness.
还可以通过获取群集特征的平均值并将其绘制到雷达图上来进行分析。这可能更容易一目了然地查看所有群集之间的差异。
雷达图的读数与上面给出的曲线相似。还可以看到第2组和第4组具有类似的统计数据。不同之处在于群集2更侧重于可舞蹈性,而群集4更侧重于声学。
集群样本
看看每个群集中的歌曲是否适合群集配置文件。每个群集中有3首歌曲,你可以听一听,看看是否有意义:
Cluster 0 (Instrumental):
Go Back Home by FKJ
Hypnotised by Coldplay
Libertango by Astor Piazzolla, Bond
Cluster 1 (Lyrical):
September Rose by Cailin Russo
Candlelight by Zhavia Ward
BBIBBI by IU
Cluster 2 (Chill vibes):
Drop the Game by Flume, Chet Faker
Livid by ELIZA
Find a Way by Matt Quentin, Rinca Yang
Cluster 3 (Dance):
Ultralife by Oh Wonder
Little Man by The Pb Underground
Finesse (Remix) [feat. Cardi B] by Bruno Mars,Cardi B
Cluster 4 (Wind down):
Frozen by Sabrina Claudio
Break the Distance 2.0 by Ashton Edminster
Someone To Stay by Vancouver Sleep Clinic
结论
首先看一下不同的功能,并试着弄清楚音乐品味是否有所改变。从过滤后的数据集中,进行了聚类分析。然后可视化以大致了解它的外观并确保聚类很好。最后绘制了每个特征的分布并对其进行了分析。在一天结束时,能够更好地理解喜欢的歌曲类型。
数据的收集,可以发现在这里,可以找到分析在Github上。
https://github.com/jkwd/spotify/blob/master/Code/Spotify%20Get%20Data.ipynb
https://github.com/jkwd/spotify/blob/master/Code/Favourite%20songs%20EDA.ipynb
参考
绘制构面图:
https://seaborn.pydata.org/examples/many_facets.html
主成分分析(PCA)的分步指南:
https://www.youtube.com/watch?v = FgakZw6K1QQ
关于t-SNE的教程:
https://www.datacamp.com/community/tutorials/introduction-t-sne
绘制雷达/蜘蛛图:
https://python-graph-gallery.com/392-use-faceting-for-radar-chart/
推荐阅读
关于图书
《深度学习之TensorFlow:入门、原理与进阶实战》和《Python带我起飞——入门、进阶、商业实战》两本图书是代码医生团队精心编著的 AI入门与提高的精品图书。配套资源丰富:配套视频、QQ读者群、实例源码、 配套论坛:http://bbs.aianaconda.com 。更多请见:aianaconda.com
点击“阅读原文”配套图书资源
本文分享自微信公众号 - 相约机器人(xiangyuejiqiren)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。
来源:oschina
链接:https://my.oschina.net/u/3267804/blog/4564892