让数据科学家代替DJ?Python帮你实现

2023-10-22 15:40

本文主要是介绍让数据科学家代替DJ?Python帮你实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

全文共5105字,预计学习时长28分钟

 

让数据科学家代替DJ?Python帮你实现

图源:unsplash

 

数据科学是一门庞大的学科,它不断地扩展到新的行业,音乐产业就是其中之一。如果把这些应用程序当作一个“黑匣子”,可以观察到它的输入(数据)和输出(产品)。该项目旨在使用Python操作Spotify音乐数据,其范围有两个:

 

· 证明API(应用程序编程接口)的存在对于向算法提供超精细数据具有重要意义。

· 演示简单的统计数据(适当应用时)如何对日常行为进行编码,将其分解为基本要素,并在其基础上构建有价值的产品。

 

这个故事,最开始是为了调查音乐背后的统计数据,最后发现方程式背后也有“音乐”……

 

让数据科学家代替DJ?Python帮你实现

图源:unsplash

 

让数据科学家代替DJ?Python帮你实现

 

概念

 

假设一个情景。作为一名数据科学家,笔者工作的数据公司(Data Corp)记录了青年营销部门获得的可观利润,因此公司决定举办聚会犒劳年轻的客户。

在没有DJ的情况下,主管让笔者负责音乐,让派对持续到早上!她给了笔者一些Spotify播放列表,让笔者最终选定并创建一个。然而,忽视现代音乐趋势让笔者遇到一个棘手的问题。

使用Python访问所有播放列表,提取每个曲目的每个音频特征进行统计分析,并将最适合(派对)的曲目包装到最终的播放列表中,如何?当然,这里有一个技术性的问题:一个节拍也听不到!

 

让数据科学家代替DJ?Python帮你实现

 

图源:unsplash

 

为了更好地传达结果,假定:

 

#1:个人Spotify播放列表代表的是公司给笔者的。

#2:该聚会的目标群体是18至30岁的年轻人,这意味着……跳舞!然而,他们中的许多人可能会有家人陪伴,也就是说,一小部分客人会更好地享受到欢快的音乐。

#3:在音频特性中,Spotify只考虑了 danceability, energy, tempo, loudness & valence (见第2节)。那是因为,它们能更好地表达一首曲子是否适合一个舞会。

#4:改进所选播放列表的方法有两种:删除或添加分别被视为“坏”或“好”(涉及一个或多个音频特征)的曲目。笔者只采用后者,以扩大最终的播放列表。

 

笔者打算按下面的步骤来做:

 

· 设置运行代码的环境。

· 请求Spotify API获取所有相关音乐数据并提供简要说明。

· 使用Numpy、Pandas和一些附加的Python库执行EDA(探索性数据分析),以数字和可视化的方式探索候选播放列表。

· 选择-使用两种统计技术优化最合适的播放列表。

 

让数据科学家代替DJ?Python帮你实现

 

图源:unsplash

 

让数据科学家代替DJ?Python帮你实现

 

一、设置

 

在本节中,设置所需的环境,以便应用分析技术。如果已经准备好下面列出的任何部分,可以跳过它们。

 

· 申请Spotify开发者帐户并创建应用程序。[在此过程中,将创建一个客户ID,并为应用程序提供一个客户机密]。

· 安装Jupyter Notebook-一个开源的web应用程序,用于创建/共享包含实时代码、方程式、可视化和叙述性文本的文档。

· 安装Spotipy-用于访问Spotify Web API和请求的轻量级Python库-用于寻址API的Python模块。可以使用CLI(命令行界面)或Jupyter notebook来运行以下命令:

 

pip install spotipypipinstall requests

install.py

 

•导入必要的库:

 

# Import the librariesimport osimport pandas as pdimport numpy as npimport jsonimportmatplotlib.pyplot as pltimport seaborn as snsimport spotipyimportspotipy.util as utilfromspotipy.oauth2 importSpotifyClientCredentials

 

•执行授权代码流:

 

