首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Pytorch的十二生肖分类挑战

Pytorch的十二生肖分类挑战

作者头像
代码医生工作室
发布2020-02-19 16:43:53
发布2020-02-19 16:43:53
1.4K00
代码可运行
举报
文章被收录于专栏:相约机器人相约机器人
运行总次数:0
代码可运行

作者 | M. Rake Linggar A

来源 | Medium

编辑 | 代码医生团队

在贝塔斯曼AI Udacity奖学金中,学者们不仅必须完成AI Udacity课程,而且还相互挑战,以应用在课程中收集和实践的技能和知识。这些挑战之一是中国十二生肖分类挑战。马上就是中国农历新年之际。

中国的十二生肖分为十二个年度周期,每年由特定的动物识别。

对于那些想尝试这一挑战的人,可以在此处获取数据。

https://drive.google.com/file/d/1Bjope31ZX9p4jXyaYK6CazIOGcYhOjI6/view

搭建环境

首先是使用GPU会使任务变得更容易,因此尝试同时使用Google Colab和Kaggle Notebook来构建此模型。但是由于希望能够编辑(添加,更改,移动或删除)数据,因此更喜欢使用Google Colab,因为数据存储在Google云端硬盘中。

加载并检查数据

有12类图像,希望对Pytorch模型进行分类。将数据分为三类是一个好主意,即用于训练模型的训练数据,用于确保模型不会过拟合的验证和测试数据。

首先检查这些数据的分布。

代码语言:javascript
代码运行次数:0
运行
复制
for dirname, _, filenames in os.walk('./signs/'):
    print("{0} \t-\t {1}".format(dirname, len(filenames)))

十二生肖图像分布

对于每次训练,都有600幅训练图像(简称goat),54幅验证图像(代表一张goat,这很可能是因为一幅图像放错了位置)以及54-55张测试图像。

看一下这些图像的样本。

样本图片

对来说也很好。还可以看到,也在合并绘图图像(因为龙不存在,也不全是)。

使用Pytorch创建模型

Pytorch(以及其他机器学习/深度学习框架)的优点之一是它提供了简化的样板代码。其中之一是加载训练测试数据。

代码语言:javascript
代码运行次数:0
运行
复制
data_dir = 'signs'
 
batch_size = 32
 
train_transforms = transforms.Compose([transforms.Resize([224,224]),
                                        transforms.RandomHorizontalFlip(0.5),
                                        transforms.ToTensor(),
                                        transforms.Normalize([0.5, 0.5, 0.5],
                                        [0.5, 0.5, 0.5])])
 
val_transforms = transforms.Compose([transforms.Resize([224,224]),
                                        transforms.ToTensor(),
                                        transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])])
 
test_transforms = transforms.Compose([transforms.Resize([224,224]),
                                        transforms.ToTensor(),
                                        transforms.Normalize([0.5, 0.5, 0.5],
                                        [0.5, 0.5, 0.5])])
 
train_data = datasets.ImageFolder(data_dir + '/train', transform=train_transforms)
valid_data = datasets.ImageFolder(data_dir + '/valid', transform=test_transforms)
test_data = datasets.ImageFolder(data_dir + '/test', transform=test_transforms)
 
 
trainloader = torch.utils.data.DataLoader(train_data, batch_size=batch_size, shuffle=True, num_workers=4)
validloader = torch.utils.data.DataLoader(valid_data, batch_size=batch_size, num_workers=4)
testloader = torch.utils.data.DataLoader(test_data, batch_size=batch_size, shuffle=True, num_workers=4)

现在建立模型。

将使用经过预训练的Resnet34模型来转移其学习内容,以建立此分类模型。还尝试了其他经过预训练的模型,例如带有BatchNorm的Resnet101和VGG 19,但是Resnet34提供了相当不错的性能,因此继续这样做。Resnet34要求输入图像的宽度和高度为224。

完整的模型架构如下。

