使用Pytorch框架,训练ESC-50数据集

        本文主要介绍在Pytorch框架下,利用K折交叉验证来训练ESC-50数据集,并保存最优模型。由于只有2000个样本音频,样本数量较少,故把训练集划分为训练集、测试集,且采用5折交叉验证法,同时加深网络层数。使得最终的准确率达到要求

语言:python

框架和设备:pytorch,CPU

关键词:ESC-50数据集、Dataset和Dataloader的编写、网络模型搭建、5折交叉验证、平均准确率、记录训练时间

一、ESC-50数据集介绍

ESC-50(Environmental Sound Classification)是一个用于环境音分类的音频数据集。该数据集由50个带标签的音频分类组成,每个音频片段长度为5秒,采样率为44.1kHz。这些音频片段都是从Freesound.org免费音频库中选取的。

该数据集主要用于环境声音的分类和识别,是机器学习和深度学习研究中经常使用的数据集之一。

ESC-50数据集可以从以下链接下载:

https://github.com/karolpiczak/ESC-50#download

可以下载压缩包并解压到本地,也可以使用Python的wget库下载,示例代码如下:

import wget

url = 'https://github.com/karolpiczak/ESC-50/archive/master.zip'
filename = wget.download(url)

这个代码片段会下载ESC-50数据集的压缩文件,并保存到当前工作目录下。下载完成后,需要将其解压缩,使用命令行或文件管理器即可完成。

二、编写ESC-50数据集的Dataset和Dataloader

        ESC-50数据集下载完成后,找到audio文件夹(存放的是所有音频)、meta中的csv文件(存放的是所有音频的信息)。

代码如下:

#定义dataset
import os
import pandas as pd
import torchaudio
from torch.utils.data import Dataset
from torchaudio.transforms import MelSpectrogram,AmplitudeToDB

class ESC50Dataset(Dataset):
    def __init__(self, base_path, csv_path, folds):
        """
        自定义的ESC-50数据集类
        :param base_path: 存储音频文件的基本路径
        :param csv_path: 包含元数据的CSV文件路径
        :param folds: 一个列表,包含要包括在数据集中的折叠编号
        """
        self.base_path = base_path
        self.csv_data = pd.read_csv(csv_path)#读取csv文件里的所有信息
        self.folds = folds#表示音频的类别,共把ESC50数据集分为了5大类
        self.data = self.csv_data[self.csv_data.fold.isin(folds)]#可以得到一个长度与csv_data相同的布尔类型Series(Series是Pandas中的一种数据类型,类似于数组),
                                                                 #该Series的每个元素表示该行数据所在的fold是否在folds列表中。
        self.amplitude_to_db = AmplitudeToDB()#幅度值转为db刻度

        #转为梅尔谱
        self.to_mel_spectrogram = MelSpectrogram(
            sample_rate=44100,
            n_fft=2048,
            hop_length=512,
            n_mels=64
        )

    def __getitem__(self, index):
        # 选择指定索引的条目
        row = self.data.iloc[index]
        # 读取音频文件
        file_path = os.path.join(self.base_path, row['filename'])
        waveform, sample_rate = torchaudio.load(file_path)
        mel_spectrogram = self.to_mel_spectrogram(waveform)
        # 转换到对数刻度(也就是db刻度)
        mel_spec_db = self.amplitude_to_db(mel_spectrogram)
        # 归一化
        mel_spec_norm = (mel_spec_db - mel_spec_db.mean()) / mel_spec_db.std()
        # 获取标签
        label = row['target']
        return mel_spec_norm, label#返回梅尔谱和对应的标签

    def __len__(self):
        return len(self.data)

# 基本路径和元数据文件路径
base_path = '/home/yc/vs_code/pytorch_audio/ESC-50/ESC-50-master/audio'  # 更新为音频文件存储的真实路径
csv_path = 'ESC-50/ESC-50-master/meta/esc50.csv'  # 更新为CSV文件存储的真实路径

# 创建一个数据集实例,包括1-5,因为csv文件里已经分为了5大类,所以不用自己划分数据集
esc_dataset = ESC50Dataset(base_path=base_path, csv_path=csv_path, folds=[1, 2, 3, 4, 5])

三、搭建网络模型

