CCF-BDCI-2020-通用音频分类

摘要:

合集:AI案例-NLP-语音等多模态
赛题:CCF-BDCI-2020-通用音频分类
主办方:中国计算机学会
主页:https://www.datafountain.cn/competitions/486
AI问题:语音等多模态识别
数据集:数据集涵盖30种不同音频,已分类训练集文件总数:57,886个。测试集文件总数:6,835个。
数据集价值:音频分类
解决方案:音乐信息检索(MIR)和语音处理librosa、LightGBM框架

一、赛题描述

背景

随着移动终端的广泛应用以及数据量的不断积累,海量多媒体信息的处理需求日益凸显。作为多媒体信息的重要载体,音频信息处理应用广泛且多样,如自动语音识别、音乐风格识别等。有些声音是独特的,可以立即识别,例如婴儿的笑声或吉他的弹拨声。有些音频背景噪声复杂,很难区分。如果闭上眼睛,您能说出电锯和搅拌机是下面哪种声音?

音频分类是音频信息处理领域的一个基本问题,从本质上说,音频分类的性能依赖于音频中的特征提取。传统特征提取算法使用音频特征的统计信息作为分类的依据,使用到的音频特征包括线性预测编码、短时平均能量等。

近年来,基于深度学习的音频分类取得了较大进展。基于端到端的特征提取方式,深度学习可以避免繁琐的人工特征设计。音频的多样化给“机器听觉”带来了巨大挑战。如何对音频信息进行有效的分类,从繁芜丛杂的数据集中将具有某种特定形态的音频归属到同一个集合,对于学术研究及工业应用具有重要意义。

任务

基于上述实际需求以及深度学习的进展,本次训练赛旨在构建通用的基于深度学习的自动音频分类系统。通过本赛题建立准确的音频分类模型,希望大家探索更为鲁棒的音频表述方法,以及转移学习、自监督学习等方法在音频分类中的应用。

二、数据集内容

数据简介

数据整理自网上公开数据集(已脱敏),数据集涵盖30种不同音频,该类数据集广泛应用于音频分类的业务场景。

数据文件说明

训练数据集音频文件目录train包括以下30种不同音频类别和对应文件个数:

bed 1537
bird 1573
cat 1567
dog 1566
down 2106
eight 2095
five 2086
four 2119
go 2121
happy 1562
house 1600
left 2086
marvin 1584
nine 2105
no 2123
off 2095
on 2121
one 2122
right 2108
seven 2138
sheila 1548
six 2125
stop 2131
three 2089
tree 1540
two 2109
up 2103
wow 1580
yes 2121
zero 2126

训练集文件总数:57,886个。

测试数据集音频文件目录test包括30种不同音频类别的文件。测试集文件总数:6,835个。

提交示例

参赛者以csv文件格式提交,提交模型结果到大数据竞赛平台,平台进行在线评分,实时排名。目前平台仅支持单文件提交,即所有提交内容需要放在一个文件中;submission.csv文件字段如下:

文件名识别后的音频分类/标签
478bndrgbs.wavbed
cxdlny4rd1.wavbed

数据集使用许可协议

BY-NC-SA 4.0
数据发布方:中国计算机学会
https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh-hans

三、解决方案样例

本次比赛 Baseline 代码:CCF-BDCI-2020-Audio-Classification.ipynb

1、主要流程

该样例使用LightGBM模型对30类音频进行分类,主要流程包括:

  • 数据准备与特征提取
  • 数据预处理
  • 模型训练与交叉验证
  • 预测与结果生成
  • 数据保存

2、技术亮点

  1. 全面的音频特征提取:使用了7种不同类型的音频特征,涵盖了时域和频域特征。
  2. 高效的模型训练:
    • 使用LightGBM这种高效的梯度提升框架
    • 采用交叉验证提高模型泛化能力
    • 实现早停机制防止过拟合
  3. 健壮的数据处理:
    • 递归展平嵌套数据结构
    • 处理不同长度的音频特征

3、安装开发包

库名称版本号
python3.12.8
pandas2.2.2
numpy1.26.4
librosa0.10.2
pickleshare0.7.5
sklearn-compat0.1.3

安装 librosa 等开发包。

