2021年美国大学生数学建模竞赛D题音乐的影响解题全过程文档及程序

2021年美国大学生数学建模竞赛

D题 音乐的影响

原题再现:

  音乐是人类社会的一部分,是文化遗产的重要组成部分。 作为理解音乐在人类集体经验中所扮演角色的努力的一部分,我们被要求开发一种方法来量化音乐进化。 当艺术家创作一首新音乐时,有许多因素可以影响他们,包括他们与生俱来的创造力、当前的社会或政治事件、获得新的乐器或工具的机会或其他个人经历。 我们的目标是了解和衡量以前制作的音乐对新音乐和音乐艺术家的影响。
  一些艺术家可以列出十几个或更多的其他艺术家,他们说他们影响了他们自己的音乐作品。 还有人建议,影响可以用歌曲特征之间的相似程度来衡量,如结构、节奏或歌词。 音乐有时会发生革命性的变化,提供新的声音或节奏,例如当一个新的体裁出现时,或者有一个现有的体裁的重新发明(例如。 古典、流行/摇滚、爵士乐等。)。 这可能是由于一系列微小的变化,艺术家的合作努力,一系列有影响力的艺术家,或社会内部的转变。
  许多歌曲有着相似的声音,许多艺术家为音乐流派的重大转变做出了贡献。 有时这些变化是由于一个艺术家影响另一个艺术家。 有时,它是针对外部事件(如重大世界事件或技术进步)而出现的变化)。 通过考虑歌曲网络及其音乐特征,我们可以开始捕捉音乐艺术家对彼此的影响。 也许,我们还可以更好地了解音乐是如何随着时间的推移在社会中演变的。
  您的团队已经被整合集体音乐(ICM)协会确定,以开发一个衡量音乐影响的模型。 这个问题要求你研究艺术家和流派的进化和革命趋势。 为了做到这一点,ICM给了您的团队几个数据集:
  1) “influence_data”1 代表音乐影响者和追随者,如艺术家自己报告的,以及行业专家的意见。 这些数据包含了过去90年来5,854名艺术家的影响者和追随者。
  2) “full_music_data”2 提供16个可变的条目,包括音乐特征,如舞蹈性,节奏,响度和键,以及98,340首歌曲的artist_name和artist_id。 这些数据用于创建两个汇总数据集,包括:
  a. 艺术家“data_by_artist”的平均价值”,
  b. 意味着多年的“data_by_year”。
  注意:这些文件中提供的数据是较大数据集的子集。 这些文件包含了你要为这个问题使用的唯一数据。
  为了实施这个具有挑战性的项目,ICM协会要求您的团队通过音乐艺术家随时间的影响来探索音乐的演变,具体做法如下:
  使用influence_data数据集或其部分创建一个(多个)有向网络的音乐影响,其中影响者连接到追随者。 开发在这个网络中捕获“音乐影响”的参数。 通过创建你的定向影响者网络的子网来探索音乐影响的子集。 描述这个子网。 你的“音乐影响”措施在这个子网中揭示了什么?
  使用full_music_data和/或两个汇总数据集(与艺术家和年份)的音乐特征,以制定音乐相似性的度量。 用你的衡量标准,流派中的艺术家是否比流派之间的艺术家更相似?
  比较体裁之间和体裁内部的相似性和影响。 一个体裁的区别是什么,体裁是如何随着时间的推移而变化的? 有些体裁与其他体裁有关吗?
  指出data_influence数据集中报告的相似性数据是否表明已识别的影响者实际上影响了各自的艺术家。 “影响者”真的会影响追随者创造的音乐吗? 有些音乐特征是否比其他音乐更具有“传染性”,或者它们在影响特定艺术家的音乐方面都有类似的作用?
  从这些数据中确定是否有可能意味着音乐进化的革命(重大飞跃)的特征? 什么艺术家代表革命者(重大变革的影响者)在你的网络?
  分析音乐演变的影响过程,随着时间的推移,在一个体裁。 你的团队能找出揭示动态影响者的指标,并解释流派或艺术家是如何随着时间的推移而变化的吗?
  你的作品如何在时间或环境中表达关于音乐文化影响的信息? 或者,如何在网络中识别社会、政治或技术变革(如互联网)的影响?
  写一份一页的文件给ICM协会,关于使用你的方法来理解音乐通过网络的影响的价值。考虑到这两个问题数据集仅限于某些类型,然后是两个数据集共同的艺术家,您的工作或解决方案将如何随着更多或更丰富的数据而变化? 建议进一步研究音乐及其对文化的影响。
  来自音乐、历史、社会科学、技术和数学领域的跨学科和多样化的ICM协会期待着您的最后报告。