# Declare the credentialscid ='XXXX'secret ='XXXX'redirect_uri='http://localhost:7777/callback'username ='XXXX'# Authorization flowscope ='user-top-read'token = util.prompt_for_user_token(username, scope, client_id=cid,client_secret=secret, redirect_uri=redirect_uri)if token:sp = spotipy.Spotify(auth=token)else:print("Can'tget token for", username)auth.py

 

请注意,与其通过笔记本直接声明凭证,还不如通过相应地设置环境变量,使它们暂时可用:

 

export SPOTIPY_CLIENT_ID="XXXX"exportSPOTIPY_CLIENT_SECRET="XXXX"exportSPOTIPY_REDIRECT_URI="http://localhost:7777/callback"

 

让数据科学家代替DJ?Python帮你实现

 

二、数据解释与获取

 

Spotify为其开发人员提供了许多表征音轨的音频特征(有关音频特性对象的更全面的解释,请参见此处)。下面列出要使用的特征,并简要说明:

 

让数据科学家代替DJ?Python帮你实现

图源:unsplash

 

· Loudness:[-60.0-0db]描述了音轨的整体响度,或者说,声音的质量,这是与体力(振幅)相关的主要心理因素。

 

· Energy:[0.0-1.0]描述了对活动和强度的感性测量。充满活力的音轨让人感觉快速、响亮和嘈杂。

· Valence:[0.0-1.0]描述音轨听起来“积极”的程度。高价意味着更积极的声音(如欢快、欢快等)。

· Tempo:以BPM为单位描述音轨的总体估计节奏(每分钟节拍),直接从节拍平均的持续时间得出。

· Danceability:[0.0-1.0]根据音乐元素(节奏、稳定性、节拍强度等)的组合,描述一个轨道是否适合跳舞。低值意味着较少的舞步。

 

数据提取部分分三步完成:访问用户播放列表;提取每个播放列表的曲目;提取每个曲目的音频特征。对于每个步骤,创建一个函数,实现相应的Spotipy方法。

 

(a)访问用户的播放列表

 

deffetch_playlists(sp,username):"""Returns theuser's playlists."""id = []name = []num_tracks = []#Make the API requestplaylists = sp.user_playlists(username)for playlist in playlists['items']:id.append(playlist['id'])name.append(playlist['name'])num_tracks.append(playlist['tracks']['total'])# Create the final df  df_playlists = pd.DataFrame({"id":id, "name":name, "#tracks": num_tracks})return df_playlistsplaylists =fetch_playlists(sp,username)playlists= playlists[:4].copy()playlists

fetch_plst.py

 

此函数返回一个数据帧,其中包含用户播放列表的id、name和曲目数#tracks。显然,有4个候选播放列表:

 

让数据科学家代替DJ?Python帮你实现

playlists 数据帧

 

(b) 获取播放列表的曲目

 

deffetch_playlist_tracks(sp, username, playlist_id):"""Returns thetracks for the given playlist."""offset =0tracks = []#Make the API requestwhileTrue:content = sp.user_playlist_tracks(username, playlist_id, fields=None, limit=100, offset=offset,market=None)tracks += content['items']if content['next'] isnotNone:offset +=100else:breaktrack_id = []track_name = []for track in tracks:track_id.append(track['track']['id'])track_name.append(track['track']['name'])#Create the final dfdf_playlists_tracks = pd.DataFrame({"track_id":track_id, "track_name": track_name})return df_playlists_tracks

fetch_trcs.py

 

这个函数以playlist_id作为参数,返回一个数据帧,包括每个曲目的曲目 track_id 和 track_name 。不直接调用它,而是在下面的函数中使用它。

 

(c) 获取曲目的音频特征

 

