轻量模型之Mobilenet

课程摘要
 1.现有方法:
轻量模型之Mobilenet

2.本文方法:
轻量模型之Mobilenet

 创新点:
轻量模型之Mobilenet
知识树:
轻量模型之Mobilenet
 3.模型结构
轻量模型之Mobilenet
轻量模型之Mobilenet

轻量模型之Mobilenet

轻量模型之Mobilenet

4.深度可分离卷积
轻量模型之Mobilenet

轻量模型之Mobilenet

轻量模型之Mobilenet

 5.超参数

轻量模型之Mobilenet

轻量模型之Mobilenet

轻量模型之Mobilenet

  6.MobileNet后续改进地方:

MobileNetV2:
轻量模型之Mobilenet
轻量模型之Mobilenet
轻量模型之Mobilenet

   MobileNetV3:
轻量模型之Mobilenet
轻量模型之Mobilenet
轻量模型之Mobilenet
三种模型对比:
轻量模型之Mobilenet

 


作业
1.推导:MobileNets中的深度可分离卷积与标准卷积的算力消耗之比?

(input feature: FxFxC, kernel size: KxKxCxM, padding=same)

标准卷积的算力消耗:$K \times K \times F \times F \times C \times M$;

深度可分离卷积算力消耗:$(K \times K \times F \times F \times C \times 1) + (F \times F \times C \times M \times 1 \times 1) = (F \times F \times C \times K \times K) + (F \times F \times M \times C)$

消耗比:
$$
\frac{{(F \times F \times C \times K \times K) + (M \times K \times K \times C)}}{{F \times F \times K \times K \times C \times M}} = \frac{1}{M} + \frac{1}{{{F^2}}}
$$

2.代码实践:利用pytorch复现MobileNet 28层网络结构,模型参数设置同论文一致。
主代码:

import argparse
import torch
import numpy as np
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.optim.lr_scheduler import StepLR
from torchvision import datasets, transforms
from torch.autograd import Variable
from torch.utils.data.sampler import SubsetRandomSampler
from sklearn.metrics import accuracy_score
from mobilenets import mobilenet
import pickle
use_cuda = torch.cuda.is_available()



def train(epoch):
    model.train()
    for batch_idx, (data, target) in enumerate(train_loader):
        if use_cuda:
            data, target = data.cuda(), target.cuda()
        data, target = Variable(data), Variable(target)
        #梯度清零
        optimizer.zero_grad()
        output = model(data)
        correct = 0
        pred = output.data.max(1, keepdim=True)[1] # get the index of the max log-probability
        correct += pred.eq(target.data.view_as(pred)).sum()
        loss = criterion(output, target)
        loss.backward()
        accuracy = 100. * correct/ len(output)
        optimizer.step()
        if batch_idx % 1 == 0:
            print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}, Accuracy: {:.2f}'.format(
                epoch, batch_idx * len(data), len(train_loader.dataset),
                100. * batch_idx / len(train_loader), loss.item(), accuracy))
    scheduler.step()


def validate(epoch):
    model.eval()
    valid_loss = 0
    correct = 0
    for data, target in valid_loader:
        if use_cuda:
            data, target = data.cuda(), target.cuda()
        with torch.no_grad():
            data, target = Variable(data), Variable(target)
        output = model(data)
        # .data[0]
        valid_loss += F.cross_entropy(output, target, size_average=False).item()  # sum up batch loss
        pred = output.data.max(1, keepdim=True)[1]  # get the index of the max log-probability
        correct += pred.eq(target.data.view_as(pred)).sum()

    valid_loss /= len(valid_idx)
    accuracy = 100. * correct / len(valid_idx)
    print('\nValidation set: Average loss: {:.4f}, Accuracy: {}/{} ({:.2f}%)\n'.format(
        valid_loss, correct, len(valid_idx),
        100. * correct / len(valid_idx)))
    return valid_loss, accuracy



def test(epoch):
    model.eval()
    test_loss = 0
    correct = 0
    for data, target in test_loader:
        if use_cuda:
            data, target = data.cuda(), target.cuda()
        data, target = Variable(data, volatile=True), Variable(target)
        output = model(data)
        test_loss += F.cross_entropy(output, target, size_average=False).item() # sum up batch loss
        pred = output.data.max(1, keepdim=True)[1] # get the index of the max log-probability
        correct += pred.eq(target.data.view_as(pred)).cpu().sum()

    test_loss /= len(test_loader.dataset)
    print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.2f}%)\n'.format(
        test_loss, correct, len(test_loader.dataset),
        100. * correct / len(test_loader.dataset)))


