Pytorch学习(2)- tensor

本文深入探讨PyTorch中的张量概念,包括其分类、创建、操作、线性代数函数、比较函数及与Numpy的交互。涵盖索引、调整形状、归并、向量化、持久化等实用技巧。
部署运行你感兴趣的模型镜像

Tensor:张量,可以是标量(一个数)、向量(一维数组)、矩阵(二维数组)或者更高维的数组。

它与numpy和ndarrays相似,但是PyTorch的tensor支持GPU加速。

一、tensor分类

  • 从接口的角度分类

        

torch.function如torch.save()
tensor.function如tensor.view()
  • 从存储的角度分类
不会修改自身的数据如a.add(b),加法的结果会返回一个新的tensor
会修改自身的数据如a.add_(b),加法的结果仍然存储在a中,a被修改了

二、创建Tensor

在PyTorch中新建tensor的方法有很多,具体如下:

函数功能
Tensor(*sizes)基础构造函数
ones(*sizes)全1Tensor
zeros(*sizes)全0Tensor
eye(*sizes)对角线为1,其他为0
arange(s,e,step)从s到e,步长为step
linspace(s,e,steps)从s到e,均匀切分成steps份
rand/randn(*sizes)均匀/标准分布
normal(mean,std)/uniform(from,to)正态分布/均匀分布
randperm(m)随机排列

三、常用Tensor操作

       通过tensor.view方法调整tensor的形状,但必须保证调整前后元素总数一致。view不会修改自身的数据,

返回的新tensor与源tensor共享内存,即更改其中一个,另一个也随之改变。

主要用在经常需要添加或者减少某一维度,这时就需要squeeze和unsqueeze这两个函数。

       resize是另一种可以用来调整size的方法,但与view不同,它可以修改tensor的尺寸。如果新尺寸超过了原尺寸,会自动分配新的内存空间,但如果新尺寸小于原尺寸,则之前的数据依旧会被保存。

      Tensor支持numpy.ndarray类似的索引操作,语法也类似。如无特殊说明,索引出来的结果与原tensor共享内存。

from __future__ import print_function
import torch as t

a = t.randn(3, 4)
print(a)
print(a[0])  # 第0行(下标从0开始)
print(a[:, 0])  # 第0列

结果如下:

四、常用的选择函数

函数功能
index_select(input,dim,index)在指定维度dim上选取,例如选取某些行或列
masked_select(input,mask)例a[a>0],使用ByteTensor进行选取
non_zero(input)非0元素的下标
gather(input,dim,index)根据index,在dim维度上选取数据,输出的size与index一样

五、常见的逐元素操作

函数功能
abs//sqrt/div/exp/fmod/log/pow绝对值/平方根/除法/指数/求余/求幂
cos/sin/asin/atan2/cosh三角函数
clamp(input,min,max)超过min和max部分截断
ceil/round/floor/trunc上取整/四舍五入/下取整/只保留整数部分
sigmod/tanh激活函数

     clamp常用在某些需要比较大小的地方,如取一个tensor的每个元素与另一个数的较大值。

a = t.arange(0, 6).view(2, 3)
print(a)
# 不转换为float,则会报错:RuntimeError: cos_vml_cpu not implemented for 'Long'
print(t.cos(a.float()))

      

a = t.arange(0, 6).view(2, 3)
print(a)
print(a % 3)  # 等价于t.fmod(a, 3)
print(a ** 2)  # 等价于t.pow(a, 2)

       

a = t.arange(0, 6).view(2, 3)
print(a)
# a中每个元素都与3相比,取较大的一个
print(t.clamp(a, min=3))

     

 

六、归并操作

       归并操作会是输出形状小于输入形状,并可以沿着某一维度进行指定操作。

常用的归并操作:

函数功能
mean/sum/median/mode均值/和/中位数/众数
norm/dist范数/距离
std/var标准差/方差
cumsum/cumprod累加/累乘

以上大多数函数都有一个参数dim,用来指定这些操作是在哪个维度上执行的。

假设输入的形状是(m, n, k)——m行n列

输入dim输出的形状
0(1, n, k)或者(n, k)——沿着列,变成一行
1(m, 1, k)或者(m, k)——沿着行,变成一列
2(m, n, 1)或者(m, n)

注意: size中是否有“1”,取决于参数keepdim,keepdim=True会保留维度1。默认为false

七、常用的比较函数

函数功能
gt/lt/ge/le/eq/ne大于/小于/大于等于/小于等于/等于/不等
topk最大的k个数
sort排序
max/min比较两个tensor的最大值和最小值

