Pytorch实现LeNet网络

  1.  LeNet的网络结构图是:  
  2.   
    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))  

  3. 在运行过程中出现这样的问题,fork函数是Unix系统特有的,Windows系统没有,根据提示加上  
  4. if __name__ == '__main__':就可以  
  5.   
  6. RuntimeError:   
  7.         An attempt has been made to start a new process before the  
  8.         current process has finished its bootstrapping phase.  
  9.   
  10.         This probably means that you are not using fork to start your  
  11.         child processes and you have forgotten to use the proper idiom  
  12.         in the main module:  
  13.   
  14.             if __name__ == '__main__':  
  15.                 freeze_support()  
  16.                 ...  
  17.   
  18.         The "freeze_support()" line can be omitted if the program  
  19.         is not going to be frozen to produce an executable.  
  20.   
  21. 正确的程序代码只是多加 if __name__ == '__main__':  
  22.   
  23. 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))  

  24.   
  25. 运行的结果是:  
  26. [1/50] Loss: 1.66764, Acc: 76.20  
  27. [2/50] Loss: 1.48704, Acc: 96.65  
  28. [3/50] Loss: 1.47988, Acc: 97.56  
  29. [4/50] Loss: 1.47562, Acc: 98.08  
  30. [5/50] Loss: 1.47277, Acc: 98.48  
  31. [6/50] Loss: 1.47142, Acc: 98.55  
  32. [7/50] Loss: 1.47108, Acc: 98.71  
  33. [8/50] Loss: 1.46989, Acc: 98.83  
  34. [9/50] Loss: 1.46912, Acc: 98.96  
  35. [10/50] Loss: 1.46844, Acc: 99.02  
  36. [11/50] Loss: 1.46789, Acc: 99.10  
  37. [12/50] Loss: 1.46728, Acc: 99.17  
  38. [13/50] Loss: 1.46731, Acc: 99.17  
  39. [14/50] Loss: 1.46662, Acc: 99.27  
  40. [15/50] Loss: 1.46540, Acc: 99.46  
  41.   
  42.  Relu激活函数这里是收敛的挺快的,如果将Relu函数修改为sigmoid函数,这里的情况就有些不同  
  43. class LeNet修改为:  
  44.   
  45. #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  

  46.   
  47. 运行的结果是:收敛的很慢,可能不能使用  
  48. [1/100] Loss: 2.30338, Acc: 10.81  
  49. [2/100] Loss: 2.30207, Acc: 11.10  
  50. [3/100] Loss: 2.30171, Acc: 11.13  
  51. [4/100] Loss: 2.30163, Acc: 11.19  
  52. [5/100] Loss: 2.30157, Acc: 11.23  
  53. [6/100] Loss: 2.30153, Acc: 11.24  
  54. [7/100] Loss: 2.30146, Acc: 11.24  
  55. [8/100] Loss: 2.30152, Acc: 11.24  
  56. [9/100] Loss: 2.30139, Acc: 11.24  
  57. [10/100] Loss: 2.30147, Acc: 11.24  

你可能感兴趣的:(pytorch,深度学习,神经网络)