zoukankan      html  css  js  c++  java
  • 【笔记】PyTorch框架学习 -- 1. 张量创建及操作,线性回归的实现

    目录:

    1. PyTorch简介
    2. 张量的概念及创建
    2.1 直接创建Tensor
    2.2 依据数值创建Tensor
    2.3 依据概率分布创建Tensor
    3. 张量的操作
    3.1 张量的拼接和切分
    3.2 张量索引
    3.3 张量变换
    4. 实现线性回归

    1. PyTorch简介

    2017年,FAIR(Facebook AI Research)发布PyTorch,是在Torch框架基础上打造的,(Torch使用Lua语言,受众小未普及)。

    英文文档:https://pytorch.org/docs/stable/index.html
    中文文档:https://pytorch-cn.readthedocs.io/zh/latest/

    本地安装: python, Anaconda, PyCharm, CUDA, cuDNN, torch, torchvision,
    安装指南:https://www.cnblogs.com/yanqiang/p/12749030.html

    返回目录

    2. 张量的概念及创建

    张量就是一个多维数组,是标量(0维)、向量(1维)、矩阵(2维)的拓展。

    Variable: 是torch.autograd中的数据类型。有data(被封装的Tensor),grad(data的梯度),grad_fn(创建Tensor的Function),requires_grad(是否需要梯度),is_leaf(是否为叶子节点)几个属性。

    PyTorch 0.4.0 之后,Variable并入Tensor,还包括有dtype(张量的数据类型,如torch.FloatTensor,torch.cuda.FloatTensor),shape(张量形状),device(张量所在设备,cpu/gpu)。

    返回目录

    2.1 直接创建Tensor

    torch.tensor 功能:从data创建tensor

    import torch
    import numpy as np
    torch.manual_seed(1)
    
    # torch.tensor(data,                # 数据,可以是list, numpy
    #              dtype=None,          # 数据类型,与data一致
    #              device=None,         # 所在设备,cuda/cpu
    #              requires_grad=False, # 是否需要梯度
    #              pin_memory=False)    # 是否需要锁页内存
    
    arr = np.ones((3, 3))
    print("ndarray的数据类型:", arr.dtype) # float64
    
    t = torch.tensor(arr, device='cuda')
    print(t)
    # tensor([[1., 1., 1.],
    #         [1., 1., 1.],
    #         [1., 1., 1.]], device='cuda:0', dtype=torch.float64)
    
    t = torch.tensor(arr)
    print(t)
    # tensor([[1., 1., 1.],
    #         [1., 1., 1.],
    #         [1., 1., 1.]], dtype=torch.float64)
    

    除了这种方式,还有一种是torch.from_numpy(ndarray)方法,从numpy创建tensor,区别在于:这种方式创建的tensor是和原ndarry共享内存的,当其中一个改变,另一个也会改变

    # 测试代码
    arr = np.array([[1, 2, 3], [4, 5, 6]])
    t = torch.from_numpy(arr)
    print("numpy array: ", arr)
    print("tensor : ", t)
    
    print("修改tensor")
    t[0, 0] = -1
    print("numpy array: ", arr)
    print("tensor : ", t)
    

    返回目录

    2.2 依据数值创建Tensor

    torch.zeros 创建全0张量
    torch.zeros_like() 依据input创建全0张量

    # 1.
    # torch.zeros(*size,                # 张量的形状
    #             out=None,             # 输出的张量
    #             dtype=None,
    #             layout=torch.strided, # 内存中布局形式,有strided, sparse_coo等
    #             device=None,
    #             requires_grad=False)
    
    out_t = torch.tensor([1])
    
    t = torch.zeros((3, 3), out=out_t)
    
    print(t, '
    ', out_t)
    # tensor([[0, 0, 0],
    #         [0, 0, 0],
    #         [0, 0, 0]])
    print(id(t), id(out_t), id(t) == id(out_t)) # True 同一个数据,仅命名不同
    
    # 2.
    # torch.zeros_like(input,  # 创建与input形状相同的全0张量
    #                  dtype=None,
    #                  layout=torch.strided,
    #                  device=None,
    #                  requires_grad=False)
    

    torch.ones(), torch.ones_like()类似

    torch.full(), torch.full_like()

    # torch.full(size,        # 张量的形状
    #            fill_value,  # 张量的值
    #            out=None,
    #            dtype=None,
    #            layout=torch.strided,
    #            device=None,
    #            requires_grad=False)
    
    t = torch.full((3, 3), 1)
    print(t)
    
    # tensor([[1., 1., 1.],
    #         [1., 1., 1.],
    #         [1., 1., 1.]])
    

    torch.arange()

    # torch.arange(start=0,        # 数值区间 [start, end)
    #              end,
    #              step=1,         # 数列公差
    #              out=None,
    #              dtype=None,
    #              layout=torch.strided,
    #              device=None,
    #              requires_grad=False)
    
    t = torch.arange(2, 10, 2)
    print(t) # tensor([2, 4, 6, 8])
    

    torch.linspace() 创建均分的一维张量

    # torch.linespace(start,        # 数值区间 [start, end],闭区间
    #                 end,
    #                 step=100,     # 数列长度
    #                 out=None,
    #                 dtype=None,
    #                 layout=torch.strided,
    #                 device=None,
    #                 requires_grad=False)
    
    t = torch.linspace(2, 10, 6) # (10-2)/(6-1)=1.6
    print(t) # tensor([ 2.0000,  3.6000,  5.2000,  6.8000,  8.4000, 10.0000])
    

    torch.logspace() 属性多一个base=10.0,对数底

    torch.eye() 创建对角矩阵

    # torch.eye(n, # 矩阵行数,默认为方阵
    #           m=None,
    #           out=None,
    #           dtype=None,
    #           layout=torch.strided,
    #           device=None,
    #           requires_grad=False)
    

    返回目录

    2.3 依概率分布创建Tensor

    比如,正态分布(高斯分布),均值mean, 标准差std, 分别为标量,张量,共四种模式。

    # torch.normal(mean,
    #              std,
    #              out=None)
    #
    # torch.normal(mean,
    #              std,
    #              size,
    #              out=None)
    #
    # 1. mean:张量 std: 张量
    mean = torch.arange(1, 5, dtype=torch.float)
    std = torch.arange(1, 5, dtype=torch.float)
    t_normal = torch.normal(mean, std)
    print("mean:{}
    std:{}".format(mean, std))
    print(t_normal)
    # mean:tensor([1., 2., 3., 4.])
    # std:tensor([1., 2., 3., 4.])
    # tensor([1.6614, 2.5338, 3.1850, 6.4853])
    # mean和std各位置一一对应
    
    # 2. mean:标量 std: 标量
    t_normal = torch.normal(0., 1., size=(4,))
    print(t_normal)
    # tensor([-0.4519, -0.1661, -1.5228,  0.3817])
    
    # 3. mean:张量 std: 标量
    mean = torch.arange(1, 5, dtype=torch.float)
    std = 1
    t_normal = torch.normal(mean, std)
    print("mean:{}
    std:{}".format(mean, std))
    print(t_normal)
    # mean:tensor([1., 2., 3., 4.])
    # std:1
    # tensor([-0.0276,  1.4369,  2.1077,  3.9417])
    
    # 4. mean: 标量 std: 张量
    mean = 1
    std = torch.arange(1, 5, dtype=torch.float)
    t_normal = torch.normal(mean, std)
    print("mean:{}
    std:{}".format(mean, std))
    print(t_normal)
    # mean:1
    # std:tensor([1., 2., 3., 4.])
    # tensor([ 0.8045, -0.9313,  2.2672,  2.0693])
    

    返回目录

    3. 张量操作

    张量的操作包括:拼接、切分、索引、变换。

    3.1 张量的拼接和切分

    张量的拼接 torch.cat() torch.stack()
    stack()会扩张张量维度,cat()不会

    # torch.cat(tensors,
    #           dim=0,
    #           out=None)
    #
    # torch.stack(tensors,
    #             dim=0,
    #             out=None)
    
    t = torch.ones((2, 3))
    
    t_0 = torch.cat([t, t], dim=0)
    # t_0:tensor([[1., 1., 1.],
    #         [1., 1., 1.],
    #         [1., 1., 1.],
    #         [1., 1., 1.]]) shape:torch.Size([4, 3])
    
    t_1 = torch.cat([t, t, t], dim=1)
    # t_1:tensor([[1., 1., 1., 1., 1., 1., 1., 1., 1.],
    #         [1., 1., 1., 1., 1., 1., 1., 1., 1.]]) shape:torch.Size([2, 9])
    
    print("t_0:{} shape:{}
    t_1:{} shape:{}".format(t_0, t_0.shape, t_1, t_1.shape))
    
    t = torch.ones((2, 3))
    
    t_stack = torch.stack([t, t, t], dim=0)
    # t_stack:tensor([[[1., 1., 1.],
    #          [1., 1., 1.]],
    # 
    #         [[1., 1., 1.],
    #          [1., 1., 1.]],
    # 
    #         [[1., 1., 1.],
    #          [1., 1., 1.]]]) shape:torch.Size([3, 2, 3])
    
    print("
    t_stack:{} shape:{}".format(t_stack, t_stack.shape))
    

    torch.chunk() 将张量按维度dim进行平均切分
    返回值:张量列表,若不能整除,最后一个张量小于其他张量

    torch.split() 功能更强大,可以指定切分的长度

    # torch.chunk(input,
    #             chunks, # 要切分的份数
    #             dim=0)
    
    a = torch.ones((2, 7))  # 7
    list_of_tensors = torch.chunk(a, dim=1, chunks=3)   # 3
    
    # 第1个张量:tensor([[1., 1., 1.],
    #         [1., 1., 1.]]), shape is torch.Size([2, 3])
    # 第2个张量:tensor([[1., 1., 1.],
    #         [1., 1., 1.]]), shape is torch.Size([2, 3])
    # 第3个张量:tensor([[1.],
    #         [1.]]), shape is torch.Size([2, 1])
    
    for idx, t in enumerate(list_of_tensors):
        print("第{}个张量:{}, shape is {}".format(idx+1, t, t.shape))
    
    # torch.split(tensor,
    #             split_size_or_sections, # int, 每一份的长度, list, 按list元素切分
    #             dim=0)
    
    t = torch.ones((2, 5))
    list_of_tensors = torch.split(t, [2, 1, 2], dim=1)
    
    # 第1个张量:tensor([[1., 1.],
    #         [1., 1.]]), shape is torch.Size([2, 2])
    # 第2个张量:tensor([[1.],
    #         [1.]]), shape is torch.Size([2, 1])
    # 第3个张量:tensor([[1., 1.],
    #         [1., 1.]]), shape is torch.Size([2, 2])
    
    for idx, t in enumerate(list_of_tensors):
        print("第{}个张量:{}, shape is {}".format(idx+1, t, t.shape))
    

    返回目录

    3.2 张量索引

    torch.index_select() 在维度dim上,按index索引数据

    torch.masked_select() 按mask中的True进行索引,返回值:一维张量

    # torch.index_select(input,
    #                    dim,
    #                    index,
    #                    out=None)
    
    t = torch.randint(0, 9, size=(3, 3))
    idx = torch.tensor([0, 2], dtype=torch.long)    # float
    t_select = torch.index_select(t, dim=0, index=idx)
    
    # t:
    # tensor([[4, 5, 0],
    #         [5, 7, 1],
    #         [2, 5, 8]])
    # t_select:
    # tensor([[4, 5, 0],
    #         [2, 5, 8]])
    
    print("t:
    {}
    t_select:
    {}".format(t, t_select))
    
    # torch.masked_select(input,
    #                     mask,
    #                     out=None)
    
    t = torch.randint(0, 9, size=(3, 3))
    mask = t.le(5)  # ge is mean greater than or equal/   gt: greater than  le  lt
    t_select = torch.masked_select(t, mask)
    
    # t:
    # tensor([[0, 2, 3],
    #         [1, 8, 4],
    #         [0, 3, 6]])
    # mask:
    # tensor([[ True,  True,  True],
    #         [ True, False,  True],
    #         [ True,  True, False]])
    # t_select:
    # tensor([0, 2, 3, 1, 4, 0, 3])
    
    print("t:
    {}
    mask:
    {}
    t_select:
    {} ".format(t, mask, t_select))
    

    返回目录

    3.3 张量变换

    torch.reshape()
    当张量在内存中是连续的时,新张量与input共享数据内存

    # torch.reshape(input,
    #               shape)
    
    t = torch.randperm(8)
    t_reshape = torch.reshape(t, (-1, 2, 2))    # -1 根据其他维度计算,不需要关心
    print("t:{}
    t_reshape:
    {}".format(t, t_reshape))
    
    # t:tensor([5, 4, 2, 6, 7, 3, 1, 0])
    # t_reshape:
    # tensor([[[5, 4],
    #          [2, 6]],
    #
    #         [[7, 3],
    #          [1, 0]]])
    
    t[0] = 1024
    print("t:{}
    t_reshape:
    {}".format(t, t_reshape))
    print("t.data 内存地址:{}".format(id(t.data)))
    print("t_reshape.data 内存地址:{}".format(id(t_reshape.data)))
    
    # t:tensor([1024,    4,    2,    6,    7,    3,    1,    0])
    # t_reshape:
    # tensor([[[1024,    4],
    #          [   2,    6]],
    # 
    #         [[   7,    3],
    #          [   1,    0]]])
    # t.data 内存地址:2461063346072
    # t_reshape.data 内存地址:2461063346072
    

    torch.transpose() 交换张量的两个维度
    torch.t() 2维张量转置,相当于torch.transpose(input, 0, 1)

    # torch.transpose(input,
    #                 dim0,
    #                 dim1)
    # torch.t(input)
    
    t = torch.rand((2, 3, 4))
    t_transpose = torch.transpose(t, dim0=1, dim1=2)    # c*h*w     h*w*c
    print("t shape:{}
    t_transpose shape: {}".format(t.shape, t_transpose.shape))
    
    # t shape:torch.Size([2, 3, 4])
    # t_transpose shape: torch.Size([2, 4, 3])
    

    torch.squeeze() 压缩长度为1的维度,dim为None,移除所有长度为1的轴,dim指定时,移除指定维度的。

    torch.unsqueeze() 依据dim扩展维度

    # torch.squeeze(input,
    #               dim=None,
    #               out=None)
    #
    # torch.unsqueeze(input,
    #                 dim,
    #                 out=None)
    
    t = torch.rand((1, 2, 3, 1))
    t_sq = torch.squeeze(t)
    t_0 = torch.squeeze(t, dim=0)
    t_1 = torch.squeeze(t, dim=1)
    t_u = torch.unsqueeze(t_sq, dim=1)
    print(t.shape)      # torch.Size([1, 2, 3, 1])
    print(t_sq.shape)   # torch.Size([2, 3])
    print(t_0.shape)    # torch.Size([2, 3, 1])
    print(t_1.shape)    # torch.Size([1, 2, 3, 1])
    print(t_u.shape)    # torch.Size([2, 1, 3])
    

    t_0 = torch.randn((3, 3))
    t_1 = torch.ones_like(t_0)
    t_add = torch.add(t_0, 10, t_1)
    
    print("t_0:
    {}
    t_1:
    {}
    t_add_10:
    {}".format(t_0, t_1, t_add))
    
    # t_0:
    # tensor([[ 0.6614,  0.2669,  0.0617],
    #         [ 0.6213, -0.4519, -0.1661],
    #         [-1.5228,  0.3817, -1.0276]])
    # t_1:
    # tensor([[1., 1., 1.],
    #         [1., 1., 1.],
    #         [1., 1., 1.]])
    # t_add_10:
    # tensor([[10.6614, 10.2669, 10.0617],
    #         [10.6213,  9.5481,  9.8339],
    #         [ 8.4772, 10.3817,  8.9724]])
    

    返回目录

    4. 实现线性回归

    import torch
    import matplotlib.pyplot as plt
    torch.manual_seed(10)
    
    lr = 0.05  # 学习率
    
    # 创建训练数据
    x = torch.rand(20, 1) * 10          # x data (tensor), shape=(20, 1) rand,  均匀分布中随机抽取
    y = 2*x + (5 + torch.randn(20, 1))  # y data (tensor), shape=(20, 1) randn, 正态分布中随机抽取
    
    # print(x, y)
    
    # 构建线性回归参数
    w = torch.randn((1), requires_grad=True)
    b = torch.zeros((1), requires_grad=True)
    
    for iteration in range(1000):
    
        # 前向传播
        wx = torch.mul(w, x)
        y_pred = torch.add(wx, b)
    
        # 计算 MSE loss
        loss = (0.5 * (y - y_pred) ** 2).mean()
    
        # 反向传播
        loss.backward()
    
        # 更新参数
        b.data.sub_(lr * b.grad) # 下划线表示原地操作 in-place,不产生返回值,不会产生副本
        w.data.sub_(lr * w.grad)
    
        # 清零张量的梯度
        w.grad.zero_()
        b.grad.zero_()
    
        # 绘图
        if iteration % 20 == 0:
    
            plt.scatter(x.data.numpy(), y.data.numpy())
            plt.plot(x.data.numpy(), y_pred.data.numpy(), 'r-', lw=5)
            plt.text(2, 20, 'Loss=%.4f' % loss.data.numpy(), fontdict={'size': 20, 'color':  'red'})
            plt.xlim(1.5, 10)
            plt.ylim(8, 28)
            plt.title("Iteration: {}
    w: {} b: {}".format(iteration, w.data.numpy(), b.data.numpy()))
            plt.pause(0.5)
    
            if loss.data.numpy() < 1:
                break
    

    返回目录

  • 相关阅读:
    tomcat---基本知识点解读;配置文件详解
    nginx常用配置参数介绍-upstream
    nginx配置文件-详解
    nginx简单介绍
    GCC编译已经引入math.h文件提示cos,sin等函数未定义
    进程与进程间通信(3)
    进程与进程间通信(1)
    进程与进程间通信(2)
    primer_c++_迭代器
    primer_C++_3.5 数组
  • 原文地址:https://www.cnblogs.com/yanqiang/p/12748578.html
Copyright © 2011-2022 走看看