使用PyTorch实现鸟类音频检测卷积网络模型(下)

本文涉及的产品
模型在线服务 PAI-EAS,A10/V100等 500元 1个月
模型训练 PAI-DLC,5000CU*H 3个月
交互式建模 PAI-DSW,每月250计算时 3个月
简介: 使用PyTorch实现鸟类音频检测卷积网络模型

模型

我为我的模型设置了必要的辅助函数,以便以后进行训练:

class ModelBase(nn.Module):
    # defines mechanism when training each batch in dl
    def train_step(self, batch):
        xb, labels = batch
        outs = self(xb)
        loss = F.cross_entropy(outs, labels)
        return loss
    # similar to `train_step`, but includes acc calculation & detach
    def val_step(self, batch):
        xb, labels = batch
        outs = self(xb)
        loss = F.cross_entropy(outs, labels)
        acc = accuracy(outs, labels)
        return {'loss': loss.detach(), 'acc': acc.detach()}
    # average out losses & accuracies from validation epoch
    def val_epoch_end(self, outputs):
        batch_loss = [x['loss'] for x in outputs]
        batch_acc = [x['acc'] for x in outputs]
        avg_loss = torch.stack(batch_loss).mean()
        avg_acc = torch.stack(batch_acc).mean()
        return {'avg_loss': avg_loss, 'avg_acc': avg_acc}
    # print all data once done
    def epoch_end(self, epoch, avgs, test=False):
        s = 'test' if test else 'val'
        print(f'Epoch #{epoch + 1}, {s}_loss:{avgs["avg_loss"]}, {s}_acc:{avgs["avg_acc"]}')

定义多个函数,以后可以使用这些函数训练继承这个类的PyTorch模型。


def accuracy(outs, labels):
    _, preds = torch.max(outs, dim=1)
    return torch.tensor(torch.sum(preds == labels).item() / len(preds))

这个函数在上述类的val_step函数中被用来确定验证dataloader上模型的%准确性。

并定义用于拟合/训练模型和在验证数据集上测试模型的主要功能

@torch.no_grad()
def evaluate(model, val_dl):
    # eval mode
    model.eval()
    outputs = [model.val_step(batch) for batch in val_dl]
    return model.val_epoch_end(outputs)
def fit(epochs, lr, model, train_dl, val_dl, opt_func=torch.optim.Adam):
    torch.cuda.empty_cache()
    history = []
    # define optimizer
    optimizer = opt_func(model.parameters(), lr)
    # for each epoch...
    for epoch in range(epochs):
        # training mode
        model.train()
        # (training) for each batch in train_dl...
        for batch in tqdm(train_dl):
            # pass thru model
            loss = model.train_step(batch)
            # perform gradient descent
            loss.backward()
            optimizer.step()
            optimizer.zero_grad()
        # validation
        res = evaluate(model, val_dl)
        # print everything useful
        model.epoch_end(epoch, res, test=False)
        # append to history
        history.append(res)
    return history

最后,这是我们等待已久的简单CNN模型:

class Classifier(ModelBase):
    def __init__(self):
        super().__init__()                                     # 1 x 128 x 24
        self.conv1 = nn.Conv2d(1, 4, kernel_size=3, padding=1) # 4 x 128 x 24
        self.conv2 = nn.Conv2d(4, 8, kernel_size=3, padding=1) # 8 x 128 x 24
        self.bm1 = nn.MaxPool2d(2)                             # 8 x 64 x 12
        self.conv3 = nn.Conv2d(8, 8, kernel_size=3, padding=1) # 8 x 64 x 12
        self.bm2 = nn.MaxPool2d(2)                             # 8 x 32 x 6
        self.fc1 = nn.Linear(8*32*6, 64)
        self.fc2 = nn.Linear(64, 2)
    def forward(self, xb):
        out = F.relu(self.conv1(xb))
        out = F.relu(self.conv2(out))
        out = self.bm1(out)
        out = F.relu(self.conv3(out))
        out = self.bm2(out)
        out = torch.flatten(out, 1)
        out = F.relu(self.fc1(out))
        out = self.fc2(out)
        return out

我使用了多个卷积层,正如我们之前的理论推断所建议的那样,我们的模型使用了一些最大池化层,然后使用一个非常简单的全连接网络来进行实际的分类。令人惊讶的是,这个架构后来表现得相当好,甚至超过了我自己的预期。

利用GPU

几乎每个人都需要GPU来训练比一般的前馈神经网络更复杂的东西。幸运的是,PyTorch让我们可以很容易地利用现有GPU的能力。首先,我们将我们的cuda设备定义为关键词设备,以便更容易访问:

device = 'cuda' if torch.cuda.is_available() else 'cpu'

 

我们还确保如果没有GPU, CPU会被使用。

这里还有另一个技巧:

torch.backends.cudnn.benchmark = True

这可以帮助提高你的训练速度(如果你的输入在大小/形状上没有变化)

显然,你可以“告诉”PyTorch在一次又一次的训练中优化自己,只要训练输入在大小和形状上保持不变。它会知道为你的特定硬件(GPU)使用最快的算法。!