if __name__ == "__main__":
    dtype = torch.cuda.FloatTensor if use_cuda else torch.FloatTensor
    normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406],std=[0.229, 0.224, 0.225])

    valid_size=0.1


    valid_transform = transforms.Compose([
        transforms.ToTensor(),
        normalize
    ])

    train_transform = transforms.Compose([
        transforms.RandomCrop(32, padding=4),
        transforms.RandomHorizontalFlip(),
        transforms.ToTensor(),
        normalize
    ])



    train_dataset = datasets.CIFAR10(root="cifar10", train=True,download=True, transform=train_transform)

    valid_dataset = datasets.CIFAR10(root="cifar10", train=True,
            download=True, transform=valid_transform)

    num_train = len(train_dataset)
    indices = list(range(num_train))
    split = int(np.floor(valid_size * num_train))


    np.random.seed(42)
    np.random.shuffle(indices)

    train_idx, valid_idx = indices[split:], indices[:split]


    train_sampler = SubsetRandomSampler(train_idx)
    valid_sampler = SubsetRandomSampler(valid_idx)


    train_loader = torch.utils.data.DataLoader(train_dataset,
                batch_size=64, sampler=train_sampler)

    valid_loader = torch.utils.data.DataLoader(valid_dataset,
                batch_size=64, sampler=valid_sampler)


    test_transform = transforms.Compose([
    transforms.ToTensor(), normalize
])

    test_dataset = datasets.CIFAR10(root="cifar10",
                                train=False,
                                download=False,transform=test_transform)

    test_loader = torch.utils.data.DataLoader(test_dataset,
                                          batch_size=64,
                                          shuffle=True)

    model = mobilenet(num_classes=10, large_img=False)
    optimizer = optim.Adam(model.parameters(), lr=0.01)
    scheduler = StepLR(optimizer, step_size=10, gamma=0.5)
    criterion = nn.CrossEntropyLoss()



    for epoch in range(50):
        train(epoch)
        loss, accuracy = validate(epoch)
        test(epoch)

模型代码:

import torch
import torch.nn as nn
use_cuda = torch.cuda.is_available()


class dw_conv(nn.Module):
    def __init__(self, in_dim, out_dim, stride):
        super(dw_conv, self).__init__()
        self.dw_conv_k3 = nn.Conv2d(
            in_dim, out_dim, kernel_size=3, stride=stride, groups=in_dim, bias=False)
        self.bn = nn.BatchNorm2d(out_dim)
        self.relu = nn.ReLU(inplace=True)

    def forward(self, x):
        x = self.dw_conv_k3(x)
        x = self.bn(x)
        x = self.relu(x)
        return x


class point_conv(nn.Module):
    def __init__(self, in_dim, out_dim):
        super(point_conv, self).__init__()
        self.p_conv_k1 = nn.Conv2d(in_dim, out_dim, kernel_size=1, bias=False)
        self.bn = nn.BatchNorm2d(out_dim)
        self.relu = nn.ReLU(inplace=True)

    def forward(self, x):
        x = self.p_conv_k1(x)
        x = self.bn(x)
        x = self.relu(x)
        return x


class MobileNets(nn.Module):

    def __init__(self, num_classes, large_img):
        super(MobileNets, self).__init__()
        self.num_classes = num_classes
        if large_img:
            self.features = nn.Sequential(
                nn.Conv2d(3, 32, kernel_size=3, stride=2),
                nn.ReLU(inplace=True),
                dw_conv(32, 32, 1),
                point_conv(32, 64),
                dw_conv(64, 64, 2),
                point_conv(64, 128),
                dw_conv(128, 128, 1),
                point_conv(128, 128),
                dw_conv(128, 128, 2),
                point_conv(128, 256),
                dw_conv(256, 256, 1),
                point_conv(256, 256),
                dw_conv(256, 256, 2),
                point_conv(256, 512),
                dw_conv(512, 512, 1),
                point_conv(512, 512),
                dw_conv(512, 512, 1),
                point_conv(512, 512),
                dw_conv(512, 512, 1),
                point_conv(512, 512),
                dw_conv(512, 512, 1),
                point_conv(512, 512),
                dw_conv(512, 512, 1),
                point_conv(512, 512),
                dw_conv(512, 512, 2),
                point_conv(512, 1024),
                dw_conv(1024, 1024, 2),
                point_conv(1024, 1024),
                nn.AvgPool2d(7),
            )
        else:
            self.features = nn.Sequential(
                nn.Conv2d(3, 32, kernel_size=3, stride=1),
                nn.ReLU(inplace=True),
                dw_conv(32, 32, 1),
                point_conv(32, 64),
                dw_conv(64, 64, 1),
                point_conv(64, 128),
                dw_conv(128, 128, 1),
                point_conv(128, 128),
                dw_conv(128, 128, 1),
                point_conv(128, 256),
                dw_conv(256, 256, 1),
                point_conv(256, 256),
                dw_conv(256, 256, 1),
                point_conv(256, 512),
                dw_conv(512, 512, 1),
                point_conv(512, 512),
                dw_conv(512, 512, 1),
                point_conv(512, 512),
                dw_conv(512, 512, 1),
                point_conv(512, 512),
                dw_conv(512, 512, 1),
                point_conv(512, 512),
                dw_conv(512, 512, 1),
                point_conv(512, 512),
                dw_conv(512, 512, 1),
                point_conv(512, 1024),
                dw_conv(1024, 1024, 1),
                point_conv(1024, 1024),
                nn.AvgPool2d(4),
            )

        self.fc = nn.Linear(1024, self.num_classes)

    def forward(self, x):
        x = self.features(x)
        x = x.view(-1, 1024)
        x = self.fc(x)
        return x


def mobilenet(num_classes, large_img, **kwargs):

    model = MobileNets(num_classes, large_img, **kwargs)
    if use_cuda:
        model = model.cuda()
    return model

 

上一篇:磁盘配置


下一篇:深度网络的参数量的计算