conda install -c conda-forge libsndfile
conda install -c conda-forge librosa

验证:

python -c "import soundfile as sf; print(sf.__version__)"

输出:0.13.1

四、工作流程

1、导入开发库

import pandas as pd
import numpy as np
import lightgbm as lgb
from sklearn.model_selection import KFold
import time
import librosa
import pickle
import os
import warnings
warnings.filterwarnings('ignore')

2. 数据准备阶段

2.1 音频类别

定义了30个音频类别,包括:

  • 数字:zero到nine
  • 方向词:up, down, left, right
  • 动作词:go, stop, yes, no等
  • 其他:bed, bird, cat, dog等

2.2 特征提取

使用librosa库从音频文件中提取了多种音频特征:

  1. 过零率(zero_crossing_rate)
  2. 光谱质心(spectral_centroid)
  3. MFCC(梅尔频率倒谱系数,40维)
  4. 色度频谱(chroma_stft)
  5. 谱对比度(spectral_contrast)
  6. 频谱带宽(spectral_bandwidth)
  7. tonnetz特征

每个音频样本最终提取了68维特征。

2.3 数据加载

  • 训练数据:从30个类别文件夹中加载音频文件
  • 测试数据:从测试文件夹加载音频文件
y = []
X_train = []

for i in range(30):
   filePath = "./data/train/%s" % filename_list[i]
   fl = os.listdir(filePath)
   print(len(fl))

   for j in range(len(fl)):
       wavpath = filePath + '//' + fl[j]
       sig, sr = librosa.load(wavpath)
       y.append(int(i))
       temp = []

       # 过零率
       a = librosa.feature.zero_crossing_rate(sig)
       b = np.mean(a)
       temp.append(b)
       # 光谱质心
       a = librosa.feature.spectral_centroid(y=sig, sr=sr)[0]
       b = np.mean(a)
       temp.append(b)
       # MFCC
       a = librosa.feature.mfcc(y=sig, sr=sr, n_mfcc=40)
       b = np.mean(a, axis = 1)
       for k in range(len(b)):
           temp.append(b[k])
       # 色度频谱
       a = librosa.feature.chroma_stft(y=sig, sr=sr)
       b = np.mean(a, axis = 1)
       for k in range(len(b)):
           temp.append(b[k])
       # 谱对比度
       a = librosa.feature.spectral_contrast(y=sig, sr=sr)
       b = np.mean(a, axis = 1)
       for k in range(len(b)):
           temp.append(b[k])
       # 频谱带宽
       a = librosa.feature.spectral_bandwidth(y=sig, sr=sr)
       b = np.mean(a, axis=1)
       temp.append(b)
       # tonnetz
       a = librosa.feature.tonnetz(y=sig, sr=sr)
       b = np.mean(a, axis = 1)

       for k in range(len(b)):
           temp.append(b[k])

       if j < 2:
           print(len(temp))

       X_train.append(temp)

   print('***** %s *****'%i)

3. 数据预处理

使用ensure_scalar函数处理嵌套结构的数据,确保所有特征都是标量值:

  • 递归计算嵌套数组的均值
  • 最大递归深度为3层
  • 将训练数据和测试数据转换为numpy数组
  • 训练数据形状:(57886, 68)
  • 测试数据形状:(6835, 68)
def ensure_scalar(data, max_depth=3):
   """递归展平嵌套结构至标量"""
   if max_depth == 0:
       return float(np.mean(data))
   if isinstance(data, (list, np.ndarray)):
       return ensure_scalar(np.mean(data), max_depth-1)
   else:
       return float(data)

# 应用至所有数据
X_train_processed = [
  [ensure_scalar(feature) for feature in sample]
   for sample in X_train
]

X_train_c = np.array(X_train_processed, dtype=np.float32)
print(X_train_c.shape)

4. 模型训练

4.1 模型配置

使用LightGBM分类器,主要参数:

  • num_leaves: 16
  • max_depth: 8
  • learning_rate: 0.08
  • 目标函数: multiclass
  • num_class: 30
  • 正则化项: lambda_l1和lambda_l2

4.2 训练过程

  • 使用5折交叉验证
  • 早停机制(early_stopping_rounds=100)
  • 每折训练约700-750轮后早停
  • 最终预测结果是5折模型预测的平均值
