IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> pytorch学习第五课-卷积神经网络的Transfer Learning -> 正文阅读

[人工智能]pytorch学习第五课-卷积神经网络的Transfer Learning

在做了简单的卷积神经网络LeNet-5进行MINIST识别之后,我们可以进行一些更加复杂的识别任务,比如小数据集,但是困难的分类任务,这个时候我们怎么样才能获得相对较好的结果呢,下面就介绍一下transfer learning。

这里我们想要完成的任务是一个二分类,区分ants 和 bee,数据量在300张左右,并且图片类型各异,对于这种数据量极小,但是识别任务相对复杂的任务:(数据集的下载地址为:https://github.com/jaddoescad/ants_and_bees)在这里插入图片描述

这里我们想要使用vgg16,我们使用pytorch上已经训练好的vgg16网络作为基础网络,然后不改变特征提取的参数,只对后面的全链接层的参数进行更新

首先仍旧是数据集的下载的处理:

import torch
import torch.nn as nn
from torchvision import transforms,datasets,models
import torch.nn.functional as F
import matplotlib.pyplot as plt
import numpy as np

transform=transforms.Compose([transform.Resize(224,224),
							  transform.ToTensor(),
							  transform.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))])
							  
train_datastes=datasets.ImageFolder('./data/ants_and_bees/train',transform=transform)
val_datastes=datasets.ImageFolder('./data/ants_and_bees/val',transform=transform)

training_loader=torch.utils.data.DataLoader(dataset=training_datasets,batch_size=10,shuffle=True)
print(len(training_loader))
val_loader=torch.utils.data.DataLoader(datasets=val_datasets,batch_size=20,suffle=False)

torchvision.datasets.ImageFolder 这个函数,可以将分在不同文件夹中的数据进行自动的打包和赋予标签,我们可以看一下 ants_and_bees文件夹中的目录情况:
在这里插入图片描述
ants 和 bees中都有很多的图片,torchvision.datasets.ImageFolder 这个函数就能将所有的图片加载上去,并将 ants定为类别0,bees类别1

下面就是对vgg网络的加载,预训练网络的下载,我们首先直接下载一下vgg16和其训练好的参数,然后看一下vgg16的整个结构:

model=models.vgg16(pretrained=True)
print(model)

可以看到vgg16的整个结构如下:

VGG(
  (features): Sequential(
    (0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (1): ReLU(inplace=True)
    (2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (3): ReLU(inplace=True)
    (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (6): ReLU(inplace=True)
    (7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (8): ReLU(inplace=True)
    (9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (11): ReLU(inplace=True)
    (12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (13): ReLU(inplace=True)
    (14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (15): ReLU(inplace=True)
    (16): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (17): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (18): ReLU(inplace=True)
    (19): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (20): ReLU(inplace=True)
    (21): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (22): ReLU(inplace=True)
    (23): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (24): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (25): ReLU(inplace=True)
    (26): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (27): ReLU(inplace=True)
    (28): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (29): ReLU(inplace=True)
    (30): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  )
  (avgpool): AdaptiveAvgPool2d(output_size=(7, 7))
  (classifier): Sequential(
    (0): Linear(in_features=25088, out_features=4096, bias=True)
    (1): ReLU(inplace=True)
    (2): Dropout(p=0.5, inplace=False)
    (3): Linear(in_features=4096, out_features=4096, bias=True)
    (4): ReLU(inplace=True)
    (5): Dropout(p=0.5, inplace=False)
    (6): Linear(in_features=4096, out_features=1000, bias=True)
  )
)

分为两个块,一块是features,然后接一个avepool,最后是classifier层,好的,然后我们根据自己的任务对这个vgg16网络进行修改,主要需要修改的部分为两个 1,固定住features模块的参数,将其 requires_grad设置为False,2. 将任务变成2分类

class VGG16(nn.Module):
	def __init__(self,feature_freeze=True,num_classes=2):
		model=models.vgg16(pretrained=True)
		self.features=model.features
		self.avgpool=model.avgpool
		self.classifier=nn.Sequential(
		nn.Linear(in_features=25088, out_features=4096, bias=True),
		nn.ReLU(),
		nn.Linear(in_features=4096, out_features=4096, bias=True),
		nn.ReLU(),
		nn.Linear(in_features=4096, out_features=num_classes, bias=True),
		)
		self.set_parameters_freeze(self.features,feature_freeze)
		
	def forward(self,x):
		features_output=self.features(x)
		features_output=self.avgpool(features_output)
		features_output=features_output.view(-1,25088)
		pred=self.classifier(features_output)
		return pred
	
	def set_parameters_freeze(self,model,flag):
		if flag:
			for params in model.parameters():
				params.requires_grad=False

然后我们可以输出模型看看修改之后的结果啦:


device={'cuda:0' if torch.cuda.is_available() else 'cpu'}
model=VGG16().to(device)
print(model)

输出结果:

VGGnet(
  (features): Sequential(
    (0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (1): ReLU(inplace=True)
    (2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (3): ReLU(inplace=True)
    (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (6): ReLU(inplace=True)
    (7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (8): ReLU(inplace=True)
    (9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (11): ReLU(inplace=True)
    (12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (13): ReLU(inplace=True)
    (14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (15): ReLU(inplace=True)
    (16): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (17): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (18): ReLU(inplace=True)
    (19): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (20): ReLU(inplace=True)
    (21): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (22): ReLU(inplace=True)
    (23): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (24): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (25): ReLU(inplace=True)
    (26): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (27): ReLU(inplace=True)
    (28): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (29): ReLU(inplace=True)
    (30): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  )
  (avgpool): AdaptiveAvgPool2d(output_size=(7, 7))
  (classifier): Sequential(
    (0): Linear(in_features=25088, out_features=4096, bias=True)
    (1): ReLU()
    (2): Linear(in_features=4096, out_features=4096, bias=True)
    (3): ReLU()
    (4): Linear(in_features=4096, out_features=2, bias=True)
  )
)

可以看到最后一层的输出已经变成了两个2,如果输出 features中的requires_grad, 也会发现都是False

最后就是进行训练啦:

criterion=nn.CrossEntropyLoss()
optimizer=torch.optim.Adam(model.parameters(),lr=0.0001)

epoch=10
losses=[]

val_losses=[]
val_acces=[]

for i in range(epoch):
    
    running_loss=0.0
    running_correct=0.0

    for steps,(inputs,labels) in enumerate(training_loader):
     
        
        inputs=inputs.to(device)
        labels=labels.to(device)
        
        y_pred=model.forward(inputs)

        loss=criterion(y_pred,labels)
        #print(loss)
        optimizer.zero_grad()
        loss.backward()
       
        optimizer.step()
        
        _,preds=torch.max(y_pred,1)
        running_correct+=torch.sum(preds==labels.data)
        running_loss=running_loss+loss.item()
        
    epoch_loss=running_loss/len(training_datasets)
    epoch_acc=running_correct/len(training_datasets)
    losses.append(epoch_loss)
    
    val_running_loss=0.0
    val_running_correct=0.0
        
    val_dataiter=iter(validation_loader)
    with torch.no_grad():
        for j in range(len(validation_loader)): 
            val_inputs,val_labels=val_dataiter.next()
            #val_inputs=val_inputs.view(val_inputs.shape[0],-1)
            val_inputs=val_inputs.to(device)
            val_labels=val_labels.to(device)
            
            #print(val_inputs.shape)

            val_pred=model.forward(val_inputs)

            valloss=criterion(val_pred,val_labels)

            _,preds=torch.max(val_pred,1)
            val_running_correct+=torch.sum(preds==val_labels.data)
            val_running_loss=val_running_loss+valloss.item()
    
        val_loss=val_running_loss/len(validation_datasets)
        val_acc=val_running_correct/len(validation_datasets)
        val_losses.append(val_loss)
        val_acces.append(val_acc)
    
    print(i,' traing loss:',epoch_loss,'epoch_acc:',epoch_acc.item())
    print(i,' validation loss:',val_loss,'validation_acc:',val_acc.item())
    
    plt.close()
    plt.plot(losses,label='training_loss')
    plt.plot(val_losses,label='validation_loss')
    plt.legend()
    plt.savefig('loss.png')

    dir='./convolution_checkpoint'
    PATH=os.path.join(dir,'model'+str(i)+'.pth')
    torch.save(model.state_dict(), PATH)

最后val 的准确度能够达到90%,这是不用 transfer learning很难达到的一个准确度

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2021-07-04 19:55:33  更:2021-07-04 19:56:19 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/31 1:21:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码