作者 | Magdalena Kortas
来源 | Medium
编辑 | 代码医生团队
拥有Python经验的女性数据科学家,博士候选人,鸟类学家,数据分析师和软件工程师共同参与了一系列为期两周的冲刺,共同致力于该项目。
该项目旨在解决现实生活中的问题,机器学习可以帮助解决数据科学项目的典型结构,包括数据研究和分析,数据准备,模型创建,结果分析(或模型改进)和最终演示文稿。
经过数周的工作,该小组设法建立了一种解决方案,该解决方案可以在测试样本上以87%的准确度预测正确的鸟的名字。
鸟儿的问题
Birdong的分析和分类是一个非常有趣的问题。
鸟有多种声音,不同的鸟有不同的功能。最常见的是歌曲和“其他声音”(例如通话类型)。
这首歌是“更漂亮”的旋律类型的声音,这使鸟儿可以标记自己的领地并结伴。它通常比“呼叫”复杂得多,并且时间更长。
呼叫类型的语音包括联系语音,诱人语音和警报语音。接触呼叫和吸引呼叫用于在飞行或觅食过程中(例如在树梢上)将鸟类保持在一组中,通过警报来提醒鸟类(例如,当掠食者到达时)。大多数情况下,这些是简短的声音。
例:
大山雀
样品
https://www.xeno-canto.org/463492
样品
https://www.xeno-canto.org/464650
为什么基于声音的鸟类分类是一项艰巨的任务?
可能会遇到许多问题:
那么过去的问题是如何解决的呢?
仅通过歌曲来识别鸟类可能是一项艰巨的任务,但这并不意味着不可能。但是如何处理这些问题呢?
为了找到答案,有必要深入研究论文,并发现大多数工作恰巧是由各种AI挑战发起的,例如BirdCLEF和DCASE。幸运的是这些挑战的获胜者通常会描述他们的方法,因此在查看排行榜后,获得了一些有趣的见解:
但是当只有录音时,如何应用CNN,用于从图像中提取特征以对其进行分类或分段的神经网络?梅尔频率倒谱(MFCC)是答案。
SOUND_DIR='../data/xeno-canto-dataset-full/Parusmajor/Lithuania/Parusmajor182513.mp3'
# Load the mp3 file
signal, sr = librosa.load(SOUND_DIR,duration=10) # sr = sampling rate
# Plot mel-spectrogram
N_FFT = 1024
HOP_SIZE = 1024
N_MELS = 128
WIN_SIZE = 1024
WINDOW_TYPE = 'hann'
FEATURE = 'mel'
FMIN = 1400
S = librosa.feature.melspectrogram(y=signal,sr=sr,
n_fft=N_FFT,
hop_length=HOP_SIZE,
n_mels=N_MELS,
htk=True,
fmin=FMIN,
fmax=sr/2)
plt.figure(figsize=(10, 4))
librosa.display.specshow(librosa.power_to_db(S**2,ref=np.max), fmin=FMIN,y_axis='linear')
plt.colorbar(format='%+2.0f dB')
plt.show()
梅尔光谱图示例
但是它是什么以及它如何工作?
听到的每个声音都同时包含多个声音频率。这就是使音频听起来“很深”的原因。
频谱图的技巧是在一个图中还可视化那些频率,而不是像波形那样仅可视化幅度。梅尔音阶被称为音高的音频音阶,对于听众而言,音阶似乎彼此相等。其背后的想法与人类的听觉方式有关。当将这两个想法联系起来时,得到一个改进的频谱图(梅尔频率倒谱),该频谱图忽略了人类听不到的声音并绘制了最重要的部分。
从中创建频谱图的音频长度越长,在图像上获得的信息越多,但模型变得越适合。如果您数据有很多杂音或静音,则持续5秒的音频可能无法捕获所需的信息。因此决定用10秒钟的持续音频来创建图像(并且最终模型的准确度提高了10%!)。由于鸟类以高频率唱歌,因此采用了高通滤波器来消除无用的噪声。
信息(静音)不足且噪声主要的5s频谱图示例
是时候建模了!
在创建具有高通滤波器的梅尔频谱图之后,从10秒钟的持久音频文件中分离出数据,然后将数据分为训练(90%),验证(10%)和测试集(10%)。
IM_SIZE = (224,224,3)
BIRDS = ['0Parus', '1Turdu', '2Passe', '3Lusci', '4Phoen', '5Erith',
'6Picap', '7Phoen', '8Garru', '9Passe', '10Cocco', '11Sitta','12Alaud', '13Strep', '14Phyll', '15Delic','16Turdu', '17Phyll','18Fring', '19Sturn', '20Ember', '21Colum', '22Trogl', '23Cardu','24Chlor', '25Motac', '26Turdu']
DATA_PATH = 'data/27_class_10s_2/'
BATCH_SIZE = 16
内置的Keras库数据生成器负责所有光谱图的数据扩充和规范化。
train_datagen = ImageDataGenerator(preprocessing_function=preprocess_input,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.1,
fill_mode='nearest')
train_batches = train_datagen.flow_from_directory(DATA_PATH+'train',classes=BIRDS, target_size=IM_SIZE, class_mode='categorical', shuffle=True,batch_size=BATCH_SIZE)
valid_datagen = ImageDataGenerator(preprocessing_function=preprocess_input)
valid_batches = valid_datagen.flow_from_directory(DATA_PATH+'val',classes=BIRDS,target_size=IM_SIZE, class_mode='categorical', shuffle=False, batch_size=BATCH_SIZE)
test_datagen = ImageDataGenerator(preprocessing_function=preprocess_input)
test_batches = test_datagen.flow_from_directory(DATA_PATH+'test', classes=BIRDS,target_size=IM_SIZE,class_mode='categorical', shuffle=False,batch_size=BATCH_SIZE)
最终模型基于EfficientNetB3和27种具有Adam优化器,分类交叉熵损失函数和平衡类权重的不同类(鸟类)。高原学习率降低。
# Define CNN's architecture
net = efn.EfficientNetB3(include_top=False, weights='imagenet', input_tensor=None, input_shape=IM_SIZE)
x = net.output
x = Flatten()(x)
x = Dropout(0.5)(x)
output_layer = Dense(len(BIRDS), activation='softmax', name='softmax')(x)
net_final = Model(inputs=net.input, outputs=output_layer) net_final.compile(optimizer=Adam(), loss='categorical_crossentropy', metrics=['accuracy'])
# Estimate class weights for unbalanced dataset
class_weights = class_weight.compute_class_weight( 'balanced', np.unique(train_batches.classes), train_batches.classes)
# Define callbacks
ModelCheck = ModelCheckpoint('models/efficientnet_checkpoint.h5', monitor='val_loss', verbose=0, save_best_only=True, save_weights_only=True, mode='auto', period=1)
ReduceLR = ReduceLROnPlateau(monitor='val_loss', factor=0.2, patience=5, min_lr=3e-4)
解决方案摘要-音频数据预处理和神经网络模型
# Train the model
net_final.fit_generator(train_batches,
validation_data = valid_batches,
epochs = 30,
steps_per_epoch= 1596,
class_weight=class_weights, callbacks[ModelCheck,ReduceLR])
最终,该解决方案在测试样本上以87%的准确度预测了正确的鸟名:
神经网络模型的分类报告
如果有兴趣在jupyter笔记本中查看代码,可以在这里找到它:
https://github.com/m-kortas/Sound-based-bird-species-detection/blob/master/medium.ipynb