max/min为例:

t.max(tensor)返回tensor中最大的一个数
t.max(tensor,dim)指定维上最大的数,返回tensor和下标
t.max(tensor1,tensor2)比较两个tensor相比较的元素

 

 

 

 

八、常用的线性代数函数

函数功能
trace对角线元素之和(矩阵的迹)
diag对角线元素
triu/tril矩阵的上三角/下三角,可指定偏移量
mm/bmm矩阵乘法/batch的矩阵乘法
addmm/addbmm/addmv矩阵运算
t转置
dot/cross内积/外积
inverse求逆矩阵
svd奇异值分解

注意:矩阵的转置会导致存储空间不连续,需调用它的.contiguous方法将其转为连续

a = t.ones(2, 3)
print(a)
# 求a的转置
b = a.t()
# 查看a的转置矩阵b是否连续
print(b.is_contiguous())
# 将其转为连续
print(b.contiguous())

结果:

             

九、对于Tensor和Numpy之间遇到的问题

需要注意的是:Numpy和Tensor共享内存。PyTorch已经支持了自动广播法则。

当遇到Tensor不支持的操作时,可以先转成Numpy数组,处理后再转为tensor,其转换开销很小。

  • 当输入数组的某个维度的长度为1时,计算时沿此维度复制扩充成一样的形状。
  • unsqueeze或view:为数据某一维的形状补1,实现法则1.
  • expand或expand_as,重复数组,实现法则3;该操作不会复制数组,所以不会占用额外的空间

     9.1、持久化

          tensor的保存:t.save

          tensor的加载:t.load

在load时还可以将GPU tensor映射到CPU或其他GPU上。

if t.cuda.is_available():
    a = a.cuda(1)  # 把a转为GPU1上的tensor
    t.save(a, 'a.path')
    # 加载为b,存储于GPU1上(因为保存时tensor就在GPU1上)
    b = t.load('a.path')
    # 加载为c,存储于CPU
    c = t.load('a.path', map_location=lambda storage, loc: storage)
    # 加载为d,存储于GPU0上
    d = t.load('a.path', map_location={'cuda:1':'cuda: 0'})

    9.2、向量化

           向量化计算是一种特殊的并行计算方式,一般程序在同一时间只执行一个操作的方式,它可以在同一时间执行多个操作,通常是对不同的数据执行同样的一个或一批指令,或者说把指令应用于一个数组/向量上。向量化可极大地提高科学运算的效率。

在科学计算程序中应当极力避免使用Python原生的for循环,尽量使用向量化的数值计算。

           还需要注意:

  • 大多数t.function都有一个参数out,这时产生的结果将保存在out指定的tensor之中
a = t.arange(0, 20000000)
b = t.LongTensor()
t.arange(0, 20000000, out=b)  # 64bit的LongTensor不会溢出
  • t.set_num_threads可以设置PyTorch进行CPU多线程并行计算时所占用的线程数,用来限制PyTorch所占用的CPU数目。
  • t.set_printoptions可以用来设置打印tensor时的数值精度和格式。

十、View的用法

a=torch.Tensor([[[1,2,3],[4,5,6]]])
b=torch.Tensor([1,2,3,4,5,6])

print(a.view(1,6))
print(b.view(1,6))

输出结果:tensor([[1., 2., 3., 4., 5., 6.]]) 
          tensor([[1., 2., 3., 4., 5., 6.]]) 
# -------------------------------------------------------
a=torch.Tensor([[[1,2,3],[4,5,6]]])
print(a.view(3,2))
输出结果:
tensor([[1., 2.],
        [3., 4.],
        [5., 6.]])
相当于就是从1,2,3,4,5,6顺序的拿数组来填充需要的形状
# --------------------------------------------------------
但是如果你想得到:
tensor([[1., 4.],
        [2., 5.],
        [3., 6.]])

就需要用到permute()
# -------------------------------------------------------
另外,参数不可为空。
参数中的-1就代表这个位置由其他位置的数字来推断,只要在不致歧义的情况的下,view参数就可以推断出来,也就是人可以推断出形状的情况下,view函数也可以推断出来。
比如a tensor的数据个数是6个,如果view(1,-1),我们就可以根据tensor的元素个数推断出-1代表6。而如果是view(-1,-1,2),人不知道怎么推断,机器也不知道。
还有一种情况是人可以推断出来,但是机器推断不出来的:view(-1,-1,6),人可以知道-1都代表1,但是机器不允许同时有两个负1。

