前言

本項目是基於PaddlePaddle的聲音分類項目,旨在實現對各種環境聲音、動物叫聲和語種的識別。項目提供了多種聲音分類模型,如EcapaTdnn、PANNS、ResNetSE、CAMPPlus和ERes2Net,以支持不同的應用場景。此外,項目還提供了常用的Urbansound8K數據集測試報告和一些方言數據集的下載和使用例子。用戶可以根據自己的需求選擇適合的模型和數據集,以實現更準確的聲音分類。項目的應用場景廣泛,可以用於室外的環境監測、野生動物保護、語音識別等領域。同時,項目也鼓勵用戶探索更多的使用場景,以推動聲音分類技術的發展和應用。

源碼地址:AudioClassification-PaddlePaddle

使用準備

  • Anaconda 3
  • Python 3.8
  • PaddlePaddle 2.4.0
  • Windows 10 or Ubuntu 18.04

項目特性

  1. 支持模型:EcapaTdnn、PANNS、TDNN、Res2Net、ResNetSE
  2. 支持池化層:AttentiveStatisticsPooling(ASP)、SelfAttentivePooling(SAP)、TemporalStatisticsPooling(TSP)、TemporalAveragePooling(TAP)
  3. 支持預處理方法:MelSpectrogram、LogMelSpectrogram、Spectrogram、MFCC、Fbank

模型論文:

模型測試表

模型 Params(M) 預處理方法 數據集 類別數量 準確率
CAMPPlus 7.2 Flank UrbanSound8K 10 0.96590
PANNS(CNN10) 4.9 Flank UrbanSound8K 10 0.95454
ResNetSE 9.1 Flank UrbanSound8K 10 0.92219
TDNN 2.7 Flank UrbanSound8K 10 0.92045
ERes2Net 6.6 Flank UrbanSound8K 10 0.90909
EcapaTdnn 6.2 Flank UrbanSound8K 10 0.90503
Res2Net 5.6 Flank UrbanSound8K 10 0.85812

安裝環境

  • 首先安裝的是PaddlePaddle的GPU版本,如果已經安裝過了,請跳過。
conda install paddlepaddle-gpu==2.4.0 cudatoolkit=10.2 --channel https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/Paddle/
  • 安裝ppacls庫。

使用pip安裝,命令如下:

python -m pip install ppacls -U -i https://pypi.tuna.tsinghua.edu.cn/simple

建議源碼安裝,源碼安裝能保證使用最新代碼。

git clone https://github.com/yeyupiaoling/AudioClassification_PaddlePaddle.git
cd AudioClassification_PaddlePaddle
python setup.py install

數據數據

生成數據列表,用於下一步的讀取需要,audio_path爲音頻文件路徑,用戶需要提前把音頻數據集存放在dataset/audio目錄下,每個文件夾存放一個類別的音頻數據,每條音頻數據長度在3秒以上,如 dataset/audio/鳥叫聲/······audio是數據列表存放的位置,生成的數據類別的格式爲 音頻路徑\t音頻對應的類別標籤,音頻路徑和標籤用製表符 \t分開。讀者也可以根據自己存放數據的方式修改以下函數。

以Urbansound8K爲例,Urbansound8K是目前應用較爲廣泛的用於自動城市環境聲分類研究的公共數據集,包含10個分類:空調聲、汽車鳴笛聲、兒童玩耍聲、狗叫聲、鑽孔聲、引擎空轉聲、槍聲、手提鑽、警笛聲和街道音樂聲。數據集下載地址:UrbanSound8K.tar.gz。以下是針對Urbansound8K生成數據列表的函數。如果讀者想使用該數據集,請下載並解壓到 dataset目錄下,把生成數據列表代碼改爲以下代碼。

執行create_data.py即可生成數據列表,裏面提供了兩種生成列表方式,第一種是自定義的數據,第二種是生成Urbansound8K的數據列表,具體看代碼。

python create_data.py

生成的列表是長這樣的,前面是音頻的路徑,後面是該音頻對應的標籤,從0開始,路徑和標籤之間用Tab隔開。

dataset/UrbanSound8K/audio/fold2/104817-4-0-2.wav   4
dataset/UrbanSound8K/audio/fold9/105029-7-2-5.wav   7
dataset/UrbanSound8K/audio/fold3/107228-5-0-0.wav   5
dataset/UrbanSound8K/audio/fold4/109711-3-2-4.wav   3

修改預處理方法

配置文件中默認使用的是MelSpectrogram預處理方法,如果要使用其他預處理方法,可以修改配置文件中的安裝下面方式修改,具體的值可以根據自己情況修改。如果不清楚如何設置參數,可以直接刪除該部分,直接使用默認值。

