日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

作者:ARAVIND PAI

翻譯:吳金笛

校對(duì):和中華

本文長(zhǎng)度為6800字,建議閱讀15分鐘

本文手把手帶你使用Python編寫(xiě)一個(gè)自動(dòng)生成音樂(lè)的模型。

總覽

  • 學(xué)習(xí)如何開(kāi)發(fā)一個(gè)自動(dòng)生成音樂(lè)的端到端模型
  • 理解WaveNet架構(gòu)并使用Keras從零開(kāi)始實(shí)現(xiàn)它
  • 在建立自動(dòng)音樂(lè)生成模型的同時(shí),比較了WaveNet和Long-Short-Term Memory的性能

介紹

“如果我不是物理學(xué)家,我可能會(huì)成為音樂(lè)家。我經(jīng)常在音樂(lè)中思考。我活在音樂(lè)的白日夢(mèng)里。我從音樂(lè)的角度來(lái)看待我的生活。”——阿爾伯特·愛(ài)因斯坦

我可能不是愛(ài)因斯坦先生那樣的物理學(xué)家,但我完全同意他對(duì)音樂(lè)的看法!我不記得有哪一天我沒(méi)有打開(kāi)音樂(lè)播放器。我上下班都伴隨著音樂(lè)的旋律,老實(shí)說(shuō),它幫助我專(zhuān)注于工作。

我一直夢(mèng)想著作曲,但卻不懂樂(lè)器。直到我遇到了深度學(xué)習(xí),這一切都成了過(guò)去。使用某些技術(shù)和框架,我能夠在不了解任何樂(lè)理的情況下創(chuàng)作自己的原創(chuàng)音樂(lè)樂(lè)譜!

這是我最喜歡的專(zhuān)業(yè)項(xiàng)目之一。我結(jié)合了兩個(gè)愛(ài)好——音樂(lè)和深度學(xué)習(xí)——創(chuàng)建了一個(gè)自動(dòng)的音樂(lè)生成模型。夢(mèng)想成真了!

你想用深度學(xué)習(xí)譜寫(xiě)自己的音樂(lè)嗎?這篇指南來(lái)幫助你!(附代碼)

 

我很高興與你分享我的方法,包括使你也能夠生成原創(chuàng)音樂(lè)的全部代碼!首先,我們將快速理解自動(dòng)音樂(lè)生成的概念,然后再深入了解用于執(zhí)行此操作的不同方法。最后,我們將啟用Python并設(shè)計(jì)我們自己的自動(dòng)音樂(lè)生成模型。

目錄

1. 什么是音樂(lè)自動(dòng)生成?

2. 音樂(lè)的組成要素是什么?

3. 生成音樂(lè)的不同方法

  • 使用WaveNet架構(gòu)
  • 使用Long-Short-Term Memory(LSTM)

4. 實(shí)現(xiàn)——使用python進(jìn)行自動(dòng)作曲

什么是音樂(lè)自動(dòng)生成?

“音樂(lè)是一種藝術(shù),是一種通用的語(yǔ)言。”

我把音樂(lè)定義為不同頻率的音調(diào)的集合。因此,自動(dòng)音樂(lè)生成是一個(gè)用最少的人為干預(yù)來(lái)創(chuàng)作一首短曲的過(guò)程。

你想用深度學(xué)習(xí)譜寫(xiě)自己的音樂(lè)嗎?這篇指南來(lái)幫助你!(附代碼)

 

產(chǎn)生音樂(lè)最簡(jiǎn)單的形式是什么?

這一切都是從隨機(jī)選擇聲音并將它們組合成一段音樂(lè)開(kāi)始的。1787年,莫扎特為這些隨機(jī)聲音的選擇提出了骰子游戲。他手動(dòng)合成了近272個(gè)音調(diào)!然后,他根據(jù)兩個(gè)骰子點(diǎn)數(shù)之和選擇一個(gè)音調(diào)。

你想用深度學(xué)習(xí)譜寫(xiě)自己的音樂(lè)嗎?這篇指南來(lái)幫助你!(附代碼)

 

另一個(gè)有趣的想法是利用音樂(lè)語(yǔ)法來(lái)生成音樂(lè)。

“音樂(lè)語(yǔ)法是指對(duì)音樂(lè)聲音的合理安排和組合以及對(duì)音樂(lè)作品的正確表現(xiàn)所必需的知識(shí)”

