深度学习 实验二 pytorch基础练习

本文详细介绍了张量在深度学习中的概念、定义,以及如何在PyTorch中创建、操作和理解张量,包括张量的形状、数据类型、设备位置、广播机制等内容,同时展示了如何使用PyTorch进行张量运算和转换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.1. 概念:张量

1.1.1定义

在深度学习的实践中,我们通常使用向量或矩阵运算来提高计算效率。比如w1x1+w2x2+⋯+wNxNw_1x_1 + w_2 x_2 +\cdots +w_N x_Nw1​x1​+w2​x2​+⋯+wN​xN​的计算可以用w⊤x\bm w^\top \bm xw⊤x来代替(其中w=[w1w2⋯wN]⊤,x=[x1x2⋯xN]⊤\bm w=[w_1 w_2 \cdots w_N]^\top,\bm x=[x_1 x_2 \cdots x_N]^\topw=[w1​w2​⋯wN​]⊤,x=[x1​x2​⋯xN​]⊤),这样可以充分利用计算机的并行计算能力,特别是利用GPU来实现高效矩阵运算。

在深度学习框架中,数据经常用张量(Tensor)的形式来存储。张量是矩阵的扩展与延伸,可以认为是高阶的矩阵。1阶张量为向量,2阶张量为矩阵。如果你对Numpy熟悉,那么张量是类似于Numpy的多维数组(ndarray)的概念,可以具有任意多的维度。


笔记

注意:这里的“维度”是“阶”的概念,和线性代数中向量的“维度”含义不同。


张量的大小可以用形状(shape)来描述。比如一个三维张量的形状是 [2,2,5][2, 2, 5][2,2,5],表示每一维(也称为轴(axis))的元素的数量,即第0轴上元素数量是2,第1轴上元素数量是2,第2轴上的元素数量为5。

图1.5给出了3种纬度的张量可视化表示。


                                              图1.5 不同维度的张量可视化表示


 

张量中元素的类型可以是布尔型数据、整数、浮点数或者复数,但同一张量中所有元素的数据类型均相同。因此我们可以给张量定义一个数据类型(dtype)来表示其元素的类型。

1.2自己的理解 

       张量连续存储,计算能力更快更强,可以看成多维数组。支持cpu和gpu加速。高阶张量由多个低阶张量组成。Pytorch中的张量为torch.Tensor,即为torch下的Tensor类,其数据类型(dtype)有多种。

1.2. 使用pytorch实现张量运算

1.2.1 创建张量

1.2.1.1 指定数据创建

直接使用torch.Tensor(数据)创建

(1)一维:

import torch
first=torch.Tensor([2.0, 3.0, 4.0])
print(first)

结果:tensor([2., 3., 4.])

(2)二维:

first=torch.Tensor([[1.0, 2.0, 3.0],[4.0, 5.0, 6.0]])
print(first)

结果:

        tensor([[1., 2., 3.],

                   [4., 5., 6.]])

(3)多维

first=torch.Tensor([[[1, 2, 3, 4, 5],
                 [6, 7, 8, 9, 10]],
                [[11, 12, 13, 14, 15],
                 [16, 17, 18, 19, 20]]])

结果:

         tensor([[[ 1.,  2.,  3.,  4.,  5.],

                    [ 6.,  7.,  8.,  9., 10.]],

                   [[11., 12., 13., 14., 15.],

                   [16., 17., 18., 19., 20.]]])

1.2.1.2 指定形状创建

torch.zeros(size) 是 PyTorch 中用来创建全 0 张量的函数。size 参数表示张量的形状(shape).

torch.ones(size) 是 PyTorch 中用来创建全 1张量的函数。size 参数表示张量的形状(shape).

torch.full(size, fill_value)返回创建size大小的形状,里面元素全部填充为fill_value的张量。

x=torch.zeros(2,3)
y=torch.ones(2,3)
print(x)
print(y)

结果:

          tensor([[0., 0., 0.],

                     [0., 0., 0.]])

          tensor([[1., 1., 1.],

                    [1., 1., 1.]])

