Pytorch实现LeNet网络

 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

猜你喜欢

转载自blog.csdn.net/shiheyingzhe/article/details/83062763