Pytorch音频分类

pytorch实现音频分类代码

  • 这两天学习了下pytorch,动手练习练习
  • 数据集:来源是KAGGLE的一个音频分类的比赛
  • 数据集介绍:(需要梯子)https://urbansounddataset.weebly.com/urbansound8k.html
  • 数据集分为10类:
  • 代表不同的声音
    在这里插入图片描述
  • 在我下载的文件里面是这样的结构 外面是一个train 里面是train.csv 以及Train Train里面包含了一堆音频WAV文件
  • 训练集文件结构在这里插入图片描述
  • train.csv文件结构
    在这里插入图片描述

Keras实现

  • 话说还是Keras好用,可能我才接触torch的原因吧,BUG改来改去的写了一堆,还不及Keras几行代码管用。
    这里先上下Keras的实现代码
  • 网络结构
    在这里插入图片描述
  • 跑出来的效果,看的出来效果还是可以的 ,过我在写torch的时候发现交叉熵损失居然不支持one-hot编码,害我改了半天BUG,被迫使用了均方误差,最终跑出来效果差了很多,只有92%的acc在这里插入图片描述
  • 随机选取一条测试的结果在这里插入图片描述

torch实现分类代码以及详细解释

首先导入一波必要的库

import IPython.display as ipd
import librosa
import glob
import os 
import pandas as pd
import random
import librosa.display
import matplotlib.pyplot as plt 
import numpy as np
from sklearn.preprocessing import LabelEncoder
from keras.utils import np_utils
from torch.utils.data import Dataset,DataLoader,TensorDataset
import torch
import torch.nn.functional as F
import torch.nn as nn
import torch.optim as optim
import pickle

随机抽取数据查看

  • 接下来读取下csv文件,并随机抽取一条出来看看数据是什么样子的
  • 数据集的数据基本都是4s,我这里用的都是是默认采样率22050/s,包括后面的特征提取也是用的默认采样率
train=pd.read_csv("train/train.csv",sep=',')

在这里插入图片描述

查看训练集分布

  • 看完数据再让我们看看数据集的分布,这里利用了pandas的计算类别的功能
  • 数据稍微有点不平衡,不过影响不大
    在这里插入图片描述

对数据批量预处理以及保存

提取音频数据的特征的方式有很多,我这里比较简单用的是mfcc,固定40个
train.apply是pandas中批处理的一个方法,会返回一个pandas.DataFrame对象,里面存放着feature和label

def parser(row):
    file_name=os.path.join('train','Train',str(row.ID)+'.wav')
    try:
        x,sample_rate=librosa.load(file_name)
        mfccs = np.mean(librosa.feature.mfcc(y=x, sr=sample_rate, n_mfcc=40).T,axis=0) 
    except Exception as e:
        print("error",file)
        return None,None
    features=mfccs
    label=row.Class
    return [features,label]
temp=train.apply(parser,axis=1,result_type='expand')
  • 在上面的apply跑完以后我们就可以得到temp对象,查看一下这个数据
    在这里插入图片描述
  • 由于数据比较多,处理要几分钟,每次打开都跑一遍不方便,所以我用pickle把变量保存下来方便以后读取
  • pickle是个好东西,谁用谁知道,使用方法如下
    在这里插入图片描述

处理标签为one-hot编码

  • 由于这里的标签还是str类型的东西,我这里把他处理为one-hot编码
  • 而torch并没有这种方法,所以我只能使用keras的工具类来处理了
    在这里插入图片描述

定义dataloader以及网络结构

  • 定义的dataloader
class Dataset(Dataset):
    def __init__(self,x,y,use_gpu):
        self.x=torch.tensor(x)
        self.y=torch.tensor(y)
        if use_gpu:
            self.x=self.x.to("cuda")
            self.y=self.y.to("cuda")
        self.len=x.shape[0]
    def __getitem__(self,index):
        return self.x[index],self.y[index]
    def __len__(self):
        return self.len
  • 定义的分类网络结构
class Classify(nn.Module):
    def __init__(self):
        super(Classify,self).__init__()
        self.fc1=nn.Linear(40,64)
        self.dp=nn.Dropout(0.03)
        self.fc2=nn.Linear(64,20)
        self.fc3=nn.Linear(20,10)
    def forward(self,x):
        x=F.relu(self.fc1(x))
        x=self.dp(x)
        x=F.relu(self.fc2(x))
        x=F.relu(self.fc3(x))
        x=F.softmax(x,dim=1)
        return x

定义训函数和测试函数

  • 训练函数
def train(train_loader,model,loss_fun,optimizer,epoches,use_gpu):
    if use_gpu:
        model=model.cuda()
        loss_fun=loss_fun.cuda()
    acc=0
    all_loss=0
    for i in range(epoches):
        for j,data in enumerate(train_loader):
            x,y=data
            y_pre=model(x)
#             print(y.dtype)
#             print(y_pre)
            loss=loss_fun(y_pre,y)
            all_loss+=loss.item()
            values,indices=torch.topk(y_pre,k=1)
            values2,indices2=torch.topk(y,k=1)
            #print(indices,indices2)
            res=(indices==indices2)
            acc+=torch.sum(res).item()
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
        print("epoch{}--acc:{}-{:.4%}--loss:{}".format(i,acc,acc/all_data_en,all_loss))
        acc=0
        all_loss=0
  • 定义验证函数
def validate(val_loader,model,use_gpu):
    if use_gpu:
        model=model.cuda()
    model.eval()
    acc=0
    with torch.no_grad():
        for _,(inputs,y) in enumerate(val_loader):
            if use_gpu:
                inputs=inputs.cuda()
                y=y.cuda()
            y_pre=model(inputs)
            values,indices=torch.topk(y_pre,k=1)
            values2,indices2=torch.topk(y,k=1)
            res=(indices==indices2)
            acc+=torch.sum(res).item()
    print("acc:{:.4%}".format(acc/all_data_en))

