Pytorch音频分类

pytorch实现音频分类代码

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

Keras实现

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

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=',')

Pytorch音频分类_第7张图片

查看训练集分布

  • 看完数据再让我们看看数据集的分布,这里利用了pandas的计算类别的功能
  • 数据稍微有点不平衡,不过影响不大
    Pytorch音频分类_第8张图片

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

提取音频数据的特征的方式有很多,我这里比较简单用的是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对象,查看一下这个数据
    Pytorch音频分类_第9张图片
  • 由于数据比较多,处理要几分钟,每次打开都跑一遍不方便,所以我用pickle把变量保存下来方便以后读取
  • pickle是个好东西,谁用谁知道,使用方法如下
    Pytorch音频分类_第10张图片

处理标签为one-hot编码

  • 由于这里的标签还是str类型的东西,我这里把他处理为one-hot编码
  • 而torch并没有这种方法,所以我只能使用keras的工具类来处理了
    Pytorch音频分类_第11张图片

定义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就很高
  • Pytorch音频分类_第12张图片

保存、加载模型与测试

  • 保存模型
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音频分类_第13张图片

  • 吐了,写这么多代码效果一般般

你可能感兴趣的:(机器学习,人工智能,pytorch,tensorflow,深度学习,神经网络)