import torch
from torch import nn
from torch.nn import ReLU,Linear,Flatten,Sequential

#搭建网络模型
class Yangc(nn.Module):
    def __init__(self):
        super(Yangc,self).__init__()
        self.model=Sequential(
            nn.Conv2d(in_channels=1, out_channels=3, kernel_size=3, padding=2),
            ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2, stride=2),

            nn.Conv2d(in_channels=3, out_channels=8, kernel_size=3, padding=2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2, stride=2),  
   
            nn.Conv2d(in_channels=8, out_channels=16, kernel_size=3, padding=2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2, stride=2),

            nn.Conv2d(in_channels=16, out_channels=32, kernel_size=3, padding=2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2, stride=2),

            nn.Conv2d(in_channels=32, out_channels=48, kernel_size=3, padding=2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2, stride=2),

            nn.Conv2d(in_channels=48, out_channels=64, kernel_size=3, padding=2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2, stride=2),

            Flatten(),
            Linear(1024,512),
            nn.Dropout(),

            Linear(512,64),
            nn.Dropout(),

            Linear(64,50)
        )

    def forward(self,x):
        x=self.model(x)
        return x
    
if __name__ == '__main__':#写主函数,是为了检验神经网络模型是否搭建正确
    yangc=Yangc()
    input=torch.ones(64,1,64,431)
    output=yangc(input)
    print(output.shape)

输出:

torch.Size([64, 50])

四、开始交叉验证,并保存最优模型

import torch
import os
import pandas as pd
import torchaudio
from torch.utils.data import DataLoader,Dataset
from torchaudio.transforms import MelSpectrogram,AmplitudeToDB
import time#用于计时
from model import Yangc#导入模型

from torch.utils.data import DataLoader, SubsetRandomSampler
from sklearn.model_selection import KFold

# 参数设置
batch_size = 64
k_folds = 5
num_epochs = 50#训练总轮数
learning_rate = 0.001#学习率

# K折交叉验证模型
kf = KFold(n_splits=k_folds, shuffle=True)

#最终结果
results = []

min_acc = 0.#保存最好模型的参考值
# 外层循环遍历每一折
for fold, (train_ids, test_ids) in enumerate(kf.split(esc_dataset)):
    print(f'FOLD {fold}')
    print('--------------------------------')

    # 采样器
    train_subsampler = SubsetRandomSampler(train_ids)
    test_subsampler = SubsetRandomSampler(test_ids)

    # 数据加载器
    train_loader = DataLoader(esc_dataset, batch_size=batch_size, sampler=train_subsampler, num_workers = 5)
    test_loader = DataLoader(esc_dataset, batch_size=batch_size, sampler=test_subsampler, num_workers = 5)

    # 初始化模型
    model = Yangc() # 音频分类模型
    optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)#选择Adam优化器
    loss_fn = torch.nn.CrossEntropyLoss()

    best_vacc = 0.0#每一个fold中最高的准确率
    best_epoch = 0#保存最好模型对应的轮数
    best_fold = 0#保存最好模型对应的类别

    # 训练
    start_time=time.time()#训练开始计时
    for epoch in range(num_epochs):
        model.train()
        for i,(X,targets) in enumerate(train_loader):
            outputs = model(X)
            optimizer.zero_grad()
            loss = loss_fn(outputs, targets)

            # 优化器优化模型
            loss.backward()
            optimizer.step()
            
        model.eval()
        corrects,num = 0.0,0.0
        total_loss = 0.0
        with torch.no_grad():
            for i,(X,targets) in enumerate(test_loader):
                outputs = model(X)
                loss = loss_fn(outputs,targets)

                corrects += (outputs.argmax(1)  == targets).sum().item()
                num += X.shape[0]

        vacc = corrects/num#计算准确率
        accuracy=vacc*100

        if accuracy > best_vacc:
            best_vacc = accuracy
            best_epoch = epoch+1
            best_fold = fold+1
        print(f'Epoch [{epoch+1}/{num_epochs}], Fold [{fold+1}/{k_folds}], Accuracy: {accuracy:.2f}%')
    
    print(f'best_acc: {best_vacc:.2f}%')

    # 保存最好的模型权重
    if best_vacc > min_acc:
        min_acc = best_vacc
        print(f'保存最好的模型,并打印Epoch和folds')
        print(f'Epoch: {best_epoch}, Fold: {best_fold}')
            
        torch.save(model.state_dict(), 'save_model/best_model.pth')

    fold_accuracy = best_vacc
    results.append(fold_accuracy)

    end_time=time.time()
    print("耗费时间:{}".format(end_time-start_time))