-《音樂(lè)語(yǔ)法基礎(chǔ)》

在20世紀(jì)50年代早期,Iannis Xenakis使用統(tǒng)計(jì)學(xué)和概率的概念來(lái)創(chuàng)作音樂(lè)——通常被稱為隨機(jī)音樂(lè)(Stochastic Music)。他將音樂(lè)定義為偶然出現(xiàn)的一系列元素(或聲音)。因此,他用隨機(jī)理論來(lái)表述它。他對(duì)元素的隨機(jī)選擇完全依賴于數(shù)學(xué)概念。

最近,深度學(xué)習(xí)架構(gòu)已經(jīng)成為自動(dòng)音樂(lè)生成的最新技術(shù)。在本文中,我將討論使用WaveNet和LSTM(Long-Short-Term Memory)架構(gòu)來(lái)實(shí)現(xiàn)自動(dòng)作曲的兩種不同方法。

注意:本文需要對(duì)一些深度學(xué)習(xí)概念有基本的理解。我建議閱讀以下文章:

  • 從頭開(kāi)始學(xué)習(xí)卷積神經(jīng)網(wǎng)絡(luò)(CNNs)的全面教程

https://www.analyticsvidhya.com/blog/2018/12/guide-convolutional-neural-network-cnn/?utm_source=blog&utm_medium=how-to-perform-automatic-music-generation

  • 深度學(xué)習(xí)要領(lǐng):長(zhǎng)短期記憶(LSTM)入門(mén)

https://www.analyticsvidhya.com/blog/2017/12/fundamentals-of-deep-learning-introduction-to-lstm/?utm_source=blog&utm_medium=how-to-perform-automatic-music-generation

  • 學(xué)習(xí)序列建模的必讀教程

https://www.analyticsvidhya.com/blog/2019/01/sequence-models-deeplearning/?utm_source=blog&utm_medium=how-to-perform-automatic-music-generation

音樂(lè)的組成要素是什么?

音樂(lè)本質(zhì)上是由音符和和弦組成的。讓我從鋼琴的角度來(lái)解釋這些術(shù)語(yǔ):

  • 音符:?jiǎn)捂I發(fā)出的聲音稱為音符
  • 和弦:由兩個(gè)或更多的鍵同時(shí)發(fā)出的聲音稱為和弦。一般來(lái)說(shuō),大多數(shù)和弦包含至少3個(gè)鍵音
  • 八度:重復(fù)的模式稱為八度。每個(gè)八度包含7個(gè)白鍵和5個(gè)黑鍵

自動(dòng)生成音樂(lè)的不同方法

我將詳細(xì)討論兩個(gè)基于深度學(xué)習(xí)的自動(dòng)生成音樂(lè)的架構(gòu)——WaveNet和LSTM。但是,為什么只有深度學(xué)習(xí)架構(gòu)?

深度學(xué)習(xí)是一個(gè)受神經(jīng)結(jié)構(gòu)啟發(fā)的機(jī)器學(xué)習(xí)領(lǐng)域。這些網(wǎng)絡(luò)自動(dòng)從數(shù)據(jù)集中提取特征,并能夠?qū)W習(xí)任何非線性函數(shù)。這就是為什么神經(jīng)網(wǎng)絡(luò)被稱為泛函逼近器(感覺(jué)泛函在數(shù)學(xué)上的定義不適合這里,網(wǎng)上也有人翻譯為 萬(wàn)能函數(shù)擬逼近器,因?yàn)樽钤缬幸黄P(guān)于 Universal Approximation Theorem的論文)。

因此,深度學(xué)習(xí)模型是自然語(yǔ)言處理(NLP)、計(jì)算機(jī)視覺(jué)、語(yǔ)音合成等各個(gè)領(lǐng)域的最新技術(shù)。讓我們來(lái)看看如何構(gòu)建這些作曲模型。

方法一:使用WaveNet

“WaveNet是谷歌DeepMind開(kāi)發(fā)的一種基于深度學(xué)習(xí)的原始音頻生成模型。”

WaveNet的主要目的是從原始的數(shù)據(jù)分布中生成新的樣本。因此,它被稱為生成模型。

“WaveNet就像是NLP中的一種語(yǔ)言模型。”