preprocess_conf:
  # 音頻預處理方法,支持:MelSpectrogram、Spectrogram、MFCC、Fbank
  feature_method: 'MelSpectrogram'
  # 設置API參數,更參數查看對應API,不清楚的可以直接刪除該部分,直接使用默認值
  method_args:
    sample_rate: 16000
    n_fft: 1024
    hop_length: 320
    win_length: 1024
    f_min: 50.0
    f_max: 14000.0
    n_mels: 64

訓練

接着就可以開始訓練模型了,創建 train.py。配置文件裏面的參數一般不需要修改,但是這幾個是需要根據自己實際的數據集進行調整的,首先最重要的就是分類大小dataset_conf.num_class,這個每個數據集的分類大小可能不一樣,根據自己的實際情況設定。然後是dataset_conf.batch_size,如果是顯存不夠的話,可以減小這個參數。

# 單卡訓練
CUDA_VISIBLE_DEVICES=0 python train.py
# 多卡訓練
python -m paddle.distributed.launch --gpus '0,1' train.py

訓練輸出日誌:

[2023-08-07 23:02:08.807036 INFO   ] utils:print_arguments:14 - ----------- 額外配置參數 -----------
[2023-08-07 23:02:08.807036 INFO   ] utils:print_arguments:16 - configs: configs/ecapa_tdnn.yml
[2023-08-07 23:02:08.807036 INFO   ] utils:print_arguments:16 - pretrained_model: None
[2023-08-07 23:02:08.807036 INFO   ] utils:print_arguments:16 - resume_model: None
[2023-08-07 23:02:08.807036 INFO   ] utils:print_arguments:16 - save_model_path: models/
[2023-08-07 23:02:08.807036 INFO   ] utils:print_arguments:16 - use_gpu: True
[2023-08-07 23:02:08.807036 INFO   ] utils:print_arguments:17 - ------------------------------------------------
[2023-08-07 23:02:08.811036 INFO   ] utils:print_arguments:19 - ----------- 配置文件參數 -----------
[2023-08-07 23:02:08.812035 INFO   ] utils:print_arguments:22 - dataset_conf:
[2023-08-07 23:02:08.812035 INFO   ] utils:print_arguments:25 -     aug_conf:
[2023-08-07 23:02:08.812035 INFO   ] utils:print_arguments:27 -         noise_aug_prob: 0.2
[2023-08-07 23:02:08.812035 INFO   ] utils:print_arguments:27 -         noise_dir: dataset/noise
[2023-08-07 23:02:08.812035 INFO   ] utils:print_arguments:27 -         speed_perturb: True
[2023-08-07 23:02:08.812035 INFO   ] utils:print_arguments:27 -         volume_aug_prob: 0.2
[2023-08-07 23:02:08.812035 INFO   ] utils:print_arguments:27 -         volume_perturb: False
[2023-08-07 23:02:08.812035 INFO   ] utils:print_arguments:25 -     dataLoader:
[2023-08-07 23:02:08.812035 INFO   ] utils:print_arguments:27 -         batch_size: 64
[2023-08-07 23:02:08.812035 INFO   ] utils:print_arguments:27 -         num_workers: 4
[2023-08-07 23:02:08.812035 INFO   ] utils:print_arguments:29 -     do_vad: False
[2023-08-07 23:02:08.812035 INFO   ] utils:print_arguments:25 -     eval_conf:
[2023-08-07 23:02:08.812035 INFO   ] utils:print_arguments:27 -         batch_size: 1
[2023-08-07 23:02:08.812035 INFO   ] utils:print_arguments:27 -         max_duration: 20
[2023-08-07 23:02:08.812035 INFO   ] utils:print_arguments:29 -     label_list_path: dataset/label_list.txt
[2023-08-07 23:02:08.812035 INFO   ] utils:print_arguments:29 -     max_duration: 3
[2023-08-07 23:02:08.812035 INFO   ] utils:print_arguments:29 -     min_duration: 0.5
[2023-08-07 23:02:08.812035 INFO   ] utils:print_arguments:29 -     sample_rate: 16000
[2023-08-07 23:02:08.812035 INFO   ] utils:print_arguments:25 -     spec_aug_args:
[2023-08-07 23:02:08.812035 INFO   ] utils:print_arguments:27 -         freq_mask_width: [0, 8]
[2023-08-07 23:02:08.812035 INFO   ] utils:print_arguments:27 -         time_mask_width: [0, 10]
[2023-08-07 23:02:08.812035 INFO   ] utils:print_arguments:29 -     target_dB: -20
[2023-08-07 23:02:08.812035 INFO   ] utils:print_arguments:29 -     test_list: dataset/test_list.txt
[2023-08-07 23:02:08.812035 INFO   ] utils:print_arguments:29 -     train_list: dataset/train_list.txt
[2023-08-07 23:02:08.812035 INFO   ] utils:print_arguments:29 -     use_dB_normalization: True
[2023-08-07 23:02:08.812035 INFO   ] utils:print_arguments:29 -     use_spec_aug: True
[2023-08-07 23:02:08.812035 INFO   ] utils:print_arguments:22 - model_conf:
[2023-08-07 23:02:08.816062 INFO   ] utils:print_arguments:29 -     num_class: 10
[2023-08-07 23:02:08.816062 INFO   ] utils:print_arguments:29 -     pooling_type: ASP
[2023-08-07 23:02:08.816062 INFO   ] utils:print_arguments:22 - optimizer_conf:
[2023-08-07 23:02:08.816062 INFO   ] utils:print_arguments:29 -     optimizer: Adam
[2023-08-07 23:02:08.816062 INFO   ] utils:print_arguments:29 -     scheduler: WarmupCosineSchedulerLR
[2023-08-07 23:02:08.816062 INFO   ] utils:print_arguments:25 -     scheduler_args:
[2023-08-07 23:02:08.816062 INFO   ] utils:print_arguments:27 -         learning_rate: 0.001
[2023-08-07 23:02:08.816062 INFO   ] utils:print_arguments:27 -         min_lr: 1e-05
[2023-08-07 23:02:08.816062 INFO   ] utils:print_arguments:27 -         warmup_epoch: 5
[2023-08-07 23:02:08.816062 INFO   ] utils:print_arguments:29 -     weight_decay: 1e-06
[2023-08-07 23:02:08.816062 INFO   ] utils:print_arguments:22 - preprocess_conf:
[2023-08-07 23:02:08.816062 INFO   ] utils:print_arguments:29 -     feature_method: Fbank
[2023-08-07 23:02:08.816062 INFO   ] utils:print_arguments:25 -     method_args:
[2023-08-07 23:02:08.816062 INFO   ] utils:print_arguments:27 -         n_mels: 80
[2023-08-07 23:02:08.816062 INFO   ] utils:print_arguments:27 -         sr: 16000
[2023-08-07 23:02:08.816062 INFO   ] utils:print_arguments:22 - train_conf:
[2023-08-07 23:02:08.816062 INFO   ] utils:print_arguments:29 -     log_interval: 10
[2023-08-07 23:02:08.816062 INFO   ] utils:print_arguments:29 -     max_epoch: 60
[2023-08-07 23:02:08.816062 INFO   ] utils:print_arguments:31 - use_model: EcapaTdnn
[2023-08-07 23:02:08.816062 INFO   ] utils:print_arguments:32 - ------------------------------------------------
[2023-08-07 23:02:08.817077 WARNING] trainer:__init__:69 - Windows系統不支持多線程讀取數據已自動關閉
W0807 23:02:08.822477  3192 gpu_resources.cc:61] Please NOTE: device: 0, GPU Compute Capability: 7.5, Driver API Version: 11.7, Runtime API Version: 11.6
W0807 23:02:08.826478  3192 gpu_resources.cc:91] device: 0, cuDNN Version: 8.4.
----------------------------------------------------------------------------------------
        Layer (type)             Input Shape          Output Shape         Param #    