# 计算平均性能
average_performance = sum(results) / len(results)
print(f"平均准确率: {average_performance}")  

输出:

FOLD 0
--------------------------------
Epoch [1/50], Fold [1/5], Accuracy: 3.00%
Epoch [2/50], Fold [1/5], Accuracy: 1.00%
Epoch [3/50], Fold [1/5], Accuracy: 4.00%
Epoch [4/50], Fold [1/5], Accuracy: 9.75%
Epoch [5/50], Fold [1/5], Accuracy: 11.00%
Epoch [6/50], Fold [1/5], Accuracy: 13.25%
Epoch [7/50], Fold [1/5], Accuracy: 17.75%
Epoch [8/50], Fold [1/5], Accuracy: 19.00%
Epoch [9/50], Fold [1/5], Accuracy: 22.50%
Epoch [10/50], Fold [1/5], Accuracy: 27.50%
Epoch [11/50], Fold [1/5], Accuracy: 29.25%
Epoch [12/50], Fold [1/5], Accuracy: 27.50%
Epoch [13/50], Fold [1/5], Accuracy: 31.75%
Epoch [14/50], Fold [1/5], Accuracy: 35.00%
Epoch [15/50], Fold [1/5], Accuracy: 35.25%
Epoch [16/50], Fold [1/5], Accuracy: 37.75%
Epoch [17/50], Fold [1/5], Accuracy: 40.50%
Epoch [18/50], Fold [1/5], Accuracy: 37.50%
Epoch [19/50], Fold [1/5], Accuracy: 41.25%
Epoch [20/50], Fold [1/5], Accuracy: 39.75%
Epoch [21/50], Fold [1/5], Accuracy: 39.50%
Epoch [22/50], Fold [1/5], Accuracy: 42.50%
Epoch [23/50], Fold [1/5], Accuracy: 43.00%
Epoch [24/50], Fold [1/5], Accuracy: 41.75%
Epoch [25/50], Fold [1/5], Accuracy: 42.25%
Epoch [26/50], Fold [1/5], Accuracy: 44.00%
Epoch [27/50], Fold [1/5], Accuracy: 43.50%
Epoch [28/50], Fold [1/5], Accuracy: 42.00%
Epoch [29/50], Fold [1/5], Accuracy: 42.00%
Epoch [30/50], Fold [1/5], Accuracy: 45.50%
Epoch [31/50], Fold [1/5], Accuracy: 47.25%
Epoch [32/50], Fold [1/5], Accuracy: 46.50%
Epoch [33/50], Fold [1/5], Accuracy: 45.00%
Epoch [34/50], Fold [1/5], Accuracy: 47.50%
Epoch [35/50], Fold [1/5], Accuracy: 46.00%
Epoch [36/50], Fold [1/5], Accuracy: 47.00%
Epoch [37/50], Fold [1/5], Accuracy: 48.25%
Epoch [38/50], Fold [1/5], Accuracy: 46.00%
Epoch [39/50], Fold [1/5], Accuracy: 45.25%
Epoch [40/50], Fold [1/5], Accuracy: 47.50%
Epoch [41/50], Fold [1/5], Accuracy: 46.50%
Epoch [42/50], Fold [1/5], Accuracy: 49.75%
Epoch [43/50], Fold [1/5], Accuracy: 47.25%
Epoch [44/50], Fold [1/5], Accuracy: 47.50%
Epoch [45/50], Fold [1/5], Accuracy: 49.00%
Epoch [46/50], Fold [1/5], Accuracy: 47.25%
Epoch [47/50], Fold [1/5], Accuracy: 48.50%
Epoch [48/50], Fold [1/5], Accuracy: 47.50%
Epoch [49/50], Fold [1/5], Accuracy: 47.00%
Epoch [50/50], Fold [1/5], Accuracy: 48.25%
best_acc: 49.75%
保存最好的模型,并打印Epoch和folds
Epoch 50, Fold 1
耗费时间:460.83227133750916
FOLD 1
--------------------------------
Epoch [1/50], Fold [2/5], Accuracy: 1.25%
Epoch [2/50], Fold [2/5], Accuracy: 1.50%
Epoch [3/50], Fold [2/5], Accuracy: 3.75%
Epoch [4/50], Fold [2/5], Accuracy: 9.50%
Epoch [5/50], Fold [2/5], Accuracy: 10.25%
Epoch [6/50], Fold [2/5], Accuracy: 17.00%
Epoch [7/50], Fold [2/5], Accuracy: 18.50%
Epoch [8/50], Fold [2/5], Accuracy: 26.50%
Epoch [9/50], Fold [2/5], Accuracy: 29.25%
Epoch [10/50], Fold [2/5], Accuracy: 28.00%
Epoch [11/50], Fold [2/5], Accuracy: 31.75%
Epoch [12/50], Fold [2/5], Accuracy: 32.75%
Epoch [13/50], Fold [2/5], Accuracy: 35.75%
Epoch [14/50], Fold [2/5], Accuracy: 34.25%
Epoch [15/50], Fold [2/5], Accuracy: 37.50%
Epoch [16/50], Fold [2/5], Accuracy: 39.75%
Epoch [17/50], Fold [2/5], Accuracy: 44.00%
Epoch [18/50], Fold [2/5], Accuracy: 39.00%
Epoch [19/50], Fold [2/5], Accuracy: 41.50%
Epoch [20/50], Fold [2/5], Accuracy: 45.50%
Epoch [21/50], Fold [2/5], Accuracy: 47.00%
Epoch [22/50], Fold [2/5], Accuracy: 47.25%
Epoch [23/50], Fold [2/5], Accuracy: 52.00%
Epoch [24/50], Fold [2/5], Accuracy: 52.75%
Epoch [25/50], Fold [2/5], Accuracy: 51.75%
Epoch [26/50], Fold [2/5], Accuracy: 48.75%
Epoch [27/50], Fold [2/5], Accuracy: 51.50%
Epoch [28/50], Fold [2/5], Accuracy: 48.25%
Epoch [29/50], Fold [2/5], Accuracy: 51.25%
Epoch [30/50], Fold [2/5], Accuracy: 51.50%
Epoch [31/50], Fold [2/5], Accuracy: 51.75%
Epoch [32/50], Fold [2/5], Accuracy: 53.25%
Epoch [33/50], Fold [2/5], Accuracy: 53.25%
Epoch [34/50], Fold [2/5], Accuracy: 54.00%
Epoch [35/50], Fold [2/5], Accuracy: 55.00%
Epoch [36/50], Fold [2/5], Accuracy: 53.00%
Epoch [37/50], Fold [2/5], Accuracy: 53.50%
Epoch [38/50], Fold [2/5], Accuracy: 52.00%
Epoch [39/50], Fold [2/5], Accuracy: 54.50%
Epoch [40/50], Fold [2/5], Accuracy: 53.50%
Epoch [41/50], Fold [2/5], Accuracy: 53.75%
Epoch [42/50], Fold [2/5], Accuracy: 57.75%
Epoch [43/50], Fold [2/5], Accuracy: 55.25%
Epoch [44/50], Fold [2/5], Accuracy: 52.50%
Epoch [45/50], Fold [2/5], Accuracy: 51.50%
Epoch [46/50], Fold [2/5], Accuracy: 53.75%
Epoch [47/50], Fold [2/5], Accuracy: 52.50%
Epoch [48/50], Fold [2/5], Accuracy: 55.00%
Epoch [49/50], Fold [2/5], Accuracy: 53.25%
Epoch [50/50], Fold [2/5], Accuracy: 52.50%
best_acc: 57.75%
保存最好的模型,并打印Epoch和folds
Epoch 50, Fold 2
耗费时间:427.56484937667847
FOLD 2
--------------------------------
Epoch [1/50], Fold [3/5], Accuracy: 2.50%
Epoch [2/50], Fold [3/5], Accuracy: 5.25%
Epoch [3/50], Fold [3/5], Accuracy: 7.00%
Epoch [4/50], Fold [3/5], Accuracy: 10.00%
Epoch [5/50], Fold [3/5], Accuracy: 13.75%
Epoch [6/50], Fold [3/5], Accuracy: 18.25%
Epoch [7/50], Fold [3/5], Accuracy: 20.25%
Epoch [8/50], Fold [3/5], Accuracy: 22.00%
Epoch [9/50], Fold [3/5], Accuracy: 25.00%
Epoch [10/50], Fold [3/5], Accuracy: 28.25%
Epoch [11/50], Fold [3/5], Accuracy: 27.50%
Epoch [12/50], Fold [3/5], Accuracy: 30.75%
Epoch [13/50], Fold [3/5], Accuracy: 29.50%
Epoch [14/50], Fold [3/5], Accuracy: 34.25%
Epoch [15/50], Fold [3/5], Accuracy: 34.75%
Epoch [16/50], Fold [3/5], Accuracy: 37.50%
Epoch [17/50], Fold [3/5], Accuracy: 40.50%
Epoch [18/50], Fold [3/5], Accuracy: 38.75%
Epoch [19/50], Fold [3/5], Accuracy: 38.75%
Epoch [20/50], Fold [3/5], Accuracy: 38.75%
Epoch [21/50], Fold [3/5], Accuracy: 38.75%
Epoch [22/50], Fold [3/5], Accuracy: 40.50%
Epoch [23/50], Fold [3/5], Accuracy: 39.50%
Epoch [24/50], Fold [3/5], Accuracy: 42.50%
Epoch [25/50], Fold [3/5], Accuracy: 41.50%
Epoch [26/50], Fold [3/5], Accuracy: 42.75%
Epoch [27/50], Fold [3/5], Accuracy: 45.75%
Epoch [28/50], Fold [3/5], Accuracy: 44.50%
Epoch [29/50], Fold [3/5], Accuracy: 46.25%
Epoch [30/50], Fold [3/5], Accuracy: 43.75%
Epoch [31/50], Fold [3/5], Accuracy: 45.50%
Epoch [32/50], Fold [3/5], Accuracy: 48.25%
Epoch [33/50], Fold [3/5], Accuracy: 47.75%
Epoch [34/50], Fold [3/5], Accuracy: 48.75%
Epoch [35/50], Fold [3/5], Accuracy: 51.75%
Epoch [36/50], Fold [3/5], Accuracy: 51.75%
Epoch [37/50], Fold [3/5], Accuracy: 51.25%
Epoch [38/50], Fold [3/5], Accuracy: 52.25%
Epoch [39/50], Fold [3/5], Accuracy: 52.25%
Epoch [40/50], Fold [3/5], Accuracy: 49.75%
Epoch [41/50], Fold [3/5], Accuracy: 53.00%
Epoch [42/50], Fold [3/5], Accuracy: 53.25%
Epoch [43/50], Fold [3/5], Accuracy: 51.25%
Epoch [44/50], Fold [3/5], Accuracy: 52.25%
Epoch [45/50], Fold [3/5], Accuracy: 53.25%
Epoch [46/50], Fold [3/5], Accuracy: 51.25%
Epoch [47/50], Fold [3/5], Accuracy: 54.25%
Epoch [48/50], Fold [3/5], Accuracy: 55.00%
Epoch [49/50], Fold [3/5], Accuracy: 53.25%
Epoch [50/50], Fold [3/5], Accuracy: 52.00%
best_acc: 55.00%
耗费时间:425.57921600341797
FOLD 3
--------------------------------
Epoch [1/50], Fold [4/5], Accuracy: 0.75%
Epoch [2/50], Fold [4/5], Accuracy: 2.75%
Epoch [3/50], Fold [4/5], Accuracy: 5.75%
Epoch [4/50], Fold [4/5], Accuracy: 9.00%
Epoch [5/50], Fold [4/5], Accuracy: 10.50%
Epoch [6/50], Fold [4/5], Accuracy: 13.00%
Epoch [7/50], Fold [4/5], Accuracy: 20.00%
Epoch [8/50], Fold [4/5], Accuracy: 21.75%
Epoch [9/50], Fold [4/5], Accuracy: 21.75%
Epoch [10/50], Fold [4/5], Accuracy: 24.25%
Epoch [11/50], Fold [4/5], Accuracy: 27.25%
Epoch [12/50], Fold [4/5], Accuracy: 27.50%
Epoch [13/50], Fold [4/5], Accuracy: 26.25%
Epoch [14/50], Fold [4/5], Accuracy: 30.00%
Epoch [15/50], Fold [4/5], Accuracy: 32.00%
Epoch [16/50], Fold [4/5], Accuracy: 35.00%
Epoch [17/50], Fold [4/5], Accuracy: 34.75%
Epoch [18/50], Fold [4/5], Accuracy: 38.25%
Epoch [19/50], Fold [4/5], Accuracy: 38.50%
Epoch [20/50], Fold [4/5], Accuracy: 37.50%
Epoch [21/50], Fold [4/5], Accuracy: 36.00%
Epoch [22/50], Fold [4/5], Accuracy: 38.25%
Epoch [23/50], Fold [4/5], Accuracy: 37.50%
Epoch [24/50], Fold [4/5], Accuracy: 38.75%
Epoch [25/50], Fold [4/5], Accuracy: 42.75%
Epoch [26/50], Fold [4/5], Accuracy: 44.50%
Epoch [27/50], Fold [4/5], Accuracy: 41.00%
Epoch [28/50], Fold [4/5], Accuracy: 45.50%
Epoch [29/50], Fold [4/5], Accuracy: 47.25%
Epoch [30/50], Fold [4/5], Accuracy: 49.00%
Epoch [31/50], Fold [4/5], Accuracy: 47.75%
Epoch [32/50], Fold [4/5], Accuracy: 48.50%
Epoch [33/50], Fold [4/5], Accuracy: 47.25%
Epoch [34/50], Fold [4/5], Accuracy: 47.50%
Epoch [35/50], Fold [4/5], Accuracy: 47.75%
Epoch [36/50], Fold [4/5], Accuracy: 44.50%
Epoch [37/50], Fold [4/5], Accuracy: 45.25%
Epoch [38/50], Fold [4/5], Accuracy: 49.00%
Epoch [39/50], Fold [4/5], Accuracy: 47.50%
Epoch [40/50], Fold [4/5], Accuracy: 50.75%
Epoch [41/50], Fold [4/5], Accuracy: 50.75%
Epoch [42/50], Fold [4/5], Accuracy: 49.75%
Epoch [43/50], Fold [4/5], Accuracy: 48.50%
Epoch [44/50], Fold [4/5], Accuracy: 49.00%
Epoch [45/50], Fold [4/5], Accuracy: 51.25%
Epoch [46/50], Fold [4/5], Accuracy: 49.25%
Epoch [47/50], Fold [4/5], Accuracy: 48.75%
Epoch [48/50], Fold [4/5], Accuracy: 52.50%
Epoch [49/50], Fold [4/5], Accuracy: 52.50%
Epoch [50/50], Fold [4/5], Accuracy: 51.00%
best_acc: 52.50%
耗费时间:427.9511728286743
FOLD 4
--------------------------------
Epoch [1/50], Fold [5/5], Accuracy: 2.50%
Epoch [2/50], Fold [5/5], Accuracy: 7.75%
Epoch [3/50], Fold [5/5], Accuracy: 7.00%
Epoch [4/50], Fold [5/5], Accuracy: 14.00%
Epoch [5/50], Fold [5/5], Accuracy: 17.50%
Epoch [6/50], Fold [5/5], Accuracy: 22.00%
Epoch [7/50], Fold [5/5], Accuracy: 21.00%
Epoch [8/50], Fold [5/5], Accuracy: 25.00%
Epoch [9/50], Fold [5/5], Accuracy: 28.75%
Epoch [10/50], Fold [5/5], Accuracy: 30.25%
Epoch [11/50], Fold [5/5], Accuracy: 31.25%
Epoch [12/50], Fold [5/5], Accuracy: 31.50%
Epoch [13/50], Fold [5/5], Accuracy: 34.00%
Epoch [14/50], Fold [5/5], Accuracy: 36.25%
Epoch [15/50], Fold [5/5], Accuracy: 41.25%
Epoch [16/50], Fold [5/5], Accuracy: 38.50%
Epoch [17/50], Fold [5/5], Accuracy: 41.50%
Epoch [18/50], Fold [5/5], Accuracy: 42.25%
Epoch [19/50], Fold [5/5], Accuracy: 40.00%
Epoch [20/50], Fold [5/5], Accuracy: 43.75%
Epoch [21/50], Fold [5/5], Accuracy: 41.75%
Epoch [22/50], Fold [5/5], Accuracy: 43.00%
Epoch [23/50], Fold [5/5], Accuracy: 48.00%
Epoch [24/50], Fold [5/5], Accuracy: 41.50%
Epoch [25/50], Fold [5/5], Accuracy: 45.50%
Epoch [26/50], Fold [5/5], Accuracy: 46.25%
Epoch [27/50], Fold [5/5], Accuracy: 47.25%
Epoch [28/50], Fold [5/5], Accuracy: 47.75%
Epoch [29/50], Fold [5/5], Accuracy: 46.75%
Epoch [30/50], Fold [5/5], Accuracy: 47.75%
Epoch [31/50], Fold [5/5], Accuracy: 49.00%
Epoch [32/50], Fold [5/5], Accuracy: 49.50%
Epoch [33/50], Fold [5/5], Accuracy: 52.00%
Epoch [34/50], Fold [5/5], Accuracy: 48.25%
Epoch [35/50], Fold [5/5], Accuracy: 49.00%
Epoch [36/50], Fold [5/5], Accuracy: 43.75%
Epoch [37/50], Fold [5/5], Accuracy: 49.00%
Epoch [38/50], Fold [5/5], Accuracy: 48.75%
Epoch [39/50], Fold [5/5], Accuracy: 49.25%
Epoch [40/50], Fold [5/5], Accuracy: 51.00%
Epoch [41/50], Fold [5/5], Accuracy: 47.50%
Epoch [42/50], Fold [5/5], Accuracy: 49.50%
Epoch [43/50], Fold [5/5], Accuracy: 49.00%
Epoch [44/50], Fold [5/5], Accuracy: 48.25%
Epoch [45/50], Fold [5/5], Accuracy: 48.00%
Epoch [46/50], Fold [5/5], Accuracy: 51.25%
Epoch [47/50], Fold [5/5], Accuracy: 49.75%
Epoch [48/50], Fold [5/5], Accuracy: 47.75%
Epoch [49/50], Fold [5/5], Accuracy: 51.50%
Epoch [50/50], Fold [5/5], Accuracy: 48.75%
best_acc: 52.00%
耗费时间:439.0925712585449
平均准确率: 53.4