x=torch.full([2,3],10)
print(x)

结果:

       tensor([[10, 10, 10],

                 [10, 10, 10]])

1.2.1.3 指定区间创建

x=torch.arange(start,end,step)      等间隔取值的张量

start:起始值,默认值:0         end:结束值     step:步长,默认值:1。[ start , end )

y=torch.linspace(start,end,steps)     等间隔取值的张量

start:开始值       end:结束值     steps:分割的点数,默认是100 [ start , end ]

x=torch.arange(start=1,end=5,step=1)#start:起始值,默认值:0   end:结束值  step:步长,默认值:1[ start , end ) 

y=torch.linspace(start=1,end=5,steps=4)#start:开始值 end:结束值 steps:分割的点数,默认是100 [ start , end ]
print(x)
print(y)

结果:

         tensor([1, 2, 3, 4])

         tensor([1.0000, 2.3333, 3.6667, 5.0000])

1.2.2 张量的属性

1.2.2.1 张量的形状

x=torch.Tensor([[2, 3, 4, 5],[2,3,4,6]])
print(x.ndim)#张量的维度
print(x.shape)#张量每个维度上元素的数量
print(x.shape[0])#张量第 𝑛 维的大小。第 𝑛 维也称为轴(axis
print(x.size)  #存在的内存位置

结果:

       2

       torch.Size([2, 4])

      2

      <built-in method size of Tensor object at 0x0000020E02AAE810>

1.2.2.2 形状的改变

torch.reshape() 

torch.unsqueeze()升维

x=torch.Tensor([[[1, 2, 3, 4, 5],
                [6, 7, 8, 9, 10]],
                [[11, 12, 13, 14, 15],
                [16, 17, 18, 19, 20]],
                [[21, 22, 23, 24, 25],
                [26, 27, 28, 29, 30]]])
print(x.shape)
y=torch.reshape(x,[2,3,5])#注意变换前后元素个数必须相等,元素顺序没有发生改变
print(y)

结果:

          torch.Size([3, 2, 5])

         tensor([[[ 1.,  2.,  3.,  4.,  5.],

                      [ 6.,  7.,  8.,  9., 10.],

                     [11., 12., 13., 14., 15.]],

                    [[16., 17., 18., 19., 20.],

                     [21., 22., 23., 24., 25.],

                     [26., 27., 28., 29., 30.]]])

#torch.squeeze(input, dim=None, out=None)函数的功能是维度压缩。返回一个tensor(张量),其中 input 中维度大小为1的所有维都已删除。
#unsqueeze()函数起升维的作用,参数dim表示在哪个地方加一个维度
x=torch.ones([5,10])
y=torch.unsqueeze(x,1)
y=torch.unsqueeze(y,2)
print(y.shape)

结果:torch.Size([5, 1, 1, 10])

1.2.2.3 张量的数据类型

数据类型的访问

x=torch.tensor(1)
print(x.dtype)#返回元素的数据类型
print(x.type())#返回参数的数据类型
s=torch.tensor([2,3,4],dtype=torch.float64)#也可指定数据类型创建张量
print(s)

结果:

         torch.int64

         torch.LongTensor

         tensor([2., 3., 4.], dtype=torch.float64)

元素数据类型的改变

t=s.int()     #,t变成元素数据类型为int的了,但并不会改变s原来的元素的数据类型
print(s.dtype)
print(t.dtype)

结果:

         torch.float64

         torch.int32 

1.2.2.4 张量的设备位置

初始化张量时可以通过place来指定其分配的设备位置,可支持的设备位置有三种:CPU、GPU和固定内存。固定内存也称为不可分页内存或锁页内存,它与GPU之间具有更高的读写效率,并且支持异步传输,这对网络整体性能会有进一步提升,但它的缺点是分配空间过多时可能会降低主机系统的性能,因为它减少了用于存储虚拟内存数据的可分页内存。

