欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 美食 > 深度学习框架PyTorch——从入门到精通(2)张量

深度学习框架PyTorch——从入门到精通(2)张量

2025/3/20 12:44:35 来源:https://blog.csdn.net/fansv587/article/details/146326246  浏览:    关键词:深度学习框架PyTorch——从入门到精通(2)张量

又名:张亮的一生~~

  • 张量(Tensors)
    • 初始化张量
    • 张量的属性
    • 张量上的操作
    • 与NumPy桥接

张量(Tensors)

张量是一种专门的数据结构,类似Python中的数组或者矩阵。在Torch中,我们使用张量来编码模型的输入和输出,以及模型的参数。

张量类似于NumPy库中的的数据类型:ndarray,只是张量可以在GPU或其他硬件加速器上运行。事实上,张量和NumPy数组通常可以共享相同的底层内存,从而无需复制数据(请参阅Bridge with NumPy)。

张量还针对自动微分进行了优化(我们将在稍后的自动求导部分中看到更多信息)。如果您熟悉ndarray,您将对Tensor API了如指掌。如果没有,请继续学习!

在你使用下面的代码测试之前,请先引入包。

import torch
import numpy as np

初始化张量

张量可以通过各种方式初始化。看看下面的例子:

  • 直接来自数据:张量可以直接从数据中创建。数据类型是自动推断的。
data = [[1, 2],[3, 4]]
x_data = torch.tensor(data)
  • 来自NumPy数组:张量可以从NumPy数组创建(反之亦然-请参阅Bridge with NumPy)。
np_array = np.array(data)
x_np = torch.from_numpy(np_array)
  • 来自另一个张量:除非显式覆盖,否则新张量保留参数张量的属性(形状、数据类型)。
x_ones = torch.ones_like(x_data) # retains the properties of x_data
print(f"Ones Tensor: \n {x_ones} \n")x_rand = torch.rand_like(x_data, dtype=torch.float) # overrides the datatype of x_data
print(f"Random Tensor: \n {x_rand} \n")
# 他们的输出会像下面这样:
Ones Tensor:tensor([[1, 1],[1, 1]])Random Tensor:tensor([[0.8823, 0.9150],[0.3829, 0.9593]])
  • 具有随机或恒定值shape是张量维度的元组。在下面的函数中,它确定输出张量的维度。
shape = (2,3,)
rand_tensor = torch.rand(shape)
ones_tensor = torch.ones(shape)
zeros_tensor = torch.zeros(shape)print(f"Random Tensor: \n {rand_tensor} \n")
print(f"Ones Tensor: \n {ones_tensor} \n")
print(f"Zeros Tensor: \n {zeros_tensor}")# 他们的输出会像下面这样:
Random Tensor:tensor([[0.3904, 0.6009, 0.2566],[0.7936, 0.9408, 0.1332]])Ones Tensor:tensor([[1., 1., 1.],[1., 1., 1.]])Zeros Tensor:tensor([[0., 0., 0.],[0., 0., 0.]])

张量的属性

张量的属性描述了它们的形状、数据类型和存储它们的设备。

tensor = torch.rand(3,4)print(f"Shape of tensor: {tensor.shape}")
print(f"Datatype of tensor: {tensor.dtype}")
print(f"Device tensor is stored on: {tensor.device}")# 他们的输出:
Shape of tensor: torch.Size([3, 4])
Datatype of tensor: torch.float32
# 创建张量默认在cpu上,除非指定设备:tensor = torch.rand(3, 4, device=device)或者使用 .to() 方法移动张量
Device tensor is stored on: cpu

张量上的操作

超过1200种张量运算,包括算术、线性代数、矩阵操作(转置、索引、切片)、采样和更全面的描述在这里。

这些操作中的每一个都可以在CPU和加速器上运行,例如CUDA、MPS、MTIA或XPU。如果您使用Colab,请通过转到运行时>更改运行时类型>GPU来分配加速器。

加速器的含义
在PyTorch存储库中,我们将加速器定义为与CPU一起使用以加快计算速度的设备(torch.device)。这些设备使用异步执行方案,使用torch.Stream和torch.Event作为执行同步的主要方式。我们还假设给定主机上一次只能使用一个这样的加速器。这允许使用当前加速器作为相关概念的默认设备,例如:

  • Pinned Memory(固定内存,也称为页锁定内存)
  • Stream device_type(流设备类型)
  • FSDP(Fully Sharded Data Parallel,全分片数据并行)

默认情况下,张量是在CPU上创建的。我们需要使用.to方法将张量显式移动到加速器(在检查加速器可用性之后)。请记住,跨设备复制大型张量在时间和内存方面可能很昂贵!