然后我们定义帮助函数来移动dataloaders、tensors和我们的模型到我们的GPU设备。

def to_device(data, device):
    """Move tensor(s) to chosen device"""
    if isinstance(data, (list, tuple)):
        return [to_device(x, device) for x in data]
    return data.to(device, non_blocking=True)
class DeviceDataLoader():
    """Wrap a dataloader to move data to a device"""
    def __init__(self, dl, device):
        self.dl = dl
        self.device = device
    def __iter__(self):
        """Yield a batch of data after moving it to device"""
        for b in self.dl:
            yield to_device(b, self.device)
    def __len__(self):
        """Number of batches"""
        return len(self.dl)

训练

使用我们的设备辅助功能,我们将一切移动到我们的GPU如下:

train_dl = DeviceDataLoader(train_dl, device)
val_dl = DeviceDataLoader(val_dl, device)
model = to_device(Classifier(), device)

我们还指定了我们的学习速度和我们的训练次数,我花了很长时间来找到一个好的值。

lr = 1e-5
epochs = 8

在进行任何训练之前,我们会发现模型的表现:

history = [evaluate(model, val_dl)]
[{'avg_loss': tensor(0.7133, device='cuda:0'), 'avg_acc': tensor(0.6042)}]

很显然,我们在开始时的准确性上有点幸运,但经过多次试验,最终结果即使不相同,也会非常相似。

接下来,我们使用之前定义的fit函数来训练我们的简单分类器模型实例:

history += fit(epochs, lr, model, train_dl, val_dl)
HBox(children=(FloatProgress(value=0.0, max=352.0), HTML(value='')))
 Epoch #1, val_loss:0.6354132294654846, val_acc:0.7176136374473572
HBox(children=(FloatProgress(value=0.0, max=352.0), HTML(value='')))
 Epoch #2, val_loss:0.6065077781677246, val_acc:0.7439352869987488
HBox(children=(FloatProgress(value=0.0, max=352.0), HTML(value='')))
 Epoch #3, val_loss:0.56722491979599, val_acc:0.77376788854599
HBox(children=(FloatProgress(value=0.0, max=352.0), HTML(value='')))
 Epoch #4, val_loss:0.5528884530067444, val_acc:0.7751822471618652
HBox(children=(FloatProgress(value=0.0, max=352.0), HTML(value='')))
 Epoch #5, val_loss:0.5130119323730469, val_acc:0.8004600405693054
HBox(children=(FloatProgress(value=0.0, max=352.0), HTML(value='')))
 Epoch #6, val_loss:0.4849482774734497, val_acc:0.8157732486724854
HBox(children=(FloatProgress(value=0.0, max=352.0), HTML(value='')))
 Epoch #7, val_loss:0.4655478596687317, val_acc:0.8293880224227905
HBox(children=(FloatProgress(value=0.0, max=352.0), HTML(value='')))
 Epoch #8, val_loss:0.4765000343322754, val_acc:0.8155447244644165

在发现精确度有一点下降后,我决定再训练一点点,让模型重定向回到正确的方向:

history += fit(3, 1e-6, model, train_dl, val_dl)
HBox(children=(FloatProgress(value=0.0, max=352.0), HTML(value='')))
 Epoch #1, val_loss:0.4524107873439789, val_acc:0.8329823613166809
HBox(children=(FloatProgress(value=0.0, max=352.0), HTML(value='')))
 Epoch #2, val_loss:0.44666698575019836, val_acc:0.8373703360557556
HBox(children=(FloatProgress(value=0.0, max=352.0), HTML(value='')))
 Epoch #3, val_loss:0.4442901611328125, val_acc:0.8412765860557556

忽略“HBox”工件,这是tqdm提供的,请多关注准确性!

总结一下,以下是我们过去11个时期的训练统计数据:

plt.plot([x['avg_loss'] for x in history])
plt.title('Losses over epochs')
plt.xlabel('epochs')
plt.ylabel('loss')
plt.show()

640.png

plt.plot([x['avg_acc'] for x in history])
plt.title('Accuracy over epochs')
plt.xlabel('epochs')
plt.ylabel('acc')
plt.show()

640.png

总的来说,我们的模型训练得相当好,从它的外观来看,我们可能已经为我们的模型的损失找到了一个相对最小的值。

等等,一个更复杂的模型或者使用不同的转换怎么样?

相信我,在我的simple Classifier()第一次尝试成功之后不久,我也尝试过这两种方法。我决定不包括这两个细节,因为我发现他们的结果实际上比我们已经取得的结果更糟糕,这很奇怪。

对于额外的谱图转换,我尝试了随机时移和噪声注入。长话短说,它似乎根本没有提高验证的准确性。此后,我认为是这样,因为数据集规范明确表示,所有啾啾将位于中间的录音,因此随机变化的光谱图的目的允许更好的模型泛化实际上可能已经作为损害的表现。然而,我还没有尝试过随机噪声注入。

