神经网络常用库-torch(基础操作张量)

embedded/2025/3/14 9:54:27/

1.理解张量

从简单到复杂逐步理解张量

  • 标量:可以将标量看作是零维张量,它只有一个数值,比如温度、质量等。例如,今天的气温是 25 摄氏度,这里的 25 就是一个标量。
  • 向量:一维张量就是向量,它由一组有序的数值组成,可以表示具有大小和方向的量。比如在平面直角坐标系中,向量 (3, 4) 表示从原点到点 (3, 4) 的有向线段。
  • 矩阵:二维张量是矩阵,它是一个由行和列组成的二维数组。矩阵在图像处理、线性代数等领域有广泛应用。例如,一个表示图像的矩阵,每个元素可以代表图像中对应像素的灰度值或颜色值。
  • 多维张量:当维度超过二维时,就进入了多维张量的范畴。例如,三维张量可以想象成一个立方体,每个元素都有三个索引来确定其位置。在视频数据中,三维张量可以表示一个视频片段,其中三个维度分别可以是时间、高度和宽度。而四维张量则可以在三维张量的基础上,再增加一个维度,比如颜色通道,这样就可以更全面地表示视频数据的信息。

1.直接创建张量:使用 torch.tensor() 函数可以直接将 Python 列表转换为 PyTorch 张量。