如果没有-1,那么所有参数的乘积就要和tensor中元素的总个数一致了,否则就会出现错误。

十一、sequeeze和unsqueeze

 简介和用法

squeezeunsqueeze的作用与其翻译基本一致,被作用维度压缩和解压缩.用法相对简单,具体如下:

tensor_unsqueeze = tensor.unsqueeze(dim)

tensor存在n个维度,则dim的取值为[-n+1,n]区间的整数,且dim的取值不能为空.

tensor_squeeze = tensor.squeeze(dim)

tensor存在n个维度,则dim的取值为[-n,n-1]区间的整数,但dim的值可以为空

具体示例:

首先看unsqueeze,其中的参数dim不能为空。

f = torch.arange(0, 6).view(3, 2)
print(f, f.size())
# 参数表示在哪一维的前面增加一个维度
print(f.unsqueeze(0), f.unsqueeze(0).size())  # 1×3×2
print(f.unsqueeze(1), f.unsqueeze(1).size())  # 3×1×2
print(f.unsqueeze(2), f.unsqueeze(2).size())  # 3×2×1
# --------------------------------------------------
tensor([[0, 1],
        [2, 3],
        [4, 5]]) torch.Size([3, 2])

tensor([[[0, 1],
         [2, 3],
         [4, 5]]]) torch.Size([1, 3, 2])