我还尝试训练一个ResNet50模型,希望进一步提高验证的准确性。这是最令人难以置信的部分:我的模型从来没有超过50%的准确率!直到今天我写这篇文章的时候,我还不确定我做错了什么,所以如果其他人能看看笔记本并帮助我,我很高兴收到任何建议!

结论

总而言之,这是一个真正有趣的努力,花一些时间进行研究。首先,我得重新审视我去年夏天调查过的东西,无可否认,这有一种怀旧的感觉。更重要的是,我们学习了如何实现一个很可能用于真实场景的PyTorch数据集类,在真实场景中,数据不一定像您预期的那样设置。最后,最终的验证分数为84%,对于我即兴创建的如此简单的网络架构来说,这是相当整洁的!

相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
目录
相关文章
|
3天前
|
机器学习/深度学习 人工智能 算法
猫狗宠物识别系统Python+TensorFlow+人工智能+深度学习+卷积网络算法
宠物识别系统使用Python和TensorFlow搭建卷积神经网络,基于37种常见猫狗数据集训练高精度模型,并保存为h5格式。通过Django框架搭建Web平台,用户上传宠物图片即可识别其名称,提供便捷的宠物识别服务。
92 55
|
12天前
|
机器学习/深度学习 人工智能 算法
【宠物识别系统】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+图像识别
宠物识别系统,本系统使用Python作为主要开发语言,基于TensorFlow搭建卷积神经网络算法,并收集了37种常见的猫狗宠物种类数据集【'阿比西尼亚猫(Abyssinian)', '孟加拉猫(Bengal)', '暹罗猫(Birman)', '孟买猫(Bombay)', '英国短毛猫(British Shorthair)', '埃及猫(Egyptian Mau)', '缅因猫(Maine Coon)', '波斯猫(Persian)', '布偶猫(Ragdoll)', '俄罗斯蓝猫(Russian Blue)', '暹罗猫(Siamese)', '斯芬克斯猫(Sphynx)', '美国斗牛犬
83 29
【宠物识别系统】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+图像识别
|
16天前
|
机器学习/深度学习 资源调度 算法
图卷积网络入门:数学基础与架构设计
本文系统地阐述了图卷积网络的架构原理。通过简化数学表述并聚焦于矩阵运算的核心概念,详细解析了GCN的工作机制。
43 3
图卷积网络入门:数学基础与架构设计
|
12天前
|
机器学习/深度学习 人工智能 自然语言处理
深入理解深度学习中的卷积神经网络(CNN)##
在当今的人工智能领域,深度学习已成为推动技术革新的核心力量之一。其中,卷积神经网络(CNN)作为深度学习的一个重要分支,因其在图像和视频处理方面的卓越性能而备受关注。本文旨在深入探讨CNN的基本原理、结构及其在实际应用中的表现,为读者提供一个全面了解CNN的窗口。 ##
|
22天前
|
机器学习/深度学习 人工智能 自然语言处理
深度学习中的卷积神经网络(CNN): 从理论到实践
本文将深入浅出地介绍卷积神经网络(CNN)的工作原理,并带领读者通过一个简单的图像分类项目,实现从理论到代码的转变。我们将探索CNN如何识别和处理图像数据,并通过实例展示如何训练一个有效的CNN模型。无论你是深度学习领域的新手还是希望扩展你的技术栈,这篇文章都将为你提供宝贵的知识和技能。
71 7
|
19天前
|
机器学习/深度学习 自然语言处理 算法
深入理解深度学习中的卷积神经网络(CNN)
深入理解深度学习中的卷积神经网络(CNN)
27 1
|
25天前
|
机器学习/深度学习 人工智能 自然语言处理
深度学习中的卷积神经网络(CNN)及其在图像识别中的应用
本文旨在通过深入浅出的方式,为读者揭示卷积神经网络(CNN)的神秘面纱,并展示其在图像识别领域的实际应用。我们将从CNN的基本概念出发,逐步深入到网络结构、工作原理以及训练过程,最后通过一个实际的代码示例,带领读者体验CNN的强大功能。无论你是深度学习的初学者,还是希望进一步了解CNN的专业人士,这篇文章都将为你提供有价值的信息和启发。
|
22天前
|
机器学习/深度学习 人工智能 自然语言处理
探索深度学习中的卷积神经网络(CNN)及其在现代应用中的革新
探索深度学习中的卷积神经网络(CNN)及其在现代应用中的革新
|
26天前
|
机器学习/深度学习 人工智能 网络架构
深入理解深度学习中的卷积神经网络(CNN)
深入理解深度学习中的卷积神经网络(CNN)
39 1
|
28天前
|
机器学习/深度学习 人工智能 算法框架/工具
深度学习中的卷积神经网络(CNN)入门
【10月更文挑战第41天】在人工智能的璀璨星空下,卷积神经网络(CNN)如一颗耀眼的新星,照亮了图像处理和视觉识别的路径。本文将深入浅出地介绍CNN的基本概念、核心结构和工作原理,同时提供代码示例,带领初学者轻松步入这一神秘而又充满无限可能的领域。

热门文章

最新文章