import torch# 创建一个一维张量
tensor_1d = torch.tensor([1, 2, 3, 4, 5])
print("一维张量:")
print(tensor_1d)# 创建一个二维张量
tensor_2d = torch.tensor([[1, 2, 3], [4, 5, 6]])
print("\n二维张量:")
print(tensor_2d)# 创建一个三维张量
tensor_3d = torch.tensor([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
print("\n三维张量:")
print(tensor_3d)

2.从 numpy.ndarray 转换为 PyTorch 张量

import torch
import numpy as np# 创建一个一维的 numpy 数组
np_array_1d = np.array([1, 2, 3, 4, 5])
# 转换为 PyTorch 张量
tensor_from_np_1d = torch.from_numpy(np_array_1d)
print("从一维 numpy 数组转换的张量:")
print(tensor_from_np_1d)# 创建一个二维的 numpy 数组
np_array_2d = np.array([[1, 2, 3], [4, 5, 6]])
# 转换为 PyTorch 张量
tensor_from_np_2d = torch.from_numpy(np_array_2d)
print("\n从二维 numpy 数组转换的张量:")
print(tensor_from_np_2d)# 创建一个三维的 numpy 数组
np_array_3d = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
# 转换为 PyTorch 张量
tensor_from_np_3d = torch.from_numpy(np_array_3d)
print("\n从三维 numpy 数组转换的张量:")
print(tensor_from_np_3d)

 3.从 pandas.DataFrame 或 pandas.Series 转换为 PyTorch 张量

import torch
import pandas as pd# 创建一个 pandas Series
series = pd.Series([1, 2, 3, 4, 5])
# 将 Series 转换为 numpy 数组,再转换为 PyTorch 张量
tensor_from_series = torch.from_numpy(series.values)
print("从 pandas Series 转换的张量:")
print(tensor_from_series)# 创建一个 pandas DataFrame
data = {'col1': [1, 2, 3], 'col2': [4, 5, 6]}
df = pd.DataFrame(data)
# 将 DataFrame 转换为 numpy 数组,再转换为 PyTorch 张量
tensor_from_df = torch.from_numpy(df.values)
print("\n从 pandas DataFrame 转换的张量:")
print(tensor_from_df)

 默认的数据类型是 torch.float32(有很多大佬研究了混合精度训练的训练技巧)

也可以通过指定dtype

tensor_float64 = torch.tensor([1.0, 2.0, 3.0], dtype=torch.float64)

2.操作张量

2.1shape和size

在 PyTorch 中,shape 和 size() 都与张量(Tensor)的维度信息相关,但它们在使用形式和表现上存在一些差异,下面为你详细介绍:

相同点

shape 和 size() 本质上都用于获取张量各维度的大小,返回的结果是一致的,都能反映出张量的维度信息。以下是一个示例代码:

import torch# 创建一个二维张量
tensor = torch.tensor([[1, 2, 3], [4, 5, 6]])# 使用 shape 属性获取张量的形状
print("使用 shape 属性:", tensor.shape)# 使用 size() 方法获取张量的形状
print("使用 size() 方法:", tensor.size())

不同点

1. 类型和调用方式

shape:它是张量的一个属性,使用时直接通过点号访问,就像访问对象的普通属性一样。

import torch
tensor = torch.tensor([1, 2, 3])
print(tensor.shape)

size():这是张量的一个方法,使用时需要在后面加上括号,括号内可以传入参数来获取特定维度的大小。

import torch
tensor = torch.tensor([1, 2, 3])
print(tensor.size())

2.关于参数

  • shape[0]shape 是张量的一个属性,它返回一个 torch.Size 对象,该对象类似于元组,shape[0] 是对这个 torch.Size 对象进行索引操作,获取其第一个元素。
  • size(0)size() 是张量的一个方法,通过传入参数 0 来指定获取第一维的大小
  • shape[0]:只能获取第一维的大小,如果要获取其他维度的大小,需要通过索引 shape[1]shape[2] 等方式。
import torch
tensor = torch.tensor([[1, 2, 3], [4, 5, 6]])
print("第二维的大小 (使用 shape):", tensor.shape[1])
  • size():方法更加灵活,它可以不传入参数,直接返回整个张量的形状信息(返回值类型为 torch.Size),也可以传入不同的整数参数来获取指定维度的大小。
import torch
tensor = torch.tensor([[1, 2, 3], [4, 5, 6]])
h,w=tensor.size()
print(h,w)

 2.2 操作维度

1.torch.unsqueeze() 方法 

torch.unsqueeze() 函数用于在指定的维度上插入一个新的维度,其语为 torch.unsqueeze(input, dim),其中 input 是输入的张量,dim 是要插入新维度的位置(索引从 0 开始)

import torch# 创建一个一维张量
tensor_1d = torch.tensor([1, 2, 3])
print("原一维张量形状:", tensor_1d.shape)# 在第 0 维插入一个新维度
tensor_2d_0 = torch.unsqueeze(tensor_1d, dim=0)
print("在第 0 维插入新维度后的形状:", tensor_2d_0.shape)# 在第 1 维插入一个新维度
tensor_2d_1 = torch.unsqueeze(tensor_1d, dim=1)
print("在第 1 维插入新维度后的形状:", tensor_2d_1.shape)

2. 在 PyTorch 中,可以使用 None 索引来增加维度,这与 torch.unsqueeze() 效果类似。示例如下

import torch# 创建一个一维张量
tensor_1d = torch.tensor([1, 2, 3])
print("原一维张量形状:", tensor_1d.shape)# 在第 0 维插入一个新维度
tensor_2d_0 = tensor_1d[None, :]
print("在第 0 维插入新维度后的形状:", tensor_2d_0.shape)# 在第 1 维插入一个新维度
tensor_2d_1 = tensor_1d[:, None]
print("在第 1 维插入新维度后的形状:", tensor_2d_1.shape)

3.拼接维度torch.cat(tensors, dim=0, out=None)

import torch# 创建两个二维张量
tensor1 = torch.tensor([[1, 2, 3], [4, 5, 6]])
tensor2 = torch.tensor([[7, 8, 9], [10, 11, 12]])# 在第 0 维上拼接
result_0 = torch.cat((tensor1, tensor2), dim=0)
print("在第 0 维上拼接的结果:")
print(result_0)
print("拼接后张量的形状:", result_0.shape)

4.expand方法

expand() 方法只能对大小为 1 的维度进行扩展,与单个或多个维度大小是否为 1 并无直接关系,关键在于维度的大小是否为 1。

可以拓展

import torch# 创建一个形状为 (1, 1, 3) 的张量
tensor = torch.tensor([[[1, 2, 3]]])
print("原张量形状:", tensor.shape)# 对第 0 维和第 1 维进行扩展
expanded_tensor = tensor.expand(2, 2, 3)
print("扩展后张量形状:", expanded_tensor.shape)

不可拓展

import torch# 创建一个形状为 (2, 1, 3) 的张量
tensor = torch.tensor([[[1, 2, 3]], [[4, 5, 6]]])
try:# 尝试对第 0 维(大小为 2)进行扩展,会报错expanded_tensor = tensor.expand(3, 1, 3)
except RuntimeError as e:print("错误信息:", e)

 5.squeeze

在 PyTorch 中,squeeze() 方法用于移除张量中维度大小为 1 的维度。这在处理一些维度冗余的数据时非常有用,可以让张量的形状更加简洁,便于后续的计算和处理。下面详细介绍 squeeze() 方法的使用、参数和注意事项。

# 形式一:不指定维度,移除所有大小为 1 的维度
tensor.squeeze()# 形式二:指定维度,仅移除指定维度上大小为 1 的维度
tensor.squeeze(dim)

 不指定维度移除所有大小为 1 的维度

import torch# 创建一个形状为 (1, 3, 1, 2) 的张量
tensor = torch.randn(1, 3, 1, 2)
print("原张量形状:", tensor.shape)# 不指定维度,移除所有大小为 1 的维度
squeezed_tensor = tensor.squeeze()
print("移除所有大小为 1 的维度后形状:", squeezed_tensor.shape)

指定维度移除大小为 1 的维度

import torchtensor = torch.randn(1, 3, 1, 2)
print("原张量形状:", tensor.shape)# 指定维度 0,移除该维度上大小为 1 的维度
squeezed_tensor_0 = tensor.squeeze(0)
print("移除第 0 维后形状:", squeezed_tensor_0.shape)# 指定维度 1,由于该维度大小不为 1,不会进行移除操作
squeezed_tensor_1 = tensor.squeeze(1)
print("尝试移除第 1 维后形状:", squeezed_tensor_1.shape)

 6.permute

permute 方法用于对张量的维度进行重新排列,也就是改变张量各维度的顺序。这在处理不同维度排列的数据时非常有用,比如在图像处理、深度学习模型的数据输入处理等场景中经常会用到。

permute 方法的基本语法如下:

import torch# 创建一个二维张量
tensor_2d = torch.randn(2, 3)
print("原二维张量形状:", tensor_2d.shape)# 交换第 0 维和第 1 维的顺序
permuted_tensor_2d = tensor_2d.permute(1, 0)
print("维度重排后二维张量形状:", permuted_tensor_2d.shape)

在这个例子中,原二维张量 tensor_2d 的形状是 (2, 3),通过 permute(1, 0) 把第 0 维和第 1 维的顺序进行了交换,重排后的张量形状变为 (3, 2)

7.view方法

view 方法是用于改变张量(Tensor)形状(shape)的重要工具,不过它不会改变张量中元素的数量和元素本身的值,并且要求原张量的存储是连续的。下面为你详细介绍 view 方法的使用、特性及注意事项。

一维张量转换为二维张量:

import torch# 创建一个一维张量,包含 6 个元素
tensor_1d = torch.arange(6)
print("原一维张量:", tensor_1d)
print("原一维张量形状:", tensor_1d.shape)# 使用 view 方法将其转换为形状为 (2, 3) 的二维张量
tensor_2d = tensor_1d.view(2, 3)
print("转换后的二维张量:", tensor_2d)
print("转换后二维张量形状:", tensor_2d.shape)

 在 view 方法里,可以使用 -1 让 PyTorch 自动推断该维度的大小,但 -1 在一次调用中只能出现一次。

import torchtensor_1d = torch.arange(6)
# 使用 -1 自动推断维度,将其转换为二维张量
tensor_reshaped = tensor_1d.view(2, -1)
print("使用 -1 自动推断维度后的形状:", tensor_reshaped.shape)

2.3 加乘法 

广播机制的规则

广播机制的核心规则是从右向左比较两个张量的形状,对于每一个维度,需要满足以下条件之一:

  1. 维度大小相等:两个张量在该维度上的大小相同。
  2. 其中一个维度大小为 1:如果一个张量在某一维度上的大小为 1,而另一个张量在该维度上有非 1 的大小,那么大小为 1 的维度会被扩展为与另一个张量该维度大小相同
  3. 其中一个张量缺少该维度如果一个张量在某一维度上不存在(即形状中没有对应位置),则可以将其视为该维度大小为 1,然后按照规则 2 进行扩展。

 1.加法

如果两个张量形状不同,但满足广播机制的规则,PyTorch 会自动进行广播操作,使它们的形状匹配后再进行逐元素相加。广播规则是从右向左比较两个张量的维度,要么维度大小相等,要么其中一个维度大小为 1 或缺少该维度。

import torch# 创建一个二维张量和一个一维张量
tensor_2d = torch.tensor([[1, 2, 3], [4, 5, 6]])
tensor_1d = torch.tensor([1, 1, 1])# 利用广播机制相加
result = tensor_2d + tensor_1d
print("广播相加结果:")
print(result)

这里 tensor_1d 形状是 (3,)tensor_2d 形状是 (2, 3)tensor_1d 在第 0 维上会广播,逻辑上扩展为 [[1, 1, 1], [1, 1, 1]],也就是复用原来的数据,然后和 tensor_2d 逐元素相加

2.乘法

矩阵乘法

在 PyTorch 中,使用 torch.matmul() 函数或 @ 运算符进行矩阵乘法。矩阵乘法要求左矩阵的列数等于右矩阵的行数。

import torch# 创建两个二维张量用于矩阵乘法
tensor1 = torch.tensor([[1, 2], [3, 4]])
tensor2 = torch.tensor([[5, 6], [7, 8]])# 矩阵乘法
result = torch.matmul(tensor1, tensor2)
# 或者使用 @ 运算符
# result = tensor1 @ tensor2
print("矩阵乘法结果:")
print(result)


http://www.ppmy.cn/embedded/172462.html

相关文章

Android 11.0 监听某个app启动或者退出功能实现

1.前言 在进行11.0的系统定制开发中,在某些app的定制过程中,需要知道某个app的启动记录和退出记录, 所以就需要监听某个app的启动和退出的过程,需要在Activity的生命周期中来实现监听功能 2.监听某个app启动或者退出功能实现的核心类 frameworks\base\core\java\android…

Python 3.14尾调用解释器的性能剖析

在当今数字化浪潮中,编程语言的性能优化一直是开发者们关注的焦点。Python作为一种广泛使用的高级编程语言,其解释器的性能提升对于众多应用程序具有重要意义。近期,CPython项目引入了一种新的尾调用解释器实现策略,据称能带来显著…

Linux修改conda默认环境位置

# 1. 在终端查看conda 默认环境路径 conda infopackage为缓存路径,envs为虚拟环境路径。以Ubuntu系统为例,默认情况下 /.conda路径排在第一位,表示默认环境安装路径。 2. 修改默认环境路径方法: # 在对应的home/user_name 下&…

人工智能与人的智能,思维模型分享【3】直觉

我认为直觉是人的智能中,很神奇的部分,这是人工智能所不能达到的。 直觉:INTUITIVE THINKING 直觉就是未经逐步分析,仅依据内因的判断,就对事物的答案进行判断。或者突然获得“灵感”和“顿悟”。这是非常有魅力的时…

【深度学习】图像卷积

图像卷积 上节我们解析了卷积层的原理,现在我们看看它的实际应用。由于卷积神经网络的设计是用于探索图像数据,本节我们将以图像为例。 互相关运算 严格来说,卷积层是个错误的叫法,因为它所表达的运算其实是互相关运算&#xf…

计算机视觉cv2入门之图像的读取,显示,与保存

在计算机视觉领域,Python的cv2库是一个不可或缺的工具,它提供了丰富的图像处理功能。作为OpenCV的Python接口,cv2使得图像处理的实现变得简单而高效。 示例图片 目录 opencv获取方式 图像基本知识 颜色空间 RGB HSV 图像格式 BMP格式 …

微信小程序wx.request接口报错(errno: 600001, errMsg: “request:fail -2:net::ERR_FAILED“)

来看看报错 报错如下: 请求发送部分,代码如下: uni.request({url: self.serverUrl "/getRealName",method: GET,data: {"code": self.info.code,},header: {"Authorization": uni.getStorageSync(tokenHead) uni.getStorageSync(token)}}…

【面试题系列】Redis 常见面试题答案

一、基础概念 1. Redis 有哪些数据结构?各自的应用场景是什么? 答案: Redis 支持以下数据结构: String:最基础类型,存储字符串、数字、二进制数据。 场景:缓存用户信息、计数器、分布式锁。H…