tensor([[[0, 1]],

        [[2, 3]],

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

tensor([[[0],
         [1]],

        [[2],
         [3]],

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

再看squeeze,它是将被操作目标中维度为1的部分去除。

其中dim表示需要在哪一维去掉一个维度,如果不指定则自动寻找,如果指定则当指定的维度为1时去掉,如果不为1则不改变。

f = torch.arange(0, 6).view(3, 2, 1)
print(f, f.size())  # 3*2*1
print(f.squeeze(0), f.squeeze(0).size())  # 3*2*1,维度为3,不能去掉,所以不变
print(f.squeeze(1), f.squeeze(1).size())  # 3*2*1,维度为2,不能去掉,所有不变
print(f.squeeze(2), f.squeeze(2).size())  # 3*2  ,维度为1,可以去掉,所有改变
print(f.squeeze(), f.squeeze().size())    # 如果无参数,则自动寻找,找到则删除。
# -------------------------------------------------------------------------------
tensor([[[0],
         [1]],

        [[2],
         [3]],

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

tensor([[[0],
         [1]],

        [[2],
         [3]],

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

tensor([[[0],
         [1]],

        [[2],
         [3]],

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

tensor([[0, 1],
        [2, 3],
        [4, 5]]) torch.Size([3, 2])

tensor([[0, 1],
        [2, 3],
        [4, 5]]) torch.Size([3, 2])

 

十二、cat的用法

cat是用于将两个矩阵进行拼接,0表示按行拼接,1表示按列拼接

a = torch.ones(2, 3)
b = 2 * torch.ones(4, 3)
c = 4 * torch.ones(2, 4)
print(a)
print(b)
print(c)
d = torch.cat((a, b), 0)  # 0表示按行拼接
e = torch.cat((a, c), 1)  # 1表示按列拼接
print(d)
print(e)
# -----------------------------------------------
tensor([[1., 1., 1.],
        [1., 1., 1.]])

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

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

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

tensor([[1., 1., 1., 4., 4., 4., 4.],
        [1., 1., 1., 4., 4., 4., 4.]])

 

 

 

 

 

您可能感兴趣的与本文相关的镜像

PyTorch 2.5

PyTorch 2.5

PyTorch
Cuda

PyTorch 是一个开源的 Python 机器学习库,基于 Torch 库,底层由 C++ 实现,应用于人工智能领域,如计算机视觉和自然语言处理

<think>首先,用户要求查询关于PyTorchTensor的使用和特性。用户提供了多个引用,这些引用是关于PyTorch Tensor的概述、创建、属性、操作等。 系统级指令: - 使用$...$格式行内数学表达式。 - 独立公式用$$...$$。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,如[^1]。 用户可见层: - 回答结构清晰,帮助用户逐步解决问题。 - 保证回答真实可靠。 用户的问题:PyTorchTensor的使用和特性。 从引用中提取关键信息: - 引用[1]: Tensor是核心数据结构,支持多维数组、自动求导、GPU加速。 - 引用[2]: Tensor类方便创建、操作、计算张量,隐藏底层细节。 - 引用[3]: 详细结构:概念、特点、数据类型、创建方式、属性、数据转换、常见操作。 - 引用[4]: 示例代码,展示形状操作如view()和resize()。 我需要结构化回答: 1. **介绍Tensor**:简要定义Tensor及其重要性。 2. **特性**:列出Tensor的主要特性,如多维数组、自动求导、GPU支持。 3. **使用方法**: - 创建Tensor- 操作Tensor(如形状操作、运算)。 - 数据类型和属性。 - 与NumPy的转换。 4. **示例**:参考引用[4],提供简单代码示例。 5. **引用标识**:在相关段落末尾添加引用标识。 6. **生成相关问题**:在最后添加相关问题部分。 步骤: - **开头介绍**:解释什么是PyTorch Tensor- **详细内容**: - 特性:多维数据、自动求导、GPU加速、高效计算。 - 创建方式:使用torch.tensor, torch.Tensor等。 - 常见操作:如view(), reshape(), transpose(), 元素运算。 - 属性:shape, dtype, device。 - 数据类型转换和设备切换。 - 与NumPy互操作。 - **添加引用**:基于引用内容,在适当位置添加[^1], [^2], [^3], [^4]。 - **示例代码**:保持简短,使用Python代码块。 - **结尾**:总结重要性。 - **相关问题**:生成至少三个相关问题,如优化、应用场景等。 确保数学表达式格式: - 如果有数学,使用$...$,例如在描述形状时,或是运算。 -PyTorch上下文中,可能没有太多数学,但如果有,如形状变换,可以用数学表示。 最终输出格式: - 回答主体。 - 相关问题部分,以"§§相关问题§§"开头。 现在,草拟回答结构: 1. **Tensor概述**:定义和重要性。引用[1]和[^2]。 2. **主要特性**: - 多维数组功能。 - 自动求导(关键于深度学习)。 - GPU加速计算。 - 灵活性:支持多种数据类型和设备。 3. **创建Tensor**: - 基本创建如torch.tensor(), torch.rand()- 创建线性和随机张量。 4. **Tensor操作**: - 形状操作:view(), reshape(), transpose(), permute()- 元素运算:加法、乘法等。 - 索引和切片。 5. **属性管理**: - 获取shape, dtype, device。 - 切换设备(CPU到GPU)。 - 数据类型转换。 6. **示例**:引用[4]的代码,简要说明。 7. **与NumPy交互**。 8. **总结**。 9. **相关问题**。 添加引用标识: - 在描述特性时加[^1]。 - 在创建部分加[^3]。 - 在操作部分加[^3]和[^4]。 - 在示例加[^4]。 生成相关问题: 1. 如何优化Tensor操作以提高性能? 2. Tensor在深度学习模型中的应用? 3. Tensor和NumPy数组的优缺点比较? </think>### PyTorch Tensor 的使用和特性详解 PyTorch 中的 Tensor 是其核心数据结构,用于表示多维数组,支持高效计算、自动求导和 GPU 加速,是深度学习模型开发的基础。下面我将逐步介绍 Tensor 的主要特性、使用方法,并结合示例帮助您理解。内容基于站内引用,确保真实可靠。 #### 1. Tensor 概述 PyTorchTensor 是多维数组的封装,类似于 NumPy 的 ndarray,但增加了自动求导和 GPU 支持等高级功能。它允许用户在 Python 层面轻松创建、操作数据,同时隐藏底层实现细节,使开发者能专注于模型构建。Tensor 的核心概念包括维度、数据类型和存储设备,这些特性使其在深度学习任务中不可或缺[^1][^2]。 #### 2. 主要特性 Tensor 的设计目标是为深度学习提供高效、灵活的计算基础。以下是其关键特性: - **多维数组功能**:Tensor 可以表示标量(0 维)、向量(1 维)、矩阵(2 维)或更高维数据,例如图像数据可存储为 $ \text{shape}~(C \times H \times W) $ 的 3D Tensor,其中 $ C $ 是通道数,$ H $ 和 $ W $ 是高度和宽度。这使得处理复杂数据(如卷积神经网络输入)变得简单[^1]。 - **自动求导(Autograd)**:Tensor 支持梯度计算,通过设置 `requires_grad=True`,PyTorch 会自动跟踪操作并构建计算图,便于反向传播优化模型参数。例如,在损失函数计算中,梯度可通过 `.backward()` 方法自动获取[^1][^2]。 - **GPU 加速**:Tensor 可以轻松迁移到 GPU 设备(如 NVIDIA CUDA),利用并行计算大幅提升训练速度。使用 `.to('cuda')` 方法即可将 Tensor 从 CPU 移动到 GPU,显著加速大规模矩阵运算[^1]。 - **灵活的数据类型**:支持多种数据类型,如整数 (`torch.int32`)、浮点数 (`torch.float32`),以及布尔型 (`torch.bool`)。数据类型可通过 `.dtype` 属性查询,并用 `.to()` 方法转换,例如 `tensor.to(torch.float64)`[^3]。 - **内存连续性优化**:Tensor 的存储是连续的,操作如 `view()` 或 `reshape()` 可高效改变形状而不复制数据(前提是内存连续)。这减少了资源开销,提升了性能[^3][^4]。 #### 3. Tensor 的创建 Tensor 的创建方式多样,常用方法包括: - **基本创建**:使用 `torch.tensor()` 或 `torch.Tensor()` 从 Python 列表或 NumPy 数组初始化。例如,`tensor = torch.tensor([1, 2, 3])` 创建一个 1D Tensor。`torch.IntTensor()` 等函数指定特定数据类型[^3]。 - **创建特定张量**: - **随机张量**:`torch.rand(shape)` 生成均匀分布的随机数 Tensor,如 `rand_tensor = torch.rand(2, 3)`。 - **线性张量**:`torch.linspace(start, end, steps)` 创建等间隔序列,如 `lin_tensor = torch.linspace(0, 10, 5)` 生成 $[0, 2.5, 5, 7.5, 10]$。 - **特殊张量**:`torch.zeros()`, `torch.ones()`, 或 `torch.eye()` 创建零矩阵、单位矩阵等[^3]。 #### 4. Tensor 的常见操作 Tensor 支持丰富的操作,包括形状调整、运算和索引: - **形状操作**:关键于数据预处理: - `view()` 或 `reshape()`:改变 Tensor 形状而不复制数据(如果内存连续)。例如,一个 $2 \times 3$ Tensor 可重塑为 $3 \times 2$,形状变换满足元素总数不变,即原始形状 $a \times b$ 和变换后 $c \times d$ 满足 $ a \times b = c \times d $。 - `transpose()` 或 `permute()`:交换维度,如将 $ \text{shape}~(N \times C \times H \times W) $ 转置为 $ \text{shape}~(N \times H \times W \times C) $。 - `squeeze()` 和 `unsqueeze()`:压缩或增加维度。例如,`unsqueeze(dim=0)` 在指定维度添加大小为 1 的维度[^3][^4]。 - **元素运算**:支持逐元素操作,包括加法、乘法(阿达玛积)、矩阵乘法 (`torch.matmul()`)。例如,两个 Tensor $A$ 和 $B$ 的逐元素乘法为 $ A \odot B $。 - **索引和切片**:类似 NumPy,使用索引获取子集,如 `tensor[0, :]` 获取第一行所有元素[^3]。 - **数据类型和设备切换**:使用 `.to()` 方法,如 `tensor.to('cuda')` 移动到 GPU 或 `tensor.to(torch.float16)` 转换精度[^3]。 #### 5. 示例代码 以下代码演示了 Tensor 的创建和形状操作,基于引用[^4]。它展示了 `view()` 方法改变形状,并验证内存共享(原 Tensor 和重塑后的 Tensor 指向相同存储): ```python import torch # 创建一个 2x3 的随机 Tensor tensor = torch.rand(2, 3) print("原始形状:", tensor.shape) # 输出: torch.Size([2, 3]) # 使用 view() 改变形状为 3x2 new_tensor = tensor.view(3, 2) print("新形状:", new_tensor.shape) # 输出: torch.Size([3, 2]) # 检查内存地址,相同表示共享存储 print("原 Tensor 存储地址:", tensor.storage().data_ptr()) print("新 Tensor 存储地址:", new_tensor.storage().data_ptr()) # 地址相同 ``` #### 6. 与 NumPy 互操作 Tensor 可与 NumPy 数组无缝转换: - `torch.from_numpy(np_array)` 将 NumPy 数组转为 Tensor- `tensor.numpy()` 将 Tensor 转为 NumPy 数组。 这在数据加载和预处理中非常实用,允许结合 PyTorch 和传统科学计算库的优势[^3]。 #### 总结 PyTorch Tensor 提供了高效、灵活的数据处理能力,是深度学习开发和优化的核心。通过多维数组支持、自动求导和 GPU 加速,它简化了模型实现。掌握创建、操作和属性管理,能提升您在项目中的效率[^1][^2][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值