EfficientNet 训练测试自己的分类数据集

EfficientNet 训练测试自己的分类数据集

Google团队19年的EfficientNetEfficientDet图像分类目标检测方面都取得了惊艳的效果。EfficientNet既快又准,目测这两年将会成为比ResNet更广泛使用的Backbone。下面简单介绍在自己的分类数据集上运行EfficientNet。

1. 准备代码

Pytorch版本官方代码在这:EfficientNet-Pytorch
为了方便,你也可以下载这个完整代码:Code 来更快知道如何使用。

2. 准备数据集

数据集的文件位置大概是这样:

  • dataset_name
    • model
    • train
      • 1
      • 2
    • test
      • 1
      • 2

为了便于理解,我提供了一个OxFlower17公开的花卉数据集,转换好格式供参考:

百度云链接: https://pan.baidu.com/s/1oBqSMuyuYmiCg7LVbqUtAQ
密码: cf19

3. 准备权重

这一步在完整代码里可以自行选择何种方式加载权重

(1)自动下载
model_ft = EfficientNet.from_pretrained('efficientnet-b0')
(2)手动下载
net_name = 'efficientnet-b0'
model_ft = EfficientNet.from_name(net_name)
net_weight = 'eff_weights/' + 'efficientnet-b0-355c32eb.pth'
state_dict = torch.load(net_weight)
model_ft.load_state_dict(state_dict)

4. 训练测试完整代码

修改最前面的一些参数符合你的数据集即可,另外需要根据你是使用git工程还是pip安装库决定EfficientNet的导入方式,代码里面已经标了一下程序会自动保存最好的结果,并在最后进行测试

from __future__ import print_function, division

import torch
import torch.nn as nn
import torch.optim as optim
from torch.autograd import Variable
from torchvision import datasets, models, transforms
import time
import os
# 如果使用上面的Git工程的话这样导入
# from efficientnet.model import EfficientNet
# 如果使用pip安装的Efficient的话这样导入
from efficientnet_pytorch import EfficientNet

# some parameters
use_gpu = torch.cuda.is_available()
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
data_dir = 'Flowers'
batch_size = 64
lr = 0.01
momentum = 0.9
num_epochs = 60
input_size = 224
class_num = 17
net_name = 'efficientnet-b0'


def loaddata(data_dir, batch_size, set_name, shuffle):
    data_transforms = {
        'train': transforms.Compose([
            transforms.Resize(input_size),
            transforms.CenterCrop(input_size),
            transforms.RandomAffine(degrees=0, translate=(0.05, 0.05)),
            transforms.RandomHorizontalFlip(),
            transforms.ToTensor(),
            transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
        ]),
        'test': transforms.Compose([
            transforms.Resize(input_size),
            transforms.CenterCrop(input_size),
            transforms.ToTensor(),
            transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
        ]),
    }

    image_datasets = {x: datasets.ImageFolder(os.path.join(data_dir, x), data_transforms[x]) for x in [set_name]}
    # num_workers=0 if CPU else =1
    dataset_loaders = {x: torch.utils.data.DataLoader(image_datasets[x],
                                                      batch_size=batch_size,
                                                      shuffle=shuffle, num_workers=1) for x in [set_name]}
    data_set_sizes = len(image_datasets[set_name])
    return dataset_loaders, data_set_sizes