整体求解过程概述(摘要)

  为了理解音乐的演变,我们结合了物理学中的网络科学、余弦相似性、冷却模型和重力模型以及其他静态方法,以探索音乐如何通过跨艺术家和流派的影响而演变。
  最重要的是,我们创建了定向影响者网络,以可视化影响者和追随者之间的关系。然后,我们借助冷却模型解释音乐影响力的概念,以描述随着时间间隔变长而下降的影响力。完成此操作后,我们通过节点的大小显示子网中艺术家的音乐影响力并进行详细分析。
  接下来,经过数据预处理后,我们使用PCA来降维音乐特征并提取四个因子。基于由四个因子形成的特征向量,我们计算了作品或流派之间的余弦相似性。我们衡量相似性的方法被证明是正确的,因为流派中的艺术家比流派之间的艺术家获得更高的相似性。
  然后,我们开发网络和相似性的基本模型,以解决有关音乐演变的任务。我们的分析从以下四个角度进行。
  对于关于影响者和追随者的任务,我们比较了追随者和影响者或非影响者之间的相似性密度曲线,并确认了影响者对追随者音乐的影响。然后,我们重建特征向量以通过删除每个特征来计算相似性,以查看在特定流派的影响过程中哪个特征更具传染性。
  对于流派趋势的任务,首先我们计算流派的相似矩阵,并相应地描述流派之间的关系和差异。接下来,基于重力模型,我们估计了每年的主要流派,并分析了流派随时间变化的趋势。此外,我们还分析了乡村音乐的演变,特别是通过使用受欢迎程度和计数来找出动态影响因素,并解释乡村和其他流派在其演变过程中的融合。
  对于有关音乐革命的任务,我们分析每年与其下一年之间的余弦相似性,以确定重大变化为革命。我们发现1940年代,1960年代和1980年代是革命时期,我们特别分析了1965年至1967年的革命,以发现披头士乐队和鲍勃迪伦是代表这一时期革命的两位艺术家。
  对于有关音乐演变的其他影响的任务,我们详细分析了流派时间表和革命时期以及重大的文化,社会,政治或技术变化,解释了冷战,民权运动等事件如何影响音乐的发展。
  综上所述,我们的模型因其在灵敏分析中的全面性、创新性和良好性能而具有进一步研究的启发性价值。

模型假设:

  随着时间间隔变大,音乐影响力会降低。作品一般都有一定的时效性,作品的热度会随着时间的流逝而衰减。下降量与发行年份和流行年份无关,但与时间间隔有关。从评审点到发行年份的时间间隔越长,作品对当今音乐人的影响就越小。
  每个追随者在他们开始制作音乐的那一年都受到有影响力的人的影响。很难定义一个人的高峰期是什么时候,所以用一个人的活跃开始年份来计算是公平合理的。
  每个艺术家只属于一种流派,在他的整个职业生涯中,流派没有改变。一般来说,一个决定选择流派的艺术家一定受到前人作品的影响,所以他不太可能在后来的创作中改变流派。
  艺术家可以反映他的流派的特征。艺术家需要反映他所在类别的特征,否则他不会被归类为这一类型。
  现有的数据集可以反映音乐市场的情况。我们完全相信关注者数量、热度等各种指标的统计数据,相信所反映的趋势是正确的。

问题重述:

  在过去的100年里,音乐经历了快速的发展。为了从艺术家的影响角度来揭示音乐的演变,我们需要解决以下问题:
  根据提供的“influence_data”数据集构建影响关系的定向网络,并开发音乐影响力的度量。网络工程应包括父网络和子网,并附有详细说明;
  建立一个模型,根据其余给定数据集来衡量音乐相似性,并通过比较流派内艺术家之间的相似性和流派之间的艺术家之间的相似性来检查该模型;
  探索影响者是否真的影响了追随者的音乐,以及音乐的每个特征在影响过程中是否起着同样重要的作用;
  找出流派之间的差异和联系,探索流派随时间的发展,不仅是不同时期代表性音乐流派的发展,还有同一音乐流派在不同时期的发展;确定指标以找出最具活力的影响因素并分析特定流派的演变过程;
  引入一个指标,暗示进化过程中的重大变化,并指出代表革命者的艺术家;
  讨论音乐的文化影响或其他可能影响音乐演变的因素;

