作者 | Aakash
来源 | Medium
编辑 | 代码医生团队
什么是分类问题?
对对象进行分类就是将其分配给特定的类别。这本质上是一个分类问题是什么,即将输入数据从一组这样的类别,也称为类分配到预定义的类别。
机器学习中的分类问题示例包括:识别手写数字,区分垃圾邮件和非垃圾邮件或识别核中的不同蛋白质。
https://www.kaggle.com/c/jovian-pytorch-z2g
使用的数据集
为了演示分类问题的工作原理,将使用UrbanSound8K数据集。该数据集包括10种类别的城市声音:空调,汽车喇叭,儿童游戏,狗吠,钻探,enginge_idling,gun_shot,手提钻,警笛和street_music。
https://urbansounddataset.weebly.com/urbansound8k.html
目的是将数据提供给模型(目前可以将其视为黑匣子),并确定模型预测的准确性。
数据集的结构
该数据集可以作为压缩包使用,大小约为5.6GB。与某些机器学习数据集不同,此特定数据集中的音频数据与元数据文件夹一起存在于10个不同的文件夹中,元数据文件夹包含名为“ UrbanSound8K.csv”的文件。
D:\DL\ZEROTOGANS\06-URBAN8K-CLASSIFICATION\DATA\URBANSOUND8K
├───audio
│ ├───fold1
│ ├───fold10
│ ├───fold2
│ ├───fold3
│ ├───fold4
│ ├───fold5
│ ├───fold6
│ ├───fold7
│ ├───fold8
│ └───fold9
└───metadata
大多数ML数据集都有训练/测试文件夹,每个文件夹分别包含用于训练和测试的数据。但是在此数据集中,所有文件夹中都可以使用所有(10)类数据。建议使用10折中的9折作为训练数据,其余的折作为测试数据。
依赖关系
import torch
import pandas as pd
import librosa
import numpy as np
from torch.utils.data import TensorDataset, DataLoader, random_split
import librosa.display
import matplotlib.pyplot as plt
import tarfile
import torch.nn as nn
import torch.nn.functional as F
上面的库以python编程语言提供。专门使用它们来创建两个具有不同架构的模型。用来进行此项目的环境在anaconda云上可用。
https://anaconda.org/aakash_/pytorch-cuda
可视化数据
音频数据通常以波状图的形式可视化。波形图是由两个轴组成的图形。X轴表示时间,Y轴表示距平均位置(即振幅)的位移。以下代码行使用python中的librosa包为每个类显示一个波形图。最初提取每个音频文件的路径并将其存储在字典中。
classes=list(df["class"].unique())
df=pd.read_csv("data/UrbanSound8K/metadata/UrbanSound8K.csv")
paths=dict()
for i in range(len(classes)):
temp_df=df[df["class"]==classes[i]].reset_index()
fold=temp_df["fold"].iloc[0] # The fold of the first audio sample for the specific class
sample_name=temp_df["slice_file_name"].iloc[0]
path="data/UrbanSound8K/audio/fold{0}/{1}".format(fold, sample_name)
paths[classes[i]]=path
提取路径后,可以使用此词典显示波图。
for i, label in enumerate(classes):
sample=paths[label]
plt.clf()
plt.title(label)
data, sample_rate=librosa.load(sample)
librosa.display.waveplot(data, sr=sample_rate)
plt.show()
产生以下输出
每个班级的Waveplots。
产生特征
要将音频数据输入模型,必须将其转换为某种数字形式。在ML中音频数据通常会转换为梅尔频率倒谱系数(MFCC)特征向量。librosa软件包用于生成这些系数。此外该视频还提供了对MFCC的深入了解。
# Helper function to generate mfccs
def extract_mfcc(path):
audio, sr=librosa.load(path)
mfccs=librosa.feature.mfcc(audio, sr, n_mfcc=40)
return np.mean(mfccs.T, axis=0)
features=[]
labels=[]
folds=[]
for i in range(len(df)):
fold=df["fold"].iloc[i]
filename=df["slice_file_name"].iloc[i]
path="data/UrbanSound8K/audio/fold{0}/{1}".format(fold, filename)
mfccs=extract_mfcc(path)
features.append(mfccs)
folds.append(fold)
labels.append(df["classID"].iloc[i])
features=torch.tensor(features)
labels=torch.tensor(labels)
folds=torch.tensor(folds)
# Saving the dataset to disk to prevent re-Loading
torch.save(features, "data/features_mfccs.pt")
torch.save(labels, "data/labels.pt")
torch.save(folds, "data/folds.pt")
定义模型
最初定义了两种模型都通用的基类。它主要包括用于为训练数据集和验证数据集计算损失(即模型的预测与实际类别的距离)的函数。
class AudioClassificationBase(nn.Module):
def training_step(self, batch):
images, labels = batch
out = self(images)
loss = F.cross_entropy(out, labels)
return loss
def validation_step(self, batch):
images, labels = batch
out = self(images)
loss = F.cross_entropy(out, labels)
acc = accuracy(out, labels)
return {'val_loss': loss.detach(), 'val_acc': acc}
def validation_epoch_end(self, outputs):
batch_losses = [x['val_loss'] for x in outputs]
epoch_loss = torch.stack(batch_losses).mean()
batch_accs = [x['val_acc'] for x in outputs]
epoch_acc = torch.stack(batch_accs).mean()
return {'val_loss': epoch_loss.item(), 'val_acc': epoch_acc.item()}
模型架构如下:
# Model 1
class UrbanSound8KModel(AudioClassificationBase):
def __init__(self):
super().__init__()
self.network=nn.Sequential(
nn.Linear(input_size,128),
nn.ReLU(),
nn.Linear(128, 64),
nn.ReLU(),
nn.Linear(64,output_size),
nn.Sigmoid()
)
def forward(self, x_batch):
return self.network(x_batch)
# Model 2
class UrbanSound8KModel2(AudioClassificationBase):
def __init__(self):
super().__init__()
self.network=nn.Sequential(
nn.Linear(input_size,128),
nn.ReLU(),
nn.Linear(128, 256),
nn.ReLU(),
nn.Linear(256, 512),
nn.ReLU(),
nn.Linear(512,64),
nn.ReLU(),
nn.Linear(64,output_size),
nn.Tanh()
)
def forward(self, xb):
return self.network(xb)
model=UrbanSound8KModel()
model2=UrbanSound8KModel2()
为了更快地进行训练,将模型与数据集一起移至GPU(图形处理单元)。请注意这仅在安装了cuda工具包的Nvidia GPU上有效。或者可以使用Kaggle部署其ML模型。Kaggle提供了基于云的GPU,每周可使用30个小时。
def get_default_device():
if torch.cuda.is_available():
return torch.device("cuda")
return torch.device("cpu")
device=get_default_device()
device
# Function to move data to the chosen default device
def to_device(data, device):
if isinstance(data, (list,tuple)):
return [to_device(x, device) for x in data]
return data.to(device, non_blocking=True)
# Defining an instance that moves all the tensors (DataLoaders) into the default device
class DeviceDataLoader():
def __init__(self, dl, device):
self.dl = dl
self.device = device
def __iter__(self):
for b in self.dl:
yield to_device(b, self.device)
def __len__(self):
return len(self.dl)
所以现在模型看起来像这样
UrbanSound8KModel(
(network): Sequential(
(0): Linear(in_features=40, out_features=128, bias=True)
(1): ReLU()
(2): Linear(in_features=128, out_features=64, bias=True)
(3): ReLU()
(4): Linear(in_features=64, out_features=10, bias=True)
(5): Sigmoid()
)
)
UrbanSound8KModel2(
(network): Sequential(
(0): Linear(in_features=40, out_features=128, bias=True)
(1): ReLU()
(2): Linear(in_features=128, out_features=256, bias=True)
(3): ReLU()
(4): Linear(in_features=256, out_features=512, bias=True)
(5): ReLU()
(6): Linear(in_features=512, out_features=64, bias=True)
(7): ReLU()
(8): Linear(in_features=64, out_features=10, bias=True)
(9): Tanh()
)
)
在每个模型训练了约50个时期后,第一个模型获得了1.769的验证损失和58%的验证精度。第二个模型产生约1.42的验证损失和约65%的验证精度。
Model 1
Validation loss -> 1.7691158056259155, Validation accuracy -> 0.5827487111091614
Model 2
Validation loss -> 1.4253952503204346, Validation accuracy -> 0.6507228016853333
最后可以将模型保存到磁盘以防止重新训练。
torch.save(model.state_dict(), "outputs/model1.pth")
torch.save(model2.state_dict(), "outputs/model2.pth")
为了重新加载模型,初始化模型的方式类似于初始化新模型,然后运行以下代码
model.load_state_dict(torch.load("outputs/model.pth"))
model2.load_state_dict(torch.load("outputs/model2.pth"))
现在所有指标和超参数均已记录并成功加载回GPU。
结论
虽然这些模型可能不是最先进的架构,但它们可以作为一个人进入机器学习之旅的良好起点。通过实施诸如Dropout和Normalization等正则化技术,可以在更大程度上改善模型。学习率还可以根据“单周期策略”而变化。
代码可以在这里,在jovian.ml这是一个伟大的网站主机和运行jupyter笔记本电脑,登录ML指标等等。
https://jovian.ml/aakashshankar/urbansound8kclassification
推荐阅读
高性能PyTorch是如何炼成的?过来人吐血整理的10条避坑指南
本文分享自微信公众号 - 相约机器人(xiangyuejiqiren)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。
来源:oschina
链接:https://my.oschina.net/u/3267804/blog/4375403