<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # 八、音頻事件識別與分類 在前面的章節中,我們已經研究了一些非常有趣的案例研究,這些案例將遷移學習應用于實際問題。 圖像和文本數據是我們先前已解決的兩種非結構化數據形式。 我們已經展示了各種方法來應用遷移學習來獲得更強大和更出色的模型,以及解決諸如缺少訓練數據之類的約束。 在本章中,我們將解決識別和分類音頻事件的新現實問題。 為音頻數據創建預訓練的深度學習模型是一個巨大的挑戰,因為我們沒有高效的預訓練的視覺模型(例如 VGG 或 Inception(適用于圖像數據)或基于詞嵌入的模型(如 Word2vec 或 GloVe)的優勢) 文本數據)。 然后可能會出現一個問題,那就是我們對音頻數據的策略是什么。 我們將在本章中探索一些創新方法,敬請期待! 本章將涵蓋以下主要方面: * 了解音頻事件分類 * 制定我們的現實問題 * 探索性音頻事件分析 * 特征工程和音頻事件的表示 * 使用遷移學習的音頻事件分類 * 構建深度學習音頻事件識別器 在本章中,我們將研究識別和分類音頻事件的實際案例研究。 諸如音頻特征工程,轉換學習,深度學習和面向對象編程等概念將用于構建健壯的,自動化的音頻事件標識符以進行分類。 您可以在 [GitHub 存儲庫](https://github.com/dipanjanS/hands-on-transfer-learning-with-python)中的`Chapter 8`文件夾中快速閱讀本章的代碼。 可以根據需要參考本章。 # 了解音頻事件分類 到現在為止,您應該了解分類或分類的基本任務,在這里我們已經有了結構化或非結構化的數據,這些數據通常用特定的組或類別進行標記或標注。 自動分類的主要任務是建立一個模型,以便使用未來的數據點,我們可以根據各種數據屬性或特征將每個數據點分類或記錄為一種特定的類別。 在前面的章節中,我們已經研究了文本和圖像的分類。 在本章中,我們將研究對音頻事件進行分類。 音頻事件基本上是通常由音頻信號捕獲的事件或活動的發生。 通常,短的音頻片段用于表示音頻事件,因為即使它們反復出現,聲音通常也很相似。 但是,有時,可能會使用更長的音頻剪輯來表示更復雜的音頻事件。 音頻事件的示例可能是兒童在操場上玩耍,警笛警報,狗吠等。 實際上,谷歌已經建立了一個名為 [**AudioSet**](https://research.google.com/audioset/index.html) 的海量數據集,它是帶標注的音頻事件的一個手動的大規模數據集,他們還發表了幾篇有關音頻事件識別和分類的論文。 我們將使用較小的數據集來解決問題,但有興趣的讀者一定應該查看這個龐大的數據集,其中包含 632 個音頻事件類,其中包括從 YouTube 視頻中提取的 208420 個人工標記的 10 秒聲音剪輯的集合。 # 制定我們的現實問題 我們這里的實際案例研究的主要目標是音頻事件的識別和分類。 這是一個監督學習問題,我們將在音頻事件數據集上使用屬于特定類別(它們是聲音的來源)的音頻數據樣本進行處理。 我們將利用遷移學習和深度學習中的概念來構建可靠的分類器,從而在任何給定音頻樣本屬于我們預定類別之一的情況下,我們都應該能夠正確預測該聲音的來源。 我們將使用的數據集通常被稱為 [UrbanSound8K 數據集](https://urbansounddataset.weebly.com/),并且具有 8,732 個帶標簽的音頻聲音文件(其持續時間通常等于或大于 4 秒),其中包含城市常見聲音的摘錄。 該數據集中的聲音的十個類別如下: * `air_conditioner` * `car_horn` * `children_playing` * `dog_bark` * `drilling` * `engine_idling` * `gun_shot` * `jackhammer` * `siren` * `streen_music` 有關此數據集以及其他可能的數據集和計劃的詳細說明,我們建議讀者訪問 UrbanSound 網站,并查看創建者 J. Salamon,C。Jacoby 和 JP Bello 的這篇令人驚異的論文,[《數據集和城市聲音研究分類法》](http://www.justinsalamon.com/uploads/4/3/9/4/4394963/salamon_urbansound_acmmm14.pdf)(22 屆 ACM 國際多媒體國際會議,2014 年 11 月,美國奧蘭多)。我們感謝他們,以及紐約大學**城市科學與進步中心**(**CUSP**), 現實。 要獲取數據,您需要在其網站上填寫表格,然后您將通過電子郵件獲得下載鏈接。 解壓縮文件后,您應該能夠看到十個文件夾(十折)中的所有音頻文件,以及一個包含有關數據集更多詳細信息的`readme`文件。 # 探索性音頻事件分析 我們將遵循標準的工作流程,對音頻數據進行模型的分析,可視化,建模和評估。 下載完所有數據后,您會注意到總共有十個文件夾包含`WAV`格式的音頻數據樣本。 我們還有一個元數據文件夾,其中包含`UrbanSound8K.csv`文件中每個音頻文件的元數據信息。 您可以使用此文件為每個文件分配類標簽,也可以了解文件命名術語以進行相同的操作。 每個音頻文件都以特定格式命名。 該名稱采用`[fsID]-[classID]-[occurrenceID]-[sliceID].wav`格式,其格式如下: * `[fsID]`:從中摘錄該片段(片段)的錄音的自由聲音 ID * `[classID]`:聲音類別的數字標識符 * `[occurrenceID]`:數字標識符,用于區分原始錄音中聲音的不同出現 * `[sliceID]`:數字標識符,用于區分同一事件中獲取的不同片段 每個類標識符都是一個數字,可以映射到特定的類標簽。 我們將在不久的將來對此進行更多的擴展。 讓我們從對音頻數據的一些基本探索性分析開始。 如果您想自己運行示例,可以從我們的 GitHub 存儲庫中引用`Exploratory Analysis Sound Data.ipynb` Jupyter 筆記本。 首先,我們加載以下依賴項,包括`librosa`模塊,如果沒有該模塊,則可能需要安裝: ```py import glob import os import librosa import numpy as np import matplotlib.pyplot as plt from matplotlib.pyplot import specgram import pandas as pd import librosa.display import IPython.display import soundfile as sf %matplotlib inline ``` `librosa`模塊是用于音頻和音樂分析的出色的開源 Python 框架。 我們建議讀者更詳細地檢查該框架。 在接下來的部分中,我們將使用它來分析音頻數據并從中提取特征。 現在讓我們加載一個數據文件夾進行分析: ```py files = glob.glob('UrbanSound8K/audio/fold1/*') len(files) 873 ``` 我們可以看到每個文件夾大致包含 870 多個音頻樣本。 現在,基于`metadata`和`readme`文件的信息,我們可以創建一個類 ID,以名稱映射音頻樣本類別: ```py class_map = {'0' : 'air_conditioner', '1' : 'car_horn', '2' : 'children_playing', '3' : 'dog_bark', '4' : 'drilling', '5' : 'engine_idling', '6' : 'gun_shot', '7' : 'jackhammer', '8' : 'siren', '9' : 'street_music'} pd.DataFrame(sorted(list(class_map.items()))) ``` 現在讓我們從屬于這些類別的每個類別中抽取十個不同的音頻樣本,以進行進一步分析: ```py samples = [(class_map[label], [f for f in files if f.split('-')[1] == label][0]) for label in class_map.keys()] samples [('street_music', 'UrbanSound8K/audio/fold1\108041-9-0-11.wav'), ('engine_idling', 'UrbanSound8K/audio/fold1\103258-5-0-0.wav'), ('jackhammer', 'UrbanSound8K/audio/fold1\103074-7-0-0.wav'), ('air_conditioner', 'UrbanSound8K/audio/fold1\127873-0-0-0.wav'), ('drilling', 'UrbanSound8K/audio/fold1\14113-4-0-0.wav'), ('children_playing', 'UrbanSound8K/audio/fold1\105415-2-0-1.wav'), ('gun_shot', 'UrbanSound8K/audio/fold1\102305-6-0-0.wav'), ('siren', 'UrbanSound8K/audio/fold1\106905-8-0-0.wav'), ('car_horn', 'UrbanSound8K/audio/fold1\156194-1-0-0.wav'), ('dog_bark', 'UrbanSound8K/audio/fold1\101415-3-0-2.wav')] ``` 現在我們有了示例數據文件,在執行任何分析之前,我們仍然需要將音頻數據讀入內存。 我們注意到`librosa`對某些音頻文件拋出了錯誤(因為它們的長度或采樣率很短)。 因此,我們利用`soundfile` Python 框架讀取音頻文件,以獲取其原始數據和原始采樣率。 您可以在此處獲取[有關`soundfile`框架的更多信息](https://pypi.org/project/SoundFile/)。 音頻采樣率定義為每秒傳輸的音頻采樣數,通常以 Hz 或 kHz(1 kHz 為 1,000 Hz)為單位。 `librosa`的默認采樣率為 22,050 Hz,這是我們將重新采樣所有音頻數據以保持一致性的方式。 以下代碼可幫助我們讀取數據,并顯示原始音頻數據的總長度: ```py def get_sound_data(path, sr=22050): data, fsr = sf.read(path) data_22k = librosa.resample(data.T, fsr, sr) if len(data_22k.shape) > 1: data_22k = np.average(data_22k, axis=0) return data_22k, sr sample_data = [(sample[0], get_sound_data(sample[1])) for sample in samples] [(sample[0], sample[1][0].shape) for sample in sample_data] ``` ```py [('street_music', (88200,)), ('engine_idling', (88200,)), ('jackhammer', (88200,)), ('air_conditioner', (44982,)), ('drilling', (88200,)), ('children_playing', (88200,)), ('gun_shot', (57551,)), ('siren', (88200,)), ('car_horn', (5513,)), ('dog_bark', (88200,))] ``` 很明顯,大多數音頻采樣的持續時間約為四秒鐘,但有些采樣的持續時間卻很短。 Jupyter 筆記本的魅力在于,您甚至可以將音頻嵌入筆記本本身,并使用以下片段播放它。 對于`sample_data`中的數據: ```py print(data[0], ':') IPython.display.display(IPython.display.Audio(data=data[1[0],rate=data[ 1][1])) ``` 這將創建以下內容: ![](https://img.kancloud.cn/09/4b/094b7671199db5a20c7213c4ed405b99_344x146.png) 現在讓我們通過繪制它們的波形來形象化這些不同的音頻源的外觀。 通常,這將是每個音頻樣本的波形幅度圖: ```py i = 1 fig = plt.figure(figsize=(15, 6)) for item in sample_data: plt.subplot(2, 5, i) librosa.display.waveplot(item[1][0], sr=item[1][1], color='r', alpha=0.7) plt.title(item[0]) i += 1 plt.tight_layout() ``` 創建的圖將如下所示: ![](https://img.kancloud.cn/e2/c0/e2c0d6962451eeb8f323af3ebbb15364_974x391.png) 您可以在上圖中清楚地看到不同的音頻數據樣本及其源標簽和相應的音頻波形圖。 這描繪了一些有趣的見解。 `engine_idling`,`jackhammer`和`air_conditioner`等音源通常具有恒定的聲音,不會隨時間變化。 因此,您可以注意到波形中的振幅恒定。 `siren`和`car_horn`通常也具有恒定的音頻波形,并具有間歇性的幅度增加。`gun_shot`通常在開始時會發出很大的聲音,然后保持沉默。 `dog_bark`間歇地進入。 因此,除了靜音以外,聲音還具有短的高振幅間隔。 您還能找到更多有趣的模式嗎? 音頻數據的另一種有趣的可視化技術是聲譜圖。 通常,聲譜圖是一種視覺表示技術,用于表示音頻數據中的頻譜。 它們也被普遍稱為**超聲檢查儀**和**語音圖**。 讓我們將音頻樣本可視化為頻譜圖: ```py i = 1 fig = plt.figure(figsize=(15, 6)) for item in sample_data: plt.subplot(2, 5, i) specgram(item[1][0], Fs=item[1][1]) plt.title(item[0]) i += 1 plt.tight_layout() ``` 頻譜圖顯示如下: ![](https://img.kancloud.cn/08/61/0861eb6c627e4cdf0a2bda54baae83de_985x388.png) 我們可以看到如何用頻譜圖將音頻數據表示為很好的圖像表示形式,這對于像**卷積神經網絡**(**CNN**)這樣的模型很有用,因為可以肯定地看到不同音頻源在聲譜圖中存在明顯差異。 但是,我們將使用梅爾譜圖,它通常比基本譜圖更好,因為它代表了梅爾刻度的譜圖。 名稱 **mel** 來自單詞 *melody*。 這表明比例尺基于音高比較。 因此,梅爾音階是對音高的感知尺度,聽眾已將其判斷為彼此之間的距離相等。 如果我們使用 CNN 從這些頻譜圖中提取特征,這將非常有用。 以下代碼段描繪了梅爾頻譜圖: ```py i = 1 fig = plt.figure(figsize=(15, 6)) for item in sample_data: plt.subplot(2, 5, i) S = librosa.feature.melspectrogram(item[1][0], sr=item[1] [1],n_mels=128) log_S = librosa.logamplitude(S) librosa.display.specshow(log_S, sr=item[1][1], x_axis='time',y_axis='mel') plt.title(item[0]) plt.colorbar(format='%+02.0f dB') i += 1 plt.tight_layout() ``` 梅爾頻譜圖顯示如下: ![](https://img.kancloud.cn/ce/b1/ceb1db2abaa608fce681b198a63600b7_988x387.png) 我們可以看到,借助梅爾音階,可以更容易地根據音頻源來區分頻譜圖。 現在,讓我們集中討論下一節中將用作特征工程基礎資源的一些特定視覺技術。 首先,讓我們看一下`gun_shot`音頻樣本作為梅爾頻譜圖的樣子: ```py y = sample_data[6][1][0] S = librosa.feature.melspectrogram(y, sr=22050, n_mels=128) log_S = librosa.logamplitude(S) plt.figure(figsize=(12,4)) librosa.display.specshow(log_S, sr=22050, x_axis='time', y_axis='mel') plt.colorbar(format='%+02.0f dB') ``` 頻譜圖顯示如下: ![](https://img.kancloud.cn/a3/72/a372d02cc136bc6ed7551142b86e5a2d_694x272.png) 頻譜圖與該音頻源的音頻波形圖一致。 音頻的另一個有趣方面是,通常任何音頻時間序列數據都可以分解為諧波和打擊樂成分。 這些可以呈現任何音頻樣本的全新有趣的表示形式。 讓我們獲取這些組件并將它們繪制成頻譜圖: ```py y_harmonic, y_percussive = librosa.effects.hpss(y) S_harmonic = librosa.feature.melspectrogram(y_harmonic,sr=22050, n_mels=128) S_percussive = librosa.feature.melspectrogram(y_percussive,sr=22050) log_Sh = librosa.power_to_db(S_harmonic) log_Sp = librosa.power_to_db(S_percussive) # Make a new figure plt.figure(figsize=(12,6)) plt.subplot(2,1,1) librosa.display.specshow(log_Sh, sr=sr, y_axis='mel') plt.title('mel power spectrogram (Harmonic)') plt.colorbar(format='%+02.0f dB') plt.subplot(2,1,2) librosa.display.specshow(log_Sp, sr=sr, x_axis='time', y_axis='mel') plt.title('mel power spectrogram (Percussive)') plt.colorbar(format='%+02.0f dB') plt.tight_layout() ``` 頻譜圖將顯示如下: ![](https://img.kancloud.cn/c0/91/c09178ea836cb9ff632254726fe50e43_788x416.png) 您可以看到音頻樣本的兩個不同成分顯示為兩個獨特的聲譜圖,分別描述了諧波成分和打擊樂成分。 音頻數據的另一個非常有趣的描述是使用一個色譜圖,該圖顯示了基于十二種不同音高類別(即`{C, C#, D, D#, E, F, F#, G, G#, A, A#, B}`。 這是用于描述音頻信號隨時間變化的各種音調強度的出色視覺工具。 通常,在構建色譜圖之前,會對原始音頻信號執行傅立葉變換或 Q 變換: ```py C = librosa.feature.chroma_cqt(y=y_harmonic, sr=sr) # Make a new figure plt.figure(figsize=(12, 4)) # Display the chromagram: the energy in each chromatic pitch class # as a function of time librosa.display.specshow(C, sr=sr, x_axis='time', y_axis='chroma', vmin=0, vmax=1) plt.title('Chromagram') plt.colorbar() plt.tight_layout() ``` 色譜圖將顯示如下: ![](https://img.kancloud.cn/a6/f5/a6f54d77a647b767553173594f63a743_772x262.png) 隨著時間的推移,我們可以清楚地看到`gun_shot`音頻樣本的各種音調強度,這對于作為特征提取的基礎圖像肯定是有效的。 在下一節中,我們將使用其中一些技術進行特征提取。 # 特征工程和音頻事件的表示 要構建可靠的分類模型,我們需要從原始音頻數據中獲得可靠且良好的特征表示。 我們將利用上一節中學到的一些技術進行特征工程。 如果您想自己運行示例,可以在`Feature Engineering.ipynb` Jupyter 筆記本中使用本節中使用的代碼段。 我們將重用先前導入的所有庫,并在此處利用`joblib`將特征保存到磁盤: ```py from sklearn.externals import joblib ``` 接下來,我們將加載所有文件名,并定義一些工具函數以讀取音頻數據,還使我們能夠獲取音頻子樣本的窗口索引,我們將在短期內利用它們: ```py # get all file names ROOT_DIR = 'UrbanSound8K/audio/' files = glob.glob(ROOT_DIR+'/**/*') # load raw audio data def get_sound_data(path, sr=22050): data, fsr = sf.read(path) data_resample = librosa.resample(data.T, fsr, sr) if len(data_resample.shape) > 1: data_resample = np.average(data_resample, axis=0) return data_resample, sr # function to get start and end indices for audio sub-sample def windows(data, window_size): start = 0 while start < len(data): yield int(start), int(start + window_size) start += (window_size / 2) ``` 我們將遵循的特征工程策略有些復雜,但是我們將在此處嘗試以簡潔的方式對其進行說明。 我們已經看到我們的音頻數據樣本的長度不同。 但是,如果我們要構建一個強大的分類器,則每個樣本的特征必須保持一致。 因此,我們將從每個音頻文件中提取(固定長度的)音頻子樣本,并從每個這些子樣本中提取特征。 我們將總共使用三種特征工程技術來構建三個特征表示圖,這最終將為我們的每個音頻子樣本提供一個三維圖像特征圖。 下圖描述了我們將采用的工作流程: ![](https://img.kancloud.cn/5e/d8/5ed897e593bc8839248990b2f96a4255_777x202.png) 這個想法來自 Karol J. Piczak 的出色論文,[《具有卷積神經網絡的環境聲音分類》](https://ieeexplore.ieee.org/document/7324337/)(IEEE2015)。他將梅爾頻譜圖用于一般必要的特征,CNN 可以使用這些特征來進行特征提取。 但是,我們已經考慮了對最終特征圖的一些其他轉換。 第一步是將幀(列)的總數定義為 **64** ,將波段(行)的總數定義為 **64**,這形成了每個特征圖的尺寸(`64 x 64`)。 然后,基于此,我們提取音頻數據的窗口,從每個音頻數據樣本中形成子樣本。 考慮每個音頻子樣本,我們首先創建一個梅爾聲譜圖。 由此,我們創建了一個對數縮放的梅爾頻譜圖,作為特征圖之一,音頻子樣本的諧波分量和敲擊分量的平均特征圖(再次對數縮放),以及對數縮放的 mel 頻譜圖的增量或導數作為第三特征圖。 這些特征圖的每一個都可以表示為`64 x 64`圖像,并且通過組合它們,我們可以為每個音頻子樣本獲得尺寸為`(64, 64, 3)`的 3-D 特征圖。 現在,為該工作流程定義函數: ```py def extract_features(file_names, bands=64, frames=64): window_size = 512 * (frames - 1) log_specgrams_full = [] log_specgrams_hp = [] class_labels = [] # for each audio sample for fn in file_names: file_name = fn.split('\')[-1] class_label = file_name.split('-')[1] sound_data, sr = get_sound_data(fn, sr=22050) # for each audio signal sub-sample window of data for (start,end) in windows(sound_data, window_size): if(len(sound_data[start:end]) == window_size): signal = sound_data[start:end] # get the log-scaled mel-spectrogram melspec_full = librosa.feature.melspectrogram(signal, n_mels = bands) logspec_full = librosa.logamplitude(melspec_full) logspec_full = logspec_full.T.flatten()[:,np.newaxis].T # get the log-scaled, averaged values for the # harmonic and percussive components y_harmonic, y_percussive =librosa.effects.hpss(signal) melspec_harmonic = librosa.feature.melspectrogram(y_harmonic, n_mels=bands) melspec_percussive = librosa.feature.melspectrogram(y_percussive, n_mels=bands) logspec_harmonic = librosa.logamplitude(melspec_harmonic) logspec_percussive = librosa.logamplitude(melspec_percussive) logspec_harmonic = logspec_harmonic.T.flatten()[:, np.newaxis].T logspec_percussive = logspec_percussive.T.flatten()[:, np.newaxis].T logspec_hp = np.average([logspec_harmonic, logspec_percussive], axis=0) log_specgrams_full.append(logspec_full) log_specgrams_hp.append(logspec_hp) class_labels.append(class_label) # create the first two feature maps log_specgrams_full = np.asarray(log_specgrams_full).reshape( len(log_specgrams_full), bands, frames, 1) log_specgrams_hp = np.asarray(log_specgrams_hp).reshape( len(log_specgrams_hp), bands, frames, 1) features = np.concatenate((log_specgrams_full, log_specgrams_hp, np.zeros(np.shape( log_specgrams_full))), axis=3) # create the third feature map which is the delta (derivative) # of the log-scaled mel-spectrogram for i in range(len(features)): features[i, :, :, 2] = librosa.feature.delta(features[i, :, :, 0]) return np.array(features), np.array(class_labels, dtype = np.int) ``` 現在我們準備使用此函數。 我們將在前面的工作流程中討論的策略基礎上,將其用于所有 8,732 音頻樣本,以從該數據的許多子樣本中創建特征圖。 ```py features, labels = extract_features(files) features.shape, labels.shape ((30500, 64, 64, 3), (30500,)) ``` 我們從 8,732 個音頻數據文件中總共獲得了 30,500 個特征圖。 這非常好,并且正如我們前面所討論的,每個特征圖都是尺寸`(64, 64, 3)`。 現在,基于以下 30,500 個數據點,查看音頻源的整體類表示形式: ```py from collections import Counter Counter(labels) Counter({0: 3993, 1: 913, 2: 3947, 3: 2912, 4: 3405, 5: 3910, 6: 336, 7: 3473, 8: 3611, 9: 4000}) ``` 我們可以看到,不同類別中數據點的總體分布是相當均勻和適當的。 對于諸如 1(`car_horn`)和 6(`gun_shot`)的某些類別,表示與其他類別相比非常低; 這是可以預期的,因為這些類別的音頻數據持續時間通常比其他類別要短得多。 現在讓我們繼續可視化這些特征圖: ```py class_map = {'0' : 'air_conditioner', '1' : 'car_horn', '2' : 'children_playing','3' : 'dog_bark', '4' : 'drilling','5' : 'engine_idling','6' : 'gun_shot', '7' : 'jackhammer', '8' : 'siren', '9' : 'street_music'} categories = list(set(labels)) sample_idxs = [np.where(labels == label_id)[0][0] for label_id in categories] feature_samples = features[sample_idxs] plt.figure(figsize=(16, 4)) for index, (feature_map, category) in enumerate(zip(feature_samples, categories)): plt.subplot(2, 5, index+1) plt.imshow(np.concatenate((feature_map[:,:,0], feature_map[:,:,1], feature_map[:,:,2]), axis=1), cmap='viridis') plt.title(class_map[str(category)]) plt.tight_layout() t = plt.suptitle('Visualizing Feature Maps for Audio Clips') ``` 特征圖將顯示如下: ![](https://img.kancloud.cn/fa/6e/fa6e664c4ee5ce0fab248534ab7fab28_989x232.png) 上圖向我們展示了每個音頻類別的一些示例特征圖看起來是什么樣的,并且顯而易見的是,每個特征圖都是三維圖像。 現在,我們將這些基本特征保存到磁盤: ```py joblib.dump(features, 'base_features.pkl') joblib.dump(labels, 'dataset_labels.pkl') ``` 這些基本特征將作為下一部分進一步特征設計的起點,在此我們將釋放遷移學習的真正力量。 # 使用遷移學習的音頻事件分類 現在,我們準備開始構建音頻事件分類器。 我們有基本的特征圖,但仍然需要做更多的特征工程。 您始終可以從頭開始構建 CNN 以攝取這些圖像,然后將其連接到完全連接的深**多層感知器**(**MLP**)來構建分類器。 但是,在這里,我們將通過使用一種預訓練的模型進行特征提取來利用遷移學習的力量。 更具體地說,我們將使用 VGG-16 模型作為特征提取器,然后在這些特征上訓練完全連接的深度網絡。 # 從基本特征構建數據集 第一步是加載基本特征,并創建訓練,驗證和測試數據集。 為此,我們需要從磁盤加載基本特征和標簽: ```py features = joblib.load('base_features.pkl') labels = joblib.load('dataset_labels.pkl') data = np.array(list(zip(features, labels))) features.shape, labels.shape ((30500, 64, 64, 3), (30500,)) ``` 現在,我們將隨機整理數據并創建訓練,驗證和測試數據集: ```py np.random.shuffle(data) train, validate, test = np.split(data, [int(.6*len(data)),int(.8*len(data))]) train.shape, validate.shape, test.shape ((18300, 2), (6100, 2), (6100, 2)) ``` 最后,我們還可以使用以下代碼段檢查每個數據集中的每類分布: ```py print('Train:', Counter(item[1] for item in train),'nValidate:', Counter(item[1] for item in validate),'nTest:',Counter(item[1] for item in test)) Train: Counter({9: 2448, 2: 2423, 0: 2378, 5: 2366, 8: 2140, 7: 2033, 4: 2020, 3: 1753, 1: 542, 6: 197}) Validate: Counter({0: 802, 5: 799, 2: 774, 9: 744, 8: 721, 7: 705, 4: 688, 3: 616, 1: 183, 6: 68}) Test: Counter({0: 813, 9: 808, 2: 750, 8: 750, 5: 745, 7: 735, 4: 697, 3: 543, 1: 188, 6: 71}) ``` 因此,我們可以看到整個數據集中每個類的數據點一致且均勻地分布。 # 遷移學習以進行特征提取 現在來了有趣的部分。 我們準備利用遷移學習從基本特征映射圖中為每個數據點提取有用的特征。 為此,我們將使用出色的預訓練深度學習模型,該模型已被證明是圖像上非常有效的特征提取器。 我們將在這里使用 VGG-16 模型。 但是,我們將在這里使用它作為簡單的特征提取器,而無需進行任何微調(這是我們在前幾章中探討的內容)。 隨意利用微調,這甚至可以帶來更好的分類器。 我們首先定義一些基本的工具和函數來處理基本圖像: ```py from keras.preprocessing import image from keras.applications.imagenet_utils import preprocess_input from PIL import Image def process_sound_data(data): data = np.expand_dims(data, axis=0) data = preprocess_input(data) return data ``` 現在,我們將加載 VGG-16 模型,但僅作為特征提取器。 因此,我們最終將不會使用其密集層: ```py from keras.applications import vgg16 from keras.models import Model import keras vgg = vgg16.VGG16(include_top=False, weights='imagenet',input_shape= (64, 64, 3)) output = vgg.layers[-1].output output = keras.layers.Flatten()(output) model = Model(vgg.input, output) model.trainable = False model.summary() _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= input_2 (InputLayer) (None, 64, 64, 3) 0 _________________________________________________________________ block1_conv1 (Conv2D) (None, 64, 64, 64) 1792 _________________________________________________________________ block1_conv2 (Conv2D) (None, 64, 64, 64) 36928 _________________________________________________________________ ... ... _________________________________________________________________ block5_conv3 (Conv2D) (None, 4, 4, 512) 2359808 _________________________________________________________________ block5_pool (MaxPooling2D) (None, 2, 2, 512) 0 _________________________________________________________________ flatten_2 (Flatten) (None, 2048) 0 ================================================================= Total params: 14,714,688 Trainable params: 0 Non-trainable params: 14,714,688 _________________________________________________________________ ``` 從前面的模型摘要中可以明顯看出,我們輸入的基本特征圖圖像的尺寸為`(64, 64, 3)`,從中我們最終將得到大小為 2,048 的一維特征向量。 讓我們構建一個通用函數,以幫助我們利用遷移學習并獲得這些特征,這些特征通常被稱為**瓶頸特征**: ```py def extract_tl_features(model, base_feature_data): dataset_tl_features = [] for index, feature_data in enumerate(base_feature_data): if (index+1) % 1000 == 0: print('Finished processing', index+1, 'sound feature maps') pr_data = process_sound_data(feature_data) tl_features = model.predict(pr_data) tl_features = np.reshape(tl_features, tl_features.shape[1]) dataset_tl_features.append(tl_features) return np.array(dataset_tl_features) ``` 現在可以將此函數與我們的 VGG-16 模型一起使用,以從我們的每個音頻子樣本基本特征圖圖像中提取有用的特征。 我們將對所有數據集執行此操作: ```py # extract train dataset features train_base_features = [item[0] for item in train] train_labels = np.array([item[1] for item in train]) train_tl_features = extract_tl_features(model=model, base_feature_data=train_base_features) # extract validation dataset features validate_base_features = [item[0] for item in validate] validate_labels = np.array([item[1] for item in validate]) validate_tl_features = extract_tl_features(model=model, base_feature_data=validate_base_features) # extract test dataset features test_base_features = [item[0] for item in test] test_labels = np.array([item[1] for item in test]) test_tl_features = extract_tl_features(model=model, base_feature_data=test_base_features) train_tl_features.shape, validate_tl_features.shape, test_tl_features.shape ((18300, 2048), (6100, 2048), (6100, 2048)) ``` 現在,我們可以將這些特征和標簽保存到磁盤上,以便以后可以隨時用于構建分類器,而不必依賴于始終保持筆記本計算機處于打開狀態: ```py joblib.dump(train_tl_features, 'train_tl_features.pkl') joblib.dump(train_labels, 'train_labels.pkl') joblib.dump(validate_tl_features, 'validate_tl_features.pkl') joblib.dump(validate_labels, 'validate_labels.pkl') joblib.dump(test_tl_features, 'test_tl_features.pkl') joblib.dump(test_labels, 'test_labels.pkl') ``` # 建立分類模型 現在,我們準備在上一節中提取的特征上構建分類模型。 如果您想自己運行示例,可以在`Modeling.ipynb` Jupyter 筆記本中使用此部分的代碼。 首先,讓我們加載一些基本的依賴項: ```py from sklearn.externals import joblib import keras from keras import models from keras import layers import model_evaluation_utils as meu import matplotlib.pyplot as plt %matplotlib inline ``` 我們將使用名為`model_evaluation_utils`的漂亮模型評估工具模塊來評估我們的分類器并稍后測試其表現。 現在讓我們加載特征集和數據點類標簽: ```py train_features = joblib.load('train_tl_features.pkl') train_labels = joblib.load('train_labels.pkl') validation_features = joblib.load('validate_tl_features.pkl') validation_labels = joblib.load('validate_labels.pkl') test_features = joblib.load('test_tl_features.pkl') test_labels = joblib.load('test_labels.pkl') train_features.shape, validation_features.shape, test_features.shape ((18300, 2048), (6100, 2048), (6100, 2048)) train_labels.shape, validation_labels.shape, test_labels.shape ((18300,), (6100,), (6100,)) ``` 因此,我們可以看到我們所有的特征集和相應的標簽均已加載。 輸入特征集是從上一節中使用的 VGG-16 模型獲得的大小為 2,048 的一維向量。 現在,我們需要對分類類標簽進行一次熱編碼,然后才能將其輸入到深度學習模型中。 以下代碼段可幫助我們實現這一目標: ```py from keras.utils import to_categorical train_labels_ohe = to_categorical(train_labels) validation_labels_ohe = to_categorical(validation_labels) test_labels_ohe = to_categorical(test_labels) train_labels_ohe.shape, validation_labels_ohe.shape, test_labels_ohe.shape ((18300, 10), (6100, 10), (6100, 10)) ``` 現在,我們將使用具有四個隱藏層的完全連接的網絡來構建深度學習分類器。 我們將使用常見的組件(如丟棄法)來防止過擬合,并使用模型的 Adam 優化器。 以下代碼描述了模型架構的詳細信息: ```py model = models.Sequential() model.add(layers.Dense(1024, activation='relu', input_shape=(train_features.shape[1],))) model.add(layers.Dropout(0.4)) model.add(layers.Dense(1024, activation='relu')) model.add(layers.Dropout(0.4)) model.add(layers.Dense(512, activation='relu')) model.add(layers.Dropout(0.5)) model.add(layers.Dense(512, activation='relu')) model.add(layers.Dropout(0.5)) model.add(layers.Dense(train_labels_ohe.shape[1],activation='softmax')) model.compile(loss='categorical_crossentropy', optimizer='adam',metrics=['accuracy']) model.summary() _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= dense_1 (Dense) (None, 1024) 2098176 _________________________________________________________________ dropout_1 (Dropout) (None, 1024) 0 _________________________________________________________________ dense_2 (Dense) (None, 1024) 1049600 _________________________________________________________________ dropout_2 (Dropout) (None, 1024) 0 _________________________________________________________________ dense_3 (Dense) (None, 512) 524800 _________________________________________________________________ dropout_3 (Dropout) (None, 512) 0 _________________________________________________________________ dense_4 (Dense) (None, 512) 262656 _________________________________________________________________ dropout_4 (Dropout) (None, 512) 0 _________________________________________________________________ dense_5 (Dense) (None, 10) 5130 ================================================================= Total params: 3,940,362 Trainable params: 3,940,362 Non-trainable params: 0 ``` 然后,在 AWS **p2.x** 實例上對該模型進行了約 50 個周期的訓練,批量大小為 128。 您可以嘗試使用時間和批量大小來獲得可靠的模型,如下所示: ```py history = model.fit(train_features, train_labels_ohe,epochs=50, batch_size=128, validation_data=(validation_features, validation_labels_ohe),shuffle=True, verbose=1) Train on 18300 samples, validate on 6100 samples Epoch 1/50 18300/18300 - 2s - loss: 2.7953 - acc: 0.3959 - val_loss: 1.0665 - val_acc: 0.6675 Epoch 2/50 18300/18300 - 1s - loss: 1.1606 - acc: 0.6211 - val_loss: 0.8179 - val_acc: 0.7444 ... ... Epoch 48/50 18300/18300 - 1s - loss: 0.2753 - acc: 0.9157 - val_loss: 0.4218 - val_acc: 0.8797 Epoch 49/50 18300/18300 - 1s - loss: 0.2813 - acc: 0.9142 - val_loss: 0.4220 - val_acc: 0.8810 Epoch 50/50 18300/18300 - 1s - loss: 0.2631 - acc: 0.9197 - val_loss: 0.3887 - val_acc: 0.8890 ``` 我們獲得的驗證準確率接近 **89%**,這非常好,看起來很有希望。 我們還可以繪制模型的整體精度圖和損耗圖,以更好地了解事物的外觀,如下所示: ```py f, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4)) t = f.suptitle('Deep Neural Net Performance', fontsize=12) f.subplots_adjust(top=0.85, wspace=0.2) epochs = list(range(1,51)) ax1.plot(epochs, history.history['acc'], label='Train Accuracy') ax1.plot(epochs, history.history['val_acc'], label='Validation Accuracy') ax1.set_ylabel('Accuracy Value') ax1.set_xlabel('Epoch') ax1.set_title('Accuracy') l1 = ax1.legend(loc="best") ax2.plot(epochs, history.history['loss'], label='Train Loss') ax2.plot(epochs, history.history['val_loss'], label='Validation Loss') ax2.set_ylabel('Loss Value') ax2.set_xlabel('Epoch') ax2.set_title('Loss') l2 = ax2.legend(loc="best") ``` 這將創建以下圖: ![](https://img.kancloud.cn/61/95/61954122f2d5f499e40159b219f36ed4_735x288.png) 我們可以看到模型在訓練和驗證之間的損失和準確率是相當一致的。 也許略有過擬合,但考慮到它們之間的差異很小,可以忽略不計。 # 評估分類器表現 從字面上看,現在該對我們的模型進行測試了。 我們將使用測試數據集對模型進行預測,然后根據基本事實標簽對它們進行評估。 為此,我們首先需要使用以下代碼片段獲取測試數據對模型的預測,并從數字標簽到實際文本標簽進行反向映射: ```py predictions = model.predict_classes(test_features) class_map = {'0' : 'air_conditioner', '1' : 'car_horn', '2' : 'children_playing', '3' : 'dog_bark', '4' : 'drilling', '5' : 'engine_idling', '6' : 'gun_shot', '7' : 'jackhammer', '8' : 'siren', '9' : 'street_music'} test_labels_categories = [class_map[str(label)]for label in test_labels] prediction_labels_categories = [class_map[str(label)]for label in predictions] category_names = list(class_map.values()) ``` 現在讓我們使用`model_evaluation_utils`模塊來根據測試數據評估模型的表現。 我們首先獲得總體表現指標: ```py meu.get_metrics(true_labels=test_labels_categories, predicted_labels=prediction_labels_categories) Accuracy: 0.8869 Precision: 0.8864 Recall: 0.8869 F1 Score: 0.8861 ``` 我們獲得了總體模型準確率,并且`f1-score`接近 89%,這非常好,并且與我們從驗證數據集中獲得的一致。 接下來讓我們看一下每類模型的表現: ```py meu.display_classification_report(true_labels=test_labels_categories, predicted_labels=prediction_labels_categories, classes=category_names) precision recall f1-score support car_horn 0.87 0.73 0.79 188 siren 0.95 0.94 0.94 750 drilling 0.88 0.93 0.90 697 gun_shot 0.94 0.94 0.94 71 children_playing 0.83 0.79 0.81 750 air_conditioner 0.89 0.94 0.92 813 jackhammer 0.92 0.93 0.92 735 engine_idling 0.94 0.95 0.95 745 dog_bark 0.87 0.83 0.85 543 street_music 0.81 0.81 0.81 808 avg / total 0.89 0.89 0.89 6100 ``` 這使我們可以更清楚地了解模型確實運行良好以及可能遇到問題的確切類。 大多數類似乎運行良好,尤其是設備聲音,例如`gun_shot`,`jackhammer`和`engine_idling`等。 似乎`street_music`和`children_playing`最麻煩。 混淆矩陣可以幫助我們了解最可能發生錯誤分類的地方,并幫助我們更好地理解這一點: ```py meu.display_confusion_matrix_pretty(true_labels=test_labels_categories, predicted_labels=prediction_labels_categories, classes=category_names) ``` 矩陣將顯示如下: ![](https://img.kancloud.cn/bb/5a/bb5a306e1cffc441620bc814538f6285_955x312.png) 從矩陣的對角線看,我們可以看到大多數模型預測都是正確的,這非常好。 關于錯誤分類,我們可以看到,屬于`street_music`,`dog_bark`和`children_playing`的許多樣本彼此之間都被錯誤分類了,考慮到所有這些事件都是在公開場合和外部發生的,一種預期的他們有可能一起發生。 對于`drilling`和`jackhammer`也是一樣。 幸運的是,`gun_shot`和`children_playing`之間的錯誤分類幾乎沒有重疊。 因此,在這個復雜的案例研究中,我們可以看到有效的遷移學習是如何工作的,在該案例中,我們利用圖像分類器幫助我們構建了強大而有效的音頻事件分類器。 現在,我們可以使用以下代碼保存此模型以供將來使用: ```py model.save('sound_classification_model.h5') ``` 您現在可能會認為這很好。 但是,我們在靜態數據集上進行了所有操作。 我們將如何在現實世界中使用此模型進行音頻事件識別和分類? 我們將在下一節中討論策略。 # 構建深度學習音頻事件識別器 現在,我們將研究一種策略,利用該策略,我們可以利用上一節中構建的分類模型來構建實際的音頻事件標識符。 這將使我們能夠利用本章中定義的整個工作流程來獲取任何新的音頻文件,并預測該文件可能屬于的類別,從構建基本特征圖開始,使用 VGG-16 模型提取特征,然后利用我們的分類模型做出預測。 如果您想自己運行示例,可以在`Prediction Pipeline.ipynb` Jupyter 筆記本中使用本節中使用的代碼段。 筆記本包含`AudioIdentifier`類,該類是通過重用本章前面各節中構建的所有組件而創建的。 請參閱筆記本以訪問該類的完整代碼,因為我們將更加關注實際的預測流水線,以使內容更加簡潔。 我們將通過為類的實例提供分類模型的路徑來初始化它: ```py ai = AudioIdentifier(prediction_model_path='sound_classification_model.h5') ``` 現在,我們已經下載了十個音頻類別中的三個的三個全新的音頻數據文件。 讓我們加載它們,以便我們可以在它們上測試模型的表現: ```py siren_path = 'UrbanSound8K/test/sirenpolice.wav' gunshot_path = 'UrbanSound8K/test/gunfight.wav' dogbark_path = 'UrbanSound8K/test/dog_bark.wav' siren_audio, siren_sr = ai.get_sound_data(siren_path) gunshot_audio, gunshot_sr = ai.get_sound_data(gunshot_path) dogbark_audio, dogbark_sr = ai.get_sound_data(dogbark_path) actual_sounds = ['siren', 'gun_shot', 'dog_bark'] sound_data = [siren_audio, gunshot_audio, dogbark_audio] sound_rate = [siren_sr, gunshot_sr, dogbark_sr] sound_paths = [siren_path, gunshot_path, dogbark_path] ``` 讓我們可視化這三個音頻文件的波形,并了解它們的結構: ```py i = 1 fig = plt.figure(figsize=(12, 3.5)) t = plt.suptitle('Visualizing Amplitude Waveforms for Audio Clips', fontsize=14) fig.subplots_adjust(top=0.8, wspace=0.2) for sound_class, data, sr in zip(actual_sounds, sound_data,sound_rate): plt.subplot(1, 3, i) librosa.display.waveplot(data, sr=sr, color='r', alpha=0.7) plt.title(sound_class) i += 1 plt.tight_layout(pad=2.5) ``` 可視化效果如下所示: ![](https://img.kancloud.cn/ba/37/ba37851ca2e9defe5100e4d140b287a1_835x236.png) 基于可視化,基于音頻源,它們似乎是一致的,到目前為止,我們的流水線運行良好。 現在,我們為這些音頻文件提取基本特征圖: ```py siren_feature_map = ai.extract_base_features(siren_audio)[0] gunshot_feature_map = ai.extract_base_features(gunshot_audio)[0] dogbark_feature_map = ai.extract_base_features(dogbark_audio)[0] feature_maps = [siren_feature_map, gunshot_feature_map,dogbark_feature_map] plt.figure(figsize=(14, 3)) t = plt.suptitle('Visualizing Feature Maps for Audio Clips',fontsize=14) fig.subplots_adjust(top=0.8, wspace=0.1) for index, (feature_map, category) in enumerate(zip(feature_maps,actual_sounds)): plt.subplot(1, 3, index+1) plt.imshow(np.concatenate((feature_map[:,:,0], feature_map[:,:,1], feature_map[:,:,2]), axis=1), cmap='viridis') plt.title(category) plt.tight_layout(pad=1.5) ``` 特征圖將顯示如下: ![](https://img.kancloud.cn/d7/c1/d7c1fa57ec0638e4b7d77b9233122109_987x184.png) 根據我們在訓練階段觀察到的圖像,圖像特征圖看起來非常一致。 現在,我們可以利用我們的預測流水線來預測每種聲音的音頻源類別: ```py predictions = [ai.prediction_pipeline(audiofile_path,return_class_label=True) for audiofile_path in sound_paths] result_df = pd.DataFrame({'Actual Sound': actual_sounds, 'Predicted Sound': predictions, 'Location': sound_paths}) result_df ``` 我們得出以下預測: ![](https://img.kancloud.cn/ab/91/ab91244b752dfabf0fdde3aad4efcece_443x115.png) 看起來我們的模型能夠正確識別所有這些音頻樣本。 我們鼓勵您檢查筆記本中的`AudioIdentifier`類,以了解我們如何在后臺實現預測流水線。 我們利用了在本章中學到的所有概念來構建此流水線。 # 總結 在本章中,我們研究了一個全新的問題和案例研究,涉及音頻識別和分類。 涵蓋了圍繞音頻數據和信號的概念,包括可視化和理解此數據類型的有效技術。 我們還研究了有效的特征工程技術,以及如何使用遷移學習從音頻數據的圖像表示中提取有效特征。 這向我們展示了遷移學習的希望,以及如何利用知識從一個領域(圖像)遷移到另一個領域(音頻),并建立一個非常強大且有效的分類器。 最后,我們建立了一個完整的端到端流水線,用于識別和分類音頻數據的新樣本。 請在網絡上進一步檢查帶標注的音頻的數據集,看看是否可以利用從此處學習的遷移學習中獲得的概念來構建更大,更好的音頻標識符和分類器。 請繼續關注有關遷移學習的更多有趣示例和案例研究。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看