[數(shù)據(jù)分析實踐]-音頻分析-BirdCLE-3
https://www.kaggle.com/code/utcarshagrawal/birdclef-audio-pytorch-tutorial
數(shù)據(jù)背景
作為“世界滅絕之都”弥激,夏威夷已經(jīng)失去了68%的鳥類物種厚满,其后果可能會損害整個食物鏈。研究人員利用種群監(jiān)測來了解本地鳥類對環(huán)境變化和保護措施的反應(yīng)。但島上的許多鳥類都被隔離在難以接近的高海拔棲息地。由于身體監(jiān)測困難,科學(xué)家們轉(zhuǎn)向了聲音記錄。這種被稱為生物聲學(xué)監(jiān)測的方法可以為研究瀕危鳥類種群提供一種被動的、低成本的焚廊、經(jīng)濟的策略冶匹。
目前處理大型生物聲學(xué)數(shù)據(jù)集的方法涉及對每個記錄的手工注釋。這需要專門的訓(xùn)練和大量的時間咆瘟。因此使用機器學(xué)習(xí)技能嚼隘,通過聲音來識別鳥類的種類,可以節(jié)約大量成本袒餐。具體來說飞蛹,開發(fā)一個模型,可以處理連續(xù)的音頻數(shù)據(jù)灸眼,然后從聲音上識別物種卧檐。最好的條目將能夠用有限的訓(xùn)練數(shù)據(jù)訓(xùn)練可靠的分類器。
數(shù)據(jù)介紹
數(shù)據(jù)集來源:https://www.kaggle.com/competitions/birdclef-2022/data
下載方式:https://github.com/Kaggle/kaggle-api
kaggle competitions download -c birdclef-2022
-
train_metadata.csv
:為訓(xùn)練數(shù)據(jù)提供了廣泛的元數(shù)據(jù)- primary_label -鳥類的編碼焰宣∶骨簦可以通過將代碼附加到https://ebird.org/species/來查看有關(guān)鳥類代碼的詳細信息,例如美國烏鴉的代碼添加到https://ebird.org/species/amecro
- secondary_labels: 記錄員標注的背景物種匕积,空列表并不意味著沒有背景鳥的聲音盈罐。
- author - 提供錄音的eBird用戶
- Filename:關(guān)聯(lián)音頻文件。
- rating: 浮動值在0.0到5.0之間闪唆,作為Xeno-canto的質(zhì)量等級和背景物種數(shù)量的指標盅粪,其中5.0是最高的,1.0是最低的悄蕾。0.0表示此記錄還沒有用戶評級票顾。
train_audio
:大量的訓(xùn)練數(shù)據(jù)由xenocanto.org的用戶慷慨上傳的單個鳥類叫聲的短錄音組成。這些文件已被下采樣到32khz帆调,適用于匹配測試集的音頻奠骄,并轉(zhuǎn)換為ogg格式。test_soundscapes
:當您提交一個筆記本時贷帮,test_soundscapes目錄將填充大約5500段錄音戚揭,用于評分。每一個都是1分鐘幾毫秒的ogg音頻格式撵枢,并只有一個音景可供下載。-
test.csv
:測試數(shù)據(jù)- row_id:行的唯一標識符精居。
- file_id:音頻文件的唯一標識符锄禽。
- bird :一行的ebird代碼。每個音頻文件每5秒窗口有一排為每個得分物種靴姿。
- end_time:5秒時間窗口(5沃但、10、15等)的最后一秒佛吓。
<h1 style = "font-size:45px;font-family: Comic Sans MS;text-align: center;background-color:#800080;color:#FFFFFF">音頻特征提取</h1>
<h3 style="font-family:Comic Sans MS">特征提取是突出信號中最具辨別力和影響力的特征的過程宵晚。本文將引導(dǎo)完成音頻處理中的一些重要特征提取垂攘,你可以將其擴展到適合的問題域的許多其他類型的特征。本文的其余部分只是一個生物技術(shù)學(xué)生的嘗試淤刃,向你解釋ta在過去幾天能夠理解的任何信號處理晒他。
import os
import gc
import ast
import random
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
import seaborn as sns
from tqdm import tqdm
import torchaudio
import IPython.display as ipd
from collections import Counter
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import StratifiedKFold
from sklearn.metrics import f1_score
import torch
import torch.nn as nn
from torch.optim import Adam
import torch.nn.functional as F
from torch.utils.data import Dataset, DataLoader
from torchvision import models
import warnings
warnings.filterwarnings('ignore')
class config:
seed=2022
num_fold = 5
sample_rate= 32_000
n_fft=1024
hop_length=512
n_mels=64
duration=7
num_classes = 152
train_batch_size = 32
valid_batch_size = 64
model_name = 'resnet50'
epochs = 2
device = 'cuda' if torch.cuda.is_available() else 'cpu'
learning_rate = 1e-4
def seed_everything(seed):
random.seed(seed)
os.environ['PYTHONHASHSEED'] = str(seed)
np.random.seed(seed)
torch.manual_seed(seed)
torch.cuda.manual_seed(seed)
torch.backends.cudnn.deterministic = True
seed_everything(config.seed)
#讀取數(shù)據(jù)
df = pd.read_csv('../input/birdclef-2022/train_metadata.csv')
df.head()
df.info()
df.describe()
分析Train_Metadata
plt.figure(figsize=(20, 6))
sns.countplot(df['primary_label'])
plt.xticks(rotation=90)
plt.title("Distribution of Primary Labels", fontsize=20)
plt.show()
plt.figure(figsize=(20, 6))
sns.countplot(df['rating'])
plt.title("Distribution of Ratings", fontsize=20)
plt.show()
df['type'] = df['type'].apply(lambda x : ast.literal_eval(x))
top = Counter([typ.lower() for lst in df['type'] for typ in lst])
top = dict(top.most_common(10))
plt.figure(figsize=(20, 6))
sns.barplot(x=list(top.keys()), y=list(top.values()), palette='hls')
plt.title("Top 10 song types")
plt.show()
分析音頻文件
使用 Torchaudio(這是一個 PyTorch 的音頻庫)來處理音頻數(shù)據(jù)
fig, ax = plt.subplots(2, 1, figsize=(20, 10))
fig.suptitle("Sound Waves", fontsize=15)
signal_1, sr = torchaudio.load(f"../input/birdclef-2022/train_audio/{filename_1}")
# The audio data consist of two things-
# Sound: sequence of vibrations in varying pressure strengths (y)
# Sample Rate: (sr) is the number of samples of audio carried per second, measured in Hz or kHz
sns.lineplot(x=np.arange(len(signal_1[0,:].detach().numpy())), y=signal_1[0,:].detach().numpy(), ax=ax[0], color='#4400FF')
ax[0].set_title("Audio 1")
signal_2, sr = torchaudio.load(f"../input/birdclef-2022/train_audio/{filename_2}")
sns.lineplot(x=np.arange(len(signal_2[0,:].detach().numpy())), y=signal_2[0,:].detach().numpy(), ax=ax[1], color='#4400FF')
ax[1].set_title("Audio 2")
plt.show()
數(shù)據(jù)預(yù)處理
由于我們的目標變量是字符串格式,因此將其轉(zhuǎn)換為整數(shù)逸贾,這里我使用了 LabelEncoder 來執(zhí)行
encoder = LabelEncoder()
df['primary_label_encoded'] = encoder.fit_transform(df['primary_label'])
skf = StratifiedKFold(n_splits=config.num_fold)
for k, (_, val_ind) in enumerate(skf.split(X=df, y=df['primary_label_encoded'])):
df.loc[val_ind, 'fold'] = k
模型輸入是音頻文件陨仅,但模型無法直接理解這些音頻。 因此為了使用它們铝侵,我通過執(zhí)行某種類型的特征提取技術(shù)將其轉(zhuǎn)換為可理解的格式
特征提取
通常情況下提取的特征是圖像的形式灼伤,然后使用它們來訓(xùn)練我們的模型,這里使用MelSpectrogram咪鲜,這是一種將頻率轉(zhuǎn)換為梅爾標度的頻譜圖
fig, ax = plt.subplots(1, 2, figsize=(20, 7))
fig.suptitle("Mel Spectrogram", fontsize=15)
mel_spectrogram = torchaudio.transforms.MelSpectrogram(sample_rate=config.sample_rate,
n_fft=config.n_fft,
hop_length=config.hop_length,
n_mels=config.n_mels)
mel_1 = mel_spectrogram(signal_1)
ax[0].imshow(mel_1.log2()[0,:,:].detach().numpy(), aspect='auto', cmap='cool')
ax[0].set_title("Audio 1")
mel_2 = mel_spectrogram(signal_2)
ax[1].imshow(mel_2.log2()[0,:,:].detach().numpy(), aspect='auto', cmap='cool')
ax[1].set_title("Audio 2")
plt.show()