笔者也是最近刚学不久的深度学习,也有很多地方不懂,下面给大家使用pytorch实现一个简单的Resnet网络(残差网络),并且训练MNIST数据集.话不多说,直接上代码.
笔者认为最主要的地方就是网络模型,网络模型出来其实基本上就完成了大概了.首先是残差块.之后是残差网络,数据集,训练,测试.完整代码请下拉看最后.
残差块的结构如下所示:
#残差块
class ResidualBlock(nn.Module):
def __init__(self,channel):
super(ResidualBlock, self).__init__()
self.channel=channel
self.conv1=nn.Sequential(
nn.Conv2d(in_channels=channel,
out_channels=channel,
kernel_size=3,
stride=1,
padding=1),
nn.BatchNorm2d(channel),
nn.ReLU(inplace=True)
)
self.conv2=nn.Sequential(
nn.Conv2d(channel,channel,kernel_size=3,stride=1,padding=1),
# nn.BatchNorm2d(channel)
)
def forward(self,x):
out=self.conv1(x)
out=self.conv2(out)
out+=x
out=F.relu(out)
return out
残差块完成之后,就是残差网络,如下图:
#残差网络
class ResNet(nn.Module):
def __init__(self):
super(ResNet, self).__init__()
self.conv1=nn.Sequential(
nn.Conv2d(in_channels=1,out_channels=32,kernel_size=5), #(1,28,28)
nn.BatchNorm2d(32), #(32,24,24)
nn.ReLU(),
nn.MaxPool2d(2) #(32,12,12)
)
self.conv2 = nn.Sequential(
nn.Conv2d(in_channels=32, out_channels=16, kernel_size=5), #(16,8,8)
nn.BatchNorm2d(16),
nn.ReLU(),
nn.MaxPool2d(2) #(16,4,4)
)
self.reslayer1=ResidualBlock(32)
self.reslayer2=ResidualBlock(16)
self.fc=nn.Linear(256,10) #这里的输入256是因为16*4*4=256
def forward(self,x):
out=self.conv1(x)
out=self.reslayer1(out)
out=self.conv2(out)
out=self.reslayer2(out)
out=out.view(out.size(0),-1)
out=self.fc(out)
return out
数据集:
Epoch=3
Batch_Size=50
LR=0.01
#训练集
trainData=torchvision.datasets.MNIST(
root="/home/sunrui/zqtstudy/卷积网络/ResNetsimple/data",
train=True,
transform=torchvision.transforms.ToTensor(),
download=False)
train_loader=Data.DataLoader(dataset=trainData,batch_size=Batch_Size,shuffle=True)
test_data=torchvision.datasets.MNIST(root="/home/sunrui/zqtstudy/卷积网络/ResNetsimple/data",train=False,download=False)
test_x = torch.unsqueeze(test_data.data, dim=1).type(torch.FloatTensor)[:5000]/255. # shape from (2000, 28, 28) to (2000, 1, 28, 28), value in range(0,1)
test_y = test_data.targets[:5000]
训练:
#关于训练
def Train(Res):
# 损失函数,以及优化器
loss_func = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(Res.parameters(), lr=LR)
for epoch in range(Epoch):
for step,(b_x,b_y)in enumerate(train_loader):
output=Res(b_x)
loss=loss_func(output,b_y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if(step%50==0):
test_output=Res(test_x)
pred_y = torch.max(test_output, 1)[1].data.numpy()
accuracy = float((pred_y == test_y.data.numpy()).astype(int).sum()) / float(test_y.size(0))
print('Epoch: ', epoch, '| train loss: %.4f' % loss.data.numpy(), '| test accuracy: %.6f' % accuracy)
torch.save(Res, 'res_minist.pkl')
print('res finish training')
测试:
# 测试
def Restest():
res=torch.load('res_minist.pkl')
test_output=res(test_x[:100])
prediction=torch.max(test_output,1)[1].data.numpy()
print(prediction, 'prediction number')
print(test_y[:100].numpy(), 'real number')
test_output1 = res(test_x)
pred_y1 = torch.max(test_output1, 1)[1].data.numpy()
accuracy = float((pred_y1 == test_y.data.numpy()).astype(int).sum()) / float(test_y.size(0))
print('accuracy', accuracy)
大体就是这样,然后,在一个py文件中全部写出来就OK了,下面是完整代码:
import torch
import torch.nn as nn
import torchvision
from torch.autograd import Variable
import matplotlib.pyplot as plt
import torch.nn.functional as F
import torch.utils.data as Data
Epoch=3
Batch_Size=50
LR=0.01
#训练集
trainData=torchvision.datasets.MNIST(
root="/home/sunrui/zqtstudy/卷积网络/ResNetsimple/data",
train=True,
transform=torchvision.transforms.ToTensor(),
download=False)
train_loader=Data.DataLoader(dataset=trainData,batch_size=Batch_Size,shuffle=True)
test_data=torchvision.datasets.MNIST(root="/home/sunrui/zqtstudy/卷积网络/ResNetsimple/data",train=False,download=False)
test_x = torch.unsqueeze(test_data.data, dim=1).type(torch.FloatTensor)[:5000]/255. # shape from (2000, 28, 28) to (2000, 1, 28, 28), value in range(0,1)
test_y = test_data.targets[:5000]
#残差块
class ResidualBlock(nn.Module):
def __init__(self,channel):
super(ResidualBlock, self).__init__()
self.channel=channel
self.conv1=nn.Sequential(
nn.Conv2d(in_channels=channel,
out_channels=channel,
kernel_size=3,
stride=1,
padding=1),
nn.BatchNorm2d(channel),
nn.ReLU(inplace=True)
)
self.conv2=nn.Sequential(
nn.Conv2d(channel,channel,kernel_size=3,stride=1,padding=1),
# nn.BatchNorm2d(channel)
)
def forward(self,x):
out=self.conv1(x)
out=self.conv2(out)
out+=x
out=F.relu(out)
return out
#残差网络
class ResNet(nn.Module):
def __init__(self):
super(ResNet, self).__init__()
self.conv1=nn.Sequential(
nn.Conv2d(in_channels=1,out_channels=32,kernel_size=5), #(1,28,28)
nn.BatchNorm2d(32), #(32,24,24)
nn.ReLU(),
nn.MaxPool2d(2) #(32,12,12)
)
self.conv2 = nn.Sequential(
nn.Conv2d(in_channels=32, out_channels=16, kernel_size=5), #(16,8,8)
nn.BatchNorm2d(16),
nn.ReLU(),
nn.MaxPool2d(2) #(16,4,4)
)
self.reslayer1=ResidualBlock(32)
self.reslayer2=ResidualBlock(16)
self.fc=nn.Linear(256,10) #这里的输入256是因为16*4*4=256
def forward(self,x):
out=self.conv1(x)
out=self.reslayer1(out)
out=self.conv2(out)
out=self.reslayer2(out)
out=out.view(out.size(0),-1)
out=self.fc(out)
return out
#关于训练
def Train(Res):
# 损失函数,以及优化器
loss_func = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(Res.parameters(), lr=LR)
for epoch in range(Epoch):
for step,(b_x,b_y)in enumerate(train_loader):
output=Res(b_x)
loss=loss_func(output,b_y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if(step%50==0):
test_output=Res(test_x)
pred_y = torch.max(test_output, 1)[1].data.numpy()
accuracy = float((pred_y == test_y.data.numpy()).astype(int).sum()) / float(test_y.size(0))
print('Epoch: ', epoch, '| train loss: %.4f' % loss.data.numpy(), '| test accuracy: %.6f' % accuracy)
torch.save(Res, 'res_minist.pkl')
print('res finish training')
# x=torch.randn(16,1,28,28)
# res=ResNet()
# 测试
def Restest():
res=torch.load('res_minist.pkl')
test_output=res(test_x[:100])
prediction=torch.max(test_output,1)[1].data.numpy()
print(prediction, 'prediction number')
print(test_y[:100].numpy(), 'real number')
test_output1 = res(test_x)
pred_y1 = torch.max(test_output1, 1)[1].data.numpy()
accuracy = float((pred_y1 == test_y.data.numpy()).astype(int).sum()) / float(test_y.size(0))
print('accuracy', accuracy)
if __name__=='__main__':
# Train(res)
Restest()
测试或者训练的话,在 if __name__=='__main__': 部分注释掉相应的部分就好啦.另外训练或者测试的数据大小可以自己选择,毕竟MNIST的训练数据集有6W张来着......笔者自己试了accuracy是在98%99%左右,这个是能够跑通的,跑通了才放上来的.数据集的加载训练测试代码参考,还有简单残差网络的知识请看下面链接,个人觉得对于刚开始的新手还是很有帮助的.
有问题可以留言,不定期看到会回复~(另外因为是第一次另外我不知道这算原创还是算转载,感觉没有特别合适的.所以我发表出来的时候选的类型是原创,要是并不属于这个类型,请告知我,我会改掉的,谢谢)