精华内容
下载资源
问答
  • 最近要学习dqn,项目组用pytorch作为深度学习框架,以此记录pytorch的学习笔记 因为是速成的,一周看的python,半周numpy,到现在一周半的pytorch,如果有错误请大家指出 Mnistpytorch官方代码可以说是非常好的一...

    前言

    最近要学习dqn,项目组用pytorch作为深度学习框架,以此记录pytorch的学习笔记
    因为是速成的,一周看的python,半周numpy,到现在一周半的pytorch,如果有错误请大家指出
    Mnist的pytorch官方代码可以说是非常好的一个案例,这里以我现在的理解能力对其进行了详细注释,后面再给出可用的简化代码,官方代码保证了跨平台的可用性,个人的话许多写法可以去掉。

    全部代码

    from __future__ import print_function
    #这句话是针对python2引入python3的print函数,可以不写
    import argparse
    #一个参数管理包
    import torch
    #pytorch模块包,不用多解释
    import torch.nn as nn
    #nn主要包含了各种网络,例如Linear,Conv2D,Droupout等,详见 https://pytorch.org/docs/stable/nn.html
    import torch.nn.functional as F
    #functional主要包含了各类激活函数,详见 https://pytorch.org/docs/stable/nn.functional.html
    #functional包含了nn的部分网络层功能,但需要额外指定w,b等
    import torch.optim as optim
    #各类优化器的功能包,详见 https://pytorch.org/docs/stable/optim.html
    #优化器的选择一定要注意学习率问题,越快的优化器要用更小的学习率lr才能不发散
    from torchvision import datasets, transforms
    #datasets包含了各类开源的数据集,如果用自己的数据集可以不调用
    #transforms是批量变换成torch类型的功能包,从各种其他类型如numpy转成tensor类型都要用到。
    from torch.optim.lr_scheduler import StepLR
    #这是学习率衰减函数,为了在后期更好地下降到梯度为0的点,但不加影响也不大,后期在一定范围内震荡
    
    
    class Net(nn.Module):
        def __init__(self):
            super(Net, self).__init__()#使用父类的所有__init__功能
            self.conv1 = nn.Conv2d(1, 32, 3, 1)
            #28*28*1->26*26*32
            self.conv2 = nn.Conv2d(32, 64, 3, 1)
            #26*26*32->24*24*64
            #注意这里的卷积核大小是64*32*3*3,而不是2*3*3,可见卷积的参数量极其庞大
            self.dropout1 = nn.Dropout(0.25)
            self.dropout2 = nn.Dropout(0.5)
            self.fc1 = nn.Linear(9216, 128)
            #9216 = 12*12*64128作为全连接的过渡层
            self.fc2 = nn.Linear(128, 10)
    
        def forward(self, x):
            x = self.conv1(x)
            x = F.relu(x)
            x = self.conv2(x)
            x = F.relu(x)
            x = F.max_pool2d(x, 2)
            #最大池化,相比平均池化特征更明显,24*24*64->12*12*64
            x = self.dropout1(x)
            x = torch.flatten(x, 1)
            x = self.fc1(x)
            x = F.relu(x)
            x = self.dropout2(x)
            x = self.fc2(x)
            output = F.log_softmax(x, dim=1)
            #log_softmax激活函数一定要搭配 nll_loss() 损失函数处理分类问题
            #如果直接输出x,则可以用 CrossEntropyLoss() 损失函数处理分类问题,见莫凡教程
            #两者区别不大 CrossEntropyLoss() 在内部求了 log_softmax(x,dim =1)return output
    
    
    def train(args, model, device, train_loader, optimizer, epoch):
        model.train()
        #注意和test时的 model.eval()区分,这里启用 BatchNormalization 和 Dropout
        for batch_idx, (data, target) in enumerate(train_loader):
        # enumerate()将数据组合为可索引的序列,并返回下标
            data, target = data.to(device), target.to(device)
            # 将输入数据,期望值传入到cuda中,如果用gpu必须写,不然和net无法连通
            optimizer.zero_grad()
            #梯度归零
            output = model(data)
            #计算输出值,整个batch的输出值,返回一个tensor
            loss = F.nll_loss(output, target)
            #计算loss,具体哪种loss对应哪种问题自行查阅
            loss.backward()
            #误差的反向计算,更新梯度
            optimizer.step()
            #由算出来的梯度进行优化
            if batch_idx % args.log_interval == 0:
            #训练时的输出
                print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
                    epoch, batch_idx * len(data), len(train_loader.dataset),
                    100. * batch_idx / len(train_loader), loss.item()))
                # .item()取torch变量的数据值
                if args.dry_run:
                    break
    
    
    def test(model, device, test_loader):
        model.eval()
        #计算测试样本的效果时,这里不启用 BatchNormalization 和 Dropout
        test_loss = 0
        correct = 0
        with torch.no_grad():
        #确保不进行梯度计算
            for data, target in test_loader:
                data, target = data.to(device), target.to(device)
                output = model(data)
                test_loss += F.nll_loss(output, target, reduction='sum').item()  # sum up batch loss
                pred = output.argmax(dim=1, keepdim=True)  # get the index of the max log-probability
                correct += pred.eq(target.view_as(pred)).sum().item()
                # a.view_as(b)与reshape类似,将a变成b的维度格式。 a.eq(b)计算数值相等,返回bool类型列表。
    
        test_loss /= len(test_loader.dataset)
    
        print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
            test_loss, correct, len(test_loader.dataset),
            100. * correct / len(test_loader.dataset)))
    
    
    def main():
        # Training settings
        parser = argparse.ArgumentParser(description='PyTorch MNIST Example')
        parser.add_argument('--batch-size', type=int, default=64, metavar='N',
                            help='input batch size for training (default: 64)')
        parser.add_argument('--test-batch-size', type=int, default=1000, metavar='N',
                            help='input batch size for testing (default: 1000)')
        parser.add_argument('--epochs', type=int, default=14, metavar='N',
                            help='number of epochs to train (default: 14)')
        parser.add_argument('--lr', type=float, default=1.0, metavar='LR',
                            help='learning rate (default: 1.0)')
        parser.add_argument('--gamma', type=float, default=0.7, metavar='M',
                            help='Learning rate step gamma (default: 0.7)')
        parser.add_argument('--no-cuda', action='store_true', default=False,
                            help='disables CUDA training')
        parser.add_argument('--dry-run', action='store_true', default=False,
                            help='quickly check a single pass')
        parser.add_argument('--seed', type=int, default=1, metavar='S',
                            help='random seed (default: 1)')
        parser.add_argument('--log-interval', type=int, default=10, metavar='N',
                            help='how many batches to wait before logging training status')
        parser.add_argument('--save-model', action='store_true', default=False,
                            help='For Saving the current Model')
        args = parser.parse_args()
        use_cuda = not args.no_cuda and torch.cuda.is_available()
    
        torch.manual_seed(args.seed)
    
        device = torch.device("cuda" if use_cuda else "cpu")
    	#是否使用GPU计算
    	
        train_kwargs = {'batch_size': args.batch_size}
        test_kwargs = {'batch_size': args.test_batch_size}
        if use_cuda:
            cuda_kwargs = {'num_workers': 4,
            			   #同时使用的线程数,>2个加载数据集速度会变快
                           'pin_memory': True,
                           #如果使用gpu计算,则要先锁内存
                           'shuffle': True}
                           #是否打乱顺序
            train_kwargs.update(cuda_kwargs)
            #python字典的update方法,将两个字典合并
            test_kwargs.update(cuda_kwargs)
        #通过创建字典作为DataLoader的形参
    
        transform=transforms.Compose([
            transforms.ToTensor(),
            #将数据集numpy等类型转成tensor类型,并且初始化为-11之间的值
            transforms.Normalize((0.1307,), (0.3081,))
            #正则化,可以不要
            ])
        dataset1 = datasets.MNIST('../data', train=True, download=True,
                           transform=transform)
                           #加载训练数据集,并做变换
        dataset2 = datasets.MNIST('../data', train=False,
                           transform=transform)
                           #加载测试集
        train_loader = torch.utils.data.DataLoader(dataset1,**train_kwargs)
        #用dataloader生成用于批训练的数据集
        test_loader = torch.utils.data.DataLoader(dataset2, **test_kwargs)
    
        model = Net().to(device)
        #生成net对象并传送至gpu
        optimizer = optim.Adadelta(model.parameters(), lr=args.lr)
        #使用Adadelta优化函数,注意各种优化函数的学习率选择,大多数时候默认值就可以
    
        scheduler = StepLR(optimizer, step_size=1, gamma=args.gamma)
        #学习率衰减
        for epoch in range(1, args.epochs + 1):
            train(args, model, device, train_loader, optimizer, epoch)
            test(model, device, test_loader)
            scheduler.step()
    
        if args.save_model:
            torch.save(model.state_dict(), "mnist_cnn.pt")
            #这里是保存的w,b的参数值,没有保存整个模型
    
    if __name__ == '__main__':
        main()
    

    简化了一点点的代码,换了Cross_entropy损失函数

    import torch
    import torch.nn as nn
    import torch.nn.functional as F 
    import torch.optim as optim
    from torchvision import datasets,transforms
    import torch.utils.data as Data 
    
    class Net(nn.Module):
        def __init__(self):
            super(Net,self).__init__()
            self.conv1 = nn.Conv2d(1,32,3,1,1)
            self.conv2 = nn.Conv2d(32,64,3,1,1)
            self.dropout1 = nn.Dropout(0.25)
            self.dropout2 = nn.Dropout(0.25)
            self.fc1 = nn.Linear(14*14*64,128)
            self.fc2 = nn.Linear(128,10)
    
        def forward(self,x):
            x = self.conv1(x)
            x = F.relu(x)
            x = self.conv2(x)
            x = F.relu(x)
            x = F.max_pool2d(x,2)
            x = self.dropout1(x)
    
            x = torch.flatten(x,1)
            x = self.fc1(x)
            x = F.relu(x)
            x = self.dropout2(x)
            x = self.fc2(x)
            #直接输出的话用F.cross_entropy()
            output = F.log_softmax(x,dim=1)
            #套用log_softmax()输出后用nll_loss()
            return output,x
    
    def train(model,device,train_loader,optimizer,epochs):
        model.train()
        for batch_idx,(data,target) in enumerate(train_loader):
            data,target = data.to(device),target.to(device)
            optimizer.zero_grad()
            output,x= model(data)
            loss = F.cross_entropy(x,target)
            #loss = F.nll_loss(output,target)
            loss.backward()
            optimizer.step()
    
            if batch_idx%10 ==0:
                print('train epochs:{} [{}/{} ({:.0f}%)]\t Loss: {:.6f}'.format(
                    epochs,batch_idx*len(data),len(train_loader.dataset),
                    100.*batch_idx/len(train_loader),loss.item()
                ))
    
    def test(model,device,test_loader):
        model.eval()
        test_loss = 0
        correct = 0
        with torch.no_grad():
            for data,target in test_loader:
                data,target = data.to(device),target.to(device)
                output,x= model(data)
                test_loss += F.cross_entropy(x,target,reduction='sum').item()
                #test_loss += F.nll_loss(output,target,reduction='sum').item()
                pred = output.argmax(dim = 1,keepdim = True)
                correct += pred.eq(target.view_as(pred)).sum().item()
        test_loss /= len(test_loader.dataset)
    
        print('\nTest set: Average loss: {:.6f}, Accuracy: {}/{} ({:.3f}%)\n'.format(
            test_loss,correct,len(test_loader.dataset),
            100.*correct/len(test_loader.dataset)))
    
    def main():
        device = torch.device('cuda')
    
        transform = transforms.ToTensor()
    
        datasets1 = datasets.MNIST('../data',train = True,download=True,transform=transform)
        datasets2 = datasets.MNIST('../data',train = False,transform=transform)
    
        train_kws = {'batch_size':64,'num_workers':4,'pin_memory':True,'shuffle':True}
        test_kws = {'batch_size':1000,'num_workers':2,'pin_memory':True,'shuffle':True}
    
        train_loader = Data.DataLoader(datasets1,**train_kws)
        test_loader = Data.DataLoader(datasets2,**test_kws)
    
        model = Net().to(device)
        optimizer = optim.Adam(model.parameters(),lr = 0.001)
        for epoch in range(10):
            train(model,device,train_loader,optimizer,epoch)
            test(model,device,test_loader)
    
        torch.save(model,'net1.pt')
    
    if __name__ == '__main__':
        main()
    
    展开全文
  • 动手学深度学习 by Mu Li @ Amazon AI Apache MXNet으로 배워보는 딥러닝(Deep Learning) - 김무현 (AWS 솔루션즈아키텍트) Visualization t-SNE on Fashion-MNIST (left) and original MNIST (right) PCA on ...
  • PyTorch深度学习:60分钟入门(Translation) 胡莱人形 6 个月前 某天在微博上看到@爱可可-爱生活 老师推了Pytorch的入门教程,就顺手下来翻了。虽然完工的比较早但是手头菜的没有linux服务器没法子运行结果。开学...
    PyTorch深度学习:60分钟入门(Translation)

    PyTorch深度学习:60分钟入门(Translation)

    胡莱人形 胡莱人形
    6 个月前
    某天在微博上看到@爱可可-爱生活 老师推了Pytorch的入门教程,就顺手下来翻了。虽然完工的比较早但是手头菜的没有linux服务器没法子运行结果。开学以来终于在师兄的机器装上了Torch,中间的运行结果也看明白了。所以现在发一下这篇两周之前做的教程翻译。

    首先惯例上原文链接,特别的原作者是以ipyhton notebook来写的教程,运行相当的方便。但带来的问题就是翻译作为专栏文章的效果实在是太差。

    原文档链接在此:Deep Learning with PyTorch.ipynb

    特别注明:原教程是以ipython notebook写就,因此代码部分非常零散,我在翻译的过程中将部分代码进行了整合以保证文章的紧凑,翻译的目的是将教程说明部分表达完整,具体的代码运行步骤请移步Github下载源文件进行代码的运行。

    以下是教程的主体部分:

    本教程的目的:

    • 更高层级地理解PyTorch的Tensor库以及神经网络。
    • 训练一个小的神经网络来对图像进行分类。

    本教程以您拥有一定的numpy基础的前提下展开

    Note: 务必确认您已经安装了 torch torchvision 两个包。

    PyTorch是什么?

    这是一个基于Python的科学计算包,其旨在服务两类场合:

    • 替代numpy发挥GPU潜能
    • 一个提供了高度灵活性和效率的深度学习实验性平台

    我们开搞

    Tensors

    Tensors和numpy中的ndarrays较为相似, 因此Tensor也能够使用GPU来加速运算。

    from __future__ import print_function
    import torch
    x = torch.Tensor(5, 3)  # 构造一个未初始化的5*3的矩阵
    x = torch.rand(5, 3)  # 构造一个随机初始化的矩阵
    x # 此处在notebook中输出x的值来查看具体的x内容
    x.size()
    
    #NOTE: torch.Size 事实上是一个tuple, 所以其支持相关的操作*
    y = torch.rand(5, 3)
    
    #此处 将两个同形矩阵相加有两种语法结构
    x + y # 语法一
    torch.add(x, y) # 语法二
    
    # 另外输出tensor也有两种写法
    result = torch.Tensor(5, 3) # 语法一
    torch.add(x, y, out=result) # 语法二
    y.add_(x) # 将y与x相加
    
    # 特别注明:任何可以改变tensor内容的操作都会在方法名后加一个下划线'_'
    # 例如:x.copy_(y), x.t_(), 这俩都会改变x的值。
    
    #另外python中的切片操作也是资次的。
    x[:,1] #这一操作会输出x矩阵的第二列的所有值
    

    阅读材料

    100+ Tensor的操作,包括换位、索引、切片、数学运算、线性算法和随机数等等。

    详见:torch - PyTorch 0.1.9 documentation

    Numpy桥

    将Torch的Tensor和numpy的array相互转换简直就是洒洒水啦。注意Torch的Tensor和numpy的array会共享他们的存储空间,修改一个会导致另外的一个也被修改。

    # 此处演示tensor和numpy数据结构的相互转换
    a = torch.ones(5)
    b = a.numpy()
    
    # 此处演示当修改numpy数组之后,与之相关联的tensor也会相应的被修改
    a.add_(1)
    print(a)
    print(b)
    
    # 将numpy的Array转换为torch的Tensor
    import numpy as np
    a = np.ones(5)
    b = torch.from_numpy(a)
    np.add(a, 1, out=a)
    print(a)
    print(b)
    
    # 另外除了CharTensor之外,所有的tensor都可以在CPU运算和GPU预算之间相互转换
    # 使用CUDA函数来将Tensor移动到GPU上
    # 当CUDA可用时会进行GPU的运算
    if torch.cuda.is_available():
        x = x.cuda()
        y = y.cuda()
        x + y
    

    PyTorch中的神经网络

    接下来介绍pytorch中的神经网络部分。PyTorch中所有的神经网络都来自于autograd包

    首先我们来简要的看一下,之后我们将训练我们第一个的神经网络。

    Autograd: 自动求导

    autograd 包提供Tensor所有操作的自动求导方法。
    这是一个运行时定义的框架,这意味着你的反向传播是根据你代码运行的方式来定义的,因此每一轮迭代都可以各不相同。

    以这些例子来讲,让我们用更简单的术语来看看这些特性。

    autograd.Variable 这是这个包中最核心的类。 它包装了一个Tensor,并且几乎支持所有的定义在其上的操作。一旦完成了你的运算,你可以调用 .backward()来自动计算出所有的梯度。

    你可以通过属性 .data 来访问原始的tensor,而关于这一Variable的梯度则集中于 .grad 属性中。

    还有一个在自动求导中非常重要的类 Function。

    Variable 和 Function 二者相互联系并且构建了一个描述整个运算过程的无环图。每个Variable拥有一个 .creator 属性,其引用了一个创建Variable的 Function。(除了用户创建的Variable其 creator 部分是 None)。

    如果你想要进行求导计算,你可以在Variable上调用.backward()。 如果Variable是一个标量(例如它包含一个单元素数据),你无需对backward()指定任何参数,然而如果它有更多的元素,你需要指定一个和tensor的形状想匹配的grad_output参数。

    from torch.autograd import Variable
    x = Variable(torch.ones(2, 2), requires_grad = True)
    y = x + 2
    y.creator
    
    # y 是作为一个操作的结果创建的因此y有一个creator 
    z = y * y * 3
    out = z.mean()
    
    # 现在我们来使用反向传播
    out.backward()
    
    # out.backward()和操作out.backward(torch.Tensor([1.0]))是等价的
    # 在此处输出 d(out)/dx
    x.grad
    

    最终得出的结果应该是一个全是4.5的矩阵。设置输出的变量为o。我们通过这一公式来计算:

    o = \frac{1}{4}\sum_i z_iz_i = 3(x_i+2)^2z_i\bigr\rvert_{x_i=1} = 27,因此,\frac{\partial o}{\partial x_i} = \frac{3}{2}(x_i+2),最后有\frac{\partial o}{\partial x_i}\bigr\rvert_{x_i=1} = \frac{9}{2} = 4.5

    你可以使用自动求导来做许多疯狂的事情。
    x = torch.randn(3)
    x = Variable(x, requires_grad = True)
    y = x * 2
    while y.data.norm() < 1000:
        y = y * 2
    gradients = torch.FloatTensor([0.1, 1.0, 0.0001])
    y.backward(gradients)
    x.grad
    

    阅读材料

    你可以在这读更多关于Variable 和 Function的文档: pytorch.org/docs/autograd.html

    神经网络

    使用 torch.nn 包可以进行神经网络的构建。

    现在你对autograd有了初步的了解,而nn建立在autograd的基础上来进行模型的定义和微分。

    nn.Module中包含着神经网络的层,同时forward(input)方法能够将output进行返回。

    举个例子,来看一下这个数字图像分类的神经网络。

    这是一个简单的前馈神经网络。 从前面获取到输入的结果,从一层传递到另一层,最后输出最后结果。

    一个典型的神经网络的训练过程是这样的:

    • 定义一个有着可学习的参数(或者权重)的神经网络
    • 对着一个输入的数据集进行迭代:
      • 用神经网络对输入进行处理
      • 计算代价值 (对输出值的修正到底有多少)
      • 将梯度传播回神经网络的参数中
      • 更新网络中的权重
        • 通常使用简单的更新规则: weight = weight + learning_rate * gradient

    让我们来定义一个神经网络:

    import torch.nn as nn
    import torch.nn.functional as F
    
    class Net(nn.Module):
        def __init__(self):
            super(Net, self).__init__()
            self.conv1 = nn.Conv2d(1, 6, 5) # 1 input image channel, 6 output channels, 5x5 square convolution kernel
            self.conv2 = nn.Conv2d(6, 16, 5)
            self.fc1   = nn.Linear(16*5*5, 120) # an affine operation: y = Wx + b
            self.fc2   = nn.Linear(120, 84)
            self.fc3   = nn.Linear(84, 10)
    
        def forward(self, x):
            x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2)) # Max pooling over a (2, 2) window
            x = F.max_pool2d(F.relu(self.conv2(x)), 2) # If the size is a square you can only specify a single number
            x = x.view(-1, self.num_flat_features(x))
            x = F.relu(self.fc1(x))
            x = F.relu(self.fc2(x))
            x = self.fc3(x)
            return x
        
        def num_flat_features(self, x):
            size = x.size()[1:] # all dimensions except the batch dimension
            num_features = 1
            for s in size:
                num_features *= s
            return num_features
    
    net = Net()
    net
    
    '''神经网络的输出结果是这样的
    Net (
      (conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1))
      (conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
      (fc1): Linear (400 -> 120)
      (fc2): Linear (120 -> 84)
      (fc3): Linear (84 -> 10)
    )
    '''
    

    仅仅需要定义一个forward函数就可以了,backward会自动地生成。

    你可以在forward函数中使用所有的Tensor中的操作。

    模型中可学习的参数会由net.parameters()返回。

    params = list(net.parameters())
    print(len(params))
    print(params[0].size()) # conv1's .weight
    
    input = Variable(torch.randn(1, 1, 32, 32))
    out = net(input)
    '''out 的输出结果如下
    Variable containing:
    -0.0158 -0.0682 -0.1239 -0.0136 -0.0645  0.0107 -0.0230 -0.0085  0.1172 -0.0393
    [torch.FloatTensor of size 1x10]
    '''
    
    net.zero_grad() # 对所有的参数的梯度缓冲区进行归零
    out.backward(torch.randn(1, 10)) # 使用随机的梯度进行反向传播
    

    注意: torch.nn 只接受小批量的数据

    整个torch.nn包只接受那种小批量样本的数据,而非单个样本。 例如,nn.Conv2d能够结构一个四维的TensornSamples x nChannels x Height x Width。

    如果你拿的是单个样本,使用input.unsqueeze(0)来加一个假维度就可以了。

    复习一下前面我们学到的:

    • torch.Tensor - 一个多维数组
    • autograd.Variable - 改变Tensor并且记录下来操作的历史记录。和Tensor拥有相同的API,以及backward()的一些API。同时包含着和张量相关的梯度。
    • nn.Module - 神经网络模块。便捷的数据封装,能够将运算移往GPU,还包括一些输入输出的东西。
    • nn.Parameter - 一种变量,当将任何值赋予Module时自动注册为一个参数。
    • autograd.Function - 实现了使用自动求导方法的前馈和后馈的定义。每个Variable的操作都会生成至少一个独立的Function节点,与生成了Variable的函数相连之后记录下操作历史。
    到现在我们已经明白的部分:
    • 定义了一个神经网络。
    • 处理了输入以及实现了反馈。
    仍然没整的:
    • 计算代价。
    • 更新网络中的权重。

    一个代价函数接受(输出,目标)对儿的输入,并计算估计出输出与目标之间的差距。

    nn package包中一些不同的代价函数.

    一个简单的代价函数:nn.MSELoss计算输入和目标之间的均方误差。

    举个例子:

    output = net(input)
    target = Variable(torch.range(1, 10))  # a dummy target, for example
    criterion = nn.MSELoss()
    loss = criterion(output, target)
    '''loss的值如下
    Variable containing:
     38.5849
    [torch.FloatTensor of size 1]
    '''
    

    现在,如果你跟随loss从后往前看,使用.creator属性你可以看到这样的一个计算流程图:

    input -> conv2d -> relu -> maxpool2d -> conv2d -> relu -> maxpool2d  
          -> view -> linear -> relu -> linear -> relu -> linear 
          -> MSELoss
          -> loss
    

    因此当我们调用loss.backward()时整个图通过代价来进行区分,图中所有的变量都会以.grad来累积梯度。

    # For illustration, let us follow a few steps backward
    print(loss.creator) # MSELoss
    print(loss.creator.previous_functions[0][0]) # Linear
    print(loss.creator.previous_functions[0][0].previous_functions[0][0]) # ReLU
    
    '''
    <torch.nn._functions.thnn.auto.MSELoss object at 0x7fe8102dd7c8>
    <torch.nn._functions.linear.Linear object at 0x7fe8102dd708>
    <torch.nn._functions.thnn.auto.Threshold object at 0x7fe8102dd648>
    '''
    
    # 现在我们应当调用loss.backward(), 之后来看看 conv1's在进行反馈之后的偏置梯度如何
    net.zero_grad() # 归零操作
    print('conv1.bias.grad before backward')
    print(net.conv1.bias.grad)
    loss.backward()
    print('conv1.bias.grad after backward')
    print(net.conv1.bias.grad)
    
    ''' 这些步骤的输出结果如下
    conv1.bias.grad before backward
    Variable containing:
     0
     0
     0
     0
     0
     0
    [torch.FloatTensor of size 6]
    
    conv1.bias.grad after backward
    Variable containing:
     0.0346
    -0.0141
     0.0544
    -0.1224
    -0.1677
     0.0908
    [torch.FloatTensor of size 6]
    '''
    

    现在我们已经了解如何使用代价函数了。

    阅读材料

    神经网络包中包含着诸多用于神经网络的模块和代价函数,带有文档的完整清单在这里: torch.nn - PyTorch 0.1.9 documentation

    只剩下一个没学了:

    • 更新网络的权重

    最简单的更新的规则是随机梯度下降法(SGD):

    weight = weight - learning_rate * gradient

    我们可以用简单的python来表示:

    learning_rate = 0.01
    for f in net.parameters():
        f.data.sub_(f.grad.data * learning_rate)
    

    然而在你使用神经网络的时候你想要使用不同种类的方法诸如:SGD, Nesterov-SGD, Adam, RMSProp, etc.

    我们构建了一个小的包torch.optim来实现这个功能,其中包含着所有的这些方法。 用起来也非常简单:

    import torch.optim as optim
    # create your optimizer
    optimizer = optim.SGD(net.parameters(), lr = 0.01)
    
    # in your training loop:
    optimizer.zero_grad() # zero the gradient buffers
    output = net(input)
    loss = criterion(output, target)
    loss.backward()
    optimizer.step() # Does the update
    

    就是这样。

    但你现在也许会想。

    那么数据怎么办呢?

    通常来讲,当你处理图像,声音,文本,视频时需要使用python中其他独立的包来将他们转换为numpy中的数组,之后再转换为torch.*Tensor。

    • 图像的话,可以用Pillow, OpenCV。
    • 声音处理可以用scipy和librosa。
    • 文本的处理使用原生Python或者Cython以及NLTK和SpaCy都可以。

    特别的对于图像,我们有torchvision这个包可用,其中包含了一些现成的数据集如:Imagenet, CIFAR10, MNIST等等。同时还有一些转换图像用的工具。 这非常的方便并且避免了写样板代码。

    本教程使用CIFAR10数据集。 我们要进行的分类的类别有:'airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck'。 这个数据集中的图像都是3通道,32x32像素的图片。

    下面是对torch神经网络使用的一个实战练习。

    训练一个图片分类器

    我们要按顺序做这几个步骤:

    1. 使用torchvision来读取并预处理CIFAR10数据集
    2. 定义一个卷积神经网络
    3. 定义一个代价函数
    4. 在神经网络中训练训练集数据
    5. 使用测试集数据测试神经网络

    1. 读取并预处理CIFAR10

    使用torchvision读取CIFAR10相当的方便。

    import torchvision
    import torchvision.transforms as transforms
    
    
    # torchvision数据集的输出是在[0, 1]范围内的PILImage图片。
    # 我们此处使用归一化的方法将其转化为Tensor,数据范围为[-1, 1]
    
    transform=transforms.Compose([transforms.ToTensor(),
                                  transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),
                                 ])
    trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
    trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, 
                                              shuffle=True, num_workers=2)
    
    testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform)
    testloader = torch.utils.data.DataLoader(testset, batch_size=4, 
                                              shuffle=False, num_workers=2)
    classes = ('plane', 'car', 'bird', 'cat',
               'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
    '''注:这一部分需要下载部分数据集 因此速度可能会有一些慢 同时你会看到这样的输出
    
    Downloading http://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz to ./data/cifar-10-python.tar.gz
    Extracting tar file
    Done!
    Files already downloaded and verified
    '''
    

    我们来从中找几张图片看看。

    # functions to show an image
    import matplotlib.pyplot as plt
    import numpy as np
    %matplotlib inline
    def imshow(img):
        img = img / 2 + 0.5 # unnormalize
        npimg = img.numpy()
        plt.imshow(np.transpose(npimg, (1,2,0)))
    
    # show some random training images
    dataiter = iter(trainloader)
    images, labels = dataiter.next()
    
    # print images
    imshow(torchvision.utils.make_grid(images))
    # print labels
    print(' '.join('%5s'%classes[labels[j]] for j in range(4)))
    

    结果是这样的:

    2. 定义一个卷积神经网络

    class Net(nn.Module):
        def __init__(self):
            super(Net, self).__init__()
            self.conv1 = nn.Conv2d(3, 6, 5)
            self.pool  = nn.MaxPool2d(2,2)
            self.conv2 = nn.Conv2d(6, 16, 5)
            self.fc1   = nn.Linear(16*5*5, 120)
            self.fc2   = nn.Linear(120, 84)
            self.fc3   = nn.Linear(84, 10)
    
        def forward(self, x):
            x = self.pool(F.relu(self.conv1(x)))
            x = self.pool(F.relu(self.conv2(x)))
            x = x.view(-1, 16*5*5)
            x = F.relu(self.fc1(x))
            x = F.relu(self.fc2(x))
            x = self.fc3(x)
            return x
    
    net = Net()
    

    3. 定义代价函数和优化器

    criterion = nn.CrossEntropyLoss() # use a Classification Cross-Entropy loss
    optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
    

    4. 训练网络

    事情变得有趣起来了。 我们只需一轮一轮迭代然后不断通过输入来进行参数调整就行了。

    for epoch in range(2): # loop over the dataset multiple times
        
        running_loss = 0.0
        for i, data in enumerate(trainloader, 0):
            # get the inputs
            inputs, labels = data
            
            # wrap them in Variable
            inputs, labels = Variable(inputs), Variable(labels)
            
            # zero the parameter gradients
            optimizer.zero_grad()
            
            # forward + backward + optimize
            outputs = net(inputs)
            loss = criterion(outputs, labels)
            loss.backward()        
            optimizer.step()
            
            # print statistics
            running_loss += loss.data[0]
            if i % 2000 == 1999: # print every 2000 mini-batches
                print('[%d, %5d] loss: %.3f' % (epoch+1, i+1, running_loss / 2000))
                running_loss = 0.0
    print('Finished Training')
    '''这部分的输出结果为
    [1,  2000] loss: 2.212
    [1,  4000] loss: 1.892
    [1,  6000] loss: 1.681
    [1,  8000] loss: 1.590
    [1, 10000] loss: 1.515
    [1, 12000] loss: 1.475
    [2,  2000] loss: 1.409
    [2,  4000] loss: 1.394
    [2,  6000] loss: 1.376
    [2,  8000] loss: 1.334
    [2, 10000] loss: 1.313
    [2, 12000] loss: 1.264
    Finished Training
    '''
    

    我们已经训练了两遍了。 此时需要测试一下到底结果如何。

    通过对比神经网络给出的分类和已知的类别结果,可以得出正确与否,如果预测的正确,我们可以将样本加入正确预测的结果的列表中。

    好的第一步,让我们展示几张照片来熟悉一下。

    dataiter = iter(testloader)
    images, labels = dataiter.next()
    
    # print images
    imshow(torchvision.utils.make_grid(images))
    print('GroundTruth: ', ' '.join('%5s'%classes[labels[j]] for j in range(4)))
    

    结果是这样的:

    好的,接下来看看神经网络如何看待这几个照片。

    outputs = net(Variable(images))
    
    # the outputs are energies for the 10 classes. 
    # Higher the energy for a class, the more the network 
    # thinks that the image is of the particular class
    
    # So, let's get the index of the highest energy
    _, predicted = torch.max(outputs.data, 1)
    
    print('Predicted: ', ' '.join('%5s'% classes[predicted[j][0]] for j in range(4)))
    
    '''输出结果为
    Predicted:    cat plane   car plane
    '''
    

    结果看起来挺好。

    看看神经网络在整个数据集上的表现结果如何。

    correct = 0
    total = 0
    for data in testloader:
        images, labels = data
        outputs = net(Variable(images))
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum()
    
    print('Accuracy of the network on the 10000 test images: %d %%' % (100 * correct / total))
    
    '''输出结果为
    Accuracy of the network on the 10000 test images: 54 %
    '''
    

    看上去这玩意输出的结果比随机整的要好,随机选择的话从十个中选择一个出来,准确率大概只有10%。

    看上去神经网络学到了点东西。

    嗯。。。那么到底哪些类别表现良好又是哪些类别不太行呢?

    class_correct = list(0. for i in range(10))
    class_total = list(0. for i in range(10))
    for data in testloader:
        images, labels = data
        outputs = net(Variable(images))
        _, predicted = torch.max(outputs.data, 1)
        c = (predicted == labels).squeeze()
        for i in range(4):
            label = labels[i]
            class_correct[label] += c[i]
            class_total[label] += 1
    
    for i in range(10):
        print('Accuracy of %5s : %2d %%' % (classes[i], 100 * class_correct[i] / class_total[i]))
    
    '''输出结果为
    Accuracy of plane : 73 %
    Accuracy of   car : 70 %
    Accuracy of  bird : 52 %
    Accuracy of   cat : 27 %
    Accuracy of  deer : 34 %
    Accuracy of   dog : 37 %
    Accuracy of  frog : 62 %
    Accuracy of horse : 72 %
    Accuracy of  ship : 64 %
    Accuracy of truck : 53 %
    '''
    

    好吧,接下来该怎么搞了?

    我们该如何将神经网络运行在GPU上呢?

    在GPU上进行训练

    就像你把Tensor传递给GPU进行运算一样,你也可以将神经网络传递给GPU。

    这一过程将逐级进行操作,直到所有组件全部都传递到GPU上。

    net.cuda()
    
    '''输出结果为
    Net (
      (conv1): Conv2d(3, 6, kernel_size=(5, 5), stride=(1, 1))
      (pool): MaxPool2d (size=(2, 2), stride=(2, 2), dilation=(1, 1))
      (conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
      (fc1): Linear (400 -> 120)
      (fc2): Linear (120 -> 84)
      (fc3): Linear (84 -> 10)
    )
    '''
    

    记住,每一步都需要把输入和目标传给GPU。

        inputs, labels = Variable(inputs.cuda()), Variable(labels.cuda())
    

    我为什么没有进行CPU运算和GPU运算的对比呢?因为神经网络实在太小了,其中的差距并不明显。

    目标达成:

    • 在更高层级上理解PyTorch的Tensor库和神经网络。
    • 训练一个小的神经网络。

    接下来我该去哪?

    Trans by lawbda,edit in 2017.03.05 15:38

    展开全文
  • pytorch深度学习

    2021-02-25 11:43:52
    pytorch深度学习之路 写在前面:在入门pytorch和深度学习时发现了很多优质资源,分享给大家,希望对大家能有所帮助,同时记录自己的学习过程。 1、PyTorch深度学习实践 传送门:Pyorch深度学习实践 老师讲的非常好,...

    pytorch深度学习之路

    写在前面:在入门pytorch和深度学习时发现了很多优质资源,分享给大家,希望对大家能有所帮助,同时记录自己的学习过程。
    1、PyTorch深度学习实践
    传送门:Pyorch深度学习实践
    老师讲的非常好,在我有了一定基础之后去看这个视频也有了不少新的体会

    贴一段复现的第十讲代码:

    import torch
    from torchvision import datasets
    from torchvision import transforms
    from torch.utils.data import DataLoader
    import torch.nn.functional as F
    import torch.optim as optim
    import matplotlib.pyplot as plt
    
    batch_size = 64
    transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])
    
    train_dataset = datasets.MNIST(root='../dataset/mnist', train=True, download=True, transform=transform)
    train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size)
    test_dataset = datasets.MNIST(root='../dataset/mnist', train=False, download=True, transform=transform)
    test_loader = DataLoader(test_dataset, shuffle=False, batch_size=batch_size)
    
    class Net(torch.nn.Module):
        def __init__(self):
            super(Net, self).__init__()
            self.conv1 = torch.nn.Conv2d(1, 10, kernel_size=5)
            self.conv2 = torch.nn.Conv2d(10, 20, kernel_size=5)
            self.pooling = torch.nn.MaxPool2d(2)
            self.fc = torch.nn.Linear(320, 10)
    
        def forward(self, x):
            batch_size = x.size(0)
            # a = x.shape
            x = F.relu(self.pooling(self.conv1(x)))
            x = F.relu(self.pooling(self.conv2(x)))
            x = x.view(batch_size, -1)
            x = self.fc(x)
            return x
    
    model = Net()
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    model.to(device)
    
    criterion = torch.nn.CrossEntropyLoss()
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
    
    def train(epoch):
        running_loss = 0.0
        for batch_idx, data in enumerate(train_loader, 0):
            inputs, target = data
            # a = data.size
            inputs, target = inputs.to(device), target.to(device)
            optimizer.zero_grad()
    
            outputs = model(inputs)
            loss = criterion(outputs, target)
            loss.backward()
            optimizer.step()
    
            running_loss += loss.item()
            if batch_idx % 300 == 299:
                print('[%d, %5d] loss: %.3f' % (epoch+1, batch_idx+1, running_loss/300))
                running_loss = 0.0
    
    def test():
        correct = 0
        total = 0
        with torch.no_grad():
            for data in test_loader:
                images, labels = data
                images, labels = images.to(device), labels.to(device)
                outputs = model(images)
                _, predicted = torch.max(outputs.data, dim=1)
                total += labels.size(0)
                correct += (predicted == labels).sum().item()
        print('accuracy on test set: %d %%' % (100*correct/total))
        return correct/total
    
    if __name__ == '__main__':
        epoch_list = []
        acc_list = []
    
        for epoch in range(10):
            train(epoch)
            acc = test()
            epoch_list.append(epoch)
            acc_list.append(acc)
    
        plt.plot(epoch_list, acc_list)
        plt.xlabel('epoch')
        plt.ylabel('accuracy')
        plt.show()
    

    运行结果如下:
    在这里插入图片描述
    在这里插入图片描述
    可以看出最后的精度在98%左右,应该是最后只有一层全连接层的原因。而且使用卷积层相比于只用全连接层,精度也只是从97%升到了98%,但是老师说不能这样看,因为我们的错误率从3%降到了2%,性能可是提高了三分之一,哈哈。

    代码比较简单,当时对经过Dataloader之后的数据格式有点好奇,于是加了断点打算看一下
    在这里插入图片描述
    inputs的格式为
    在这里插入图片描述
    target的格式为
    在这里插入图片描述

    然后老师推荐的一些资料:
    pytorch文档:大佬翻译的中文文档
    还有就是深度学习花书,后续打算啃一下,不过听说很难啃。

    2、图像目标检测学习
    另一个大佬up主:目标检测学习
    大佬讲了很多网络的理论,然后对着代码教你怎么看,确实对我这个萌新比较友好。
    目前看了SSD,Faster-rcnn的理论和部分代码,后续打算看看yolo的理论和代码

    展开全文
  • 深度学习领域还有其他一些流行的数据集,这些数据集常被用于建立不同算法的性能基准: MNIST; COCO数据集; CIFAR; The Street View House Numbers; PASCAL VOC; Wikipedia dump; 20 Newsgroups; Penn Tree...
  • Pytorch深度学习入门

    千次阅读 多人点赞 2018-12-08 21:03:37
    title: Pytorch深度学习入门 mathjax: false date: 2018-12-06 12:34:12 categories: - 深度学习 tags: - 深度学习 - Pytorch 在本教程中,将使用PyTorch框架介绍深度学习,并通过一个案例进行实验,通过本教程,你...

    在本教程中,将使用Pytorch框架介绍深度学习,并通过一个简单案例进行实验,通过本教程,你将可以轻松地使用Pytorch框架构建深度学习模型。(我也刚刚接触Pytorch)

    Pytorch 简介

    Pytorch 是一个基于 Torch 的 Python 机器学习包,而 Torch 则是一个基于编程语言 Lua 的开源机器学习包。Pytorch 有两个主要的特点:

    • 利用强大的 GPU 加速进行张量计算(如 NumPy)
    • 用于构建和训练神经网络的自动微分机制

    相比其它深度学习库,Pytorch 具有以下两点优势:

    • 与 TensorFlow 等其它在运行模型之前必须先定义整个计算图的库不同,Pytorch 允许动态定义图。
    • Pytorch 也非常适合深度学习研究,提供了最大的灵活性和运行速度。

    Tensors

    Pytorch 张量与 NumPy 数组非常相似,而且它们可以在 GPU 上运行。这一点很重要,因为它有助于加速数值计算,从而可以将神经网络的速度提高 50 倍甚至更多。为了使用 Pytorch,你需要先访问其官网并安装 Pytorch。如果你正在使用 Conda,你可以通过运行以下简单命令来安装Pytorch:

    conda install PyTorch torchvision -c PyTorch
    

    为了定义 Pytorch 张量,首先需要导入 torch 包。PyTorch 允许你定义两种类型的张量,即 CPU 和 GPU 张量。在本教程中,假设你运行的是使用 CPU 进行深度学习运算的机器,但我也会向你展示如何在 GPU 中定义张量:

    import torch
    

    Pytorch 的默认张量类型是一个浮点型张量,定义为torch.FloatTensor。例如,你可以根据 Python 的 list 数据结构创建张量:

    torch.FloatTensor([[20, 30, 40], [90, 60, 70]])
    

    如果你使用的是支持 GPU 的机器,你可以通过以下方法定义张量:

    torch.cuda.FloatTensor([[20, 30, 40], [90, 60, 70]])
    

    你也可以使用 Pytorch 张量执行加法和减法等数学运算:

    x = torch.FloatTensor([25])
    y = torch.FloatTensor([30])
    x + y
    

    你还可以定义矩阵并执行矩阵运算。我们来看看如何定义一个矩阵然后将其转置:

    matrix = torch.randn(4, 5)
    matrix
    matrix.t()
    

    Autograd 机制

    Pytorch 使用了一种叫做自动微分的技术,它可以对函数的导数进行数值估计。自动微分在神经网络中计算反向传递(backward pass)。在训练过程中,神经网络的权重被随机初始化为接近零但不是零的数。反向传递是指从右到左调整权重的过程,而正向传递则是从左到右调整权重的过程。

    torch.autograd是 Pytorch 中支持自动微分的库。这个包的核心类是torch.Tensor。如果你想要跟踪这个类的所有操作,请将.requires_grad设置为 True。如果要计算所有的梯度,请调用.backward()。这个张量的梯度将在.grad属性中积累。

    如果你想要从计算历史中分离出一个张量,请调用.detach()函数。这也可以防止将来对张量的计算被跟踪。另一种防止历史跟踪的方法是用torch.no_grad()方法封装代码。

    你可以将张量Tensor和函数Function类相连接,构建一个编码了完整计算历史的无环图。张量的.grad_fn属性会引用创建了这个张量的Function。如果你要计算导数,可以调用张量的.backward()。如果该张量包含一个元素,你不需要为backward()函数指定任何参数。如果张量包含多个元素,你需要指定一个规模(shape)相匹配的张量的梯度。

    例如,你可以创建两个张量,将其中一个张量的requires_grad设定为 True,将另一个的设定为 False。接着你可以用这两个张量来执行加法和求和运算。然后你可以计算其中一个张量的梯度。

    a = torch.tensor([3.0, 2.0], requires_grad=True)
    b = torch.tensor([4.0, 7.0])
    ab_sum = a + b
    ab_sum
    ab_res = (ab_sum*8).sum()
    ab_res.backward()
    ab_res
    a.grad
    

    b上调用.grad的返回值为空,因为你没有将它的requires_grad设置为 True。

    nn 模块

    这是在 Pytorch 中构建神经网络的模块。nn模块依赖于autograd来定义模型并对其进行微分处理。首先,定义训练一个神经网络的过程:

    • 用一些可学习的参数(即权重)定义神经网络
    • 在输入的数据集上进行迭代
    • 通过网络处理输入
    • 将预测结果和实际值进行比较,并测量误差
    • 将梯度传播回网络的参数中
    • 使用简单的更新规则更新网络的权重:weight = weight - learning_rate * gradient

    现在,你可以使用nn模块创建一个双层的神经网络:

    N, D_in, H, D_out = 64, 1000, 100, 10
    x = torch.randn(N, D_in)
    y = torch.randn(N, D_out)
    model = torch.nn.Sequential(
    torch.nn.Linear(D_in, H),
    torch.nn.ReLU(),
    torch.nn.Linear(H, D_out),
    )
    loss_fn = torch.nn.MSELoss()
    learning_rate = 1e-4
    

    在这里我们将解释一下上面用到的参数:

    • N 是批处理大小。批处理大小是观测数据的数量,观测之后权重将被更新。

    • D_in: 是输入的维度

    • H: 是隐藏层的维度

    • D_out: 是输出层的维度

    • torch.randn: 定义了指定维度的矩阵

    • torch.nn.Sequential :初始化了神经网络层的线性堆栈

    • torch.nn.Linear: 对输入数据应用了线性变换

    • torch.nn.ReLU: 在元素层级上应用了ReLU激活函数

    • torch.nn.MSELoss: 创建了一个标准来度量输入 x 和目标 y 中 n 个元素的均方误差

    optim 模块

    接下来,你要使用 optim 包来定义一个优化器,该优化器将为你更新权重。optim 包抽象出了优化算法的思想,并提供了常用优化算法(如 AdaGrad、RMSProp 和 Adam)的实现。我们将使用 Adam 优化器,它是最流行的优化器之一。

    该优化器接受的第一个参数是张量,这些张量需要更新。在正向传递中,你要通过向模型传递 x 来计算出预测的 y。然后,计算并显示出损失。在运行反向传递之前,你要将使用优化器更新的所有变量的梯度设置为零。这样做的原因是,默认情况下,在调用.backward()方法时,梯度不会被重写。然后,你需要在优化器上调用step函数,该步骤会更新其参数。具体的实现代码如下所示:

     optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
     for t in range(500):
    	  y_pred = model(x)
    	  loss = loss_fn(y_pred, y)
    	  print(t, loss.item())
    	  optimizer.zero_grad()
    	  loss.backward()
    	  optimizer.step()
    

    自定义的 nn 模块

    有时你需要构建自己的自定义模块。这种情况下,你需要创建nn.Module的子类,然后定义一个接收输入张量并产生输出张量的 forward。使用nn.Module实现双层网络的方法如下图所示。这个模型与上面的模型非常相似,但不同之处在于你要使用torch.nn.Module创建神经网络。另一个区别是这个模型会使用 stochastic gradient descent optimizer 而不是 Adam。你可以使用下面的代码实现一个自定义的 nn 模块:

    import torch
    class TwoLayerNet(torch.nn.Module):
        def __init__(self, D_in, H, D_out):
            super(TwoLayerNet, self).__init__()
            self.linear1 = torch.nn.Linear(D_in, H)
            self.linear2 = torch.nn.Linear(H, D_out)
        def forward(self, x):
            h_relu = self.linear1(x).clamp(min=0)
            y_pred = self.linear2(h_relu)
            return y_pred
    N, D_in, H, D_out = 64, 1000, 100, 10
    x = torch.randn(N, D_in)
    y = torch.randn(N, D_out)
    model = TwoLayerNet(D_in, H, D_out)
    criterion = torch.nn.MSELoss()
    optimizer = torch.optim.SGD(model.parameters(), lr=1e-4)
    for t in range(500):
        y_pred = model(x)
        loss = criterion(y_pred, y)
        print(t, loss.item())
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
    

    案例

    上面介绍完一些Pytorch的基础之后,接下来,我们将通过一个完整地案例进一步加深对Pytorch的认识。

    我们将按照下列目录进行实验:

    --- pytorchFashion
    | |--- __init__.py
    | |--- callback
    | |--- config
    | |--- dataset
    | |--- output
    | |--- test
    | |--- train
    | |--- io
    | |--- model
    | | |--- __init__.py
    | | |--- cnn
    | | | |--- __init__.py
    | | | |--- alexnet.py
    | |--- preprocessing
    | |--- utils
    

    简单地对每个目录进行说明,其中:

    • callback: 我们自定义的callback
    • config: 整个实验的配置文件目录
    • dataset: 数据集目录
    • output:实验输出目录
    • test: 预测器目录
    • train:训练器目录
    • io: 数据交互目录
    • model: 模型目录
    • preprocessing: 数据预处理目录
    • utils: 常用工具目录

    我们主要以常见的FashionMNIST数据集进行实验。

    FashionMNIST

    FashionMNIST 是一个替代 MNIST 手写数字集 的图像数据集。 它是由 Zalando(一家德国的时尚科技公司)旗下的研究部门提供。其涵盖了来自 10 种类别的共 7 万个不同商品的正面图片。

    FashionMNIST 的大小、格式和训练集/测试集划分与原始的 MNIST 完全一致。60000/10000 的训练测试数据划分,28x28 的灰度图片。你可以直接用它来测试你的机器学习和深度学习算法性能,且不需要改动任何的代码。说白了就是手写数字没有衣服鞋子之类的更复杂。

    数据案例如下所示:

    备注: 该数据集可以从地址进行下载。

    实际上,Pytorch模块中已经包含了下载以及处理FashionMNIST数据的脚本,我们只需运行:

        transform = transforms.Compose([transforms.ToTensor(),
                                        transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
        train_dataset = datasets.FashionMNIST(root='./dataset/fashion',
                                              train=True,
                                              download=False,
                                              transform=transform)
        test_dataset = datasets.FashionMNIST(root='./dataset/fashion',
                                             train=False,
                                             download=False,
                                             transform=transform)
        # Loading dataset into dataloader
        trainIter = torch.utils.data.DataLoader(dataset=train_dataset,
                                                   batch_size=batch_size,
                                                   shuffle=True)
        valIter = torch.utils.data.DataLoader(dataset=test_dataset,
                                                  batch_size=batch_size,
                                                  shuffle=False)
    

    之后会在./dataset/fashion目录中生成一份数据集,之后,我们就可以使用torch.utils.data.DataLoader进行加载。

    各个模块的代码可以从github上获取,这里将不详细描述。

    我们主要实现run.py脚本文件,详细代码可看源文件。在pytorchFashion同目录下新建一个run.py文件,并写入以下代码:

    #encoding:utf-8
    import argparse
    import torch
    import numpy as np
    from torch.optim import Adam
    import torchvision.transforms as transforms
    import torchvision.datasets as datasets
    from pytorchFashion.train.trainer import Trainer
    from pytorchFashion.utils.logginger import init_logger
    from pytorchFashion.config import alexnet_config as config
    from pytorchFashion.train.losses import CrossEntropy
    from pytorchFashion.train.metrics import Accuracy
    from pytorchFashion.callback.lrscheduler import StepLr
    from pytorchFashion.io.data_loader import ImageDataIter
    from pytorchFashion.model.cnn.alexnet import AlexNet
    from pytorchFashion.callback.earlystopping import EarlyStopping
    from pytorchFashion.callback.modelcheckpoint import ModelCheckpoint
    from pytorchFashion.callback.trainingmonitor import TrainingMonitor
    from pytorchFashion.callback.writetensorboard import WriterTensorboardX
    

    首先,我们加载所需模块,可以看到大部分都是我们自定义的模块。接下里,我们定义一个执行的主函数main(),如下:

    def main():
        # 路径变量
        checkpoint_dir = config.CHECKPOINT_PATH # checkpoint路径
        fig_path = config.FIG_PATH
        json_path = config.JSON_PATH
        # 初始化日志
        logger = init_logger(log_name=config.ARCH,
                             log_path=config.LOG_PATH)
        if args['seed'] is not None:
            logger.info("seed is %d"%args['seed'])
            np.random.seed(args['seed'])
            torch.manual_seed(args['seed'])
    

    其中 :

    • checkpoint_dir:模型保存路径
    • fig_path:训练结果可视化保存路径
    • json_path:训练指标变化保存路径

    另外,我们还初始化一个日志记录器logger,记录整个实验过程。以及一个固定的随机种子变量seed(保证结果可复现)。

    接着,加载数据,即:

        # 加载数据集
        logger.info('starting load train data from disk')
        transform = transforms.Compose([transforms.ToTensor(),
                                        transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
        train_dataset = datasets.FashionMNIST(root='./dataset/fashion',
                                              train=True,
                                              download=True,
                                              transform=transform)
        test_dataset = datasets.FashionMNIST(root='./dataset/fashion',
                                             train=False,
                                             download=True,
                                             transform=transform)
        # Loading dataset into dataloader
        trainIter = torch.utils.data.DataLoader(dataset=train_dataset,
                                                   batch_size=config.BATCH_SIZE,
                                                   shuffle=True)
        valIter = torch.utils.data.DataLoader(dataset=test_dataset,
                                                  batch_size=config.BATCH_SIZE,
                                                  shuffle=False)
    

    其中,transform负责整个数据转换过程,需要注意的是transforms.ToTensor()将变量转化为张量时,默对每张图片像素除以256操作,所以,你会看到我们在进行归一化时,传入的各个通道均值位于0到1之间。

    定义好数据之后,接下来,初始化模型和优化器,即:

        # 初始化模型和优化器
        logger.info("initializing model")
        model = SimpleNet(num_classes = config.NUM_CLASSES)
        optimizer = Adam(params = model.parameters(),
                         lr = config.LEARNING_RATE,
                         weight_decay=config.WEIGHT_DECAY,
                        )
    

    其中,SimpleNet是我们自定义的一个简单卷积神经网络,并且使用Adam优化器进行训练。

    下面,初始化callback模块:

     # 写入TensorBoard
        logger.info("initializing callbacks")
        write_summary = WriterTensorboardX(writer_dir=config.WRITER_PATH,
                                           logger = logger,
                                           enable=True)
        # 模型保存
        model_checkpoint = ModelCheckpoint(checkpoint_dir=checkpoint_dir,
                                           mode= config.MODE,
                                           monitor=config.MONITOR,
                                           save_best_only= config.SAVE_BEST_ONLY,
                                           arch = config.ARCH,
                                           logger = logger)
        # eraly_stopping功能
        early_stop = EarlyStopping(mode = config.MODE,
                                   patience = config.PATIENCE,
                                   monitor = config.MONITOR)
        # 监控训练过程
        train_monitor = TrainingMonitor(fig_path = fig_path,
                                        json_path = json_path,
                                        arch = config.ARCH)
        lr_scheduler = StepLr(optimizer=optimizer,lr = config.LEARNING_RATE)
    

    其中:

    • write_summary: 主要是负责将数据写入文件中,以便于使用tensorboard工具进行可视化。
    • model_checkpoint: 保存模型,这里默认是保存最佳模型,当然也可以指定epoch频率保存模型。
    • early_stop:当模型在训练过程中,如果模型持续一段时间不再学习,那么使用该功能可以自动停止训练模型。
    • train_monitor:模型训练过程中的监控器,主要记录各个指标变化情况。
    • lr_scheduler:学习率变化模式,我们知道一般刚开始训练模型时,应设置一个大的学习率,当模型不断接近最小值时,应设置一个小的学习率。

    初始化模型训练器:

        logger.info('training model....')
        trainer = Trainer(model = model,
                          train_data = trainIter,
                          val_data = valIter,
                          optimizer = optimizer,
                          criterion=CrossEntropy(),
                          metric = Accuracy(topK=config.TOPK),
                          logger = logger,
                          config = config,
                          model_checkpoint = model_checkpoint,
                          training_monitor = train_monitor,
                          early_stopping = early_stop,
                          writer= write_summary,
                          train_from_scratch=config.RESUME,
                          lr_scheduler=lr_scheduler
                          )
    

    开始训练模型:

        # 查看模型结构
        trainer.summary()
        # 拟合模型
        trainer.train()
    if __name__ == '__main__':
        ap = argparse.ArgumentParser(description='PyTorch model training')
        ap.add_argument('-s','--seed',default=1024,type = int,
                            help = 'seed for initializing training.')
        args = vars(ap.parse_args())
        main()
    
    

    以上,我们完成了整个训练模型脚本,接下来运行下列命令进行模型训练:

    python run.py
    

    在训练结束之后,在output目录,你可以看到两个文件,分别记录了loss和accuracy的变化情况,即:
    在这里插入图片描述

    备注:完整代码可从:github下载

    展开全文
  • PyTorch学习笔记6—PyTorch深度学习入门(四)—入门实例
  • PyTorch 深度学习:60分钟快速入门

    万次阅读 多人点赞 2017-11-29 19:38:18
    一个深度学习援救平台:提供最大的灵活性和速度 开始 张量(Tensors) 张量类似于numpy的ndarrays,不同之处在于张量可以使用GPU来加快计算。 from __future__ import print_function import...
  • PyTorch学习笔记5—PyTorch深度学习入门(三)—神经网络
  • 小白能学懂的深度学习,利用FashionMNIST数据集以及pytorch,进行图像识别,该文章详细的讲解了代码,以及编程框架。 让你充分理解代码的每一个角落
  • ), (0.3081,)) ]) train_dataset = datasets.MNIST(root="./mnistDataset/", train=True, transform=transform, download=True) test_dataset = datasets.MNIST(root="./mnistDataset/", train=False, transform=...
  • pytorch深度学习-CNN google Net
  • # 手写数字识别(MNIST数据集) import torch import torchvision from torchvision import datasets,transforms #处理计算机视觉相关问题的包 from torch.autograd import Variable #自动求导包 import time #记录...
  • mnist.py import torch import torch.nn as nn from torch.autograd import Variable from torch.utils. data import DataLoader from torchvision import datasets, transforms import...
  • PyTorchAuthor:IouwillMachine Learning Lab 之前笔者提到了PyTorch的专属可视化工具visdom,参看PyTorch深度学习训练可视化...
  • PyTorch深度学习实践》学习笔记 【4】 学习资源: 《PyTorch深度学习实践》完结合集 六、Logistics Regression(逻辑斯蒂回归模型) 虽然它叫做回归模型,但是处理的是分类问题 6.0 回归问题和分类问题 有监督...
  • 课程链接:《PyTorch深度学习实践》9.多分类问题 课上示例 示例程序源代码+注释(根据个人理解) import torch from torchvision import transforms # 图像处理工具 from torchvision import datasets from torch....
  • 课程链接:Pytorch 深度学习实践——多分类问题 1、Loss Function - Cross Entropy ①Cross Entropy in Numpy import numpy as np z = np.array([0.2, 0.1, -0.1]) y = np.array([1, 0, 0]) y_pred = np.exp(z) / ...
  • Pytorch深度学习之RNN

    2021-03-20 15:42:23
    这里使用RNN中的LSTM对MNIST数据集做了分类。   首先对这个代码做一个简要概述,我自己的理解:     ①写在开头,这里采用的RNN中的长短期记忆LSTM是将RNN进行提升的一种算法,具体...
  • 深度学习是机器学习的一个子领域,它使用受大脑神经网络的结构和功能启发的算法。 深度学习中使用的神经网络为人工神经网络(ANN) ...使用PyTorch进行深度学习 PyTorch是一个深度学习框架和科学计算软件包。 ...
  • B站刘二大人老师的《PyTorch深度学习实践》Lecture_06 重点回顾+代码复现 Lecture_06 逻辑回归 Logistic Regression 一、重点回顾
  • PyTorch 深度学习实践 第9讲

    千次阅读 多人点赞 2020-11-14 11:15:05
    B站 刘二大人,传送门PyTorch深度学习实践——多分类问题 视频中截图 说明: 1、softmax的输入不需要再做非线性变换,也就是说softmax之前不再需要激活函数(relu) 2、y的标签编码方式是one-hot。我对one-hot的...
  • pytorch学习视频——《PyTorch深度学习实践》完结合集_哔哩哔哩_bilibili 以下是视频内容笔记以及视频中的手敲源码,可能会有些许改动,笔记纯属个人理解,如有错误勿介或者欢迎路过的大佬指出 。 1. torchversion...
  • 把通道放在前面是为了在PyTorch里面进行更高效的图像处理,卷积运算 所以拿到图像之后,我们就把它先转化成pytorch里面的一个Tensor,把0到255的值变成0到1的浮点数,然后把维度由2828变成128*28的张量,由单通道...
  • PyTorch 深度学习实践 第11讲

    千次阅读 多人点赞 2020-11-14 18:35:44
    B站 刘二大人,传送门PyTorch深度学习实践——卷积神经网络(高级篇) 视频中截图: 说明:Inception Moudel 1、卷积核超参数选择困难,自动找到卷积的最佳组合。 2、1x1卷积核,不同通道的信息融合。 代码...
  • PyTorch 深度学习的技巧

    千次阅读 2019-04-11 12:16:33
    7. 深度学习的技巧过拟合与欠拟合欠拟合过拟合交叉验证数据划分K-flod 交叉验证正则化奥卡姆剃刀原理防止过拟合的方法正则化L1范数L2范数动量与学习率衰减动量学习率衰减提前停止更新与 dropout提前停止更新dropout ...
  • PyTorch 深度学习实践 第10讲

    千次阅读 多人点赞 2020-11-14 15:12:40
    B站 刘二大人,传送门PyTorch深度学习实践——卷积神经网络(基础篇) 视频中截图: 说明 1、每一个卷积核它的通道数量要求和输入通道是一样的。这种卷积核的总数有多少个和你输出通道的数量是一样的。 2、卷积...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,963
精华内容 2,385
关键字:

mnistpytorch深度学习