代码语言:javascript
代码运行次数:0
运行
复制
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = models.resnet34(pretrained=True)
 
for param in model.parameters():
    param.requires_grad = False
    
model.fc = nn.Sequential(nn.Linear(512, 512),
                                 nn.ReLU(),
                                 nn.Dropout(0.2),
                                 nn.Linear(512, 12),
                                 nn.LogSoftmax(dim=1))
criterion = nn.NLLLoss()
optimizer = optim.Adam(model.fc.parameters(), lr=0.003)
model.to(device)

在这里不会使用任何非常复杂的东西。仅有两个额外的FC层,每个层具有512个神经元,而一个输出层则具有12个神经元(当然,每个生肖类都有一个)。

训练模型

现在是第一个令人兴奋的部分,训练模型。

只需要在(a)对模型进行正向和反向传递,以及(b)测量模型的当前/运行性能的同时遍历训练数据加载器。选择每100小批处理一次(b)。

选择在7-15个时期内训练模型。将在下面的图表中看到原因。

训练和验证的损失和准确性(Resnet50试用1)

在每100次小批量通过中,该模型肯定会随着时间的推移在训练数据集上得到改善。但是查看验证数据集上的性能时,它似乎并没有改善太多(尽管精度似乎随时间而提高了一点,但认为这还不够)。

但是当查看具有不同体系结构的其他模型时,会发生相同的事情。

训练和验证的损失和准确性(Resnet50试用2)

训练和验证损失与准确性(具有批处理规范的VGG 19)

第二个模型使用Resnet50,与第一个模型几乎相同,除了将学习率从0.001更改为0.003。第三是将VGG 19与Batch Norm一起使用,学习率为0.001。

三种不同的模型和参数说明了同样的情况-经过多次训练后,验证的准确性性能并没有显着提高(尤其是对于后两种模型)。

对模型的损失并不太担心,因为它只是衡量模型表现的“可信度”的一种量度,将更多的精力放在准确性上。

测试模型

看看模型是否真的好,或者满足测试数据集而破裂。

代码语言:javascript
代码运行次数:0
运行
复制
test_acc = 0.0
test_datas = 0.0
running_test_loss = 0.0
 
model.eval()
 
for i_v, data_v in enumerate(testloader):
  i_, l_ = data_v
  inputs = i_.to(device)
  labels = l_.to(device)
  outputs = model(inputs)
  loss = criterion(outputs, labels)
  running_test_loss += loss.item()
 
  _, prediction = torch.max(outputs.data, 1)
  test_acc += torch.sum(prediction == labels.data).item()
  test_datas += prediction.shape[0]
 
print('Test model\ttest loss: %.3f\t---test acc: %.3f' %
      ( running_test_loss / len(testloader),  test_acc / test_datas ))
  • ResNet(lr 0.001)-损失:0.355 acc:90.5%
  • ResNet(lr 0.003)—损失:0.385 acc:90.6%
  • 具有批处理标准的VGG 19-损失:0.586 acc:90.8%

从准确性上看,它们几乎相同。对于损失,最高为0.001 lr的ResNet占统治地位。这些数字与训练和验证几乎相同,因此可以说模型并不过分(或者至少在小时期之前就停止了),并且可以很好地对生肖进行分类。

很好奇,关于哪个图像问题最多。

混淆矩阵

可以看到,该模型很少会误认为山羊,但是如果出现这种情况,它总是带有ox(角)。

山羊图像被模型误认为是牛

还可以看到,该模型dragon与其他生肖相比较有一些困难。最值得注意的是oxes (角)和snake(身体)。

写在最后

在贝塔斯曼AI Udacity奖学金期间,中国生肖标志分类挑战的工作真是令人耳目一新。它推动并激励着去做爱做的事-在AI /机器学习/深度学习领域进行实验和构建。

可以在Github页面上查看笔记本。

https://github.com/mrakelinggar/zodiac_animal_classification

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-01-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 相约机器人 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档