热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Numpy和Tensor

Numpy和Tensor

Numpy 和 Tensor

文章目录

  • Numpy 和 Tensor
    • 1、Numpy 与 Tensor
      • 1.1、Tensor 概述
      • 1.2、创建 Tensor
      • 1.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 的操作很多,从接口的角度来划分,可以分为两类:
    1. torch.function,如 torch.sum、torch.add 等,
    2. tensor.function,如 tensor.view、tensor.add 等。
  • 如果从修改方式的角度,可以分为以下两类:
    1. 不修改自身数据,如 x.add(y),x 的数据不变,返回一个新的 tensor;
    2. 修改自身数据,如 x.add_(y)(运行符带下划线后缀),运算结果存在 x 中,x 被修改。

1.2、创建 Tensor

在这里插入图片描述

  • 注意 torch.Tensor 与 torch.tensor 的几点区别:
    1. torch.Tensor 是 torch.empty 和 torch.tensor 之间的一种混合,但是,当传入数据时,torch.Tensor 使用全局默认 dtype(FloatTensor),torch.tensor 从数据中推断数据类型;
    2. torch.tensor(1) 返回一个固定值 1,而 torch.Tensor(1) 返回一个大小为 1 的张量,它是随机初始化的值。

1.3、修改 Tensor 形状

在这里插入图片描述

  • torch.view 与 torch.reshape 的异同

    1. reshape() 可以由 torch.reshape(),也可由 torch.Tensor.reshape() 调用。view() 只可由 torch.Tensor.view() 来调用;
    2. 对于一个将要被 view 的 Tensor,新的 size 必须与原来的 size 与 stride 兼容。否则,在 view 之前必须调用contiguous() 方法;
    3. 同样也是返回与 input 数据量相同,但形状不同的 tensor。若满足 view 的条件,则不会 copy,若不满足,则会copy;
    4. 如果您只想重塑张量,请使用 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、自动求导要点

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

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

2.2、计算图

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

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

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

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

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

    3. 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}xz=yzxy=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}wz=yzwy=x

∂ z ∂ b = 1 \frac{\partial \mathrm{z}}{\partial \mathrm{b}}=1bz=1

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

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

在这里插入图片描述


3、使用 Numpy 实现机器学习

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

    主要步骤包括:

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

    import numpy as np

    from matplotlib import pyplot as plt

  2. 生成输入数据 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)

  3. 查看 x,y 数据分布情况

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

  4. 初始化权重参数

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

  5. 训练模型

    定义损失函数,假设批量大小为 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=21i=1100(wxi2+byi)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}wLoss=i=1100(wxi2+byi)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)}bLoss=i=1100(wxi2+byi)

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

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

    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

  6. 可视化结果

    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,便可利用自动反向传播来求梯度,无需手工计算梯度。

  1. 导入需要的库

    import torch as t
    from matplotlib import pyplot as plt

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

    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()

  3. 初始化权重参数

    # 随机初始化参数,参数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)

  4. 训练模型

    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_()

  5. 可视化训练结果

    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)


版权声明:本文为qq_36879493原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_36879493/article/details/123595301
推荐阅读
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • PHP图片截取方法及应用实例
    本文介绍了使用PHP动态切割JPEG图片的方法,并提供了应用实例,包括截取视频图、提取文章内容中的图片地址、裁切图片等问题。详细介绍了相关的PHP函数和参数的使用,以及图片切割的具体步骤。同时,还提供了一些注意事项和优化建议。通过本文的学习,读者可以掌握PHP图片截取的技巧,实现自己的需求。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 本文总结了在开发中使用gulp时的一些技巧,包括如何使用gulp.dest自动创建目录、如何使用gulp.src复制具名路径的文件以及保留文件夹路径的方法等。同时介绍了使用base选项和通配符来保留文件夹路径的技巧,并提到了解决带文件夹的复制问题的方法,即使用gulp-flatten插件。 ... [详细]
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
  • 本文详细介绍了如何使用MySQL来显示SQL语句的执行时间,并通过MySQL Query Profiler获取CPU和内存使用量以及系统锁和表锁的时间。同时介绍了效能分析的三种方法:瓶颈分析、工作负载分析和基于比率的分析。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • 在springmvc框架中,前台ajax调用方法,对图片批量下载,如何弹出提示保存位置选框?Controller方法 ... [详细]
  • Day2列表、字典、集合操作详解
    本文详细介绍了列表、字典、集合的操作方法,包括定义列表、访问列表元素、字符串操作、字典操作、集合操作、文件操作、字符编码与转码等内容。内容详实,适合初学者参考。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • Android系统移植与调试之如何修改Android设备状态条上音量加减键在横竖屏切换的时候的显示于隐藏
    本文介绍了如何修改Android设备状态条上音量加减键在横竖屏切换时的显示与隐藏。通过修改系统文件system_bar.xml实现了该功能,并分享了解决思路和经验。 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
author-avatar
学海无涯
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有