说明:每一折取最好的准确率,5折之后得到5个准确率,再求平均值,即可得到平均准确率53.4%

由此可见,测试效果良好。

五、完整代码

import torch
import os
import pandas as pd
import torchaudio
from torch.utils.data import DataLoader,Dataset
from torchaudio.transforms import MelSpectrogram,AmplitudeToDB
import time#用于计时
from model import Yangc#导入模型

from torch.utils.data import DataLoader, SubsetRandomSampler
from sklearn.model_selection import KFold

#定义dataset
class ESC50Dataset(Dataset):
    def __init__(self, base_path, csv_path, folds):
        """
        自定义的ESC-50数据集类
        :param base_path: 存储音频文件的基本路径
        :param csv_path: 包含元数据的CSV文件路径
        :param folds: 一个列表,包含要包括在数据集中的折叠编号
        """
        self.base_path = base_path
        self.csv_data = pd.read_csv(csv_path)
        self.folds = folds
        self.data = self.csv_data[self.csv_data.fold.isin(folds)]
        self.amplitude_to_db = AmplitudeToDB()

        #转为梅尔谱
        self.to_mel_spectrogram = MelSpectrogram(
            sample_rate=44100,
            n_fft=2048,
            hop_length=512,
            n_mels=64
        )

    def __getitem__(self, index):
        # 选择指定索引的条目
        row = self.data.iloc[index]
        # 读取音频文件
        file_path = os.path.join(self.base_path, row['filename'])
        waveform, sample_rate = torchaudio.load(file_path)
        mel_spectrogram = self.to_mel_spectrogram(waveform)
        # 转换到对数刻度
        mel_spec_db = self.amplitude_to_db(mel_spectrogram)
        # 归一化
        mel_spec_norm = (mel_spec_db - mel_spec_db.mean()) / mel_spec_db.std()
        # 获取标签
        label = row['target']
        return mel_spec_norm, label

    def __len__(self):
        return len(self.data)

