栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

numpy和tensor(numpy和tensorflow的关系)

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

numpy和tensor(numpy和tensorflow的关系)

Numpy 和 Tensor

文章目录

Numpy 和 Tensor

1、Numpy 与 Tensor

1.1、Tensor 概述1.2、创建 Tensor1.3、修改 Tensor 形状1.4、索引操作1.5、广播机制1.6、逐元素操作1.7、归并操作1.8、比较操作1.9、矩阵操作1.10、Pytorch 与 Numpy 比较 2、Tensor 与 Autograd

2.1、自动求导要点2.2、计算图 3、使用 Numpy 实现机器学习4、使用 Tensor 及 antograd 实现机器学习

1、Numpy 与 Tensor

Tensor,它可以是零维(又称为标量或一个数)、一维、二维及多维的数组。

其自称为神经网络界的 Numpy, 它与 Numpy 相似,它们共享内存,它们之间的转换非常方便和高效。

不过它们也有不同之处,最大的区别就是 Numpy 会把 ndarray 放在 CPU 中加速运算,而由 torch 产生的 tensor 会放在 GPU 中加速运算(假设当前环境有GPU)。

1.1、Tensor 概述

对 tensor 的操作很多,从接口的角度来划分,可以分为两类:

    torch.function,如 torch.sum、torch.add 等,tensor.function,如 tensor.view、tensor.add 等。
如果从修改方式的角度,可以分为以下两类:
    不修改自身数据,如 x.add(y),x 的数据不变,返回一个新的 tensor;修改自身数据,如 x.add_(y)(运行符带下划线后缀),运算结果存在 x 中,x 被修改。
1.2、创建 Tensor

注意 torch.Tensor 与 torch.tensor 的几点区别:

    torch.Tensor 是 torch.empty 和 torch.tensor 之间的一种混合,但是,当传入数据时,torch.Tensor 使用全局默认 dtype(FloatTensor),torch.tensor 从数据中推断数据类型;torch.tensor(1) 返回一个固定值 1,而 torch.Tensor(1) 返回一个大小为 1 的张量,它是随机初始化的值。
1.3、修改 Tensor 形状

torch.view 与 torch.reshape 的异同

    reshape() 可以由 torch.reshape(),也可由 torch.Tensor.reshape() 调用。view() 只可由 torch.Tensor.view() 来调用;对于一个将要被 view 的 Tensor,新的 size 必须与原来的 size 与 stride 兼容。否则,在 view 之前必须调用contiguous() 方法;同样也是返回与 input 数据量相同,但形状不同的 tensor。若满足 view 的条件,则不会 copy,若不满足,则会copy;如果您只想重塑张量,请使用 torch.reshape。 如果您还关注内存使用情况并希望确保两个张量共享相同的数据,请使用 torch.view。
1.4、索引操作

1.5、广播机制

同 Numpy。

1.6、逐元素操作

这些操作均创建新的 tensor,如果需要就地操作,可以使用这些方法的下划线版本,例如 abs_。

1.7、归并操作

归并操作顾名思义,就是对输入进行归并或合计等操作,这类操作的输入输出形状一般不相同,而且往往是输入大于输出形状。归并操作可以对整个 tensor,也可以沿着某个维度进行归并。

归并操作一般涉及一个 dim 参数,指定沿哪个维进行归并。另一个参数是 keepdim,说明输出结果中是否保留维度1,缺省情况是 False,即不保留。 1.8、比较操作

1.9、矩阵操作

torch 的 dot 与 Numpy 的 dot 有点不同,torch 中 dot 对两个为 1D 张量进行点积运算,Numpy 中的 dot 无此限制;mm 是对 2D 的矩阵进行点积,bmm 对含 batch 的 3D 进行点积运算;转置运算会导致存储空间不连续,需要调用 contiguous 方法转为连续。 1.10、Pytorch 与 Numpy 比较


2、Tensor 与 Autograd

在神经网络中,一个重要内容就是进行参数学习,而参数学习离不开求导,Pytorch 是如何进行求导的呢?

torch.autograd 包就是用来自动求导的:

autograd 包为张量上所有的操作提供了自动求导功能,而 torch.Tensor 和 torch.Function 为 autograd 上的两个核心类,他们相互连接并生成一个有向非循环图。