在語(yǔ)言模型中,給定一個(gè)單詞序列,該模型試圖預(yù)測(cè)下一個(gè)單詞。與語(yǔ)言模型類(lèi)似,在WaveNet中,給定一系列樣本,它試圖預(yù)測(cè)下一個(gè)樣本。

方法二:使用Long-Short-Term Memory(LSTM)模型

Long-Short-Term Memory (LSTM)是遞歸神經(jīng)網(wǎng)絡(luò)(RNNs)的一種變體,能夠捕獲輸入序列中的長(zhǎng)期依賴關(guān)系。LSTM在序列到序列(Seq2Seq)建模任務(wù)中有廣泛的應(yīng)用,如語(yǔ)音識(shí)別、文本摘要、視頻分類(lèi)等。

你想用深度學(xué)習(xí)譜寫(xiě)自己的音樂(lè)嗎?這篇指南來(lái)幫助你!(附代碼)

 

讓我們?cè)敿?xì)討論如何使用這兩種方法訓(xùn)練我們的模型。

WaveNet:訓(xùn)練階段

“這是一個(gè)多對(duì)一的問(wèn)題,其中輸入是一系列振幅值,輸出是后續(xù)值。”

讓我們看看如何準(zhǔn)備輸入和輸出序列。

WaveNet的輸入:

WaveNet將原始音頻波的小塊作為輸入。原始音頻波是指波在時(shí)間序列域中的表示。

在時(shí)間序列域中,音頻波以不同時(shí)間間隔音符的振幅值的形式表示:

你想用深度學(xué)習(xí)譜寫(xiě)自己的音樂(lè)嗎?這篇指南來(lái)幫助你!(附代碼)

 

WaveNet的輸出:

給定振幅值的序列,WaveNet試圖預(yù)測(cè)連續(xù)的振幅值。

讓我們通過(guò)一個(gè)示例來(lái)理解。考慮一個(gè)5秒的音頻波,采樣率為16,000(即每秒16,000個(gè)樣本)。現(xiàn)在,我們有8萬(wàn)個(gè)樣本在5秒內(nèi)以不同的時(shí)間間隔記錄下來(lái)。讓我們把音頻分成相同大小的塊,比如1024(這是一個(gè)超參數(shù))。

下圖展示了模型的輸入和輸出序列:

你想用深度學(xué)習(xí)譜寫(xiě)自己的音樂(lè)嗎?這篇指南來(lái)幫助你!(附代碼)

 

前3個(gè)塊的輸入和輸出

對(duì)于其余的塊,我們可以遵循類(lèi)似的過(guò)程。

從上面我們可以推斷出,每個(gè)塊的輸出只依賴于過(guò)去的信息(即以前的時(shí)間步長(zhǎng)),而不依賴于未來(lái)的時(shí)間步長(zhǎng)。因此,該任務(wù)稱為自回歸任務(wù),該模型稱為自回歸模型

推理階段

在推理階段,我們將嘗試生成新的樣本。讓我們看看怎么做:

1. 選擇一個(gè)隨機(jī)的樣本值數(shù)組作為建模的起點(diǎn)

2. 現(xiàn)在,模型輸出所有樣本的概率分布

3. 選擇概率最大的值并將其追加到先前的樣本值數(shù)組中

4. 刪除第一個(gè)元素并作為下一個(gè)迭代的輸入傳入模型

5. 重復(fù)步驟2和4,進(jìn)行一定次數(shù)的迭代

理解WaveNet架構(gòu)

WaveNet的基本結(jié)構(gòu)是因果擴(kuò)散的一維卷積層。首先讓我們了解相關(guān)概念的重要性。

為什么使用卷積,什么是卷積?

“使用卷積的一個(gè)主要原因是從輸入中提取特征。”

例如,在圖像處理的情況下,用過(guò)濾器對(duì)圖像進(jìn)行卷積可以得到一個(gè)特征圖。

你想用深度學(xué)習(xí)譜寫(xiě)自己的音樂(lè)嗎?這篇指南來(lái)幫助你!(附代碼)

 

卷積是一種結(jié)合了兩個(gè)函數(shù)的數(shù)學(xué)運(yùn)算。在圖像處理的情況下,卷積是圖像的某些部分與核(kernel)的線性組合。

你可以瀏覽下面的文章閱讀更多關(guān)于卷積的知識(shí):

  • 卷積神經(jīng)網(wǎng)絡(luò)(CNNs)結(jié)構(gòu)的解密