def train_model(model_ft, criterion, optimizer, lr_scheduler, num_epochs=50):
    train_loss = []
    since = time.time()
    best_model_wts = model_ft.state_dict()
    best_acc = 0.0
    model_ft.train(True)
    for epoch in range(num_epochs):
        dset_loaders, dset_sizes = loaddata(data_dir=data_dir, batch_size=batch_size, set_name='train', shuffle=True)
        print('Data Size', dset_sizes)
        print('Epoch {}/{}'.format(epoch, num_epochs - 1))
        print('-' * 10)
        optimizer = lr_scheduler(optimizer, epoch)

        running_loss = 0.0
        running_corrects = 0
        count = 0

        for data in dset_loaders['train']:
            inputs, labels = data
            labels = torch.squeeze(labels.type(torch.LongTensor))
            if use_gpu:
                inputs, labels = Variable(inputs.cuda()), Variable(labels.cuda())
            else:
                inputs, labels = Variable(inputs), Variable(labels)

            outputs = model_ft(inputs)
            loss = criterion(outputs, labels)
            _, preds = torch.max(outputs.data, 1)

            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

            count += 1
            if count % 30 == 0 or outputs.size()[0] < batch_size:
                print('Epoch:{}: loss:{:.3f}'.format(epoch, loss.item()))
                train_loss.append(loss.item())

            running_loss += loss.item() * inputs.size(0)
            running_corrects += torch.sum(preds == labels.data)

        epoch_loss = running_loss / dset_sizes
        epoch_acc = running_corrects.double() / dset_sizes

        print('Loss: {:.4f} Acc: {:.4f}'.format(
            epoch_loss, epoch_acc))

        if epoch_acc > best_acc:
            best_acc = epoch_acc
            best_model_wts = model_ft.state_dict()
        if epoch_acc > 0.999:
            break

    # save best model
    save_dir = data_dir + '/model'
    os.makedirs(save_dir, exist_ok=True)
    model_ft.load_state_dict(best_model_wts)
    model_out_path = save_dir + "/" + net_name + '.pth'
    torch.save(model_ft, model_out_path)

    time_elapsed = time.time() - since
    print('Training complete in {:.0f}m {:.0f}s'.format(
        time_elapsed // 60, time_elapsed % 60))

    return train_loss, best_model_wts


def test_model(model, criterion):
    model.eval()
    running_loss = 0.0
    running_corrects = 0
    cont = 0
    outPre = []
    outLabel = []
    dset_loaders, dset_sizes = loaddata(data_dir=data_dir, batch_size=16, set_name='test', shuffle=False)
    for data in dset_loaders['test']:
        inputs, labels = data
        labels = torch.squeeze(labels.type(torch.LongTensor))
        inputs, labels = Variable(inputs.cuda()), Variable(labels.cuda())
        outputs = model(inputs)
        _, preds = torch.max(outputs.data, 1)
        loss = criterion(outputs, labels)
        if cont == 0:
            outPre = outputs.data.cpu()
            outLabel = labels.data.cpu()
        else:
            outPre = torch.cat((outPre, outputs.data.cpu()), 0)
            outLabel = torch.cat((outLabel, labels.data.cpu()), 0)
        running_loss += loss.item() * inputs.size(0)
        running_corrects += torch.sum(preds == labels.data)
        cont += 1
    print('Loss: {:.4f} Acc: {:.4f}'.format(running_loss / dset_sizes,
                                            running_corrects.double() / dset_sizes))


def exp_lr_scheduler(optimizer, epoch, init_lr=0.01, lr_decay_epoch=10):
    """Decay learning rate by a f#            model_out_path ="./model/W_epoch_{}.pth".format(epoch)
#            torch.save(model_W, model_out_path) actor of 0.1 every lr_decay_epoch epochs."""
    lr = init_lr * (0.8**(epoch // lr_decay_epoch))
    print('LR is set to {}'.format(lr))
    for param_group in optimizer.param_groups:
        param_group['lr'] = lr

    return optimizer


# train
pth_map = {
    'efficientnet-b0': 'efficientnet-b0-355c32eb.pth',
    'efficientnet-b1': 'efficientnet-b1-f1951068.pth',
    'efficientnet-b2': 'efficientnet-b2-8bb594d6.pth',
    'efficientnet-b3': 'efficientnet-b3-5fb5a3c3.pth',
    'efficientnet-b4': 'efficientnet-b4-6ed6700e.pth',
    'efficientnet-b5': 'efficientnet-b5-b6417697.pth',
    'efficientnet-b6': 'efficientnet-b6-c76e70fd.pth',
    'efficientnet-b7': 'efficientnet-b7-dcc49843.pth',
}
# 自动下载到本地预训练
# model = EfficientNet.from_pretrained('efficientnet-b0')
# 离线加载预训练,需要事先下载好
model_ft = EfficientNet.from_name(net_name)
net_weight = 'eff_weights/' + pth_map[net_name]
state_dict = torch.load(net_weight)
model_ft.load_state_dict(state_dict)

# 修改全连接层
num_ftrs = model_ft._fc.in_features
model_ft._fc = nn.Linear(num_ftrs, class_num)

criterion = nn.CrossEntropyLoss()
if use_gpu:
    model_ft = model_ft.cuda()
    criterion = criterion.cuda()

optimizer = optim.SGD((model_ft.parameters()), lr=lr,
                      momentum=momentum, weight_decay=0.0004)

train_loss, best_model_wts = train_model(model_ft, criterion, optimizer, exp_lr_scheduler, num_epochs=num_epochs)

# test
print('-' * 10)
print('Test Accuracy:')
model_ft.load_state_dict(best_model_wts)
criterion = nn.CrossEntropyLoss().cuda()
test_model(model_ft, criterion)

5. 实验结果

没怎么调参,粗略地跑了一下:

Network# ParamsAccuracy
resnet-5025.6M95.88
resnet-10144.5M97.35
efficientnet-b05.3M95.29
efficientnet-b17.8M97.94
efficientnet-b29.2M98.24
efficientnet-b312M98.24
efficientnet-b419M98.24

结果确实出彩,参数量比Resnet少性能却依旧强劲!

  • 20
    点赞
  • 156
    收藏
    觉得还不错? 一键收藏
  • 111
    评论
### 回答1: 要使用EfficientNet训练自己的数据,您需要遵循以下步骤: 1. 准备数据集:收集和准备您的数据集,确保它们符合您的需求和标准。 2. 数据预处理:对数据进行预处理,包括图像增强、数据增强、数据划分等。 3. 构建模型:使用EfficientNet模型作为基础模型,根据您的需求和数据集进行微调和修改。 4. 训练模型:使用训练数据集对模型进行训练,并使用验证数据集进行验证和调整。 5. 测试模型:使用测试数据集对模型进行测试和评估。 6. 模型优化:根据测试结果对模型进行优化和改进,以提高模型的准确性和效率。 以上是训练自己数据集的一般步骤,具体实现需要根据您的具体情况进行调整和修改。 ### 回答2: EfficientNet是一种高效的神经网络架构,可用于训练自己的数据。它采用了一系列的网络结构扩展方式,通过提高网络的深度、宽度和分辨率来提升性能。 首先,为了训练自己的数据集,我们需要准备数据。将数据集划分为训练集和验证集,并对数据进行标注和预处理,以便让模型能够更好地学习。预处理可能包括图像增强和数据扩充等操作,以增加数据的多样性。 接下来,我们需要下载预训练的EfficientNet模型权重。这些权重可以作为预训练模型的初始参数,迁移到我们的数据集上进行微调。这样可以在有限的数据集上获得更好的性能。 然后,将自己的数据集输入EfficientNet模型进行训练。使用合适的优化算法如随机梯度下降(SGD)或自适应矩估计(Adam),根据训练集的样本进行反向传播和参数更新。同时,使用验证集评估模型的性能,避免过拟合。 在训练过程中,可以使用学习率衰减策略来调整学习率,以提高训练的稳定性和效果。此外,还可以在训练过程中使用正则化技术,如Dropout或L2正则化,以防止过拟合。 当训练达到预定的停止条件时,可以保存模型并使用测试集进行性能评估。测试集应与训练集和验证集相互独立,以确保模型的泛化能力。 最后,根据模型在测试集上的性能,可以进行模型调整、超参数调优等进一步优化工作,以获得更好的结果。 总之,使用EfficientNet训练自己的数据需要准备数据集、下载预训练权重、迁移到自己的数据集上进行微调、选择优化算法、进行训练和验证、调整超参数等步骤。通过这些步骤,就可以以高效的方式训练自己的数据。 ### 回答3: 要训练自己的数据集,可以使用EfficientNet这个强大的模型。首先,需要确保数据集已经准备好,并且正确地标注了每个样本。接下来,根据数据集的大小和复杂度,选择合适的EfficientNet模型版本,如EfficientNet-B0到EfficientNet-B7。 然后,根据数据集的情况,调整EfficientNet模型的超参数和训练参数。例如,可以调整学习率、批大小和训练轮数等参数,以获得更好的训练效果。 在训练过程中,可以使用一些常见的数据增强技术,如旋转、平移、裁剪和翻转等,来增加数据集的多样性和数量。这样可以提高模型的泛化能力和稳定性。 为了训练EfficientNet模型,可以使用流行的深度学习框架,如TensorFlow或PyTorch。使用这些框架可以方便地定义模型结构、加载数据集和进行模型训练。 在训练过程中,可以监控模型的训练损失和验证准确率等指标,以便了解模型的训练进展。如果发现模型出现过拟合或欠拟合等问题,可以尝试调整超参数或增加更多的训练数据来改善模型效果。 当模型训练完成后,可以使用测试集对模型进行评估,并计算模型的准确率、精确率、召回率和F1分数等指标。根据评估结果,可以进一步调整模型和训练策略,以获得更好的性能。 最后,可以使用训练好的EfficientNet模型对新的未知样本进行预测。将样本输入到模型中,即可得到相应的分类结果。 总而言之,EfficientNet是一个强大的模型,可以通过调整超参数和训练策略来训练自己的数据集。通过不断优化和改进,可以获得准确性高并且泛化能力强的模型。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 111
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值