介绍
torch.tensor()函数的作用是:创建张量(Tensor)的基础入口,所有深度学习的数据存储、运算都围绕张量展开。
功能
torch.tensor() 用于从Python列表、元组、NumPy数组等数据创建张量,是PyTorch中最基础、最常用的张量构造方法。
核心特点:
- 输入数据会被拷贝到新张量中(区别于
torch.as_tensor()的共享内存); - 支持指定数据类型、存储设备(CPU/GPU)、是否需要自动求导等关键属性。
基本语法
torch.tensor(
data, # 必须:数据源(列表、元组、NumPy数组、标量等)
dtype=None, # 可选:张量数据类型(如torch.float32、torch.int64)
device=None, # 可选:存储设备(如"cpu"、"cuda:0")
requires_grad=False, # 可选:是否需要自动求导(训练时参数需设True)
pin_memory=False, # 可选:是否分配锁页内存(GPU训练加速)
requires_grad_=None # 兼容旧版本,优先级低于requires_grad
)
例子
1. 基础创建(不同数据源)
import torch
import numpy as np
# 1. 从标量创建(0维张量/标量张量)
t_scalar = torch.tensor(5)
print("标量张量:", t_scalar) # tensor(5)
print("维度数:", t_scalar.ndim) # 0
print("形状:", t_scalar.shape) # torch.Size([])
# 2. 从列表创建(1维/2维张量)
t_1d = torch.tensor([1, 2, 3]) # 1维张量(向量)
t_2d = torch.tensor([[1,2], [3,4]]) # 2维张量(矩阵)
print("1维张量:", t_1d)
print("2维张量:\n", t_2d)
# 3. 从NumPy数组创建(数据拷贝,互不影响)
np_arr = np.array([1.0, 2.0, 3.0])
t_from_np = torch.tensor(np_arr)
# 修改NumPy数组,张量不受影响(拷贝特性)
np_arr[0] = 10.0
print("NumPy数组:", np_arr) # [10. 2. 3.]
print("张量:", t_from_np) # tensor([1., 2., 3.])
2. 关键参数
# 1. 指定数据类型(dtype)
t_int = torch.tensor([1,2,3], dtype=torch.int32)
t_float = torch.tensor([1,2,3], dtype=torch.float32)
print("int32张量:", t_int.dtype) # torch.int32
print("float32张量:", t_float.dtype)# torch.float32
# 2. 指定存储设备(CPU/GPU)
if torch.cuda.is_available():
t_cuda = torch.tensor([1,2,3], device="cuda:0")
print("GPU张量设备:", t_cuda.device) # cuda:0
else:
print("无CUDA环境,使用CPU张量")
# 3. 开启自动求导(requires_grad)
t_grad = torch.tensor([1.0, 2.0], requires_grad=True)
print("是否可求导:", t_grad.requires_grad) # True
# 验证求导功能
y = t_grad.sum()
y.backward()
print("梯度:", t_grad.grad) # tensor([1., 1.])
3. 特殊值张量创建
torch.tensor() 适合从已有数据创建,而PyTorch还提供了创建特殊值张量的专用函数,对比如下:
# torch.tensor:从已有数据创建
t_custom = torch.tensor([0,0,0])
# 专用函数:创建全0/全1/随机张量(更高效)
t_zero = torch.zeros(3) # [0.,0.,0.]
t_one = torch.ones(3) # [1.,1.,1.]
t_rand = torch.rand(3) # 0~1随机数
print("全0张量:", t_zero)
print("随机张量:", t_rand)
与相似函数的区别
新手容易混淆torch.tensor()和torch.Tensor()/torch.as_tensor(),这里明确区别:
| 函数 | 核心特点 | 适用场景 |
|---|---|---|
torch.tensor() |
数据拷贝,需指定数据源,dtype默认匹配输入 | 从已有数据创建独立张量 |
torch.Tensor() |
类构造函数,无数据源时创建未初始化张量 | 不推荐(易踩未初始化内存坑) |
torch.as_tensor() |
数据共享(NumPy→张量),不拷贝 | 大规模数据,节省内存 |
torch.zeros()/ones() |
直接创建全0/全1张量,无需数据源 | 初始化空张量 |
对比示例:torch.tensor() vs torch.as_tensor()
np_arr = np.array([1,2,3])
# torch.tensor:拷贝数据
t_copy = torch.tensor(np_arr)
# torch.as_tensor:共享内存
t_share = torch.as_tensor(np_arr)
# 修改NumPy数组
np_arr[0] = 100
print("torch.tensor(拷贝):", t_copy) # [1,2,3](不受影响)
print("torch.as_tensor(共享):", t_share)# [100,2,3](同步修改)
属性
| 属性名 | 含义 | 示例(以t = torch.tensor([[1.0,2.0],[3.0,4.0]], device="cuda", requires_grad=True)为例) |
|---|---|---|
shape / size() |
张量的形状(返回torch.Size对象,可索引);size()是等价方法 |
t.shape → torch.Size([2, 2]);t.size(0) → 2(第0维长度) |
ndim |
张量的维度数(阶/秩,如0维标量、1维向量、2维矩阵) | t.ndim → 2 |
dtype |
张量的数据类型(如torch.float32、torch.int64) |
t.dtype → torch.float32 |
device |
张量的存储设备(CPU/GPU,如cpu、cuda:0) |
t.device → device(type='cuda', index=0) |
requires_grad |
张量是否开启自动求导(训练时参数需设为True) |
t.requires_grad → True |
numel() |
张量的总元素个数(返回整数) | t.numel() → 4(2×2) |
例子:一维张量
import torch
# 创建测试张量:一维(7维向量)浮点张量
# 设备优先用GPU(无则用CPU),开启自动求导(模拟模型参数/梯度向量)
t = torch.tensor(
[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0], # 7个元素的一维向量
dtype=torch.float32, # 指定32位浮点类型(深度学习常用)
device="cuda:0" if torch.cuda.is_available() else "cpu",
requires_grad=True # 开启自动求导
)
# 核心属性演示(按常用程度排序)
print("1. 形状(shape):", t.shape) # 输出:torch.Size([7]) → 一维,长度7
print(" 向量长度(size(0)):", t.size(0)) # 输出:7 → 一维张量只有第0维
print("2. 维度数(ndim):", t.ndim) # 输出:1 → 一维张量(向量)
print("3. 数据类型(dtype):", t.dtype) # 输出:torch.float32
print("4. 存储设备(device):", t.device) # 输出:cuda:0 或 cpu
print("5. 是否求导(requires_grad):", t.requires_grad) # 输出:True
print("6. 总元素数(numel()):", t.numel()) # 输出:7 → 一维张量的元素数=向量长度
输出示例(CPU环境)
1. 形状(shape): torch.Size([7])
向量长度(size(0)): 7
2. 维度数(ndim): 1
3. 数据类型(dtype): torch.float32
4. 存储设备(device): cpu
5. 是否求导(requires_grad): True
6. 总元素数(numel()): 7
关键说明(针对一维张量的重点)
shape/size():一维张量的shape是torch.Size([n])(n为元素个数),size(0)直接返回向量长度(比如7维词嵌入向量的size(0)=768),这是判断向量维度的核心依据(区别于[1,7]的二维张量)。ndim:ndim=1是一维张量(向量)的核心特征,也是和标量(ndim=0)、矩阵(ndim=2)的关键区分点。numel():一维张量的numel()等于向量长度(比如7个元素就是7),这在计算向量参数量、内存占用时很常用(比如float32的7维向量占7×4=28字节)。- 实用场景:一维张量对应深度学习中的“向量”,比如BERT的768维词嵌入、模型的梯度向量、注意力打分的一维结果,这些场景下你都会用到上述属性来确认向量的长度、类型和设备。
总结
针对一维张量的核心属性关键点:
shape=[7]明确是长度为7的一维向量(区别于[1,7]的二维张量);ndim=1是向量的本质特征,也是torch.dot()等向量运算的输入要求;numel()=7等于向量长度,是一维张量元素数的直接体现;dtype/device/requires_grad标记向量的基础属性,不随维度变化,是跨场景通用的核心属性。
例子:二维张量
import torch
# 创建测试张量:2行3列的浮点张量
# 设备优先用GPU(无则用CPU),开启自动求导
t = torch.tensor(
[[1.1, 2.2, 3.3], # 第一行
[4.4, 5.5, 6.6]], # 第二行
dtype=torch.float32, # 指定浮点数据类型
device="cuda:0" if torch.cuda.is_available() else "cpu", # 指定设备
requires_grad=True # 开启自动求导
)
# 核心属性演示(按常用程度排序)
print("1. 形状(shape):", t.shape) # 输出:torch.Size([2, 3]) → 2行3列
print(" 第0维长度(行):", t.size(0)) # 输出:2 → 行数
print(" 第1维长度(列):", t.size(1)) # 输出:3 → 列数
print("2. 维度数(ndim):", t.ndim) # 输出:2 → 二维张量(矩阵)
print("3. 数据类型(dtype):", t.dtype) # 输出:torch.float32 → 32位浮点
print("4. 存储设备(device):", t.device) # 输出:cuda:0 或 cpu
print("5. 是否求导(requires_grad):", t.requires_grad) # 输出:True
print("6. 总元素数(numel()):", t.numel()) # 输出:6 → 2×3=6个元素
输出示例(CPU环境)
1. 形状(shape): torch.Size([2, 3])
第0维长度(行): 2
第1维长度(列): 3
2. 维度数(ndim): 2
3. 数据类型(dtype): torch.float32
4. 存储设备(device): cpu
5. 是否求导(requires_grad): True
6. 总元素数(numel()): 6
关键说明(针对2×3张量的重点)
shape/size():torch.Size([2, 3])中,第一个数字对应行(第0维),第二个对应列(第1维);通过size(0)/size(1)可单独获取某一维的长度,这在处理矩阵、图片张量(H×W)、文本张量(seq_len×dim)时非常常用。ndim:2维张量对应矩阵(行+列),是深度学习中最常见的张量维度之一(比如单张图片的特征矩阵、单条文本的词嵌入矩阵)。numel():2×3=6个元素,这个属性能快速计算张量的总元素数,常用于计算参数量、内存占用(比如float32张量每个元素占4字节,6个元素就是24字节)。
总结
针对2×3的核心属性关键点:
shape=[2,3]明确张量是2行3列的二维矩阵;ndim=2对应矩阵的维度特征;numel()=6是所有元素的总数,等于各维度长度的乘积(2×3);- 其他属性(
dtype/device/requires_grad)的含义不受张量形状影响,核心作用是标记数据类型、存储位置和求导状态。
二、进阶属性
这些属性主要用于调试、优化或高级操作(如自动求导、内存管理),新手可先了解,后续深入学习时再掌握:
| 属性名 | 含义 | 适用场景 |
|---|---|---|
grad |
张量的梯度值(仅requires_grad=True且调用backward()后才有值) |
查看反向传播后的梯度 |
grad_fn |
记录张量的求导函数(如AddBackward0、MulBackward0) |
调试计算图、排查求导问题 |
is_contiguous() |
张量在内存中是否连续存储 | 优化view()/reshape()操作 |
is_cuda |
张量是否在GPU上(等价于t.device.type == 'cuda') |
快速判断设备类型 |
is_floating_point() |
张量是否为浮点类型(如float32/float64) |
判断是否可求导(仅浮点支持) |
data |
返回张量的底层数据(脱离计算图,不影响求导) | 仅读取数据、避免修改计算图 |
例子
import torch
# 带求导的张量
x = torch.tensor([2.0], requires_grad=True)
y = x **2 + 3*x
# 反向传播计算梯度
y.backward()
# 进阶属性演示
print("1. 梯度(grad):", x.grad) # tensor([7.])(导数=2x+3=7)
print("2. 求导函数(grad_fn):", y.grad_fn) # <AddBackward0 object at 0x7fxxxx>
print("3. 是否连续存储(is_contiguous()):", x.is_contiguous()) # True
print("4. 是否在GPU(is_cuda):", x.is_cuda) # False(CPU张量)
print("5. 是否浮点类型(is_floating_point()):", x.is_floating_point()) # True
print("6. 底层数据(data):", x.data) # tensor([2.])(脱离计算图)
三、易错点与注意事项
shapevssize():shape是属性,size()是方法,效果完全一致,推荐用shape更简洁;grad的初始化:未调用backward()时,grad为None;多次反向传播需先x.grad.zero_()清零;requires_grad仅支持浮点张量:整数张量无法开启求导,需先转为float类型;device是只读属性:不能直接修改(如t.device = "cuda"),需用t.to("cuda")迁移设备;ndimvslen(shape):t.ndim等价于len(t.shape),前者更直观(如t = torch.rand(2,3,4),t.ndim=3,len(t.shape)=3)。
应用场景
- 数据适配:通过
shape判断输入是否符合模型要求(如检查批次数据是否为[batch_size, seq_len, dim]); - 设备迁移:通过
is_cuda判断张量设备,统一CPU/GPU张量(t = t.to("cuda") if not t.is_cuda else t); - 求导调试:通过
grad检查梯度是否为0(排查梯度消失),通过grad_fn确认计算图是否正确; - 内存优化:通过
is_contiguous()判断张量是否连续,连续张量的view()操作更快。
总结
- 核心属性:
shape(形状)、ndim(维度)、dtype(数据类型)、device(设备)、requires_grad(求导)是必掌握的5个属性,能覆盖绝大多数场景; - 进阶属性:
grad(梯度)、grad_fn(求导函数)用于调试反向传播,is_cuda/is_contiguous()用于设备和内存优化; - 关键注意:属性多为只读,修改设备/形状需用
t.to()/t.reshape()等方法,而非直接赋值。
注意事项
- 数据类型隐式转换:输入整数列表默认生成
torch.int64,输入浮点数列表默认生成torch.float32,混合类型会自动转为浮点型:t_mix = torch.tensor([1, 2.0, 3]) print(t_mix.dtype) # torch.float32(自动转为浮点) - 设备不匹配报错:CPU张量和GPU张量不能直接运算,需用
to(device)统一设备:t_cpu = torch.tensor([1,2,3]) if torch.cuda.is_available(): t_cuda = torch.tensor([1,2,3], device="cuda:0") # 错误:t_cpu + t_cuda # 正确:t_cpu.to("cuda:0") + t_cuda - 避免用
torch.Tensor()创建未初始化张量:未初始化张量包含随机垃圾值,极易导致bug:# 不推荐:创建3个元素的未初始化张量(值随机) t_bad = torch.Tensor(3) print("未初始化张量:", t_bad) # 随机值 # 推荐:用torch.empty()或torch.zeros()替代 t_good = torch.empty(3) - 标量张量的运算:0维张量可直接参与数值运算,无需额外转换:
t_scalar = torch.tensor(5) print(t_scalar + 10) # tensor(15) print(t_scalar.item()) # 转为Python标量:5
典型用法
1. 构建模型输入数据
# 模拟文本特征向量(768维词嵌入)
embedding = torch.tensor(np.random.rand(768), dtype=torch.float32)
# 模拟批次数据([batch_size, seq_len, dim])
batch_data = torch.tensor(np.random.rand(32, 128, 768), dtype=torch.float32)
print("批次数据形状:", batch_data.shape) # torch.Size([32, 128, 768])
2. 初始化模型参数(配合nn.Parameter)
import torch.nn as nn
# 自定义线性层参数
w = nn.Parameter(torch.tensor([[1.0,2.0], [3.0,4.0]], requires_grad=True))
b = nn.Parameter(torch.tensor([0.1, 0.2], requires_grad=True))
print("权重参数:\n", w)
print("偏置参数:", b)
总结
torch.tensor()是PyTorch创建张量的基础函数,核心是从已有数据拷贝创建,支持指定dtype、device、是否求导;- 关键区别:与
torch.as_tensor()(共享内存)、torch.Tensor()(未初始化)划清界限,优先用专用函数(zeros()/ones())创建特殊值张量; - 避坑要点:统一设备/数据类型、避免未初始化张量、标量张量用
item()转Python值; - 核心场景:构建输入数据、初始化参数、转换NumPy数据为张量,是深度学习数据处理的第一步。