https://www.analyticsvidhya.com/blog/2017/06/architecture-of-convolutional-neural-networks-simplified-demystified/?utm_source=blog&utm_medium=how-to-perform-automatic-music-generation

你想用深度學(xué)習(xí)譜寫(xiě)自己的音樂(lè)嗎?這篇指南來(lái)幫助你!(附代碼)

 

什么是一維卷積?

一維卷積的目標(biāo)類(lèi)似于長(zhǎng)短期記憶模型。它用于解決類(lèi)似于LSTM的任務(wù)。在一維卷積中,核或者叫過(guò)濾器只沿著一個(gè)方向運(yùn)動(dòng):

你想用深度學(xué)習(xí)譜寫(xiě)自己的音樂(lè)嗎?這篇指南來(lái)幫助你!(附代碼)

 

卷積的輸出取決于核的大小、輸入形狀、填充類(lèi)型和步長(zhǎng)。現(xiàn)在,我將帶領(lǐng)你們了解不同類(lèi)型的填充來(lái)理解使用擴(kuò)張的1D因果卷積層的重要性。

當(dāng)我們將填充設(shè)置為valid時(shí),輸入和輸出序列的長(zhǎng)度會(huì)發(fā)生變化。輸出長(zhǎng)度小于輸入長(zhǎng)度:

你想用深度學(xué)習(xí)譜寫(xiě)自己的音樂(lè)嗎?這篇指南來(lái)幫助你!(附代碼)

 

當(dāng)我們將填充設(shè)置為same時(shí),在輸入序列的兩側(cè)填充零以使輸入和輸出的長(zhǎng)度相等:

你想用深度學(xué)習(xí)譜寫(xiě)自己的音樂(lè)嗎?這篇指南來(lái)幫助你!(附代碼)

 

一維卷積的優(yōu)點(diǎn):

  • 捕獲輸入序列中出現(xiàn)的序列信息
  • 與GRU或LSTM相比,訓(xùn)練的速度要快得多,因?yàn)樗鼈儧](méi)有循環(huán)性的連接

一維卷積的缺點(diǎn):

  • 當(dāng)填充設(shè)置為same時(shí),在時(shí)間步長(zhǎng)t處的輸出也與之前的t-1和未來(lái)的時(shí)間步長(zhǎng)t+1進(jìn)行卷積。因此,它違反了自回歸原則
  • 當(dāng)填充被設(shè)置為valid時(shí),輸入和輸出序列的長(zhǎng)度會(huì)發(fā)生變化,這是計(jì)算殘差連接所需要的(后面會(huì)講到)

這為因果卷積掃清了道路。

注意: 我在這里提到的利弊是針對(duì)于此問(wèn)題的。

什么是一維因果卷積?

它被定義為這樣一種卷積,即t時(shí)刻的輸出僅與t時(shí)刻以及前一層更早的元素進(jìn)行卷積。

簡(jiǎn)單地說(shuō),正常卷積和因果卷積的區(qū)別僅僅在于填充。在因果卷積中,僅在輸入序列的左邊加0,以保持自回歸的原則:

你想用深度學(xué)習(xí)譜寫(xiě)自己的音樂(lè)嗎?這篇指南來(lái)幫助你!(附代碼)

 

因果一維卷積的優(yōu)點(diǎn):

  • 因果卷積沒(méi)有考慮未來(lái)的時(shí)間步長(zhǎng),而這是建立生成模型的一個(gè)標(biāo)準(zhǔn)

因果一維卷積的缺點(diǎn):

  • 因果卷積不能回溯到序列中過(guò)去發(fā)生的時(shí)間步長(zhǎng)。因此,因果卷積的接受域非常低。網(wǎng)絡(luò)的接受域是指影響輸出的輸入數(shù)量:
你想用深度學(xué)習(xí)譜寫(xiě)自己的音樂(lè)嗎?這篇指南來(lái)幫助你!(附代碼)

 

如你所見(jiàn),輸出只受5個(gè)輸入的影響。因此,網(wǎng)絡(luò)的接受域?yàn)?,非常低。網(wǎng)絡(luò)的接受域也可以通過(guò)增加大尺寸的核來(lái)增加,但是要記住,這樣一來(lái)計(jì)算復(fù)雜度也會(huì)增加。

這將為我們引出擴(kuò)張一維因果卷積的絕佳概念。

什么是擴(kuò)張一維因果卷積?

