Pytorch笔记---2.CNN

在使用pytorch搭建神经网络的时候,有两个最常用的包:torch.nn和torch.optim。torch.nn包中主要包含了用来搭建各个层的模块(Modules),比如全连接、二维卷积、池化等;
1.
torch.nn包中还包含了一系列有用的loss函数,这些函数也是在训练神经网络时必不可少的,比如CrossEntropyLoss、MSELoss等;
2.
torch.nn.functional子包中包含了常用的激活函数,如relu、leaky_relu、prelu、sigmoid等。
3.
torch.optim包则主要包含了用来更新参数的优化算法,比如SGD、AdaGrad、RMSProp、 Adam等。

torch.nn 与 torch.nn.functional 的区别

1.从 relu 的多种实现来看 torch.nn 与 torch.nn.functional 的区别与联系:传送门

2.或从.conv2d看torch.nn 与 torch.nn.functional 的区别:从中我们可以发现,nn.Conv2d是一个类,而F.conv2d()是一个函数,而nn.Conv2d的forward()函数实现是用F.conv2d()实现的(在Module类里的__call__实现了forward()函数的调用,所以当实例化nn.Conv2d类时,forward()函数也被执行了,详细可阅读torch源码),所以两者功能并无区别,那么为什么要有这样的两种实现方式同时存在呢?

原因其实在于,为了兼顾灵活性和便利性。

在建图过程中,往往有两种层,一种如全连接层,卷积层等,当中有Variable,另一种如Pooling层,Relu层等,当中没有Variable。

如果所有的层都用nn.functional来定义,那么所有的Variable,如weights,bias等,都需要用户来手动定义,非常不方便。

