Pytorch笔记01-Tensor

0. 前言

最近正在学习pytorch,边学习边整理了一下笔记。笔记将会按照各个模块来进行整理,从Tensor,Variable到nn,Module,Function等。将会有更多底层实现的细节,以及自己的理解。希望能够以最形象直白的方式阐述自己的理解,并在每章后综合应用该章知识,以实现灵活应用Pytorch。同时,将会在期间穿插一些有用的工具,如网络可视化等。

1. 本章结构

在本章中,将会主要介绍Pytorch最基本的模块,将包括以下内容:

  1. Tensor的直观理解
  2. Tensor的基本操作:
  • 生成Tensor
  • 基本运算
  • 与Num平移的转换
  • 在GPU上计算
  • 只利用Tensor完成简单3层神经网络
  • 2. Tensor直观理解

    • 数值计算:直观理解Tensor就类似Numpy中的array,是一个n维数组,专门用于在pytorch中做数值计算不涉及深度学习网络结构、计算图、梯度计算等
    • GPU加速:不同于Numpy中的array,torch.Tensor能够使用GPU进行加速,一般GPU速度是CPU的50
    • 总结:Tensor是一个单纯的可以用GPU加速的科学计算工具,应与后面介绍的Variable区分开

    3. Tensor基本操作

    Tensor生成

    import torch
    import numpy as np
    
    # 生成未初始化矩阵
    x = torch.Tensor(5, 3)
    
    # 生成随机矩阵
    x = torch.rand(5, 3)
    
    # 得到Tensor size
    print('x.size(): ', x.size())
    # out:('x.size(): ', torch.Size([5, 3]))
    
    # 指定生成的Tensor的数据类型
    dtype = torch.FloatTensor # 使用CPU
    # dtype = torch.cuda.FloatTensor # 使用GPU
    
    x = torch.rand(5, 3).type(dtype)
    print('x.type(): ',x.type())
    # out: ('x.type(): ', 'torch.FloatTensor')

    Tensor基本运算

    Tensor的运算有多种语法实现 具体计算详见:torch – PyTorch 0.1.12 documentation

    # 生成Tensor
    x = torch.randn(2, 3)
    y = torch.randn(2, 3)
    print 'x, y:', x, y
    print
    
    # 下面用4种语法进行Tensor加法
    # 语法1
    print 'x + y: ', x + y
    print
    
    # 语法2
    print 'torch.add(x, y): ', torch.add(x, y)
    print 
    
    # 语法3
    result = torch.Tensor(2, 3)
    torch.add(x, y, out=result)
    print 'torch.add(x, y, result): ', result
    print 
    
    # 语法4:in-place计算,类似'+='运算,此时直接赋值给y。in-place操作都使用`_`作为后缀。例如,x.copy_(y)
    y.add_(x)
    print 'y.add_(x)', y
    

    Tensor与Numpy进行转换

    • torch Tensor可以转换成Numpy arry,反之亦然
    • Tensor与numpy进行转换后,两者的内存位置共享,也就是说Tensor的值改变了,对应Numpy的值也改变,反之亦然
    # 生成Tensor与numpy arrya
    x_tensor = torch.randn(2, 3)
    y_numpy = np.random.randn(2, 3)
    
    # Tensor转换为Numpy
    x_numpy = x_tensor.numpy()
    print 'type(x_numpy):', type(x_numpy)
    
    # Numpy转换为Tensor
    y_tensor = torch.from_numpy(y_numpy)
    print 'y_tensor.type(): ', y_tensor.type()
    
    # 各自对应的Tensor与Numpy共享内存,一变俱变
    x_tensor.add_(1)
    print 'x_tensor after add 1: \n', x_tensor
    print
    print 'x_numpy after add 1: \n', x_numpy
    print
    
    np.add(y_numpy, 2, out=y_numpy)
    print 'y_tensor after add 2: ', y_tensor 
    print 
    print 'y_numpy after add 2: \n', y_numpy
    print 
    
    # 如果没有使用in-place运算,则无法共享内存
    y_numpy = y_numpy + 1
    print 'y_numpy after add 1 without in-place op: \n', y_numpy
    print
    print 'y_tensor after add 1 without in-place op: ', y_tensor

    在GPU上使用Tensor

    x = x.cuda()
    y = y.cuda()
    print 'x + y on GPU: ', x + y
    

    4. 用Tensor建立简单的神经网络

    1. Tensor提供了最基本的数值运算,但神经网络运算就是张量计算,因此可以直接利用Tensor来搭建神经网络
    2. 但由于单纯的Tensor是不具备自动求导的,因此,反向传播需要自己根据梯度公式来实现
    3. 下面我们就简单实现一个3层神经网络
    from sklearn.datasets import load_boston
    from sklearn import preprocessing
    
    dtype = torch.FloatTensor
    # dtype = torch.cuda.FloatTensor
    
    # 载入数据,并预处理
    X, y = load_boston(return_X_y=True)
    X = preprocessing.scale(X[:100,:])
    y = preprocessing.scale(y[:100].reshape(-1, 1))
    
    # 定义超参数
    data_size, D_input, D_output, D_hidden = X.shape[0], X.shape[1], 1, 50
    lr = 1e-5
    epoch = 200000
    
    # 转换为Tensor
    # X = torch.Tensor(X).type(dtype)
    # y = torch.Tensor(y).type(dtype)
    X = torch.from_numpy(X).type(dtype)
    y = torch.from_numpy(y).type(dtype)
    
    # 定义训练参数
    w1 = torch.randn(D_input, D_hidden).type(dtype)
    w2 = torch.randn(D_hidden, D_output).type(dtype)
    
    # 进行训练
    for i in range(epoch):
        
        # 前向传播
        h = torch.mm(X, w1)                # 计算隐层
        h_relu = h.clamp(min=0)            # relu
        y_pred = torch.mm(h_relu, w2)      # 输出层
        
        # loss计算,使用L2损失函数
        loss = (y_pred - y).pow(2).sum()
        
        if i % 10000 == 0:
            print('epoch: {} loss: {}'.format(i, loss))
        
        # 反向传播,计算梯度
        grad_y_pred = 2.0 * (y_pred - y)
        grad_w2 = h_relu.t().mm(grad_y_pred)
        grad_h_relu = grad_y_pred.mm(w2.t())
        grad_h = grad_h_relu.clone()
        grad_h[h < 0] = 0
        grad_w1 = X.t().mm(grad_h)
    
        # 更新计算的梯度
        w1 -= lr * grad_w1
        w2 -= lr * grad_w2
    

    5. 总结

    • Tensor是pytorch中最基本的模块
    • Tensor实现了多种数值运算,一个Tensor就像是一个能通过GPU加上的Numpy array
    • 但Tensor不具备自动求导机制,因此无法通过Tensor实现自动求导
    • 后续的Variable为了自动求导而实现的,需要与Tensor进行区分

    所有代码都可以在我的github中找到XavierLinNow/pytorch_note_CN

        原文作者:林梅林
        原文地址: https://zhuanlan.zhihu.com/p/27018802
        本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
    点赞