怎樣用深度學習發現一首歌屬於哪個流派?

怎樣用深度學習發現一首歌屬於哪個流派?

——手把手教你把自己的電腦變成一個音樂鑒賞大師


年初那幾天相信不少人的朋友圈都被網易雲音樂的年度歌單刷屏了。不過雖然雲村告訴了我們在上面最愛聽哪些歌,但這些歌都屬於什麼流派卻沒說,估計很多人自己也搞不清這個。有位叫 Julien Despois 的帥氣程序猿小哥(有多帥看到結尾就知道)決定讓深度學習幫忙發現一首歌屬於什麼流派:

我(作者 Julien Despois ——譯者注)身邊不少朋友有個很牛的技能,那就是在幾秒鐘內就能清楚的說出聽的歌屬於古典音樂還是 Rap 還是電子樂什麼的,可能是因為他們經常聽歌的緣故,但大多數人要想在幾秒內說出歌曲的流派還是有些困難的。不過,即便是我們人人都能做到這一點,網上還有幾百萬首歌曲等著人去分類呢。

這些歌曲庫平均每個有 7160 首歌,即便是僅僅花 3 秒鐘就能分類一首歌是什麼流派(聽 3 秒就能知道歌是什麼流派其實挺難的),那麼把這一個歌曲庫完全分類完畢至少要花 6 個小時。

如果再算上聽完後把它們收到標記分類的時間,基本上要十幾個小時才能完成工作。沒人想干這種活。

在本文,我們會藉助機器學習幫我們完成這項耗時耗力的工作。

這是我們的總體工作流程:

  • 將歌曲庫中的每首歌進行簡化表示
  • 訓練一個神經網路把這些歌曲分類
  • 使用訓練後的分類器對歌曲庫中流派歸屬不明的歌曲補充上流派信息

數據

首先,我們需要一個數據集。我先從我自己的 iTunes 歌曲庫著手,我這人有點輕微的強迫症,所以歌曲庫里的歌曲全都標記好了流派,按順序排列整齊。雖然這個資料庫不夠多樣,不夠完整,也不像其它傳統意義上的資料庫那麼大,但作為一個入手材料,也還不錯。我歌曲庫里大概有 2000 首歌,這也能稱得上是很多數據吧。

提煉數據集

我們觀察這個數據集會發現存在一些問題,比如曲庫中有太多的流派和子流派,還有些流派對應的歌曲樣本太少。這些問題都需要修正,比如將不合適的歌曲樣本移出數據集,或者把它們歸類到一個範圍更廣泛的流派里。例如這個協奏曲流派,我們真的不需要這個,用古典音樂就能代表了。

歌曲流派分類

整理信息

等我們獲得足夠多的歌曲流派且每個流派都有足夠多的歌曲樣本後,就可以從數據中抽取重要的信息了。平時一首歌可能看著沒啥,但是在這裡可是有一長溜的價值。經典的音頻採樣頻率為 44100 赫茲,那麼音頻中每一秒都儲存了 44100 個值,如果是立體聲,還會多一倍。

這意味著一首 3 分鐘長的立體聲歌曲包含了 7,938,000 個樣本。這可是很多信息,我們需要把這些信息縮減到更容易管理的水平,這樣方便後面使用。我們可以不用立體聲,因為它包含了太多冗餘的信息。

我們會用傅里葉變換把音頻數據轉換成頻域。這可以讓數據有了更簡單緊湊的表示形式,我們可以將其導出為聲譜圖。這個過程我們會得到一個 PNG 文件,包含一首歌的頻率隨著時間推移的變化情況。

我們上面談到的 44100 赫茲取樣率能讓我們將頻率重建至 22050 赫茲——見奈奎斯特–香農採樣定理——但由於頻率已被抽取,我們可以用更低的壓縮率。這裡,我們會使用每秒 50 像素(每像素 20 毫妙),足夠保證我們使用所需的全部信息了。

在經過這個處理過程後,我們歌曲會變成如下模樣(這裡展示的是一個 12.8 秒的樣本):

歌曲片段的聲譜圖

橫軸為時間,縱軸為頻率。頻率最高值在頂部,最低值在底部。頻率的變化幅度以灰度的深淺表示,白色表示最大值,黑色表示最小值。

我習慣了使用 128 頻率級聲譜圖,因為它包含了一首歌所有的相關信息——我們可以輕易地區分不同的音符和頻率。

進一步處理

我們需要做的下一件事就是處理歌曲的長度。解決這個問題,有兩個方法。第一個是用循環神經網路,我們用它可以按順序為聲譜圖的每一列輸入數據。我決定好好探究一下人類聽一小段歌就能判斷歌曲流派這個事情。

如果人類聽上幾秒鐘的歌就能分類歌曲,為什麼機器就不可以?