“在核的值之間有孔或空缺的因果一維卷積層稱為擴(kuò)張的一維卷積。”

所增加的空缺數(shù)由擴(kuò)張率決定。它定義了網(wǎng)絡(luò)的接受域。大小為k、擴(kuò)張率為d的核在核k的每個(gè)值之間都有d-1個(gè)孔。

你想用深度學(xué)習(xí)譜寫(xiě)自己的音樂(lè)嗎?這篇指南來(lái)幫助你!(附代碼)

 

如你所見(jiàn),將一個(gè)3 * 3的核與一個(gè)7 * 7的輸入,以擴(kuò)張率為2進(jìn)行卷積,最終接受域?yàn)? * 5。

擴(kuò)張一維因果卷積的優(yōu)點(diǎn):

  • 擴(kuò)張的一維卷積網(wǎng)絡(luò)通過(guò)指數(shù)增加每一隱藏層的擴(kuò)張率來(lái)增加接受域:
你想用深度學(xué)習(xí)譜寫(xiě)自己的音樂(lè)嗎?這篇指南來(lái)幫助你!(附代碼)

 

如你所見(jiàn),輸出受所有輸入的影響。因此,網(wǎng)絡(luò)的接受域?yàn)?6。

WaveNet的殘差塊:

為了加速模型的收斂,添加了殘差連接和跳躍連接的構(gòu)件:

你想用深度學(xué)習(xí)譜寫(xiě)自己的音樂(lè)嗎?這篇指南來(lái)幫助你!(附代碼)

 

WaveNet的工作流程:

  • 輸入進(jìn)入一個(gè)因果一維卷積
  • 輸出然后進(jìn)入到2個(gè)不同的擴(kuò)張一維卷積層并使用sigmoid和tanh激活
  • 兩個(gè)不同激活值逐元素相乘導(dǎo)致跳躍連接
  • 而跳躍連接和因果一維輸出的逐元素相加會(huì)導(dǎo)致殘差

Long Short Term Memory (LSTM)方法

另一種自動(dòng)生成音樂(lè)的方法是基于長(zhǎng)短期記憶(LSTM)模型。輸入和輸出序列的準(zhǔn)備類(lèi)似于WaveNet。在每一個(gè)時(shí)間步長(zhǎng),一個(gè)振幅值被輸入到長(zhǎng)短期記憶單元-然后它計(jì)算隱藏的向量,并把它傳遞到下一個(gè)時(shí)間步。

基于當(dāng)前的輸入a(t)和先前的隱藏向量h(t-1)來(lái)計(jì)算當(dāng)前時(shí)間的隱藏向量h(t)。序列信息在任何循環(huán)(一般recursive會(huì)翻譯為遞歸)神經(jīng)網(wǎng)絡(luò)中都是這樣捕獲的:

你想用深度學(xué)習(xí)譜寫(xiě)自己的音樂(lè)嗎?這篇指南來(lái)幫助你!(附代碼)

 

LSTM的優(yōu)點(diǎn):

  • 捕獲輸入序列中出現(xiàn)的順序信息

LSTM的缺點(diǎn):

  • 由于它是按順序處理輸入信息的,所以它在訓(xùn)練上會(huì)花費(fèi)大量的時(shí)間

實(shí)現(xiàn)-使用Python進(jìn)行自動(dòng)音樂(lè)生成

等待結(jié)束了!讓我們開(kāi)發(fā)一個(gè)用于自動(dòng)生成音樂(lè)的端到端模型。啟動(dòng)你的Jupyter

notebook或Colab(或任何你喜歡的IDE)。

下載數(shù)據(jù)集:

我從眾多資源中下載并組合了多個(gè)數(shù)字鋼琴(譯者注:Digital piano與電鋼琴Electric Piano的區(qū)別在于音源的產(chǎn)生方式)的古典音樂(lè)文件。你可以從這里下載最終的數(shù)據(jù)集。