ITERATIONS = 100000
EARLY_STOP = 100
VERBOSE = 500
i = 0

for train_index, valid_index in kf.split(X_train_c, y1_train_c):
   print("\nFold {}".format(i + 1))
   X_train, label_train = X_train_c[train_index],y1_train_c[train_index]
   X_valid, label_valid = X_train_c[valid_index],y1_train_c[valid_index]

   params = {'num_leaves': 16, # 结果对最终效果影响较大,越大值越好,太大会出现过拟合
             'min_data_in_leaf': 16,
             'objective': 'multiclass', # 定义的目标函数
             'is_unbalance' : True,
             'max_depth': 8,
             'learning_rate': 0.08,
             'boosting': 'gbdt',
             'feature_fraction': 0.98,  # 提取的特征比率
             'bagging_freq': 4,
             'bagging_fraction': 0.8,
             'lambda_l1': 0.1,     # l1正则
             'lambda_l2': 0.2,     # l2正则
             'num_class':30,
             "random_state": 2020, # 随机数种子,可以防止每次运行的结果不一致
            }

   trn_data = lgb.Dataset(X_train, label_train)
   val_data = lgb.Dataset(X_valid, label_valid)

   clf = lgb.train(params,
                   trn_data,
                   30000,
                   valid_sets=[trn_data, val_data],
                   verbose_eval=VERBOSE,
                   early_stopping_rounds=EARLY_STOP)

   x1 = clf.predict(X_valid)
   y1 = clf.predict(X_test_c)
   prediction1 += ((y1)) / nfold
   i += 1

训练过程展示:


Fold 1
[LightGBM] [Warning] Auto-choosing col-wise multi-threading, the overhead of testing was 0.010028 seconds.
You can set `force_col_wise=true` to remove the overhead.
[LightGBM] [Info] Total Bins 17340
[LightGBM] [Info] Number of data points in the train set: 46308, number of used features: 68
[LightGBM] [Info] Start training from score -3.625865
[LightGBM] [Info] Start training from score -3.618592
[LightGBM] [Info] Start training from score -3.599452
...
[LightGBM] [Info] Start training from score -3.306453
...
Training until validation scores don't improve for 100 rounds
[500] training's multi_logloss: 0.203528 valid_1's multi_logloss: 1.8641
Early stopping, best iteration is:
[755] training's multi_logloss: 0.0690814 valid_1's multi_logloss: 1.84959

5. 预测与结果生成

  1. 对测试集进行预测,得到每个样本属于30个类别的概率
  2. 取概率最大的类别作为预测结果
  3. 将数字标签转换为对应的类别名称
  4. 生成提交文件,包含文件名和预测标签
y_pred = [list(x).index(max(x)) for x in prediction1]
print(y_pred)

sub = pd.read_csv('./data/submission.csv')
cnt = 0
result = [0 for i in range(6835)]

for i in range(6835):
   ss = sub.iloc[i]['file_name']
   
   for j in range(6835):
       if fl[j] == ss:
           result[i] = y_pred[j]
           cnt = cnt+1

print(cnt)

df = pd.DataFrame({'file_name':sub['file_name'], 'label':result1})
now = time.strftime("%Y%m%d_%H%M%S", time.localtime(time.time()))
fname = "submit_" + now + r".csv"
df.to_csv(fname, index=False)

6. 数据保存

将处理后的训练数据、标签和测试数据保存为pickle文件,方便后续使用。

  • 将处理后的训练数据、标签和测试数据保存为pickle文件
fileHandle = open('traindata_v2.txt', 'wb+') 
pickle.dump(X_train_c, fileHandle)
fileHandle.close()

本样例提交文件 submit_20250517_134904.csv 包含的数据示例如下:

file_namelabel
478bndrgbs.wavyes
cxdlny4rd1.wavhouse
5k53s85k82.wavfive
c2drt4ivmi.wavstop
ug3yvk1bo8.wavgo

源码开源协议

GPL-v3
https://github.com/zjuzpw/baseline/blob/CCF2020BDCI/baseline_lgb.ipynb

四、获取案例套装

文件包大小:1.9 GB

获取:语音等多模态案例套装

发表评论