# We move our tensor to the current accelerator if available
if torch.accelerator.is_available():tensor = tensor.to(torch.accelerator.current_accelerator())

现在,尝试列表中的一些操作。如果您熟悉NumPy API,您会发现使用Tensor API轻而易举。

  • 标准的类似numpy的索引和切片
tensor = torch.ones(4, 4)
print(f"First row: {tensor[0]}")
print(f"First column: {tensor[:, 0]}")
print(f"Last column: {tensor[..., -1]}")
tensor[:,1] = 0
print(tensor)
# 输出会像是
First row: tensor([1., 1., 1., 1.])
First column: tensor([1., 1., 1., 1.])
Last column: tensor([1., 1., 1., 1.])
tensor([[1., 0., 1., 1.],[1., 0., 1., 1.],[1., 0., 1., 1.],[1., 0., 1., 1.]])
  • 连接张量:您可以使用torch.cat沿给定维度连接张量序列。另请参阅torch. stack,另一个张量连接运算符,与torch.cat略有不同。
t1 = torch.cat([tensor, tensor, tensor], dim=1)
print(t1)
# 输出
tensor([[1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.],[1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.],[1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.],[1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.]])
  • 算术运算
tensor = torch.ones(4, 4)
tensor[:,1] = 0
# 下面的代码是在计算两个张量之间的矩阵乘法,并且 y1、y2、y3 的值将相同
# tensor.T 操作会返回张量 tensor 的转置,@表示矩阵之间的乘法。
y1 = tensor @ tensor.T
# 使用张量的 matmul 方法进行矩阵乘法,同样是 tensor 与它的转置相乘,结果赋值给 y2
y2 = tensor.matmul(tensor.T)y3 = torch.rand_like(y1)
# 使用 torch.matmul 函数进行矩阵乘法,并将结果存储在 y3 中。out 参数指定了结果存储的目标张量
torch.matmul(tensor, tensor.T, out=y3)# 下面的代码是在计算两个张量之间的逐元素乘法,并且 z1、z2、z3 的值将相同
z1 = tensor * tensor
# 使用张量的 mul 方法进行逐元素乘法,将 tensor 与自身逐元素相乘,结果赋值给 z2
z2 = tensor.mul(tensor)z3 = torch.rand_like(tensor)
# 使用 torch.mul 函数进行逐元素乘法,并将结果存储在 z3 中。out 参数指定了结果存储的目标张量
torch.mul(tensor, tensor, out=z3)# 可以在y1y2,y3,z1,z2,z3处一一添加输出,y1,y2,y3是全是3的矩阵,z1,z2,z3就是tensor本身。(因为1*1 = 1 0*0 =0)
  • 单元素张量:如果您有一个单元素张量,例如通过将张量的所有值聚合为一个值,您可以使用item()将其转换为Python数值:
agg = tensor.sum()
agg_item = agg.item()
print(agg_item, type(agg_item))
#输出
12.0 <class 'float'>
  • 就地操作:将结果存储到操作数中的操作称为就地操作。它们由_后缀表示。例如:x.copy_(y)x.t_(),将更改x。
    add_:加,copy_:复制,t_:转置.sub_:减法,mul_:乘法,div_:除法,zero_:变0,fill_:所有元素变为指定元素。

    就地操作可以节省一些内存,但在计算导数时可能会出现问题,因为会立即丢失历史记录。因此,不鼓励使用它们。
    
print(f"{tensor} \n")
tensor.add_(5)
print(tensor)
# 输出
tensor([[1., 0., 1., 1.],[1., 0., 1., 1.],[1., 0., 1., 1.],[1., 0., 1., 1.]])tensor([[6., 5., 6., 6.],[6., 5., 6., 6.],[6., 5., 6., 6.],[6., 5., 6., 6.]])

与NumPy桥接

CPU上的NumPy数组与张量可以共享它们的底层内存位置,改变一个就会改变另一个。

  • 张量到NumPy数组
t = torch.ones(5)
print(f"t: {t}")
n = t.numpy()
print(f"n: {n}")
# 输出
t: tensor([1., 1., 1., 1., 1.])
n: [1. 1. 1. 1. 1.]
此时,张量的变化会反映在NumPy数组中。
t.add_(1)
print(f"t: {t}")
print(f"n: {n}")
# 输出
t: tensor([2., 2., 2., 2., 2.])
n: [2. 2. 2. 2. 2.]
  • NumPy数组到张量
n = np.ones(5)
t = torch.from_numpy(n)
NumPy数组的变化也反映在张量中。
np.add(n, 1, out=n)
print(f"t: {t}")
print(f"n: {n}")
# 输出
t: tensor([2., 2., 2., 2., 2.], dtype=torch.float64)
n: [2. 2. 2. 2. 2.]

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词