(https://drive.google.com/file/d/1qnQVK17DNVkU19MgVA4Vg88zRDvwCRXw/view)

導(dǎo)入庫(kù):

Music 21是MIT開(kāi)發(fā)的用于理解音樂(lè)數(shù)據(jù)的Python庫(kù)。MIDI是存儲(chǔ)音樂(lè)文件的一種標(biāo)準(zhǔn)格式。MIDI代表樂(lè)器數(shù)字接口。MIDI文件包含說(shuō)明而不是實(shí)際的音頻。因此,它只占用很少的內(nèi)存。這就是為什么它在傳輸文件時(shí)通常是首選的。

1. #library for understanding music  2. from music21 import *

讀取音樂(lè)文件:

我們直接定義一個(gè)函數(shù)來(lái)讀取MIDI文件。它返回音樂(lè)文件中存在的音符和和弦的數(shù)組。

1. #defining function to read MIDI files  2. def read_midi(file):  3.       4.     print("Loading Music File:",file)  5.       6.     notes=[]  7.     notes_to_parse = None  8.       9.     #parsing a midi file  10.     midi = converter.parse(file)  11.     12.     #grouping based on different instruments  13.     s2 = instrument.partitionByInstrument(midi)  14.   15.     #Looping over all the instruments  16.     for part in s2.parts:  17.       18.         #select elements of only piano  19.         if 'Piano' in str(part):   20.           21.             notes_to_parse = part.recurse()   22.         23.             #finding whether a particular element is note or a chord  24.             for element in notes_to_parse:  25.                   26.                 #note  27.                 if isinstance(element, note.Note):  28.                     notes.append(str(element.pitch))  29.                   30.                 #chord  31.                 elif isinstance(element, chord.Chord):  32.                     notes.append('.'.join(str(n) for n in element.normalOrder))  33.   34.     return np.array(notes)

現(xiàn)在,將MIDI文件加載到我們的環(huán)境中

1. #for listing down the file names  2. import os  3.   4. #Array Processing  5. import numpy as np  6.   7. #specify the path  8. path='schubert/'  9.   10. #read all the filenames  11. files=[i for i in os.listdir(path) if i.endswith(".mid")]  12.   13. #reading each midi file  14. notes_array = np.array([read_midi(path+i) for i in files])

理解數(shù)據(jù):

在本節(jié)中,我們將探索數(shù)據(jù)集并對(duì)其進(jìn)行詳細(xì)了解。

1. #converting 2D array into 1D array  2. notes_ = [element for note_ in notes_array for element in note_]  3.   4. #No. of unique notes  5. unique_notes = list(set(notes_))  6. print(len(unique_notes))

輸出:304

如你所這里見(jiàn),不重復(fù)音符的數(shù)量是304。現(xiàn)在,讓我們看一下音符的分布。

1. #importing library  2. from collections import Counter  3.   4. #computing frequency of each note  5. freq = dict(Counter(notes_))  6.   7. #library for visualiation  8. import matplotlib.pyplot as plt  9.   10. #consider only the frequencies  11. no=[count for _,count in freq.items()]  12.   13. #set the figure size  14. plt.figure(figsize=(5,5))  15.   16. #plot  17. plt.hist(no)

輸出:

你想用深度學(xué)習(xí)譜寫(xiě)自己的音樂(lè)嗎?這篇指南來(lái)幫助你!(附代碼)

 

從上圖可以看出,大多數(shù)音符的頻率都很低。因此,我們保留最常用的音符,而忽略低頻率的音符。在這里,我將閾值定義為50。不過(guò),這個(gè)參數(shù)是可以更改的。

1. frequent_notes = [note_ for note_, count in freq.items() if count>=50]  2. print(len(frequent_notes))

輸出:167

如你在這里看到的,經(jīng)常出現(xiàn)的音符大約有170個(gè)。現(xiàn)在,讓我們準(zhǔn)備新的音樂(lè)文件,其中僅包含最常見(jiàn)的音符

1. new_music=[]  2.   3. for notes in notes_array:  4.     temp=[]  5.     for note_ in notes:  6.         if note_ in frequent_notes:  7.             temp.append(note_)              8.     new_music.append(temp)  9.       10. new_music = np.array(new_music)

準(zhǔn)備數(shù)據(jù):

如文章中所述準(zhǔn)備輸入和輸出序列:

1. no_of_timesteps = 32  2. x = []  3. y = []  4.   5. for note_ in new_music:  6.     for i in range(0, len(note_) - no_of_timesteps, 1):  7.           8.         #preparing input and output sequences  9.         input_ = note_[i:i + no_of_timesteps]  10.         output = note_[i + no_of_timesteps]  11.           12.         x.append(input_)  13.         y.append(output)  14.           15. x=np.array(x)  16. y=np.array(y)

現(xiàn)在,我們將為每個(gè)音符分配一個(gè)唯一的整數(shù):

1. unique_x = list(set(x.ravel()))  2. x_note_to_int = dict((note_, number) for number, note_ in enumerate(unique_x))

我們將為輸入數(shù)據(jù)準(zhǔn)備整數(shù)序列

1. #preparing input sequences  2. x_seq=[]  3. for i in x:  4.     temp=[]  5.     for j in i:  6.         #assigning unique integer to every note  7.         temp.append(x_note_to_int[j])  8.     x_seq.append(temp)  9.       10. x_seq = np.array(x_seq)

同樣,也為輸出數(shù)據(jù)準(zhǔn)備整數(shù)序列

1. unique_y = list(set(y))  2. y_note_to_int = dict((note_, number) for number, note_ in enumerate(unique_y))   3. y_seq=np.array([y_note_to_int[i] for i in y])

讓我們保留80%的數(shù)據(jù)用于訓(xùn)練,其余20%的用于評(píng)估:

1. from sklearn.model_selection import train_test_split  2. x_tr, x_val, y_tr, y_val = train_test_split(x_seq,y_seq,test_size=0.2,random_state=0)

構(gòu)建模型

我在這里定義了2種架構(gòu)– WaveNet和LSTM。請(qǐng)嘗試兩種架構(gòu),以了解WaveNet架構(gòu)的重要性。

1. def lstm():  2.   model = Sequential()  3.   model.add(LSTM(128,return_sequences=True))  4.   model.add(LSTM(128))  5.   model.add(Dense(256))  6.   model.add(Activation('relu'))  7.   model.add(Dense(n_vocab))  8.   model.add(Activation('softmax'))  9.   model.compile(loss='sparse_categorical_crossentropy', optimizer='adam')  10.   return model

我簡(jiǎn)化了WaveNet的架構(gòu),沒(méi)有添加殘差連接和跳躍連接,因?yàn)檫@些層的作用是提高收斂速度(WaveNet以原始音頻波作為輸入)。但在我們的例子中,輸入是一組音符和和弦,因?yàn)槲覀冊(cè)谏梢魳?lè):