模型的建立与求解整体论文缩略图

在这里插入图片描述
在这里插入图片描述

全部论文请见下方“ 只会建模 QQ名片” 点击QQ名片即可

部分程序代码:(代码和文档not free)

import pandas as pd
#读取文件
data = pd.read_csv('influence_data.csv')

#选择influencer_main_genre与follower_main_genre两列数据 
influence_data = (list(data['influencer_main_genre']))
follower_data = (list(data['follower_main_genre']))

#导入计算频次模块
from collections import Counter

#统计频次并按照字典键排序
influence_data_dict = sorted(dict(Counter(influence_data)).items(),key=lambda item:item[0])
follower_data_dict = sorted(dict(Counter(follower_data)).items(),key=lambda item:item[0])

#提取influence_data的标签与频次数据
influence_data_labels = [item[0] for item in influence_data_dict]
influence_data_datas = [item[1] for item in influence_data_dict]

#提取follower_data的标签与频次数据
follower_data_labels = [item[0] for item in follower_data_dict]
follower_data_datas = [item[1] for item in follower_data_dict]

#导入画图库
from matplotlib import pyplot as plt
from matplotlib import font_manager

#x轴
a = influence_data_labels

#条形图宽度
bar_width = 0.2

#x轴范围
x_i = list(range(len(a)))
x_f = list(i+bar_width for i in x_i)

#图片大小
plt.figure(figsize=(10,8),dpi=100)

#绘制条形图influence
plt.bar(x_i,influence_data_datas,width=bar_width,label="influence",color='red')

#绘制条形图follow
plt.bar(x_f,follower_data_datas,width=bar_width,label="follow",color='gray')

# 设置图例
plt.legend(fontsize=10)

# 设置x轴刻度并倾斜展示
plt.xticks(x_f,a,rotation=70)

#刻度大小
plt.tick_params(axis='both',which='major',labelsize=14)

#条形图展示
plt.show()
import pandas as pd
#读取csv文件
data = pd.read_csv('full_music_data.csv')

#导入统计频率函数
from collections import Counter

#读入艺术家名
art_list = list(data['artist_names'])
#统计频率
artist = Counter(art_list)
#按照频率进行对艺术家排序
artist_sort = sorted(artist.items(),key=lambda item:item[1],reverse=True)

#读取其他13个因素
danceability = list(data['danceability'])
energy = list(data['energy'])
valence = list(data['valence'])
tempo = list(data['tempo'])
loudness = list(data['loudness'])
mode = list(data['mode'])
key = list(data['key'])
acousticness = list(data['acousticness'])
instrumentalness = list(data['instrumentalness'])
liveness = list(data['liveness'])
speechiness = list(data['speechiness'])
explicit = list(data['explicit'])
popularity = list(data['popularity'])

#读取歌曲名
song_title = list(data['song_title (censored)'])

#导入相似度计算函数 余弦距离
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity

#计算不同艺术家歌曲相似度函数
def getSortData(artist_sort,num):
	#遍历所有艺术家的歌曲进行相似度计算
    for i in range(num):
        if artist_sort[i][1] > 2:
        	#获艺术家名字
            artist_name = artist_sort[i][0]
            #获取歌曲数量
            length = artist_sort[i][1]
            #获取截取片段的索引
            startindex,endindex = art_list.index(artist_name),art_list.index(artist_name)+length
            #print(artist_name,length,startindex,endindex)
            print('The ',(i+1),'th artist:',artist_name,'songs num:',length)
            
            #写入文件 写入艺术家名字与歌曲数量
            with open('music_sim.txt','a') as f:
                f.write('The '+str(i+1)+'th artist:'+str(artist_name)+' songs num:'+str(length)+' songs similarity:')
			
			#截取属于该艺术家的13个因素中的片段
            danceability_pic = danceability[startindex:endindex-1]
            energy_pic = energy[startindex:endindex-1]
            valence_pic = valence[startindex:endindex-1]
            tempo_pic = tempo[startindex:endindex-1]
            loudness_pic = loudness[startindex:endindex-1]
            mode_pic = mode[startindex:endindex-1]
            key_pic = key[startindex:endindex-1]
            acousticness_pic = acousticness[startindex:endindex-1]
            instrumentalness_pic = instrumentalness[startindex:endindex-1]
            liveness_pic = liveness[startindex:endindex-1]
            speechiness_pic = speechiness[startindex:endindex-1]
            explicit_pic = explicit[startindex:endindex-1]
            popularity_pic = popularity[startindex:endindex-1]
			
			#截取属于该艺术家的歌曲名称片段
            song_title_pic = song_title[startindex:endindex-1]
            
            #存储相似度列表
            sim_list = []

			#遍历该艺术家的乐曲计算相似度
            for j in range(len(danceability_pic)):
                try:
                	#当前乐曲的13个因素数据
                    a = [danceability_pic[j],energy_pic[j],valence_pic[j],tempo_pic[j],loudness_pic[j],
                    mode_pic[j],key_pic[j],acousticness_pic[j],instrumentalness_pic[j],liveness_pic[j],
                    speechiness_pic[j],explicit_pic[j],popularity_pic[j]]
                    #下一首乐曲的13个因素数据
                    b = [danceability_pic[j+1],energy_pic[j+1],valence_pic[j+1],tempo_pic[j+1],loudness_pic[j+1],
                    mode_pic[j+1],key_pic[j+1],acousticness_pic[j+1],instrumentalness_pic[j+1],liveness_pic[j+1],
                    speechiness_pic[j+1],explicit_pic[j+1],popularity_pic[j+1]]
                    #计算相似度
                    sim = cosine_similarity(np.array([a]),np.array([b]))[0][0]
                    
                    #存储相似度
                    sim_list.append(sim)
                    
                    #将相似度写入文件
                    with open('music_sim.txt','a') as f:
                        f.write(str(sim)+' ')
                except:
                    pass
			
			#计算该艺术家所有乐曲的最小相似度
            m = min(sim_list)
            
            #获取最小相似度的索引
            index = sim_list.index(m)
            
            #写入最小相似度与发生最小相似度的乐曲
            with open('music_sim.txt','a') as f:             
                try:
                	#最小相似度
                    f.write(' minst similarity is:'+str(m))
                    #最小相似度的乐曲
                    f.write(' minst similarity songs are:'+str(song_title_pic[index-1])+'--->'+str(song_title_pic[index]+'\n'))
                    f.close()
                except:
                	#最小相似度
                    f.write(' minst similarity is:'+str(m)+'\n')
                    f.close()
        print()
#调用函数计算    
getSortData(artist_sort,len(artist_sort))

import numpy as np
from sklearn.metrics.pairwise import cosine_similarity

#计算不同艺术家的相似度
def getArtistSimilarlty(artist_sort,num):
	#存储艺术家的相似度
    artist_sim_list = []
    #存储艺术家名称
    artist_list = []
    
    #遍历进行计算相似度
    for i in range(num):
        if artist_sort[i][1] > 2:
        	#艺术家名字
            artist_name = artist_sort[i][0]
            #歌曲数
            length = artist_sort[i][1]
            #获取截取片段的索引
            startindex,endindex = art_list.index(artist_name),art_list.index(artist_name)+length
            print('The ',(i+1),'th artist:',artist_name,'songs num:',length)
            
            #写入艺术家名字
            with open('artist_sim.txt','a') as f:
                f.write(str(artist_name)+' ')
                f.close()
                
            #截取属于该艺术家的13个因素中的片段
            danceability_pic = danceability[startindex:endindex-1]
            energy_pic = energy[startindex:endindex-1]
            valence_pic = valence[startindex:endindex-1]
            tempo_pic = tempo[startindex:endindex-1]
            loudness_pic = loudness[startindex:endindex-1]
            mode_pic = mode[startindex:endindex-1]
            key_pic = key[startindex:endindex-1]
            acousticness_pic = acousticness[startindex:endindex-1]
            instrumentalness_pic = instrumentalness[startindex:endindex-1]
            liveness_pic = liveness[startindex:endindex-1]
            speechiness_pic = speechiness[startindex:endindex-1]
            explicit_pic = explicit[startindex:endindex-1]
            popularity_pic = popularity[startindex:endindex-1]
          
            #存储艺术家相似度
            sim_list = []

			#遍历进行相似度计算
            for j in range(len(danceability_pic)):
                try:
                    a = [danceability_pic[j],energy_pic[j],valence_pic[j],tempo_pic[j],loudness_pic[j],
                    mode_pic[j],key_pic[j],acousticness_pic[j],instrumentalness_pic[j],liveness_pic[j],
                    speechiness_pic[j],explicit_pic[j],popularity_pic[j]]
                    b = [danceability_pic[j+1],energy_pic[j+1],valence_pic[j+1],tempo_pic[j+1],loudness_pic[j+1],
                    mode_pic[j+1],key_pic[j+1],acousticness_pic[j+1],instrumentalness_pic[j+1],liveness_pic[j+1],
                    speechiness_pic[j+1],explicit_pic[j+1],popularity_pic[j+1]]
                    sim = cosine_similarity(np.array([a]),np.array([b]))[0][0]
                    sim_list.append(sim)
                except:
                    pass
                    
			#相似度取所有乐曲相似度的平均值
            artist_sim_list.append(np.mean(sim_list))
            artist_list.append(artist_name)
            #写入相似度
            with open('artist_sim.txt','a') as f:
                f.write(str(np.mean(sim_list))+'\n')
                f.close()
        print()
    #返回艺术家及相似度
    return artist_sim_list,artist_list
    
