pytorch 使⽤迁移学习模型MobilenetV2实现猫狗分类
MobilenetV2介绍
⽹络设计是基于MobileNetV1。它保持了简单性,同时显著提⾼了精度,在移动应⽤的多图像分类和检测任务上达到了最新的⽔平。主要贡献是⼀个新的层模块:具有线性瓶颈的倒置残差。该模块将输⼊的低维压缩表⽰⾸先扩展到⾼维并⽤轻量级深度卷积进⾏过滤。随后⽤线性卷积将特征投影回低维表⽰。
MobilenetV2⽹络结构
在介绍MobilenetV2⽹络结构之前需要先了解⼀下⽹络内部的细节。
1. Depthwise Separable Convolutions
深度可分卷积这是⼀种分解卷积的形式,它将⼀个标准卷积分解为深度卷积和⼀个1×1卷积,1x1卷积⼜叫称为点卷积,下图是
MobilenetV1中论⽂的图。
标准的卷积是输⼊⼀个 x x 的特征图,输出⼀个 x x 的特征图。
标准的卷积层的参数是 x x x ,其中是卷积核的⼩⼤,是输⼊通道数,是输出通道数。
所以标准的卷积计算量如下:
x x x x x 深度可分离卷积由两层组成:深度卷积和点卷积。
D F D F M D F D F N D K D K M N D K M N D K D K M N D F D F
resized我们使⽤深度卷积来为每个输⼊通道(输⼊深度)应⽤⼀个过滤器。然后使⽤点态卷积(⼀个简单的1×1卷积)创建深度层输出的线性组合。其计算量为: x x x x 相对于标准卷积,深度卷积是⾮常有效的。然⽽,它只过滤输⼊通道,并没有将它们组合起来创建新的功能。因此,为了⽣成这些新特征,需要⼀个额外的层,通过1 × 1的卷积计算深度卷积输出的线性组合。
其计算量为: x x x 例⼦:
标准卷积:
假设有⼀个56 x 56 x 16的特征图,其卷积核是3 x 3⼤⼩,输出通道为32,计算量⼤⼩就是56 x56 x16 x 32 x 3 x 3 = 14450688深度可分离卷积:
假设有⼀个56 x 56 x 16的特征图,输出通道为32,先⽤16个3 x 3⼤⼩的卷积核进⾏卷积,接着⽤32个1 x 1⼤⼩的卷积核分别对这⽤16个3 x 3⼤⼩的卷积核进⾏卷积之后的特征图进⾏卷积,计算量为3 x 3 x 16 x 56 x 56 + 16 x 32 x 56 x 56 = 2057216从⽽可见计算量少了许多。
2. Linear Bottlenecks
在论⽂中,实验者们发现,使⽤线性层是⾄关重要的,因为它可以防⽌⾮线性破坏太多的信息,在瓶颈中使⽤⾮线性层确实会使性能降低⼏个百分点,如下图。线性瓶颈模型的严格来说⽐⾮线性模型要弱⼀些,因为激活总是可以在线性状态下进⾏,并对偏差和缩放进⾏适当的修
改。然⽽,我们在图a中展⽰的实验表明,线性瓶颈改善了性能,为⾮线性破坏低维空间中的信息提供了⽀持。
3. Inverted residuals
4. Model Architecture
D K D K M D F D F
M N D F D F
⽹络使⽤使⽤ReLU6作为⾮线性,因为⽤于低精度计算时它的鲁棒性。其中:代表重复次数。代表有相同的通道数。代表步长。
代表扩展系数。
数据集下载
代码实现
1. 导⼊相关库
新建train.py⽂件
import torch ,os
import torch .nn as nn
import torch .nn .functional as F
from torch .utils .data import DataLoader , Dataset
from torchvision import models , transforms
from PIL import Image
from torch .autograd import Variable
2. 定义超参数
n c s t
EPOCH =100
IMG_SIZE =224
BATCH_SIZE=64
IMG_MEAN =[0.485,0.456,0.406]
IMG_STD =[0.229,0.224,0.225]
CUDA=torch.cuda.is_available()
DEVICE = torch.device("cuda"if CUDA else"cpu") train_path ='./data1_dog_cat/train'
test_path ='./data1_dog_cat/test'
classes_name = os.listdir(train_path)
3. 数据预处理
train_transforms = transforms.Compose([
transforms.Resize(IMG_SIZE),
transforms.RandomResizedCrop(IMG_SIZE), transforms.RandomHorizontalFlip(),
transforms.RandomRotation(30),
transforms.ToTensor(),
transforms.Normalize(IMG_MEAN, IMG_STD) ])
val_transforms = transforms.Compose([
transforms.Resize(IMG_SIZE),
transforms.CenterCrop(IMG_SIZE),
transforms.ToTensor(),
transforms.Normalize(IMG_MEAN, IMG_STD) ])
4. 构造数据器
class DogDataset(Dataset):
def__init__(self, paths, classes_name, transform=None):
self.paths = self.make_path(paths, classes_name)
def__len__(self):
return len(self.paths)
def__getitem__(self, idx):
image = self.paths[idx].split(';')[0]
img = Image.open(image)
label = self.paths[idx].split(';')[1]
ansform:
img = ansform(img)
return img,int(label)
def make_path(self, path, classes_name):
# path: ./data1_dog_cat/train
# path = './data1_dog_cat/train'
path_list =[]
for class_name in classes_name:
names = os.listdir(path +'/'+class_name)
for name in names:
p = os.path.join(path +'/'+ class_name, name)
label =str(classes_name.index(class_name))
path_list.append(p+';'+label)
return path_list
train_dataset = DogDataset(train_path, classes_name, train_transforms)
val_dataset = DogDataset(test_path, classes_name, val_transforms)
image_dataset ={'train':train_dataset,'valid':val_dataset}
image_dataloader ={x:DataLoader(image_dataset[x],batch_size=BATCH_SIZE,shuffle=True)for x in['train','valid']} dataset_sizes ={x:len(image_dataset[x])for x in['train','valid']}
5. 重新定义迁移模型
model_ft = bilenet_v2(pretrained=True)
for param in model_ft.parameters():
num_ftrs = model_ft.classifier[1].in_features
model_ft.classifier[1]=nn.Linear(num_ftrs,len(classes_name),bias=True)
(DEVICE)
print(model_ft)
6. 定义损失调整和优化器
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model_ft.parameters(), lr=1e-3)#指定新加的fc层的学习率
cosine_schedule = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer=optimizer,T_max=20,eta_min=1e-9)
7. 定义训练和测试函数
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论