1. from keras.layers import *  2. from keras.models import *  3. from keras.callbacks import *  4. import keras.backend as K  5.   6. K.clear_session()  7. model = Sequential()  8.       9. #embedding layer  10. model.add(Embedding(len(unique_x), 100, input_length=32,trainable=True))   11.   12. model.add(Conv1D(64,3, padding='causal',activation='relu'))  13. model.add(Dropout(0.2))  14. model.add(MaxPool1D(2))  15.       16. model.add(Conv1D(128,3,activation='relu',dilation_rate=2,padding='causal'))  17. model.add(Dropout(0.2))  18. model.add(MaxPool1D(2))  19.   20. model.add(Conv1D(256,3,activation='relu',dilation_rate=4,padding='causal'))  21. model.add(Dropout(0.2))  22. model.add(MaxPool1D(2))  23.             24. #model.add(Conv1D(256,5,activation='relu'))      25. model.add(GlobalMaxPool1D())  26.       27. model.add(Dense(256, activation='relu'))  28. model.add(Dense(len(unique_y), activation='softmax'))  29.       30. model.compile(loss='sparse_categorical_crossentropy', optimizer='adam')  31.   32. model.summary()

定義回調(diào)以在訓(xùn)練期間保存最佳模型:

mc=ModelCheckpoint('best_model.h5', monitor='val_loss', mode='min', save_best_only=True,verbose=1)

讓我們使用128的批大小將模型訓(xùn)練50個(gè)epoch:

history = model.fit(np.array(x_tr),np.array(y_tr),batch_size=128,epochs=50,validation_data=(np.array(x_val),np.array(y_val)),verbose=1, callbacks=[mc])

導(dǎo)入最好的模型:

1. #loading best model  2. from keras.models import load_model  3. model = load_model('best_model.h5')

是時(shí)候創(chuàng)作我們自己的音樂(lè)了。我們將按照推斷階段中提到的步驟進(jìn)行預(yù)測(cè)。