deffetch_audio_features(sp, username, playlist_id):"""Returns theselected audio features of every track,for the givenplaylist."""# Usethe fetch_playlist_tracks function to fetch all of the tracksplaylist =fetch_playlist_tracks(sp, username, playlist_id)index =0audio_features = []#Make the API requestwhile index < playlist.shape[0]:audio_features += sp.audio_features(playlist.iloc[index:index+50, 0])index +=50#Append the audio features in a listfeatures_list = []for features in audio_features:features_list.append([features['danceability'],features['energy'],features['tempo'],features['loudness'],features['valence']])df_audio_features = pd.DataFrame(features_list,columns=['danceability', 'energy','tempo', 'loudness', 'valence'])# Set the 'tempo' & 'loudness' in the same range withthe rest featuresfor feature in df_audio_features.columns:if feature =='tempo'or feature =='loudness':continuedf_audio_features[feature] =df_audio_features[feature] *100#Create the final df, using the 'track_id' as index for future referencedf_playlist_audio_features = pd.concat([playlist,df_audio_features], axis=1)df_playlist_audio_features.set_index('track_id', inplace=True, drop=True)return df_playlist_audio_features

fetch_aud_ftrs.py

 

给定 playlist_id 作为参数,此函数返回每个曲目的 track_id, name 和音频特征(danceability, energy, tempo, loudness, valence)。因此,对于4个播放列表中的每一个,创建相应音频特征的数据帧:

 

df_dinner =fetch_audio_features(sp, username, '37SqXO5bm81JmGCiuhin0L')df_party=fetch_audio_features(sp, username, '2m75Xwwn4YqhwsxHH7Qc9W')df_lounge=fetch_audio_features(sp, username, '6Jbi3Y7ZNNgSrPaZF4DpUp')df_pop=fetch_audio_features(sp, username, '3u2nUYNuI08yUg877JE5FI')

aud_ftrs.py

 

让数据科学家代替DJ?Python帮你实现

df_dinner 数据框示例

 

仅仅借助API的力量就获得了所有必要数据的纯编码!

 

让数据科学家代替DJ?Python帮你实现

 

三、EDA

 

为了减少混乱,这里不包括数据可视化代码,但它可以在GitHub repo上使用。

 

首先,在一个图中描绘所有播放列表的音频特征,以便容易地感知哪个最适合聚会。

 

让数据科学家代替DJ?Python帮你实现

音频特征水平条形图

 

显然,把特征作为整体来看,Party和Pop播放列表取代了另外两个。仔细看看这两个,就能更清楚地了解哪一个占上风…

 

让数据科学家代替DJ?Python帮你实现

df_party 和df_pop水平横条图

 

除了danceability特征外,其他特征在派对播放列表中更高。这是一个必须选择和建立,以完善最终的播放列表。

 

让数据科学家代替DJ?Python帮你实现

 

四、播放列表的优化

 

其主要作用是尽可能增加派对播放列表的音频特征。但是,增加一个特征可能会减少另一个特性,因此必须考虑优先级。就笔者个人而言,根据假设2,danceability(年轻人)应该是主要特征,下一个特征是valence(家庭成员)。

 

让数据科学家代替DJ?Python帮你实现

图源:unsplash

 

这些变量是定量的,同时也属于比率尺度的测量。因此,箱线图可以有效地描述每个特征的个体分布。这样的图表和描述性统计表(通过pandas.DataFrame.describe方法)可以提供关于每个特定四分位数下的值的比例的良好视觉展示。

 

下面将详细说明原始的df_party数据框,突出显示danceability和valence平均值、第二(中位数)和第三个四分位数:

 

让数据科学家代替DJ?Python帮你实现

 

 

让数据科学家代替DJ?Python帮你实现

df_party数据的描述性统计和箱线图

 

竖直的黄线是中位数,而▴符号代表平均数。一般的目标是“推动”每一个特征的分布尽可能地向右,也就是说,沿着播放列表曲目方向增加,以便获得一个更好的“聚会”体验!根据假设4,从df_pop(第二个决赛播放列表)中添加曲目,每次都寻找机会:

 

· 将平均值向右移动(增加平均音频特征)

· 或将中位数移到平均值的右侧(确保至少50%的歌曲高于平均值)

· 或两者兼而有之

 

方法一

 

一个好的出发点是,抽取一个df_pop的样本,并将其添加到主样本(df_party)中,随机的除外。通过使用pandas.DataFrame.sample()函数和weights参数,可以预先配置danceability值越大,就越有可能对相应的行进行采样。这种方法产生的数据框是df_party_exp_I(exp代表expanded)。

 