我們可以創建聲譜圖的長度固定的片段,把它們當做代表歌曲流派的獨立樣本。如果為了方便,我們可以用方形片段,也就是說我們要把聲譜圖切割成 128X128 像素的片段。這代表每個片段中的數據為 2.56 秒。

歌曲片段的聲譜圖

這個時候,我們可以用數據擴充的方法將數據集擴展(這裡不這麼做了,因為我們已經有了很多數據),比如可以給聲譜圖添加隨機噪音或者將其輕微水平拉伸後再裁切。

但是我們必須確保這麼做沒有破壞數據的模式,我們不能旋轉聲譜圖,也不能水平翻轉它,因為聲音是不對稱的。

例如,看到這些白色的漸漸衰減的線條了嗎?這些就是不斷衰減的聲音,無法顛倒和翻轉。

這些白色的逐漸衰減的線條代表不斷衰減的聲音

選擇模型——我們創建一個分類器

把所有的歌曲切割成方形的聲譜圖後,我們就有了一個數據集,包含了成千上萬個對應每個歌曲流派的樣本。現在我們可以訓練一個深度卷積神經網路將這些樣本分類。為了完成這個目標,我使用了 TensorFlow 的封裝模型 TFLearn。

卷積神經網路

使用詳情:

  • 數據集分割:訓練集(70%),驗證集(20%),測試集(10%)
  • 模型:卷積神經網路
  • 網路層:2X2大小的核心程序,步幅為2
  • 優化器:RMSProp演算法
  • 激活函數:指數線性單元(Exponential Linear Unit),因為和ReLU函數相比,它更好一點。
  • 初始化:用Xavier演算法處理所有層中的權矩陣
  • 正則化:以0.5概率進行Dropout

結果——這玩意兒有用嗎?

我把 2000 首歌曲分成了 6 個流派——硬核音樂、迴響貝斯、古典音樂、電影原聲帶和說唱樂,總共用了 12000 個 128X128 的聲譜圖片段,模型在驗證集中達到了 90% 的準確率。這個結果已經相當不錯了。注意,這還不是我們分類全部歌曲時的最終準確率(會更高),我們這裡還只是在分類片段。

是時候分類歌曲了!

目前為止,我們已經將歌曲從立體聲轉換為單聲道,創建了一個聲譜圖,並把它切割成了很多小片段。然後我們用這些片段訓練了一個深度神經網路。現在,我們可以用這個深度學習模型給一首我們從沒見過的歌曲分類了。

我們首先生成聲譜圖,和我們處理訓練數據時的方法一樣。因為切割的緣故,我們沒法一口氣預測這首新歌的流派。我們得把這首歌切割成片段,然後把預測所有片段流派的結果綜合到一起。

要完成這一步,我們會用到投票方法,是集成學習中的一種演算法。音軌上的每個樣本會給流派「投票」,我們選擇得票最多的流派。這會提升我們的預測準確率,因為使用這種集成式的學習方法在處理分類問題時可以避免很多錯誤。

註:一首3分鐘長歌曲的音軌上大約有70個片段

模型中的投票系統

利用這個方法,我們現在可以對歌曲庫中未標記的歌曲進行分類了。針對某個歌曲流派,我們可以在所有歌曲上運行這種投票方法,然後聽候分類器的預測結果。雖然結果比較理想了,但是我們還是會想改進一下模型。

完整的分類流程

改進模型的投票系統

我們創建的分類器的最後一層是個 softmax 層,這意味著它並不是真的輸出檢測到的歌曲流派,而是每種流派的概率值。我們把這稱為「分類置信度」(classification confidence)。

分類置信度

我們用它來改進模型中的投票方法。例如,我們可以拒絕置信度較低的片段的投票結果。如果投票沒有明顯的結果,我們就否定掉這次投票。

有時候,耿直的說「我不知道」比給一個自己亂猜的答案要好得多。

同樣地,我們還可以設置不止一個投票結果的勝率(比如 70% 的片段投票贊同)來給未標記流派的歌曲分類,這樣一來,我們可以避免某些歌曲無法進行標記,這樣後頭我們還可以手工標記。

因為投票的分類置信度很低,歌曲最後未能分類和標記

結語

在本文,我們探討了如何從音軌這種高維度數據結構中抽取重要信息,充分利用了音軌數據具有的短模式特性,從而可以將歌曲分割為 2.56 秒長的片段並進行分類。最後我們用深度學習模型為資料庫中未標記分類的歌曲找到了流派。

最後小哥圖片鎮樓,這是真·程序猿QAQ


參考資料:

chatbotslife.com/findin

作者:Julien Despois


推薦閱讀:

《天才槍手》要失業?AI讓作弊更容易!
比現在的智能會議不知道高到哪裡去了!

TAG:景略集智 | 人工智能 | 深度学习DeepLearning |