如下代码分别创建了CPU、GPU和固定内存上的张量,并通过Tensor.device查看张量所在的设备位置。

x=torch.tensor(1,device=torch.device('cpu'))
print(x.device)

结果:cpu

1.2.3 张量与Numpy数组转换

import torch
import numpy
x=np.array([2,3,4])
y=torch.Tensor(x)#numpy转换为张量
z=y.numpy()#张量转换为numpy
print(x)
print(y)
print(z

结果:

    [2 3 4]
    tensor([2., 3., 4.])
    [2. 3. 4.]

1.2.4 张量的访问

1.2.4.1 索引和切片

x=torch.tensor([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
print(x[0])#索引访问
print(x[0:2])#切片访问[start : end : step]左闭右开

结果:

         tensor([1, 2, 3, 4])

         tensor([[1, 2, 3, 4],

                    [5, 6, 7, 8]])

1.2.4.3 修改张量

慎重通过索引或切片操作来修改张量,此操作仅会原地修改该张量的数值,且原值不会被保存。

x=torch.tensor([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
print('刚开始',x)
x[0]=1
print('改变第一维',x)
x[...]=6
print('全改成6',x)

结果

刚开始 tensor([[ 1,  2,  3,  4],

                       [ 5,  6,  7,  8],

                       [ 9, 10, 11, 12]])

改变第一维 tensor([[ 1,  1,  1,  1],

                                [ 5,  6,  7,  8],

                               [ 9, 10, 11, 12]])

全改成6 tensor([[6, 6, 6, 6],

                          [6, 6, 6, 6],

                          [6, 6, 6, 6]])

1.2.5 张量的运算

1.2.5.1 数学运算

x=torch.tensor([1,2,3,4])
y=torch.tensor([9,10,11,12])
print(x+y)# 逐元素加
print(x*y) # 逐元素乘(积)
print(x-y) # 逐元素减
print(x/y) # 逐元素除
print(x**y)# 逐元素幂
print(x%y)  # 逐元素除并取余

结果:

tensor([10, 12, 14, 16])

tensor([ 9, 20, 33, 48])

tensor([-8, -8, -8, -8])

tensor([0.1111, 0.2000, 0.2727, 0.3333])

tensor([       1,     1024,   177147, 16777216])

tensor([1, 2, 3, 4])

1.2.5.2 逻辑运算

x=torch.tensor([1,2,3,4])
y=torch.tensor([1,2,11,12])
print(x.isfinite())# 判断Tensor中元素是否是有限的数字
print(x.equal(y))# 比较两个张量是否相等
print(x.eq(y))# 判断两个Tensor的每个元素是否相等
print(x.not_equal(y))# 判断两个Tensor的每个元素是否不相等
print(x.less_equal(y))# 判断Tensor x的元素是否小于或等于Tensor y的对应
print(x.greater_equal(y)  )# 判断Tensor x的元素是否大于或等于Tensor y的对应元素
print(x.allclose(y) ) # 判断两个Tensor的全部元素是否接近

结果:

tensor([True, True, True, True])

False

tensor([ True,  True, False, False])

tensor([False, False,  True,  True])

tensor([True, True, True, True])

tensor([ True,  True, False, False])

False

1.2.5.3 矩阵运算

x=torch.tensor([[1,2,3,4],[5,6,7,8]])
q=torch.tensor([[9,10,11,12],[15,16,17,18]])
y=x.t()# 矩阵转置
print(y)
z=torch.transpose(x, 0, 1) # 交换第 0 维与第 1 维的顺序,可以看成交换中括号的顺序
print(z)
m=torch.matmul(y,q)#矩阵乘法
print(m)

有些矩阵运算中也支持大于两维的张量,比如matmul函数,对最后两个维度进行矩阵乘。比如x是形状为[j,k,n,m]的张量,另一个y是[j,k,m,p]的张量,则x.matmul(y)输出的张量形状为[j,k,n,p]。

结果:

        tensor([[1, 5],
                    [2, 6],
                    [3, 7],
                    [4, 8]])
        tensor([[1, 5],
                    [2, 6],
                    [3, 7],
                    [4, 8]])

        tensor([[ 84,  90,  96, 102],
                  [108, 116, 124, 132],
                  [132, 142, 152, 162],
                  [156, 168, 180, 192]])

1.2.5.4 广播机制

飞桨的一些API在计算时支持广播(Broadcasting)机制,允许在一些运算时使用不同形状的张量。通常来讲,如果有一个形状较小和一个形状较大的张量,会希望多次使用较小的张量来对较大的张量执行某些操作,看起来像是形状较小的张量首先被扩展到和较大的张量形状一致,然后再做运算。

广播机制的条件

飞桨的广播机制主要遵循如下规则(参考Numpy广播机制):

1)每个张量至少为一维张量。

2)从后往前比较张量的形状,当前维度的大小要么相等,要么其中一个等于1,要么其中一个不存在

import numpy as np
import torch
# 当两个Tensor的形状一致时,可以广播
x = torch.ones((2, 3, 4))
y = torch.ones((2, 3, 4))
z = x + y
print('broadcasting with two same shape tensor: ', z.shape)

x = torch.ones((2, 3, 1, 5))
y = torch.ones((3, 4, 1))
# 从后往前依次比较:
# 第一次:y的维度大小是1
# 第二次:x的维度大小是1
# 第三次:x和y的维度大小相等,都为3
# 第四次:y的维度不存在
# 所以x和y是可以广播的
z = x + y
print('broadcasting with two different shape tensor:', z.shape)

结果:

broadcasting with two same shape tensor:  torch.Size([2, 3, 4])
broadcasting with two different shape tensor: torch.Size([2, 3, 4, 5])

广播机制的计算规则

现在我们知道在什么情况下两个张量是可以广播的。两个张量进行广播后的结果张量的形状计算规则如下:

1)如果两个张量shape的长度不一致,那么需要在较小长度的shape前添加1,直到两个张量的形状长度相等。

2) 保证两个张量形状相等之后,每个维度上的结果维度就是当前维度上较大的那个。

以张量x和y进行广播为例,x的shape为[2, 3, 1,5],张量y的shape为[3,4,1]。首先张量y的形状长度较小,因此要将该张量形状补齐为[1, 3, 4, 1],再对两个张量的每一维进行比较。从第一维看,x在一维上的大小为2,y为1,因此,结果张量在第一维的大小为2。以此类推,对每一维进行比较,得到结果张量的形状为[2, 3, 4, 5]。

按需要看看需不需要广播机制并注意是否满足条件

总结:

  • 维度不同,小维度的增加维度

  • 每个维度,计算结果取大的

  • 扩展维度是对数值进行复制

特别注意:关于torch.matmul

1)如果两个张量均为一维,则获得点积结果。

2) 如果两个张量都是二维的,则获得矩阵与矩阵的乘积。

3) 如果张量x是一维,y是二维,则将x的shape转换为[1, D],与y进行矩阵相乘后再删除前置尺寸。

4) 如果张量x是二维,y是一维,则获得矩阵与向量的乘积。

5) 如果两个张量都是N维张量(N > 2),则根据广播规则广播非矩阵维度(除最后两个维度外其余维度)。比如:如果输入x是形状为[j,1,n,m]的张量,另一个y是[k,m,p]的张量,则输出张量的形状为[j,k,n,p]。

1.3 心得体会

1、【PyTorch的张量或者NumPy数组通常在内存中存储的是一段连续的、未装箱的C数字类型】

2、【在张量中,第一维指的是最外层的维度,也就是第0维,而第二维指的是第一个嵌套的维度,即第一个非外层的维度。】

3、更加了解pytorch与tensor的关系,numpy与tensor的关系。

4、本节结合了PaddlePaddle中的张量的知识,也学习了pytorch里的张量的知识。学到了张量的创建,属性,访问及相关运算。

5、广播机制第一次了解,明白了一些规则和条件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值