# Take a sample from the Pop playlistdf_pop_sample_I= df_pop.sample(n=40, weights='danceability',random_state=1)df_pop_sample_I.describe()# Concatenate the original playlist with the sampledf_party_exp_I= pd.concat([df_party, df_pop_sample_I])df_party_exp_I.describe()

sample_I.py

 

让数据科学家代替DJ?Python帮你实现

 

 

让数据科学家代替DJ?Python帮你实现

df_party_exp_I描述性统计和方框图

 

· 主要音频特征danceability增加;平均值上升近0.5,其分布也略有优化。中位数从68.20移到69.30,第三(上)四分位数分别从77.20移到78.90。

· 但是, valence特征下降了0.61,四分位都没有向右移动。鉴于此,应该寻找进一步的优化机会。

 

方法二

 

这一次将利用NumPy布尔索引并过滤Pop播放列表,以便只返回满足指定条件的行。特别是,将danceability和valence特征设置为高于派对播放列表的相应平均值,分别为69.55和51.89。

 

# Take a sample from the Pop playlistdf_pop_sample_II= df_pop[(df_pop['danceability'] >69.55) & (df_pop['valence'] >51.89)].copy()# Concatenate the original playlist with the sampledf_party_exp_II= pd.concat([df_party, df_pop_sample_II])df_party_exp_II.describe()

sample_II.py

 

让数据科学家代替DJ?Python帮你实现

 

 

让数据科学家代替DJ?Python帮你实现

df_party_exp_II描述性统计和方框图

 

· danceability增加更多。这次平均值增加了将近2.17!随着中位数和上四分位数向右移动,沿着该功能的曲目分布也得到了优化,这基本上意味着至少50%的播放列表高于主要声学功能的“新”较高平均值(71.71)。

· 尽管如此,valence特征下降了4.21,第二和第三个四分位数均高于平均值。

 

方法三

 

一个特征的优化并不一定意味着其他特征的优化。为了改善这一缺点,将引入一个方程,其变量是声学特征,参数是赋予它们的权重。既然非常重视danceability特征,那么相应的权重应该更高。最后分数计算如下:

 

Score =(danceability *30)+(energy *20)+(tempo *20)+(loudness *10)+(valence *20)

 

为播放列表的每个单曲计算这个分数(创建一个新的列score),然后计算各自的描述性统计。这样,可以更好地评估,丰富df_party,同时在每个特征上实现更统一(根据权重)的优化。

 

简言之,df_party, df_party_exp_I & df_party_exp_II的平均score分别为7355分、7215分和7416分。很明显,虽然方法一相比原来的播放列表找到了更好的danceability,但它破坏了派对的整体体验(平均score从7355下降到7215)。就方法二而言,平均score提高了近62分。然而,也可以不用这两种方法…

 

这一次,通过使用新引入的score列,将过滤df_pop数据帧,并获取注意到score高于df_party平均值的行。因此,增加后者!

 

# Take a sample from the Pop playlistdf_pop_sample_III= df_pop[df_pop['score'] > df_party['score'].mean()].copy()# Concatenate the original playlist with the sampledf_party_exp_III= pd.concat([df_party, df_pop_sample_III])df_party_exp_III.describe()

sample_III.py

 

让数据科学家代替DJ?Python帮你实现

 

让数据科学家代替DJ?Python帮你实现

df_party_exp_III描述性统计和方框图

 

事实上,这次:

·

danceability特征提高了近1.17,valence增加了4.06(平均值的右移)

· 两种分布都得到改善(中位数移到平均值的右侧)

· score为122.3,是目前为止最好的!(上下文意味着更高的潜力,播放列表在加权音频特征上更加统一)

 

作为一个完整的检查,应该一次性描述和比较所有的方块图—这可能看起来有点拥挤。幸运的是,变量的性质(见上文)允许使用KDE(内核密度图)。

 

让数据科学家代替DJ?Python帮你实现

KDE图

 

现在非常清楚了,方法三(绿色分布)是最好的,因为它实现了更高的右移。

 

