入门CNN?有他就够了!保姆级教学!二分类实战

一、前期准备

  1. 虚拟环境创建

本文所用的模块版本有一定特殊性,为了不污染,建议创建虚拟环境

conda create -n pytorch python==3.6

创建好后激活,作者使用的是3.6版本,命名为pytorch

conda activate pytorch

路径前显示即为激活成功

2.下载对应模块

本文使用模块版本

torch==1.6.0

torchvision==0.7.0

torchsummary==1.5.1(非必要可不装)

torch的库版本比较远古,作者使用以下代码进行安装的

pip install torch==1.6.0 -f https://download.pytorch.org/whl/torch_stable.html

输入以下查看环境内模块,若显示则为安装成功

pip list

二、网络概述

  1. 卷积层

python将输入的图片转化为tensor(张量)形式后,使用核函数扫过其每一部分进行加权,得到输出

  1. 池化层

用选取的矩形框扫过输入的tensor,以一定的运算得出该次的结果,图示为2*2的矩形框输出其中的最大值

3、全连接层

以一定的权重对输入进行加权求和,可理解为矩阵乘法

三、环境启动

0、实验对象

本次实验目的为将图片进行二分类

1、环境设置

打开pycharm左上角文件-设置

项目-python解释器,选择虚拟环境pytorch

2、导入模块

import torch
import torch.nn as nn
from torchvision import transforms
import os
from torchvision import datasets
from torch import optim
from torch.utils.data import DataLoader
from torchsummary import summary

3、导入文件

作者使用的是本地已经下载好的图片,这里使用datasetsDataLoader导入数据集;由于图片大小各异,我们需要对其进行一定的变换增强

path=os.path.join(r'D:\torch--\ant&bee\hymenoptera_data\train')
norm_mean = [0.485, 0.456, 0.406]
norm_std = [0.229, 0.224, 0.225]

transform=transforms.Compose([
    transforms.Resize(256),
    transforms.CenterCrop(224),
    transforms.ToTensor(),
    transforms.Normalize(norm_mean,norm_std)
])
#这里用compose囊括变换,分别是裁剪至256*256,随机中心裁剪为224*224,将图片转化为tensor形式,将tensor标准化
train_set = datasets.ImageFolder(path,transform=transform)
trainDataLoader = DataLoader(dataset = train_set,batch_size = 1,shuffle = True)
#导入数据集,使用规定好的变换
#封装近trainDataLoader,每一次调取batch_size = 1个数据,并打乱顺序shuffle = True

4、构建网络

net=nn.Sequential(
    nn.Conv2d(in_channels=3,
                out_channels=16,
                kernel_size=3,
                stride=2,),
    nn.BatchNorm2d(16),
    nn.ReLU(),
    nn.MaxPool2d(kernel_size=2),


    nn.Conv2d(in_channels=16,
                out_channels=32,
                kernel_size=3,
                stride=2,),
    nn.BatchNorm2d(32),
    nn.ReLU(),
    nn.MaxPool2d(kernel_size=2),

    nn.Flatten(),

    nn.Linear(169*32, 32),
    nn.ReLU(),

    nn.Linear(32,2),
    nn.Softmax(dim=1)
)
#使用Sequential讲网络纳入

4.1卷积层

这里使用torch.nn.Conv2d

其中in_channels为输入通道数,out_channels,为输出通道数,kernel_size为卷积核大小,这三者需要手动设置

stride为步长,即卷积核以此移动多少个像素,默认为1

4.2池化层

4.3全连接层

in_features,out_features对应的输入核输出维度

5、网络结构

如果对网络shape模糊的话,可以使用summary可视化

第一个参数为待测试的网络,第二个为输入的tensorshape

summary(net,input_size=(3,224,224),batch_size=1)

了解一下输入tensor的格式

(3,224,224)

第一维度的3为通道数,由于读取的是彩色的图片,其有RGB三个通道,构成图片的色彩

第二三维度则是图片的宽高

当我们输入卷积层后读出的是一个四维的张量

其中第一维度的1代表的是batch_size,即一批中选取多少个张量

nn.Conv2d(in_channels=3,
                out_channels=16,
                kernel_size=3,
                stride=2,)

in_channels刚好对应我们输入的RGB三通道图像,经卷积层后编程16维度的,宽高根据公式变成了111*111

Flatten( )用于将张量展开,方便卷积层核全连接层的对接,其中size须等同于全连接层的input_size

nn.Flatten()

其中再穿插一系列的函数对张量进行处理,最终得到了二维张量用于我们二分类

四、训练与验证

4.1训练

首先定义前向传播的函数

def forward(x):
    x=net(x)
    return x

构建优化器以及损失函数

这里使用随机梯度下降方式优化,损失使用交叉熵损失

optimizer= optim.Adam(net.parameters(), lr=0.1)
loss=nn.CrossEntropyLoss(reduction='none')

设定为5个epchos,将模型放到gpu上后,就可以开始我们的训练了

由于每次迭代后梯度会累加,所以每一次都要将梯度清零

net.to('cuda')
epochs=5

for i in range(epochs):
    for pic,label in trainDataLoader:
        pic = pic.to(device)
        label = label.to(device)
        out= forward(pic)
        l = loss(out,label)
        l.backward()
        optimizer.step()
        optimizer.zero_grad()

训练之后将模型保存到本地,训练阶段就结束了

path=os.path.join(r'D:\torch--\ant&bee\hymenoptera_data','model.pt')
torch.save(net,path)

4.2验证

导入我们的模型,注意要切换到eval( )评估模式

save_path=os.path.join(r'D:\torch--\ant&bee\hymenoptera_data\model.pt')
device=torch.device('cuda' if torch.cuda.is_available() else 'cpu')
net=torch.load(save_path)
net.to(device)
net.eval()
pic_path=os.path.join(r'D:\torch--\ant&bee\hymenoptera_data\val')
test_data=datasets.ImageFolder(pic_path,transform=transform)
testDataloader=DataLoader(test_data,batch_size=1,shuffle=True)

同样的进行数据增强

orm_mean = [0.485, 0.456, 0.406]
norm_std = [0.229, 0.224, 0.225]

transform=transforms.Compose([
    transforms.Resize(256),
    transforms.CenterCrop(224),
    transforms.ToTensor(),
    transforms.Normalize(norm_mean,norm_std)
])

就可以愉快的使用训练好的模型去预测我们的测试集了

with torch.no_grad():
    for pic,label in testDataloader:
        pic=pic.to(device)
        label=label.to(device)
        out=net(pic)

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值