artist_sim_list,artist_list = getArtistSimilarlty(artist_sort,len(artist_sort))

#连表查询 计算派间相似度
influencedata = pd.read_csv('influence_data.csv')
#读取influencer_name influencer_main_genre列
influencer_name = influencedata['influencer_name']
influencer_main_genre = influencedata['influencer_main_genre']
#派别
artist_type = []
#派别相似度
artist_type_sim = []

#遍历存储派别信息及派别间相似度信息
for i in range(len(influencer_name)):
    print(i)
    for j in range(len(artist_list)):
        if "['"+influencer_name[i]+"']" == artist_list[j]:
            print(influencer_name[i])
            print(artist_list[j])
            artist_type.append(influencer_main_genre[i])
            artist_type_sim.append(artist_sim_list[j])
            
#派别去重处理
artist_set_type = list(set(artist_type))

#派间相似度计算
#派别相似度
type_sim = []
#遍历计算派别相似度并写入文件
for item in artist_set_type:
    print(item)
    #写入派别名
    with open('Typesim.txt','a') as f:
        f.write(item)
        f.close()
    tmp = []
    #统计派别的总相似度
    for i in range(len(artist_type)):
        if artist_type[i] == item:
            tmp.append(artist_type_sim[i])
    #写入相似度
    with open('Typesim.txt','a') as f:
        f.write(' '+str(np.mean(tmp))+'\n')
        f.close()
    print(len(tmp))
    #存储总相似度的平均最为派别相似度
    type_sim.append(np.mean(tmp))
    
#派中相似度
#遍历计算派中相似度
for item in artist_set_type:
    print(item)
    #写入派别名
    with open('TypeZhongsim.txt','a') as f:
        f.write(item)
        f.close()
    #写入派别的所有艺术家的相似度
    for i in range(len(artist_type)):
        if artist_type[i] == item:
            with open('TypeZhongsim.txt','a') as f:
                f.write(' '+str(artist_type_sim[i])+' ')
                f.close()
    with open('TypeZhongsim.txt','a') as f:
        f.write('\n')
        f.close()

#导入绘图函数
from matplotlib import pyplot as plt
import random

#派别相似度
y_1 = type_sim
#派别名称
x = artist_set_type

#设置图形大小
plt.figure(figsize=(20,8),dpi=80)

#设置颜色
color = ['red', 'orange', 'slategrey', 'green', 'cyan', 'blue', 'purple']

#绘制折线图
plt.plot(x,y_1,color=color[random.randint(0,len(color)-1)])

#设置x轴刻度
plt.xticks(x,rotation=45,fontsize=10)

#绘制网格, alpha 设置网格透明度
plt.grid(alpha=0.1)

#图片展示
plt.show()
全部论文请见下方“ 只会建模 QQ名片” 点击QQ名片即可

猜你喜欢

转载自blog.csdn.net/weixin_43292788/article/details/131696862