Pytorch张量核心运算精讲:从类型转换到数值操作全解析
- 一、张量基础转换:跨类型操作的核心方法
-
- [1.1 张量转Numpy数组](#1.1 张量转Numpy数组)
- [1.2 Numpy数组转张量](#1.2 Numpy数组转张量)
- [1.3 标量、张量与数字的转换](#1.3 标量、张量与数字的转换)
- 二、张量数值基本运算:API与符号双操作体系
-
- [2.1 核心运算API:加减乘除与取反](#2.1 核心运算API:加减乘除与取反)
- [2.2 下划线版API:直接修改原张量](#2.2 下划线版API:直接修改原张量)
- [2.3 算术符号:更简洁的替代方案](#2.3 算术符号:更简洁的替代方案)
-
- [2.3.1 基础符号运算:不修改原张量](#2.3.1 基础符号运算:不修改原张量)
- [2.3.2 复合赋值符号:原地修改原张量](#2.3.2 复合赋值符号:原地修改原张量)
- [2.4 张量运算的两个关键特性](#2.4 张量运算的两个关键特性)
- [2.5 API与符号的选择原则](#2.5 API与符号的选择原则)
- 三、张量运算核心流程梳理
- 四、总结
在Pytorch的深度学习实践中,张量(Tensor) 作为数据处理的核心载体,其各类操作是入门者必须掌握的基础技能。从张量与numpy数组的互转,到标量、数字的类型转换,再到加减乘除的数值运算,每一个操作都直接影响着后续模型构建与反向传播的效率。本文将结合实战讲解,把Pytorch张量的核心基础操作一网打尽,让你轻松上手张量运算,夯实深度学习编程基础✨。
一、张量基础转换:跨类型操作的核心方法
在数据处理的过程中,张量与numpy数组、标量与数字之间的转换是高频操作,尤其是在反向传播环节,标量的转换更是日常使用的关键,接下来我们逐一拆解这些转换的核心方法与底层特性。
1.1 张量转Numpy数组
张量转Numpy数组的操作十分简洁,直接通过张量对象.numpy() 方法即可实现,这一方法能快速完成两种数据结构的转换,满足我们利用Numpy库进行后续数据处理的需求。
python
import torch
# 创建张量
t = torch.tensor([1, 2, 3])
# 张量转numpy数组
arr = t.numpy()
print("张量:", t)
print("转换后的numpy数组:", arr)
print("numpy数组类型:", type(arr))
运行结果:
Plain
张量: tensor([1, 2, 3])
转换后的numpy数组: [1 2 3]
numpy数组类型: <class 'numpy.ndarray'>
1.2 Numpy数组转张量
将Numpy数组转为张量有两种核心方法 ,这两种方法的核心区别在于是否共享内存,在实际使用中需根据场景选择,避免因内存共享导致的数据意外修改问题。
| 转换方法 | 内存特性 | 适用场景 |
|---|---|---|
torch.from_numpy(arr) |
与原Numpy数组共享内存 | 数据量较大,追求内存效率,无需独立修改数据 |
torch.Tensor(arr) |
与原Numpy数组不共享内存 | 需独立操作张量,避免修改张量影响原数组 |
| 代码演示: |
python
import torch
import numpy as np
# 创建numpy数组
arr = np.array([4, 5, 6])
# 方法1:from_numpy(共享内存)
t1 = torch.from_numpy(arr)
# 方法2:Tensor(不共享内存)
t2 = torch.Tensor(arr)
# 修改原数组,观察t1和t2的变化
arr[0] = 100
print("共享内存的张量t1:", t1) # 随原数组改变
print("不共享内存的张量t2:", t2) # 不随原数组改变
运行结果:
Plain
共享内存的张量t1: tensor([100, 5, 6], dtype=torch.int32)
不共享内存的张量t2: tensor([4., 5., 6.])
1.3 标量、张量与数字的转换
在模型训练的反向传播中,我们经常需要将张量形式的标量转换为Python原生数字,这一操作通过张量对象.item() 方法即可实现,该方法仅适用于标量张量(即形状为[]的张量),是反向传播中提取损失值、精度值的核心方法。
python
import torch
# 创建标量张量
t_scalar = torch.tensor(99)
# 标量张量转Python数字
num = t_scalar.item()
print("标量张量:", t_scalar)
print("转换后的数字:", num)
print("数字类型:", type(num))
运行结果:
Plain
标量张量: tensor(99)
转换后的数字: 99
数字类型: <class 'int'>
二、张量数值基本运算:API与符号双操作体系
Pytorch为张量的数值运算提供了两套操作方案 :一是专用的API函数(如add、sub),二是更简洁的算术符号(如+、-)。其中API函数又分为普通版 和下划线版 (如add_、sub_),核心区别在于是否修改原张量,这一设计与Pandas中的inplace=True异曲同工,接下来我们详细讲解这一体系的使用方法与核心特性。
2.1 核心运算API:加减乘除与取反
张量的基础数值运算包含加、减、乘、除、取反 五大核心操作,对应的API函数及含义如下表所示,所有普通版API均不会修改原张量,会返回一个新的张量作为运算结果。
| 运算类型 | 核心API | 英文全称 | 功能说明 |
|---|---|---|---|
| 加法 | torch.add()/t.add() |
add | 张量与数值/另一张量做加法 |
| 减法 | torch.sub()/t.sub() |
subtract | 张量与数值/另一张量做减法 |
| 乘法 | torch.multiply()/t.multiply() |
multiply | 张量与数值/另一张量做点乘 |
| 除法 | torch.divide()/t.divide() |
divide | 张量与数值/另一张量做除法,返回小数 |
| 取反 | torch.neg()/t.neg() |
negative | 对张量中每个元素取相反数,无需传参 |
2.2 下划线版API:直接修改原张量
在所有核心运算API后添加下划线 ,即得到原地运算API (如add_、sub_),这类API会直接修改原张量 的数值,不返回新的张量,适用于需要节省内存、直接更新数据的场景,其效果等价于API普通版 + 原张量赋值。
我们以加法为例,对比普通版API与下划线版API的差异:
python
import torch
# 创建基础张量
t = torch.tensor([1, 2, 3])
# 普通版add:不修改原张量,返回新张量
t_new = t.add(10)
print("原张量t:", t)
print("新张量t_new:", t_new)
# 下划线版add_:直接修改原张量,无返回值
t.add_(10)
print("执行add_后的原张量t:", t)
运行结果:
Plain
原张量t: tensor([1, 2, 3])
新张量t_new: tensor([11, 12, 13])
执行add_后的原张量t: tensor([11, 12, 13])
2.3 算术符号:更简洁的替代方案
对于入门者和日常开发而言,算术符号 是比API更优的选择,无需记忆繁琐的函数名,仅用+、-、*、/、-(取反)即可实现上述所有运算,且效果与普通版API完全一致。同时,复合赋值符号 (如+=、-=、*=、/=)可实现与下划线版API相同的原地修改效果,让代码更简洁、可读性更高💻。
2.3.1 基础符号运算:不修改原张量
python
import torch
t = torch.tensor([1, 2, 3])
# 加法:等价于t.add(10)
t_add = t + 10
# 减法:等价于t.sub(1)
t_sub = t - 1
# 乘法:等价于t.multiply(2)
t_mul = t * 2
# 除法:等价于t.divide(2),返回小数
t_div = t / 2
# 取反:等价于t.neg()
t_neg = -t
print("原张量:", t)
print("加法结果:", t_add)
print("减法结果:", t_sub)
print("乘法结果:", t_mul)
print("除法结果:", t_div)
print("取反结果:", t_neg)
运行结果:
Plain
原张量: tensor([1, 2, 3])
加法结果: tensor([11, 12, 13])
减法结果: tensor([0, 1, 2])
乘法结果: tensor([2, 4, 6])
除法结果: tensor([0.5000, 1.0000, 1.5000])
取反结果: tensor([-1, -2, -3])
2.3.2 复合赋值符号:原地修改原张量
python
import torch
t = torch.tensor([1, 2, 3])
# 原地加法:等价于t.add_(10)
t += 10
print("执行+=后的张量:", t)
# 原地乘法:等价于t.multiply_(2)
t *= 2
print("执行*=后的张量:", t)
运行结果:
Plain
执行+=后的张量: tensor([11, 12, 13])
执行*=后的张量: tensor([22, 24, 26])
2.4 张量运算的两个关键特性
在使用上述所有运算方式时,有两个核心特性需要牢记,这是避免运算错误、提升代码效率的关键:
特性1:广播机制------标量与张量的逐元素运算
当张量与单个数值 进行运算时,Pytorch会自动触发广播机制 ,将该数值与张量中的每一个元素依次进行运算,无需手动遍历,这一特性极大简化了标量与张量的运算代码,也是上述所有示例中能直接用张量加/减/乘/除单个数值的原因。
特性2:除法的两种形式------浮点除与整除
Pytorch中张量的除法分为浮点除(/) 和整除(//) 两种:
-
浮点除 :使用
/或divide(),返回浮点型张量,保留小数部分; -
整除 :使用
//,返回整型张量,仅保留商的整数部分,舍去余数。
代码演示:
python
import torch
t = torch.tensor([1, 2, 3])
# 浮点除
t_float_div = t / 2
# 整除
t_int_div = t // 2
print("浮点除结果:", t_float_div)
print("整除结果:", t_int_div)
运行结果:
Plain
浮点除结果: tensor([0.5000, 1.0000, 1.5000])
整除结果: tensor([0, 1, 1])
2.5 API与符号的选择原则
看到这里很多同学会问:既然符号运算更简洁,为什么Pytorch还要提供API函数?其实这一设计是为了满足不同的开发需求:
-
对于日常开发、快速原型构建 ,算术符号是最优选择,代码更简洁、易读、易写,无需记忆API;
-
对于复杂框架开发、自定义函数 ,API函数更具灵活性,可作为参数传入其他函数,适配更复杂的编程场景。
简单来说:入门用符号,进阶按需用API,无需死记硬背所有API,掌握符号运算即可应对90%以上的日常场景✅。
三、张量运算核心流程梳理
为了让大家更清晰地掌握张量基础运算的逻辑,我们用Mermaid流程图梳理从张量创建到数值运算的完整流程,涵盖「不修改原张量」和「修改原张量」两种核心场景,帮你形成系统化的操作思路。
否
是
导入torch库
创建张量t
是否修改原张量?
普通API/基础符号运算
下划线API/复合赋值符号
新张量,原张量不变
原张量直接更新
操作新张量
操作更新后原张量
图表说明:该流程图展示了Pytorch张量基础数值运算的核心决策与操作流程,核心分支为「是否修改原张量」,不同分支对应不同的操作方式,最终导向不同的张量使用结果,是日常张量运算的核心逻辑框架。
四、总结
本文详细讲解了Pytorch张量的基础类型转换 和数值基本运算两大核心模块,核心知识点可总结为以下几点:
-
张量与Numpy互转的关键在内存共享 ,
from_numpy共享内存,Tensor不共享;item()是标量张量转数字的核心方法,反向传播高频使用; -
张量数值运算有API 和算术符号 两套体系,API下划线版等价于Pandas的
inplace=True,直接修改原张量; -
算术符号是入门最优解,
+、-、*、/对应基础运算,+=、-=、*=、/=对应原地运算,取反直接用-,简洁高效; -
张量与标量运算触发广播机制 ,逐元素运算;除法分
/(浮点除)和//(整除),按需选择; -
API与符号无优劣,日常开发用符号,复杂开发用API,无需死记硬背。
张量的基础运算是Pytorch的入门基石,掌握这些操作后,我们才能进一步学习张量的点乘、矩阵乘法、维度变换等更复杂的操作,为后续的神经网络构建、模型训练打下坚实的基础。后续我们将继续讲解张量的高级运算,敬请期待🚀!
小练习:尝试用本文的知识实现以下操作:
-
创建一个Numpy数组
[7,8,9],分别用两种方法转为张量,验证内存共享特性; -
创建张量
[2,4,6],分别用API和符号实现「加5」「乘3」「整除2」,对比两种方式的结果; -
将标量张量
torch.tensor(66.6)转为Python数字,打印类型与数值。
(答案可在评论区交流,一起夯实基础~)