2.1、自动求导要点
    创建叶子节点(leaf node)的 tensor,使用 requires_grad 参数指定是否记录对其的操作,以便之后利用backward() 方法进行梯度求解。requires_grad 参数缺省值为 False,如果要对其求导需设置为 True,与之有依赖关系的节点自动变为 True。可利用 requires_grad_() 方法修改 tensor 的 requires_grad 属性可以调用 .detach() 或 with torch.no_grad():将不再计算张量的梯度,跟踪张量的历史记录。这点在评估模型、测试模型阶段常常使用。通过运算创建的 tensor(即非叶子节点),会自动被赋于 grad_fn 属性。该属性表示梯度函数。叶子节点的 grad_fn为 None。最后得到的 tensor 执行 backward() 函数,此时自动计算各变量的梯度,并将累加结果保存到各自的 grad 属性中。计算完成后,非叶子节点的梯度自动释放。backward() 函数接受参数,该参数应和调用 backward() 函数的 Tensor 的维度相同,或者是可以 broadcast 的维度。如果求导的 tensor 为标量(即一个数字),backward 中参数可省略。反向传播的中间缓存会被清空,如果需要进行多次反向传播,需要指定 backward 中的参数 retain_graph=True。多次反向传播时,梯度是累加的。非叶子节点的梯度 backward 调用后即被清空。可以通过用 torch.no_grad() 包裹代码块来阻止 autograd 去跟踪那些标记为 .requesgrad=True 的张量的历史记录。这步在测试阶段经常使用。

整个过程中,Pytorch 采用计算图的形式进行组织,该计算图为动态图,它的计算图在每次前向传播时,将重新构建。

2.2、计算图

计算图是一种有向无环图像,用图形方式表示算子与变量之间的关系,直观高效。如下图所示,圆形表示变量,矩阵表示算子。

如表达式:z = wx + b,可写成两个表示式:y = wx,则 z = y + b,

    其中 x、w、b 为变量,是用户创建的变量,不依赖于其他变量,故又称为叶子节点。

    为计算各叶子节点的梯度,需要把对应的张量参数 requires_grad 属性设置为True,这样就可自动跟踪其历史记录。

    y、z 是计算得到的变量,非叶子节点,z 为根节点。

    mul 和 add 是算子(或操作或函数)。

由这些变量及算子,就构成一个完整的计算过程(或前向传播过程)。

我们的目标是更新各叶子节点的梯度,根据复合函数导数的链式法则,不难算出各叶子节点的梯度。
∂ z ∂ x = ∂ z ∂ y ∂ y ∂ x = w frac{partial mathrm{z}}{partial mathrm{x}}=frac{partial mathrm{z}}{partial mathrm{y}} frac{partial mathrm{y}}{partial mathrm{x}}=mathrm{w} ∂x∂z​=∂y∂z​∂x∂y​=w

∂ z ∂ w = ∂ z ∂ y ∂ y ∂ w = x frac{partial mathrm{z}}{partial mathrm{w}}=frac{partial mathrm{z}}{partial mathrm{y}} frac{partial mathrm{y}}{partial mathrm{w}}=mathrm{x} ∂w∂z​=∂y∂z​∂w∂y​=x

∂ z ∂ b = 1 frac{partial mathrm{z}}{partial mathrm{b}}=1 ∂b∂z​=1

Pytorch 调用 backward(),将自动计算各节点的梯度,这是一个反向传播过程,这个过程可用下图表示。

在反向传播过程中,autograd 沿着上图,从当前根节点 z 反向溯源,利用导数链式法则,计算所有叶子节点的梯度,其梯度值将累加到 grad 属性中。对非叶子节点的计算操作(或 function)记录在 grad_fn 属性中,叶子节点的 grad_fn 值为 None。


3、使用 Numpy 实现机器学习

首先,我们用最原始的 Numpy 实现有关回归的一个机器学习任务,不用 Pytorch 中的包或类。这种方法代码可能多一点,但每一步都是透明的,有利于理解每步的工作原理。