1. import random  2. ind = np.random.randint(0,len(x_val)-1)  3.   4. random_music = x_val[ind]  5.   6. predictions=[]  7. for i in range(10):  8.   9.     random_music = random_music.reshape(1,no_of_timesteps)  10.   11.     prob  = model.predict(random_music)[0]  12.     y_pred= np.argmax(prob,axis=0)  13.     predictions.append(y_pred)  14.   15.     random_music = np.insert(random_music[0],len(random_music[0]),y_pred)  16.     random_music = random_music[1:]  17.       18. print(predictions)

現(xiàn)在,我們將整數(shù)還原為音符。

1. x_int_to_note = dict((number, note_) for number, note_ in enumerate(unique_x))   2. predicted_notes = [x_int_to_note[i] for i in predictions]  

最后一步是將預(yù)測(cè)結(jié)果轉(zhuǎn)換回MIDI文件。讓我們定義一個(gè)函數(shù)來(lái)完成此任務(wù)。

1. def convert_to_midi(prediction_output):  2.      3.     offset = 0  4.     output_notes = []  5.   6.     # create note and chord objects based on the values generated by the model  7.     for pattern in prediction_output:  8.           9.         # pattern is a chord  10.         if ('.' in pattern) or pattern.isdigit():  11.             notes_in_chord = pattern.split('.')  12.             notes = []  13.             for current_note in notes_in_chord:  14.                   15.                 cn=int(current_note)  16.                 new_note = note.Note(cn)  17.                 new_note.storedInstrument = instrument.Piano()  18.                 notes.append(new_note)  19.                   20.             new_chord = chord.Chord(notes)  21.             new_chord.offset = offset  22.             output_notes.append(new_chord)  23.               24.         # pattern is a note  25.         else:  26.               27.             new_note = note.Note(pattern)  28.             new_note.offset = offset  29.             new_note.storedInstrument = instrument.Piano()  30.             output_notes.append(new_note)  31.   32.         # increase offset each iteration so that notes do not stack  33.         offset += 1  34.     midi_stream = stream.Stream(output_notes)  35.     midi_stream.write('midi', fp='music.mid')

將預(yù)測(cè)結(jié)果轉(zhuǎn)換為音樂(lè)文件:

convert_to_midi(predicted_notes)

奧利給,對(duì)嗎,但你的學(xué)習(xí)不該止步于此。請(qǐng)記住,我們已經(jīng)構(gòu)建了一個(gè)基準(zhǔn)(baseline)模型。

有很多方法可以進(jìn)一步提高模型的性能:

  • 由于訓(xùn)練數(shù)據(jù)集的規(guī)模較小,我們可以對(duì)預(yù)訓(xùn)練的模型進(jìn)行微調(diào),以建立一個(gè)魯棒的系統(tǒng)
  • 盡可能多地收集訓(xùn)練數(shù)據(jù),因?yàn)樯疃葘W(xué)習(xí)模型在更大的數(shù)據(jù)集上泛化更好

結(jié)語(yǔ)

深度學(xué)習(xí)在我們的日常生活中有著廣泛的應(yīng)用。解決任何問(wèn)題的關(guān)鍵步驟都是理解問(wèn)題陳述、闡明并定義解決問(wèn)題的結(jié)構(gòu)。

我在這個(gè)項(xiàng)目中得到了很多樂(lè)趣(和學(xué)習(xí))。音樂(lè)是我的激情所在,將深度學(xué)習(xí)與之結(jié)合是非常有趣的。

原文鏈接:

https://www.analyticsvidhya.com/blog/2020/01/how-to-perform-automatic-music-generation/

原文題目:

Want to Generate your own Music using Deep Learning? Here’s a Guide to do just that!

編輯:于騰凱

校對(duì):洪舒越

譯者簡(jiǎn)介

你想用深度學(xué)習(xí)譜寫(xiě)自己的音樂(lè)嗎?這篇指南來(lái)幫助你!(附代碼)

 

吳金笛,雪城大學(xué)計(jì)算機(jī)科學(xué)碩士一年級(jí)在讀。迎難而上是我最舒服的狀態(tài),動(dòng)心忍性,曾益我所不能。我的目標(biāo)是做個(gè)早睡早起的Cool Girl。

—完—

想要獲得更多數(shù)據(jù)科學(xué)領(lǐng)域相關(guān)動(dòng)態(tài),誠(chéng)邀關(guān)注清華-青島數(shù)據(jù)科學(xué)研究院官方微信公眾平臺(tái)“ 數(shù)據(jù)派THU ”。

分享到:
標(biāo)簽:音樂(lè)
用戶無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定