训练模型

  • 定义一些初始变量
use_gpu=True if torch.cuda.is_available() else False#是否使用cuda
#use_gpu=False
model=Classify()
optimizer=torch.optim.Adam(model.parameters())#Adam优化器
loss_fun=nn.MSELoss()#均方误差
epoches=100
dataset=Dataset(x,y,use_gpu)
train_loader=DataLoader(dataset,batch_size=6)#batchsize=6
  • 开始训练
train(train_loader,model,loss_fun,optimizer,epoches,use_gpu)
  • 训练结果、这是我跑了几次后再跑的,所以一开始acc就很高
  • 在这里插入图片描述

保存、加载模型与测试

  • 保存模型
torch.save(model,"torchmodel.pth")
  • 加载模型
  • 话说torch的加载模型,如果在其他文件中load居然还要重新定义一遍网络结构?还是keras直接load方便,啥都不用管。这里由于还是同一个文件所以直接load就ok了
model=torch.load("torchmodel.pth")
  • 测试模型
use_gpu=True if torch.cuda.is_available() else False
train_loader=DataLoader(dataset,batch_size=all_data_en)#直接加载全部数据
validate(train_loader,model,use_gpu)

在这里插入图片描述

  • 吐了,写这么多代码效果一般般
以下是使用PyTorch实现音频分类的示例代码: ```python import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import Dataset, DataLoader import librosa import numpy as np # 定义音频数据集 class AudioDataset(Dataset): def __init__(self, file_list, label_list): self.file_list = file_list self.label_list = label_list def __len__(self): return len(self.file_list) def __getitem__(self, idx): # 加载音频文件并提取特征 audio_file, label = self.file_list[idx], self.label_list[idx] y, sr = librosa.load(audio_file) mfccs = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=40) mfccs = np.pad(mfccs, ((0, 0), (0, 260 - mfccs.shape[1])), mode='constant') mfccs = torch.from_numpy(mfccs) return mfccs.float(), label # 定义音频分类模型 class AudioClassifier(nn.Module): def __init__(self): super(AudioClassifier, self).__init__() self.conv1 = nn.Conv2d(1, 32, kernel_size=(3, 3), padding=(1, 1)) self.pool1 = nn.MaxPool2d(kernel_size=(2, 2)) self.conv2 = nn.Conv2d(32, 64, kernel_size=(3, 3), padding=(1, 1)) self.pool2 = nn.MaxPool2d(kernel_size=(2, 2)) self.conv3 = nn.Conv2d(64, 128, kernel_size=(3, 3), padding=(1, 1)) self.pool3 = nn.MaxPool2d(kernel_size=(2, 2)) self.fc1 = nn.Linear(128 * 10 * 16, 512) self.fc2 = nn.Linear(512, 10) def forward(self, x): x = x.unsqueeze(1) x = self.conv1(x) x = nn.functional.relu(x) x = self.pool1(x) x = self.conv2(x) x = nn.functional.relu(x) x = self.pool2(x) x = self.conv3(x) x = nn.functional.relu(x) x = self.pool3(x) x = x.view(-1, 128 * 10 * 16) x = nn.functional.relu(self.fc1(x)) x = self.fc2(x) return x # 训练模型 def train(model, train_loader, criterion, optimizer, device): model.train() train_loss = 0.0 train_acc = 0.0 for i, (data, target) in enumerate(train_loader): data, target = data.to(device), target.to(device) optimizer.zero_grad() output = model(data) loss = criterion(output, target) loss.backward() optimizer.step() train_loss += loss.item() * data.size(0) pred = output.argmax(dim=1, keepdim=True) train_acc += pred.eq(target.view_as(pred)).sum().item() train_loss /= len(train_loader.dataset) train_acc /= len(train_loader.dataset) return train_loss, train_acc # 测试模型 def test(model, test_loader, criterion, device): model.eval() test_loss = 0.0 test_acc = 0.0 with torch.no_grad(): for data, target in test_loader: data, target = data.to(device), target.to(device) output = model(data) test_loss += criterion(output, target).item() * data.size(0) pred = output.argmax(dim=1, keepdim=True) test_acc += pred.eq(target.view_as(pred)).sum().item() test_loss /= len(test_loader.dataset) test_acc /= len(test_loader.dataset) return test_loss, test_acc # 主函数 if __name__ == '__main__': # 加载音频数据集 train_files, train_labels = [], [] test_files, test_labels = [], [] # TODO: 加载训练集和测试集音频文件路径及其对应的标签 train_dataset = AudioDataset(train_files, train_labels) test_dataset = AudioDataset(test_files, test_labels) train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True) test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False) # 定义设备 device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") # 定义模型、损失函数和优化器 model = AudioClassifier().to(device) criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(model.parameters(), lr=0.001) # 训练模型 for epoch in range(10): train_loss, train_acc = train(model, train_loader, criterion, optimizer, device) test_loss, test_acc = test(model, test_loader, criterion, device) print('Epoch: {} Train Loss: {:.6f} Train Acc: {:.6f} Test Loss: {:.6f} Test Acc: {:.6f}'.format( epoch + 1, train_loss, train_acc, test_loss, test_acc)) ``` 上述代码中,我们定义了一个AudioDataset类来加载音频数据集,并使用librosa库来提取音频文件的MFCC特征。我们还定义了一个AudioClassifier类来实现音频分类模型,其中包含了三个卷积层和两个全连接层。在主函数中,我们使用DataLoader来加载训练集和测试集,并使用Adam优化器来训练模型。最后,我们在每个epoch结束时输出训练集和测试集的损失和准确率。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值