# 前言

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

源碼地址:AudioClassification-Pytorch

使用準備

  • Anaconda 3
  • Python 3.11
  • Pytorch 2.0.1
  • Windows 11 or Ubuntu 22.04

項目特性

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

模型論文:

模型測試表

模型 Params(M) 預處理方法 數據集 類別數量 準確率
ResNetSE 7.8 Flank UrbanSound8K 10 0.98863
CAMPPlus 7.1 Flank UrbanSound8K 10 0.97727
ERes2Net 6.6 Flank UrbanSound8K 10 0.96590
PANNS(CNN10) 5.2 Flank UrbanSound8K 10 0.96590
Res2Net 5.0 Flank UrbanSound8K 10 0.94318
TDNN 2.6 Flank UrbanSound8K 10 0.92045
EcapaTdnn 6.1 Flank UrbanSound8K 10 0.91876

安裝環境

  • 首先安裝的是Pytorch的GPU版本,如果已經安裝過了,請跳過。
conda install pytorch==2.0.1 torchvision==0.15.2 torchaudio==2.0.2 pytorch-cuda=11.7 -c pytorch -c nvidia
  • 安裝macls庫。

使用pip安裝,命令如下:

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

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

git clone https://github.com/yeyupiaoling/AudioClassification-Pytorch.git
cd AudioClassification-Pytorch/
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即可生成數據列表,裏面提供了生成多種數據集列表方式,具體看代碼。

python create_data.py

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

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

修改預處理方法(可選)

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

# 數據預處理參數
preprocess_conf:
  # 是否使用HF上的Wav2Vec2類似模型提取音頻特徵
  use_hf_model: False
  # 音頻預處理方法,也可以叫特徵提取方法
  # 當use_hf_model爲False時,支持:MelSpectrogram、Spectrogram、MFCC、Fbank
  # 當use_hf_model爲True時,指定的是HuggingFace的模型或者本地路徑,比如facebook/w2v-bert-2.0或者./feature_models/w2v-bert-2.0
  feature_method: 'Fbank'
  # 當use_hf_model爲False時,設置API參數,更參數查看對應API,不清楚的可以直接刪除該部分,直接使用默認值。
  # 當use_hf_model爲True時,可以設置參數use_gpu,指定是否使用GPU提取特徵
  method_args:
    sample_frequency: 16000
    num_mel_bins: 80

提取特徵(可選)

在訓練過程中,首先是要讀取音頻數據,然後提取特徵,最後再進行訓練。其中讀取音頻數據、提取特徵也是比較消耗時間的,所以我們可以選擇提前提取好取特徵,訓練模型的是就可以直接加載提取好的特徵,這樣訓練速度會更快。這個提取特徵是可選擇,如果沒有提取好的特徵,訓練模型的時候就會從讀取音頻數據,然後提取特徵開始。提取特徵步驟如下:

  1. 執行extract_features.py,提取特徵,特徵會保存在dataset/features目錄下,並生成新的數據列表train_list_features.txttest_list_features.txt
python extract_features.py --configs=configs/cam++.yml --save_dir=dataset/features
  1. 修改配置文件,將dataset_conf.train_listdataset_conf.test_list修改爲train_list_features.txttest_list_features.txt

訓練

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

# 單卡訓練
CUDA_VISIBLE_DEVICES=0 python train.py
# 多卡訓練
CUDA_VISIBLE_DEVICES=0,1 torchrun --standalone --nnodes=1 --nproc_per_node=2 train.py

訓練輸出日誌:

