- LeNet的网络结构图是:
-
import torch
from torch.utils.data import DataLoader
from torchvision.datasets import MNIST
from torchvision import transforms
from torch import optim
import torch.nn as nn
#Load data
def loadMNIST(batch_size): #MNIST图片的大小是28*28
trans_img=transforms.Compose([transforms.ToTensor()])
trainset=MNIST('./data',train=True,transform=trans_img,download=True)
testset=MNIST('./data',train=False,transform=trans_img,download=True)
# device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
trainloader=DataLoader(trainset,batch_size=batch_size,shuffle=True,num_workers=10)
testloader = DataLoader(testset, batch_size=batch_size, shuffle=False, num_workers=10)
return trainset,testset,trainloader,testloader
#build network
class LeNet(nn.Module):
def __init__(self):
super(LeNet, self).__init__() #调用基类的__init__()函数
'''''torch.nn.Conv2d(in_channels, out_channels, kernel_size,
stride=1, padding=0, dilation=1, groups=1, bias=True)'''
'''''torch.nn.MaxPool2d(kernel_size, stride=None,
padding=0, dilation=1, return_indices=False, ceil_mode=False)
stride – the stride of the window. Default value is kernel_size'''
self.conv=nn.Sequential( #顺序网络结构
nn.Conv2d(1,6,5,stride=1,padding=2), #卷积层 输入1通道,输出6通道,kernel_size=5*5
nn.ReLU(), #激活函数
nn.MaxPool2d(2,2), #最大池化,kernel_size=2*2,stride=2*2
#输出大小为14*14
nn.Conv2d(6,16,5,stride=1,padding=2), #卷积层 输入6通道,输出16通道,kernel_size=5*5
nn.ReLU(),
nn.MaxPool2d(2,2),
# 输出大小为7*7
nn.Conv2d(16,120,5,stride=1,padding=2), #卷积层 输入16通道,输出120通道,kernel_size=5*5
nn.ReLU(),
)
self.fc=nn.Sequential( #全连接层
nn.Linear(7*7*120,120),
nn.ReLU(),
nn.Linear(120, 84),
nn.ReLU(),
nn.Linear(84,10),
nn.Sigmoid(),
)
def forward(self, x): #前向传播
out=self.conv(x)
out=out.view(out.size(0),-1) #展平数据为7*7=49的一维向量
out=self.fc(out)
return out
learning_rate=1e-3
batch_size=100
epoches=50
lenet=Lenet()#network
trainset,testset,trainloader,testloader=loadMNIST(batch_size)#data
criterian=nn.CrossEntropyLoss(size_average=False) #loss
optimizer=optim.SGD(lenet.parameters(),lr=learning_rate) #optimizer
lenet.to("cpu")
#training
for i in range(epoches):
running_loss=0.
running_acc=0.
for (img,label) in trainloader:
optimizer.zero_grad() #求梯度之前对梯度清零以防梯度累加
output=lenet(img) #前向计算网络输出值
loss=criterian(output) #计算loss值
loss.backward() #loss反传存到相应的变量结构当中
optimizer.step() #使用计算好的梯度对参数进行更新
running_loss+=loss.item()
print(output)
_,predict=torch.max(output,1)
correct_num=(predict==label).sum()
running_acc+=correct_num.item()
running_loss/=len(trainset)
running_acc/=len(trainset)
print("[%d/%d] Loss: %.5f, Acc: %.2f"%(i+1,epoches,running_loss,
100*running_acc))
- 在运行过程中出现这样的问题,fork函数是Unix系统特有的,Windows系统没有,根据提示加上
- if __name__ == '__main__':就可以
-
- RuntimeError:
- An attempt has been made to start a new process before the
- current process has finished its bootstrapping phase.
-
- This probably means that you are not using fork to start your
- child processes and you have forgotten to use the proper idiom
- in the main module:
-
- if __name__ == '__main__':
- freeze_support()
- ...
-
- The "freeze_support()" line can be omitted if the program
- is not going to be frozen to produce an executable.
-
- 正确的程序代码只是多加 if __name__ == '__main__':
-
-
import torch
from torch.utils.data import DataLoader
from torchvision.datasets import MNIST
from torchvision import transforms
from torch import optim
import torch.nn as nn
#Load data
def loadMNIST(batch_size): #MNIST图片的大小是28*28
trans_img=transforms.Compose([transforms.ToTensor()])
trainset=MNIST('./data',train=True,transform=trans_img,download=True)
testset=MNIST('./data',train=False,transform=trans_img,download=True)
# device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
trainloader=DataLoader(trainset,batch_size=batch_size,shuffle=True,num_workers=10)
testloader = DataLoader(testset, batch_size=batch_size, shuffle=False, num_workers=10)
return trainset,testset,trainloader,testloader
#build network
class LeNet(nn.Module):
def __init__(self):
super(LeNet, self).__init__() #调用基类的__init__()函数
'''''torch.nn.Conv2d(in_channels, out_channels, kernel_size,
stride=1, padding=0, dilation=1, groups=1, bias=True)'''
'''''torch.nn.MaxPool2d(kernel_size, stride=None,
padding=0, dilation=1, return_indices=False, ceil_mode=False)
stride – the stride of the window. Default value is kernel_size'''
self.conv=nn.Sequential( #顺序网络结构
nn.Conv2d(1,6,5,stride=1,padding=2), #卷积层 输入1通道,输出6通道,kernel_size=5*5
nn.ReLU(), #激活函数
nn.MaxPool2d(2,2), #最大池化,kernel_size=2*2,stride=2*2
#输出大小为14*14
nn.Conv2d(6,16,5,stride=1,padding=2), #卷积层 输入6通道,输出16通道,kernel_size=5*5
nn.ReLU(),
nn.MaxPool2d(2,2),
# 输出大小为7*7
nn.Conv2d(16,120,5,stride=1,padding=2), #卷积层 输入16通道,输出120通道,kernel_size=5*5
nn.ReLU(),
)
self.fc=nn.Sequential( #全连接层
nn.Linear(7*7*120,120),
nn.ReLU(),
nn.Linear(120, 84),
nn.ReLU(),
nn.Linear(84,10),
nn.Sigmoid(),
)
def forward(self, x): #前向传播
out=self.conv(x)
out=out.view(out.size(0),-1) #展平数据为7*7=49的一维向量
out=self.fc(out)
return out
#training
if __name__ == '__main__':
learning_rate = 1e-2
batch_size = 199
epoches = 50
lenet = LeNet() # network
trainset, testset, trainloader, testloader = loadMNIST(batch_size) # data
criterian = nn.CrossEntropyLoss(reduction='sum') # 求和的方式计算loss
optimizer = optim.SGD(lenet.parameters(), lr=learning_rate) # optimizer
for i in range(epoches):
running_loss=0.
running_acc=0.
for (img,label) in trainloader:
optimizer.zero_grad() #求梯度之前对梯度清零以防梯度累加
output=lenet(img) #前向计算网络输出值
loss=criterian(output,label) #计算loss值
loss.backward() #loss反传存到相应的变量结构当中
optimizer.step() #使用计算好的梯度对参数进行更新
running_loss+=loss.item()
# 1的意思是按列求最大值,output的shape=torch.Size([100, 10])
#其中torch.max()返回两个值,第一个是最大值,第二个是最大值的下标
valu,predict=torch.max(output,1)
correct_num=(predict==label).sum()
running_acc+=correct_num.item()
running_loss/=len(trainset)
running_acc/=len(trainset)
print("[%d/%d] Loss: %.5f, Acc: %.2f"%(i+1,epoches,running_loss,
100*running_acc))
-
- 运行的结果是:
- [1/50] Loss: 1.66764, Acc: 76.20
- [2/50] Loss: 1.48704, Acc: 96.65
- [3/50] Loss: 1.47988, Acc: 97.56
- [4/50] Loss: 1.47562, Acc: 98.08
- [5/50] Loss: 1.47277, Acc: 98.48
- [6/50] Loss: 1.47142, Acc: 98.55
- [7/50] Loss: 1.47108, Acc: 98.71
- [8/50] Loss: 1.46989, Acc: 98.83
- [9/50] Loss: 1.46912, Acc: 98.96
- [10/50] Loss: 1.46844, Acc: 99.02
- [11/50] Loss: 1.46789, Acc: 99.10
- [12/50] Loss: 1.46728, Acc: 99.17
- [13/50] Loss: 1.46731, Acc: 99.17
- [14/50] Loss: 1.46662, Acc: 99.27
- [15/50] Loss: 1.46540, Acc: 99.46
-
- Relu激活函数这里是收敛的挺快的,如果将Relu函数修改为sigmoid函数,这里的情况就有些不同
- 将class LeNet修改为:
-
-
#build network
class LeNet(nn.Module):
def __init__(self):
super(LeNet, self).__init__() #调用基类的__init__()函数
'''''torch.nn.Conv2d(in_channels, out_channels, kernel_size,
stride=1, padding=0, dilation=1, groups=1, bias=True)'''
'''''torch.nn.MaxPool2d(kernel_size, stride=None,
padding=0, dilation=1, return_indices=False, ceil_mode=False)
stride – the stride of the window. Default value is kernel_size'''
self.conv=nn.Sequential( #顺序网络结构
nn.Conv2d(1,6,5,stride=1,padding=2), #卷积层 输入1通道,输出6通道,kernel_size=5*5
nn.Sigmoid(), #激活函数
nn.MaxPool2d(2,2), #最大池化,kernel_size=2*2,stride=2*2
#输出大小为14*14
nn.Conv2d(6,16,5,stride=1,padding=2), #卷积层 输入6通道,输出16通道,kernel_size=5*5
nn.Sigmoid(),
nn.MaxPool2d(2,2),
# 输出大小为7*7
nn.Conv2d(16,120,5,stride=1,padding=2), #卷积层 输入16通道,输出120通道,kernel_size=5*5
nn.Sigmoid(),
)
self.fc=nn.Sequential( #全连接层
nn.Linear(7*7*120,120),
nn.Sigmoid(),
nn.Linear(120, 84),
nn.Sigmoid(),
nn.Linear(84,10),
nn.Sigmoid(),
)
def forward(self, x): #前向传播
out=self.conv(x)
out=out.view(out.size(0),-1) #展平数据为7*7=49的一维向量
out=self.fc(out)
return out
-
- 运行的结果是:收敛的很慢,可能不能使用
- [1/100] Loss: 2.30338, Acc: 10.81
- [2/100] Loss: 2.30207, Acc: 11.10
- [3/100] Loss: 2.30171, Acc: 11.13
- [4/100] Loss: 2.30163, Acc: 11.19
- [5/100] Loss: 2.30157, Acc: 11.23
- [6/100] Loss: 2.30153, Acc: 11.24
- [7/100] Loss: 2.30146, Acc: 11.24
- [8/100] Loss: 2.30152, Acc: 11.24
- [9/100] Loss: 2.30139, Acc: 11.24
- [10/100] Loss: 2.30147, Acc: 11.24