Pytorch搭建基础卷积网络检测Mnist
思路:
1.加载本地mnist数据集
2.搭建网络结构
3.训练
4.测试训练模型
加载数据
import torch as tch
import torchvision.datasets.mnist as mnist
from torch.utils.data import DataLoader
def main():
train_set = (
mnist.read_image_file( \
'D:/mnist/train-images.idx3-ubyte'),
mnist.read_label_file( \
'D:/mnist/train-labels.idx1-ubyte')
)
test_set = (
mnist.read_image_file( \
'D:/mnist/t10k-images.idx3-ubyte'),
mnist.read_label_file( \
'D:/mnist/t10k-labels.idx1-ubyte')
)
#数据分组
train_data=[[x.view(1,28,28)/255,y]for (x,y) in zip(train_set[0],train_set[1])]
test_data=[[x.view(1,28,28)/255,y]for (x,y) in zip(test_set[0],test_set[1])]
#转换batch_size
train_dataload=DataLoader(train_data,batch_size=10)
test_dataload=DataLoader(test_data,batch_size=10)
return train_dataload,test_dataload
main()
遇到的问题:
1.Dataloader可将数据小批量分组,调用前需将数据图片与标签足组合[(x1,y1),(x2,y2),…]
2.输入数据要归一化(R/G/B)/255,否则可能造成梯度爆炸grad=nan
网络搭建
import torch as tch
import torch.nn as nn
#网络定义
class Network(nn.Module):
def __init__(self):
#继承父类初始化
super(Network, self).__init__()
#创建网络序列
self.model=nn.Sequential(
nn.Conv2d(1,10,5), #Conv1:输入1维,输出10维,卷积核大小5
nn.Sigmoid(), #Sigmoid激活函数
nn.MaxPool2d(2), #池化大小2
nn.Flatten(), #展平
nn.Linear(10*12*12,30), #全连接层输入10*12*12,输出30
nn.Sigmoid(),
nn.Linear(30,10), #全连接层输入30,输出10
nn.Softmax(dim=1) #柔性最大值激活函数
)
#前向传播
def forward(self,x):
x=self.model(x)
return x
if __name__=='__main__':
net=Network()
inpt=tch.randn(10,1,28,28)
output=net.model(inpt)
print(output)
遇到的问题:
1.卷积池化全连接层并不带激活函数,需再调用一层激活层,且从池化到全连接需展平
2.卷积层输入大小input,输出大小output,步长stride,卷积核大小kernel,填充输入数pad
output=(inpt+2*pad-kernel)/stride+1
训练及测试
from model import *
import data_load
import sys
def main():
net=Network()
#交叉熵损失函数
loss_fn=nn.CrossEntropyLoss()
learning_rate=0.5
epoch=30
#定义优化器,随机梯度下降
optimizer=tch.optim.SGD(net.parameters(),lr=learning_rate)
#获取Mnist数据
train_data,test_data=data_load.main()
n_train=len(train_data)
n_test=len(test_data)
for i in range(epoch):
loss_record=0
n_accuracy=0
for data in train_data:
images,labels=data
#前向传播
output=net.model(images)
loss=loss_fn(output,labels)
loss_record+=loss
#梯度清除
optimizer.zero_grad()
#反向传播
loss.backward()
#参数(w,b)更新
optimizer.step()
#测试网络
with tch.no_grad():
for data in test_data:
images,labels=data
output=net.model(images)
n_accuracy+=(output.argmax(1)==labels).sum()
loss_record/=len(train_data)
print('Epoch:{0}\nloss_record:{1}\nAccuracy:{2:.2f}%\n'.format(i,loss_record,n_accuracy/n_test*10))
main()
遇到的问题:
1.交叉熵代价函数nn.CorssEntropyLoss(a,y)
a为网络的(mini batch size,output)两维输出,y为一维整数,分别对应a中的每行的期望
#Example
import torch.nn as nn
import torch as tch
loss_fn=nn.CrossEntropyLoss()
inpt=tch.randn(3,5,requires_grad=True)
target=tch.empty(3,dtype=tch.long).random_(5)
print(inpt,target,sep='\n')
print(loss_fn(inpt,target))
2.torch.optim中存放各类优化器,如SGD(随机梯度下降),用于网络反向传播后,更新网络w、b。
3.net.parameters()返回网络的参数(w,b),在torch.optim.SGD()调用表示需更新的参数
4.进入网络的输入必须是思维tensor,(mini_batch_size,depth,height,witdh)
5.tensor.argmax(a),a=1时横向比较,a=0时纵向比较,返回最大值位置