[2023-08-07 22:54:22.148973 INFO   ] utils:print_arguments:14 - ----------- 額外配置參數 -----------
[2023-08-07 22:54:22.148973 INFO   ] utils:print_arguments:16 - configs: configs/ecapa_tdnn.yml
[2023-08-07 22:54:22.148973 INFO   ] utils:print_arguments:16 - local_rank: 0
[2023-08-07 22:54:22.148973 INFO   ] utils:print_arguments:16 - pretrained_model: None
[2023-08-07 22:54:22.148973 INFO   ] utils:print_arguments:16 - resume_model: None
[2023-08-07 22:54:22.148973 INFO   ] utils:print_arguments:16 - save_model_path: models/
[2023-08-07 22:54:22.148973 INFO   ] utils:print_arguments:16 - use_gpu: True
[2023-08-07 22:54:22.148973 INFO   ] utils:print_arguments:17 - ------------------------------------------------
[2023-08-07 22:54:22.202166 INFO   ] utils:print_arguments:19 - ----------- 配置文件參數 -----------
[2023-08-07 22:54:22.202166 INFO   ] utils:print_arguments:22 - dataset_conf:
[2023-08-07 22:54:22.202166 INFO   ] utils:print_arguments:25 -     aug_conf:
[2023-08-07 22:54:22.202166 INFO   ] utils:print_arguments:27 -         noise_aug_prob: 0.2
[2023-08-07 22:54:22.202166 INFO   ] utils:print_arguments:27 -         noise_dir: dataset/noise
[2023-08-07 22:54:22.202166 INFO   ] utils:print_arguments:27 -         speed_perturb: True
[2023-08-07 22:54:22.202166 INFO   ] utils:print_arguments:27 -         volume_aug_prob: 0.2
[2023-08-07 22:54:22.202166 INFO   ] utils:print_arguments:27 -         volume_perturb: False
[2023-08-07 22:54:22.202166 INFO   ] utils:print_arguments:25 -     dataLoader:
[2023-08-07 22:54:22.202166 INFO   ] utils:print_arguments:27 -         batch_size: 64
[2023-08-07 22:54:22.202166 INFO   ] utils:print_arguments:27 -         num_workers: 4
[2023-08-07 22:54:22.202166 INFO   ] utils:print_arguments:29 -     do_vad: False
[2023-08-07 22:54:22.202166 INFO   ] utils:print_arguments:25 -     eval_conf:
[2023-08-07 22:54:22.202166 INFO   ] utils:print_arguments:27 -         batch_size: 1
[2023-08-07 22:54:22.202166 INFO   ] utils:print_arguments:27 -         max_duration: 20
[2023-08-07 22:54:22.202166 INFO   ] utils:print_arguments:29 -     label_list_path: dataset/label_list.txt
[2023-08-07 22:54:22.202166 INFO   ] utils:print_arguments:29 -     max_duration: 3
[2023-08-07 22:54:22.202166 INFO   ] utils:print_arguments:29 -     min_duration: 0.5
[2023-08-07 22:54:22.202166 INFO   ] utils:print_arguments:29 -     sample_rate: 16000
[2023-08-07 22:54:22.202166 INFO   ] utils:print_arguments:25 -     spec_aug_args:
[2023-08-07 22:54:22.202166 INFO   ] utils:print_arguments:27 -         freq_mask_width: [0, 8]
[2023-08-07 22:54:22.202166 INFO   ] utils:print_arguments:27 -         time_mask_width: [0, 10]
[2023-08-07 22:54:22.203167 INFO   ] utils:print_arguments:29 -     target_dB: -20
[2023-08-07 22:54:22.203167 INFO   ] utils:print_arguments:29 -     test_list: dataset/test_list.txt
[2023-08-07 22:54:22.203167 INFO   ] utils:print_arguments:29 -     train_list: dataset/train_list.txt
[2023-08-07 22:54:22.203167 INFO   ] utils:print_arguments:29 -     use_dB_normalization: True
[2023-08-07 22:54:22.203167 INFO   ] utils:print_arguments:29 -     use_spec_aug: True
[2023-08-07 22:54:22.203167 INFO   ] utils:print_arguments:22 - model_conf:
[2023-08-07 22:54:22.207167 INFO   ] utils:print_arguments:29 -     num_class: 10
[2023-08-07 22:54:22.207167 INFO   ] utils:print_arguments:29 -     pooling_type: ASP
[2023-08-07 22:54:22.207167 INFO   ] utils:print_arguments:22 - optimizer_conf:
[2023-08-07 22:54:22.207167 INFO   ] utils:print_arguments:29 -     learning_rate: 0.001
[2023-08-07 22:54:22.207167 INFO   ] utils:print_arguments:29 -     optimizer: Adam
[2023-08-07 22:54:22.207167 INFO   ] utils:print_arguments:29 -     scheduler: WarmupCosineSchedulerLR
[2023-08-07 22:54:22.207167 INFO   ] utils:print_arguments:25 -     scheduler_args:
[2023-08-07 22:54:22.207167 INFO   ] utils:print_arguments:27 -         max_lr: 0.001
[2023-08-07 22:54:22.207167 INFO   ] utils:print_arguments:27 -         min_lr: 1e-05
[2023-08-07 22:54:22.207167 INFO   ] utils:print_arguments:27 -         warmup_epoch: 5
[2023-08-07 22:54:22.207167 INFO   ] utils:print_arguments:29 -     weight_decay: 1e-06
[2023-08-07 22:54:22.207167 INFO   ] utils:print_arguments:22 - preprocess_conf:
[2023-08-07 22:54:22.207167 INFO   ] utils:print_arguments:29 -     feature_method: Fbank
[2023-08-07 22:54:22.208167 INFO   ] utils:print_arguments:25 -     method_args:
[2023-08-07 22:54:22.208167 INFO   ] utils:print_arguments:27 -         num_mel_bins: 80
[2023-08-07 22:54:22.208167 INFO   ] utils:print_arguments:27 -         sample_frequency: 16000
[2023-08-07 22:54:22.208167 INFO   ] utils:print_arguments:22 - train_conf:
[2023-08-07 22:54:22.208167 INFO   ] utils:print_arguments:29 -     log_interval: 10
[2023-08-07 22:54:22.208167 INFO   ] utils:print_arguments:29 -     max_epoch: 30
[2023-08-07 22:54:22.208167 INFO   ] utils:print_arguments:31 - use_model: EcapaTdnn
[2023-08-07 22:54:22.208167 INFO   ] utils:print_arguments:32 - ------------------------------------------------
[2023-08-07 22:54:22.213166 WARNING] trainer:__init__:67 - Windows系統不支持多線程讀取數據已自動關閉
==========================================================================================
Layer (type:depth-idx)                   Output Shape              Param #
==========================================================================================
EcapaTdnn                                [1, 10]                   --
├─Conv1dReluBn: 1-1                      [1, 512, 98]              --
    └─Conv1d: 2-1                       [1, 512, 98]              204,800
    └─BatchNorm1d: 2-2                  [1, 512, 98]              1,024