主要步骤包括:

    首先,是给出一个数组 x,然后基于表达式:y=3x^2+2,加上一些噪音数据到达另一组数据 y;然后,构建一个机器学习模型,学习表达式 y=wx^2+b 的两个参数 w,b。利用数组 x,y 的数据为训练数据;最后,采用梯度梯度下降法,通过多次迭代,学习到 w、b 的值。

    导入需要的库

    import numpy as np
     
    from matplotlib import pyplot as plt
    

    生成输入数据 x 及目标数据 y

    设置随机数种子,生成同一个份数据,以便用多种方法进行比较:

    np.random.seed(100) 
    x = np.linspace(-1, 1, 100).reshape(100,1) 
    y = 3*np.power(x, 2) +2+ 0.2*np.random.rand(x.size).reshape(100,1) 
    

    查看 x,y 数据分布情况

    # 画图
    plt.scatter(x, y)
    plt.show()
    

    初始化权重参数

    # 随机初始化参数
    w1 = np.random.rand(1,1)
    b1 = np.random.rand(1,1) 
    

    训练模型

    定义损失函数,假设批量大小为 100:
    L o s s = 1 2 ∑ i = 1 100 ( w x i 2 + b − y i ) 2 Loss=frac{1}{2}sum^{100}_{i=1}{(wx_i^2+b-y_i)^2} Loss=21​i=1∑100​(wxi2​+b−yi​)2
    对损失函数求导:
    ∂ L o s s ∂ w = ∑ i = 1 100 ( w x i 2 + b − y i ) x i 2 frac{partial{Loss}}{partial{w}}=sum^{100}_{i=1}{(wx_i^2+b-y_i)x_i^2} ∂w∂Loss​=i=1∑100​(wxi2​+b−yi​)xi2​

    ∂ L o s s ∂ b = ∑ i = 1 100 ( w x i 2 + b − y i ) frac{partial{Loss}}{partial{b}}=sum^{100}_{i=1}{(wx_i^2+b-y_i)} ∂b∂Loss​=i=1∑100​(wxi2​+b−yi​)

    利用梯度下降法学习参数,学习率为 l r lr lr:
    w 1 − = l r ∗ ∂ L o s s ∂ w w_1-=lr*frac{partial{Loss}}{partial{w}} w1​−=lr∗∂w∂Loss​

    b 1 − = l r ∗ ∂ L o s s ∂ b b_1-=lr*frac{partial{Loss}}{partial{b}} b1​−=lr∗∂b∂Loss​

    lr =0.001 # 学习率
     
    for i in range(800):
        # 前向传播
        y_pred = np.power(x,2)*w1 + b1
        # 定义损失函数
        loss = 0.5 * (y_pred - y) ** 2
        loss = loss.sum()
        #计算梯度
        grad_w=np.sum((y_pred - y)*np.power(x,2))
        grad_b=np.sum((y_pred - y))
        #使用梯度下降法,是loss最小
        w1 -= lr * grad_w
        b1 -= lr * grad_b
    

    可视化结果

    plt.plot(x, y_pred,'r-',label='predict')
    plt.scatter(x, y,color='blue',marker='o',label='true') # true data
    plt.xlim(-1,1)
    plt.ylim(2,6)  
    plt.legend()
    plt.show()
    print(w1,b1)
    

4、使用 Tensor 及 antograd 实现机器学习

使用 Pytorch 的自动求导的一个包 antograd,利用这个包及对应的 Tensor,便可利用自动反向传播来求梯度,无需手工计算梯度。

    导入需要的库

    import torch as t
    
    from matplotlib import pyplot as plt
    

    生成训练数据,并可视化数据分布情况

    t.manual_seed(100) 
    dtype = t.float
    #生成x坐标数据,x为tenor,需要把x的形状转换为100x1
    x = t.unsqueeze(t.linspace(-1, 1, 100), dim=1) 
    #生成y坐标数据,y为tenor,形状为100x1,另加上一些噪音
    y = 3*x.pow(2) +2+ 0.2*t.rand(x.size())                 
     
    # 画图,把tensor数据转换为numpy数据
    plt.scatter(x.numpy(), y.numpy())
    plt.show()
    

    初始化权重参数

    # 随机初始化参数,参数w,b为需要学习的,故需requires_grad=True
    w = t.randn(1,1, dtype=dtype,requires_grad=True)
    b = t.zeros(1,1, dtype=dtype, requires_grad=True)
    

    训练模型

    lr =0.001 # 学习率
     
    for ii in range(800):
        # 前向传播,并定义损失函数loss
        y_pred = x.pow(2).mm(w) + b
        loss = 0.5 * (y_pred - y) ** 2
        loss = loss.sum()
        
        # 自动计算梯度,梯度存放在grad属性中
        loss.backward()
        
        # 手动更新参数,需要用torch.no_grad(),使上下文环境中切断自动求导的计算
        with t.no_grad():
            w -= lr * w.grad
            b -= lr * b.grad
        
        # 梯度清零
            w.grad.zero_()
            b.grad.zero_()
    

    可视化训练结果

    plt.plot(x.numpy(), y_pred.detach().numpy(),'r-',label='predict')#predict
    plt.scatter(x.numpy(), y.numpy(),color='blue',marker='o',label='true') # true data
    plt.xlim(-1,1)
    plt.ylim(2,6)  
    plt.legend()
    plt.show()
            
    print(w, b)
    
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/772471.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号