最后,最终得到的数据帧(df_party_exp_III)包含了最终的音轨。唯一悬而未决的操作是将其转换为真正的播放列表。下面,第一个函数创建最终的播放列表,将其名称作为参数以及描述。另一个,从数据帧迁移轨迹。

 

请注意,授权流将再次运行,这次将使用不同的作用域(playlist modify public)。只需查看指南就好(https://github.com/makispl/Spotify-Data-Analysis/blob/master/README.md)。

 

defcreate_playlist(sp,username, playlist_name, playlist_description):playlists = sp.user_playlist_create(username, playlist_name, description =playlist_description)create_plst.pydefenrich_playlist(sp,username, playlist_id, playlist_tracks):index =0results = []while index <len(playlist_tracks):results += sp.user_playlist_add_tracks(username, playlist_id, tracks =playlist_tracks[index:index +100])index +=100

enrich_plst.py

 

# Make a temporary list of trackslist_track =df_party_exp_III.index# Create the playlistenrich_playlist(sp,username, '779Uv1K6LcYiiWxblSDjx7', list_track)

create_plst.py

 

让数据科学家代替DJ?Python帮你实现

播放列表数据帧

 

让数据科学家代替DJ?Python帮你实现

 

Bingo!

让数据科学家代替DJ?Python帮你实现

 

结论

 

到目前为止,已经处理了数百首曲目,检查了它们的音频特征,最后选择了最适合聚会的曲目,只用到了Python。通过这种方式,成功地完成了任务:

 

· 演示了简单(描述性)的统计数据和编码(如果适当组合)是如何计算出此类耗时的活动的。

· “尝到”了拥有可请求的API的重要性,以便提取有意义的数据。

 

无论是从DJ还是从数据科学家的角度“深入”音乐世界,这无疑都是美妙的……

 

让数据科学家代替DJ?Python帮你实现

图源:unsplash

 

但是,有效地,当涉及到大量音乐数据集的精确性、敏捷性和彻底处理时,后者可以通过几行代码来指示计算机体面地执行。也就是说,有一件事是必然的:

 

数据科学已经找到了另一个发展壮大的“市场”,这意味着统计背后确实有“音乐”,达到了节拍背后有数学的水平…

 

Jupyternotebook已准备好立即运行,让Pandas摇滚吧!

 

让数据科学家代替DJ?Python帮你实现

留言 点赞 关注

我们一起分享AI学习与发展的干货
欢迎关注全平台AI垂类自媒体 “读芯术”

(添加小编微信:dxsxbb,加入读者圈,一起讨论最新鲜的人工智能科技哦~)

这篇关于让数据科学家代替DJ?Python帮你实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/262349

相关文章

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

关于数据埋点,你需要了解这些基本知识

产品汪每天都在和数据打交道,你知道数据来自哪里吗? 移动app端内的用户行为数据大多来自埋点,了解一些埋点知识,能和数据分析师、技术侃大山,参与到前期的数据采集,更重要是让最终的埋点数据能为我所用,否则可怜巴巴等上几个月是常有的事。   埋点类型 根据埋点方式,可以区分为: 手动埋点半自动埋点全自动埋点 秉承“任何事物都有两面性”的道理:自动程度高的,能解决通用统计,便于统一化管理,但个性化定

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

异构存储(冷热数据分离)

异构存储主要解决不同的数据,存储在不同类型的硬盘中,达到最佳性能的问题。 异构存储Shell操作 (1)查看当前有哪些存储策略可以用 [lytfly@hadoop102 hadoop-3.1.4]$ hdfs storagepolicies -listPolicies (2)为指定路径(数据存储目录)设置指定的存储策略 hdfs storagepolicies -setStoragePo

Hadoop集群数据均衡之磁盘间数据均衡

生产环境,由于硬盘空间不足,往往需要增加一块硬盘。刚加载的硬盘没有数据时,可以执行磁盘数据均衡命令。(Hadoop3.x新特性) plan后面带的节点的名字必须是已经存在的,并且是需要均衡的节点。 如果节点不存在,会报如下错误: 如果节点只有一个硬盘的话,不会创建均衡计划: (1)生成均衡计划 hdfs diskbalancer -plan hadoop102 (2)执行均衡计划 hd

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi