一、前期准备
虚拟环境创建
本文所用的模块版本有一定特殊性,为了不污染,建议创建虚拟环境
conda create -n pytorch python==3.6
创建好后激活,作者使用的是3.6版本,命名为pytorch
conda activate pytorch
![](https://img-blog.csdnimg.cn/img_convert/e3570938c1d380cb7ead929e4548f7e9.png)
路径前显示即为激活成功
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
二、网络概述
卷积层
python将输入的图片转化为tensor(张量)形式后,使用核函数扫过其每一部分进行加权,得到输出
![](https://img-blog.csdnimg.cn/img_convert/cfd682e0222148e550777fa399f5b1af.png)
池化层
用选取的矩形框扫过输入的tensor,以一定的运算得出该次的结果,图示为2*2的矩形框输出其中的最大值
![](https://img-blog.csdnimg.cn/img_convert/60517323f778b75f716ce820aaf0c005.png)
3、全连接层
以一定的权重对输入进行加权求和,可理解为矩阵乘法
三、环境启动
0、实验对象
本次实验目的为将图片进行二分类
1、环境设置
打开pycharm左上角文件-设置
![](https://img-blog.csdnimg.cn/img_convert/e285deb8f2110181b99a67b5247e73de.png)
项目-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、导入文件
作者使用的是本地已经下载好的图片,这里使用datasets和DataLoader导入数据集;由于图片大小各异,我们需要对其进行一定的变换增强
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
![](https://img-blog.csdnimg.cn/img_convert/5689dadfe06bfa61a991faf61a57ce61.png)
4.2池化层
![](https://img-blog.csdnimg.cn/img_convert/376ca7a4b54999df6e030405aa75de43.png)
4.3全连接层
in_features,out_features对应的输入核输出维度
![](https://img-blog.csdnimg.cn/img_convert/2bc83c33fb2f5a826bb9a3c64bb99eea.png)
5、网络结构
如果对网络shape模糊的话,可以使用summary可视化
第一个参数为待测试的网络,第二个为输入的tensor的shape
summary(net,input_size=(3,224,224),batch_size=1)
![](https://img-blog.csdnimg.cn/img_convert/dd50b8fdcfcd44c4dec415b1a0df0dd7.png)
了解一下输入tensor的格式
(3,224,224)
第一维度的3为通道数,由于读取的是彩色的图片,其有RGB三个通道,构成图片的色彩
第二三维度则是图片的宽高
当我们输入卷积层后读出的是一个四维的张量
![](https://img-blog.csdnimg.cn/img_convert/fde340a0bce289677ff22412e93689f1.png)
其中第一维度的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()
其中再穿插一系列的函数对张量进行处理,最终得到了二维张量用于我们二分类
![](https://img-blog.csdnimg.cn/img_convert/5eb6c43040753aee27fd750b0950f650.png)
四、训练与验证
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)