========================================================================================
          Conv1D-2              [[1, 80, 102]]        [1, 512, 98]         205,312    
          Conv1d-1              [[1, 80, 98]]         [1, 512, 98]            0       
           ReLU-1               [[1, 512, 98]]        [1, 512, 98]            0       
       BatchNorm1D-2            [[1, 512, 98]]        [1, 512, 98]          2,048     
       BatchNorm1d-1            [[1, 512, 98]]        [1, 512, 98]            0       
        TDNNBlock-1             [[1, 80, 98]]         [1, 512, 98]            0       
          Conv1D-4              [[1, 512, 98]]        [1, 512, 98]         262,656    
          Conv1d-3              [[1, 512, 98]]        [1, 512, 98]            0       
           ReLU-2               [[1, 512, 98]]        [1, 512, 98]            0       
       BatchNorm1D-4            [[1, 512, 98]]        [1, 512, 98]          2,048     
       BatchNorm1d-3            [[1, 512, 98]]        [1, 512, 98]            0       
        TDNNBlock-2             [[1, 512, 98]]        [1, 512, 98]            0       
          Conv1D-6              [[1, 64, 102]]        [1, 64, 98]          12,352     
          Conv1d-5              [[1, 64, 98]]         [1, 64, 98]             0       
           ReLU-3               [[1, 64, 98]]         [1, 64, 98]             0       
       BatchNorm1D-6            [[1, 64, 98]]         [1, 64, 98]            256      
       BatchNorm1d-5            [[1, 64, 98]]         [1, 64, 98]             0       
        TDNNBlock-3             [[1, 64, 98]]         [1, 64, 98]             0       
          Conv1D-8              [[1, 64, 102]]        [1, 64, 98]          12,352     
          Conv1d-7              [[1, 64, 98]]         [1, 64, 98]             0       
           ReLU-4               [[1, 64, 98]]         [1, 64, 98]             0       
       BatchNorm1D-8            [[1, 64, 98]]         [1, 64, 98]            256      
       BatchNorm1d-7            [[1, 64, 98]]         [1, 64, 98]             0       
        TDNNBlock-4             [[1, 64, 98]]         [1, 64, 98]             0       
         Conv1D-10              [[1, 64, 102]]        [1, 64, 98]          12,352     
          Conv1d-9              [[1, 64, 98]]         [1, 64, 98]             0       
           ReLU-5               [[1, 64, 98]]         [1, 64, 98]             0       
       BatchNorm1D-10           [[1, 64, 98]]         [1, 64, 98]            256      
       BatchNorm1d-9            [[1, 64, 98]]         [1, 64, 98]             0       
        TDNNBlock-5             [[1, 64, 98]]         [1, 64, 98]             0       
         Conv1D-12              [[1, 64, 102]]        [1, 64, 98]          12,352     
         Conv1d-11              [[1, 64, 98]]         [1, 64, 98]             0       
           ReLU-6               [[1, 64, 98]]         [1, 64, 98]             0       
       BatchNorm1D-12           [[1, 64, 98]]         [1, 64, 98]            256      
       BatchNorm1d-11           [[1, 64, 98]]         [1, 64, 98]             0       
        TDNNBlock-6             [[1, 64, 98]]         [1, 64, 98]             0      
