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)

在这里插入图片描述

  • 吐了,写这么多代码效果一般般
  • 13
    点赞
  • 114
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值