# 基本路径和元数据文件路径
base_path = '/home/yc/vs_code/pytorch_audio/ESC-50/ESC-50-master/audio'  # 更新为音频文件存储的真实路径
csv_path = 'ESC-50/ESC-50-master/meta/esc50.csv'  # 更新为CSV文件存储的真实路径

# 创建一个数据集实例,包括1-5,因为csv文件里已经分为了5大类,所以不要自己划分数据集,要按照1,2,3,4训练集,5做测试集来划分
esc_dataset = ESC50Dataset(base_path=base_path, csv_path=csv_path, folds=[1, 2, 3, 4, 5])

# 参数设置
batch_size = 64
k_folds = 5
num_epochs = 50#训练总轮数
learning_rate = 0.001#学习率

# K折交叉验证模型
kf = KFold(n_splits=k_folds, shuffle=True)

#最终结果
results = []

min_acc = 0.#保存最好模型的参考值

#sampler说明:https://blog.csdn.net/qq_41971355/article/details/125616331?ops_request_misc=&request_id=&biz_id=102&utm_term=DataLoader%E4%B8%AD%E7%9A%84sample&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-5-125616331.142^v99^pc_search_result_base3&spm=1018.2226.3001.4187
#https://blog.csdn.net/kuxingseng123/article/details/128501104?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522170540980316800215035507%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=170540980316800215035507&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-128501104-null-null.142^v99^pc_search_result_base3&utm_term=SubsetRandomSampler&spm=1018.2226.3001.4187
# 外层循环遍历每一折
for fold, (train_ids, test_ids) in enumerate(kf.split(esc_dataset)):
    print(f'FOLD {fold}')
    print('--------------------------------')

    # 采样器
    train_subsampler = SubsetRandomSampler(train_ids)
    test_subsampler = SubsetRandomSampler(test_ids)

    # 数据加载器
    train_loader = DataLoader(esc_dataset, batch_size=batch_size, sampler=train_subsampler, num_workers = 5)
    test_loader = DataLoader(esc_dataset, batch_size=batch_size, sampler=test_subsampler, num_workers = 5)

    # 初始化模型
    model = Yangc() # 音频分类模型
    optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)#选择Adam优化器
    loss_fn = torch.nn.CrossEntropyLoss()

    best_vacc = 0.0#每一个fold中最高的准确率
    best_epoch = 0#保存最好模型对应的轮数
    best_fold = 0#保存最好模型对应的类别

    # 训练
    start_time=time.time()#训练开始计时
    for epoch in range(num_epochs):
        model.train()
        for i,(X,targets) in enumerate(train_loader):
            outputs = model(X)
            optimizer.zero_grad()
            loss = loss_fn(outputs, targets)

            # 优化器优化模型
            loss.backward()
            optimizer.step()
            
        model.eval()
        corrects,num = 0.0,0.0
        total_loss = 0.0
        with torch.no_grad():
            for i,(X,targets) in enumerate(test_loader):
                outputs = model(X)
                loss = loss_fn(outputs,targets)
                # total_loss += loss.item()

                corrects += (outputs.argmax(1)  == targets).sum().item()
                num += X.shape[0]

        vacc = corrects/num#计算准确率
        accuracy=vacc*100

        if accuracy > best_vacc:
            best_vacc = accuracy
            best_epoch = epoch+1
            best_fold = fold+1
        print(f'Epoch [{epoch+1}/{num_epochs}], Fold [{fold+1}/{k_folds}], Accuracy: {accuracy:.2f}%')
    
    print(f'best_acc: {best_vacc:.2f}%')

    # 保存最好的模型权重
    if best_vacc > min_acc:
        min_acc = best_vacc
        print(f'保存最好的模型,并打印Epoch和folds')
        print(f'Epoch: {best_epoch}, Fold: {best_fold}')
            
        torch.save(model.state_dict(), 'save_model/best_model.pth')

    fold_accuracy = best_vacc
    results.append(fold_accuracy)

    end_time=time.time()
    print("耗费时间:{}".format(end_time-start_time))


# 计算平均性能
average_performance = sum(results) / len(results)
print(f"平均准确率: {average_performance}")  
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值