······················································  
       BatchNorm1d-59           [[1, 128, 98]]        [1, 128, 98]            0       
        TDNNBlock-30           [[1, 4608, 98]]        [1, 128, 98]            0       
           Tanh-1               [[1, 128, 98]]        [1, 128, 98]            0       
         Conv1D-74              [[1, 128, 98]]       [1, 1536, 98]         198,144    
         Conv1d-73              [[1, 128, 98]]       [1, 1536, 98]            0       
AttentiveStatisticsPooling-1   [[1, 1536, 98]]        [1, 3072, 1]            0       
       BatchNorm1D-62           [[1, 3072, 1]]        [1, 3072, 1]         12,288     
       BatchNorm1d-61           [[1, 3072, 1]]        [1, 3072, 1]            0       
         Conv1D-76              [[1, 3072, 1]]        [1, 192, 1]          590,016    
         Conv1d-75              [[1, 3072, 1]]        [1, 192, 1]             0       
          Linear-1                [[1, 192]]            [1, 10]             1,930     
========================================================================================
Total params: 6,215,306
Trainable params: 6,195,978
Non-trainable params: 19,328
----------------------------------------------------------------------------------------
Input size (MB): 0.03
Forward/backward pass size (MB): 35.53
Params size (MB): 23.71
Estimated Total Size (MB): 59.27
----------------------------------------------------------------------------------------

[2023-08-07 23:02:11.081835 INFO   ] trainer:train:317 - 訓練數據8644
[2023-08-07 23:02:15.428326 INFO   ] trainer:__train_epoch:269 - Train epoch: [1/60], batch: [0/136], loss: 2.99582, accuracy: 0.04688, learning rate: 0.00000000, speed: 14.72 data/sec, eta: 9:51:07

評估

每輪訓練結束可以執行評估,評估會出來輸出準確率,還保存了混合矩陣圖片,保存路徑output/images/,如下。

預測

在訓練結束之後,我們得到了一個模型參數文件,我們使用這個模型預測音頻。

python infer.py --audio_path=dataset/UrbanSound8K/audio/fold5/156634-5-2-5.wav

其他功能

  • 爲了方便讀取錄製數據和製作數據集,這裏提供了錄音程序record_audio.py,這個用於錄製音頻,錄製的音頻採樣率爲16000,單通道,16bit。
python record_audio.py
  • infer_record.py這個程序是用來不斷進行錄音識別,我們可以大致理解爲這個程序在即時錄音識別。通過這個應該我們可以做一些比較有趣的事情,比如把麥克風放在小鳥經常來的地方,通過即時錄音識別,一旦識別到有鳥叫的聲音,如果你的數據集足夠強大,有每種鳥叫的聲音數據集,這樣你還能準確識別是那種鳥叫。如果識別到目標鳥類,就啓動程序,例如拍照等等。
python infer_record.py --record_seconds=3

參考資料

  1. https://github.com/PaddlePaddle/PaddleSpeech
  2. https://github.com/yeyupiaoling/PaddlePaddle-MobileFaceNets
  3. https://github.com/yeyupiaoling/PPASR
  4. https://github.com/alibaba-damo-academy/3D-Speaker
小夜