├─Sequential: 1-2                        [1, 512, 98]              --
    └─Conv1dReluBn: 2-3                 [1, 512, 98]              --
        └─Conv1d: 3-1                  [1, 512, 98]              262,144
        └─BatchNorm1d: 3-2             [1, 512, 98]              1,024
    └─Res2Conv1dReluBn: 2-4             [1, 512, 98]              --
        └─ModuleList: 3-15             --                        (recursive)
        └─ModuleList: 3-16             --                        (recursive)
        └─ModuleList: 3-15             --                        (recursive)
        └─ModuleList: 3-16             --                        (recursive)
        └─ModuleList: 3-15             --                        (recursive)
        └─ModuleList: 3-16             --                        (recursive)
        └─ModuleList: 3-15             --                        (recursive)
        └─ModuleList: 3-16             --                        (recursive)
        └─ModuleList: 3-15             --                        (recursive)
        └─ModuleList: 3-16             --                        (recursive)
···································
        └─ModuleList: 3-56             --                        (recursive)
        └─ModuleList: 3-55             --                        (recursive)
        └─ModuleList: 3-56             --                        (recursive)
        └─ModuleList: 3-55             --                        (recursive)
        └─ModuleList: 3-56             --                        (recursive)
    └─Conv1dReluBn: 2-13                [1, 512, 98]              --
        └─Conv1d: 3-57                 [1, 512, 98]              262,144
        └─BatchNorm1d: 3-58            [1, 512, 98]              1,024
    └─SE_Connect: 2-14                  [1, 512, 98]              --
        └─Linear: 3-59                 [1, 256]                  131,328
        └─Linear: 3-60                 [1, 512]                  131,584
├─Conv1d: 1-5                            [1, 1536, 98]             2,360,832
├─AttentiveStatsPool: 1-6                [1, 3072]                 --
    └─Conv1d: 2-15                      [1, 128, 98]              196,736
    └─Conv1d: 2-16                      [1, 1536, 98]             198,144
├─BatchNorm1d: 1-7                       [1, 3072]                 6,144
├─Linear: 1-8                            [1, 192]                  590,016
├─BatchNorm1d: 1-9                       [1, 192]                  384
├─Linear: 1-10                           [1, 10]                   1,930
==========================================================================================
Total params: 6,188,490
Trainable params: 6,188,490
Non-trainable params: 0
Total mult-adds (M): 470.96
==========================================================================================
Input size (MB): 0.03
Forward/backward pass size (MB): 10.28
Params size (MB): 24.75
Estimated Total Size (MB): 35.07
==========================================================================================
[2023-08-07 22:54:26.726095 INFO   ] trainer:train:344 - 訓練數據8644
[2023-08-07 22:54:30.092504 INFO   ] trainer:__train_epoch:296 - Train epoch: [1/30], batch: [0/4], loss: 2.57033, accuracy: 0.06250, learning rate: 0.00001000, speed: 19.02 data/sec, eta: 0:06:43

訓練可視化:

項目的根目錄執行下面命令,併網頁訪問http://localhost:8040/,如果是服務器,需要修改localhost爲服務器的IP地址。

visualdl --logdir=log --host=0.0.0.0

打開的網頁如下:

評估

執行下面命令執行評估。

python eval.py --configs=configs/bi_lstm.yml

評估輸出如下:

[2024-02-03 15:13:25.469242 INFO   ] trainer:evaluate:461 - 成功加載模型:models/CAMPPlus_Fbank/best_model/model.pth
100%|██████████████████████████████| 150/150 [00:00<00:00, 1281.96it/s]
評估消耗時間:1s,loss:0.61840,accuracy:0.87333

評估會出來輸出準確率,還保存了混淆矩陣圖片,保存路徑output/images/,如下。

注意:如果類別標籤是中文的,需要設置安裝字體才能正常顯示,一般情況下Windows無需安裝,Ubuntu需要安裝。如果Windows確實是確實字體,只需要字體文件這裏下載.ttf格式的文件,複製到C:\Windows\Fonts即可。Ubuntu系統操作如下。

  1. 安裝字體
git clone https://github.com/tracyone/program_font && cd program_font && ./install.sh
  1. 執行下面Python代碼
import matplotlib
import shutil
import os

path = matplotlib.matplotlib_fname()
path = path.replace('matplotlibrc', 'fonts/ttf/')
print(path)
shutil.copy('/usr/share/fonts/MyFonts/simhei.ttf', path)
user_dir = os.path.expanduser('~')
shutil.rmtree(f'{user_dir}/.cache/matplotlib', ignore_errors=True)

預測

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

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
小夜