而如果所有的层都换成nn来定义,那么即便是简单的计算都需要建类来做,而这些可以用更为简单的函数来代替的。
所以在定义网络的时候,如果层内有Variable,那么用nn定义,反之,则用nn.functional定义。(转载:nn.functional和nn区别

log_softmax和softmax的区别:
我的理解是这样的:理论上对于单标签多分类问题,直接经过softmax求出概率分布,然后把这个概率分布用crossentropy做一个似然估计误差。但是softmax求出来的概率分布,每一个概率都是(0,1)的,这就会导致有些概率过小,导致下溢。 考虑到这个概率分布总归是要经过crossentropy的,而crossentropy的计算是把概率分布外面套一个-log 来似然,那么直接在计算概率分布的时候加上log,把概率从(0,1)变为(-∞,0),这样就防止中间会有下溢出。 所以log_softmax说白了就是将本来应该由crossentropy做的套log的工作提到预测概率分布来,跳过了中间的存储步骤,防止中间数值会有下溢出,使得数据更加稳定。 正是由于把log这一步从计算误差提到前面,所以用log_softmax之后,下游的计算误差的function就应该变成NLLLoss(它没有套log这一步,直接将输入取反,然后计算和label的乘积求和平均) 详细见softmax和log_softmax的区别、CrossEntropyLoss() 与 NLLLoss() 的区别、log似然代价函数
其中log_softmax的dim问题可参考:dim问题,跑跑代码很容易理解的
dim

torch.utils.data.DataLoader可见:传送门1传送门2;主要用来将自定义的数据读取接口的输出或者PyTorch已有的数据读取接口的输入按照batch size封装成Tensor,后续只需要再包装成Variable即可作为模型的输入,因此该接口有点承上启下的作用,比较重要。主要包含DataLoader和DataLoaderIter两个类。

SGD+Momentum:SGD+Momentum
eg:

# momentum 动量加速,在SGD函数里指定momentum的值即可
opt_Momentum    = torch.optim.SGD(net_Momentum.parameters(), lr=LR, momentum=0.8)

nn.Conv2d简单说明
卷积操作输出的形状计算公式是这样的:
output_shape = (image_shape-filter_shape+2*padding)/stride + 1
conv2d
1.1首先我们定义一个基于CNN的简单神经网络
这个torchvision是独立于pytorch的关于图#像操作的一些方便工具库。它包含几个数据包(包括mnist详见torchvision

import torch
import numpy as np
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms  #
print("PyTorch Version: ",torch.__version__)
PyTorch Version:  1.0.0
首先我们定义一个基于ConvNet的简单神经网络

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(1, 20, 5, 1) #28*28 ->(28+1-5输出的计算公式,见上)=24*24
        self.conv2 = nn.Conv2d(20, 50, 5, 1)#20 *20
        self.fc1 = nn.Linear(4*4*50, 500)
        self.fc2 = nn.Linear(500, 10)

    def forward(self, x):
        x = F.relu(self.conv1(x))#20*24*24
        x = F.max_pool2d(x, 2, 2)#12*12
        x = F.relu(self.conv2(x))#8*8
        x = F.max_pool2d(x, 2, 2)#4*4
        x = x.view(-1, 4*4*50)
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return F.log_softmax(x, dim=1)
        
mnist_data=datasets.MNIST("E:/path/pytorch_download",train=True,download=False,
                          #transforms.Compose是把数据集变为一个tensor
                          transform=transforms.Compose(
                              [
                                  transforms.ToTensor(),
                              ]
                          ))
#print(mnist_data[2][0].shape)  #mnist_data[x]是图片,mnist_data[x][1]是类别

data=[d[0].data.cpu().numpy() for d in mnist_data]#把图片转为numpy
#print(np.mean(data))
#print(np.std(data))

#下面两个函数,等会会调用
def train(model,device,train_loader,optimizer,epoch):
    model.train()
    #data是图片,target是图片对应的标签
    for idx,(data,target) in enumerate(train_loader):
        data,target=data.to(device),target.to(device)
        pred=model(data) #batch_size=10,pred就是相当于图片经过模型得到的一个预测值(向量(10个类的概率))
        loss=F.nll_loss(pred,target)
        #SGD
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        if idx% 100==0:
            print("Train Epoch:{},iteration:{},loss:{}".format(
                epoch,idx,loss.item()))

def test(model,device,test_loader):
    model.eval()
    total_loss=0.
    correct=0.
    with torch.no_grad():
        #data是图片,target是图片对应的标签
        for idx,(data,target) in enumerate(test_loader):
            data,target=data.to(device),target.to(device)
            output = model(data)
            total_loss+=F.nll_loss(output,target,reduction="sum").item()
            pred = output.argmax(dim=1)  # batch_size=10,pred就是相当于图片经过模型得到的一个预测值(向量(10个类的概率))
            correct+=pred.eq(target.view_as(pred)).sum().item()
            #测试不用sgd
    total_loss/=len(test_loader.dataset)#这里因为上面sum了,所以要除以所以
    acc=correct/len(test_loader.dataset)*100.
    print("Test loss:{},Accuracy:{}".format(total_loss,acc))

device=torch.device("cuda" if torch.cuda.is_available() else "cpu")
batch_size=32
train_loader=torch.utils.data.DataLoader(
    datasets.MNIST("E:/path/pytorch_download",train=True,download=False,
                          #transforms.Compose是把数据集变为一个tensor
                          transform=transforms.Compose([
                                  transforms.ToTensor(),
                                  transforms.Normalize((0.1307,),(0.3081,))])), #图片标准化
    batch_size=batch_size,shuffle=True,
    num_workers=0,pin_memory=True

)
test_loader=torch.utils.data.DataLoader(
    datasets.MNIST("E:/path/pytorch_download",train=False,download=False,
                          #transforms.Compose是把数据集变为一个tensor
                          transform=transforms.Compose([
                                  transforms.ToTensor(),
                                  transforms.Normalize((0.1307,),(0.3081,))])), #图片标准化
    batch_size=batch_size,shuffle=True,
    num_workers=0,pin_memory=True
)
lr=0.01
momentum=0.5
model=Net().to(device)
optimizer=torch.optim.SGD(model.parameters(),lr=lr,momentum=momentum)

num_epochs=2
for epoch in range(num_epochs):
    train(model,device,train_loader,optimizer,epoch)
    test(model,device,test_loader)
save_model = True
if (save_model):
    torch.save(model.state_dict(),"mnist_cnn.pt")

Batch Normalization:可见:莫凡Normalization
model.train 和 model.eval:传送门

NLLLoss:Softmax后的数值都在0~1之间,所以ln之后值域是负无穷到0。
NLLLoss的结果就是把上面的输出与Label对应的那个值拿出来,再去掉负号,再求均值。
假设我们现在Target是[0,2,1](第一张图片是猫,第二张是猪,第三张是狗)。第一行取第0个元素,第二行取第2个,第三行取第1个,去掉负号,结果是:[0.4155,1.0945,1.5285]。再求个均值,结果是:

在这里插入图片描述
转载:Pytorch详解NLLLoss和CrossEntropyLoss、、PyTorch-损失函数-NLLLoss

view_as (转载:view_as)
返回被视作与给定的tensor相同大小的原tensor。 等效于:
self.view(tensor.size())
具体用法为:
代码
a = torch.Tensor(2, 4)
b = a.view_as(torch.Tensor(4, 2))
print (b)
输出
tensor([[1.3712e-14, 6.4069e+02],
[4.3066e+21, 1.1824e+22],
[4.3066e+21, 6.3828e+28],
[3.8016e-39, 0.0000e+00]])

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值