Pytorch——Tensor

本文详细介绍了PyTorch中张量的索引、视图、形状改变及与NumPy之间的转换方法。通过实例展示了如何使用索引访问张量的部分内容,以及张量与NumPy数组之间的内存共享特性。同时,解释了view()、reshape()和clone()函数在改变张量形状时的区别,以及如何在CPU和GPU之间移动张量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Tensor

索引

Torch可以利用索引来访问Tensor的一部分,但索引出来的部分是与原Tensor共享内存的,即:修改一个,另一个也会随之改变。

import torch
x = torch.rand(5,3)
print(x)
y = x[0, :]
y += 1
print(x) # x也会随共享内存的变化而变化
print(y)
print(x[0, :])
tensor([[0.2241, 0.1542, 0.2040],
        [0.5804, 0.4996, 0.2491],
        [0.6062, 0.9463, 0.7360],
        [0.3936, 0.3053, 0.3879],
        [0.0753, 0.7341, 0.0423]])
tensor([[1.2241, 1.1542, 1.2040],
        [0.5804, 0.4996, 0.2491],
        [0.6062, 0.9463, 0.7360],
        [0.3936, 0.3053, 0.3879],
        [0.0753, 0.7341, 0.0423]])
tensor([1.2241, 1.1542, 1.2040])
tensor([1.2241, 1.1542, 1.2040])

改变形状

view() 来改变Tensor的形状:

注:view()返回的tensor与源tensor共享内存,即:改变其中一个,另一个也会随之改变。
(其实是同一个tensor,view只是改变了对这个tensor的观察角度)

import torch
x = torch.rand(5,3)
y = x.view(15)
z = x.view(-1, 5) # -1所指的纬度可以通过其他纬度值推出
print(x.size(), y.size(), z.size())
x += 1
print(x) # x,y,z都会随之改变
print(y)
print(z)
torch.Size([5, 3]) torch.Size([15]) torch.Size([3, 5])
tensor([[1.0032, 1.2100, 1.1447],
        [1.0054, 1.6816, 1.6480],
        [1.7444, 1.9329, 1.8243],
        [1.5565, 1.8191, 1.6048],
        [1.8856, 1.9817, 1.3463]])
tensor([1.0032, 1.2100, 1.1447, 1.0054, 1.6816, 1.6480, 1.7444, 1.9329, 1.8243,
        1.5565, 1.8191, 1.6048, 1.8856, 1.9817, 1.3463])
tensor([[1.0032, 1.2100, 1.1447, 1.0054, 1.6816],
        [1.6480, 1.7444, 1.9329, 1.8243, 1.5565],
        [1.8191, 1.6048, 1.8856, 1.9817, 1.3463]])

如果我们想返回一个真正新的副本(不共享内存),推荐先用 clone() 创造一个副本,然后再使用 view()。Pytorch还提供了一个 reshape() 可以改变形状,但此函数并不能保证返回的是其拷贝,故而不推荐使用。

使用 clone() 会被记录到计算图中,即:梯度回传到副本时也会传到源Tensor

import torch
x = torch.rand(5,3)
x_cp = x.clone().view(3,5)
x += 1
print(x)
print(x_cp)
tensor([[1.7448, 1.9305, 1.3424],
        [1.7032, 1.4505, 1.3283],
        [1.6731, 1.5162, 1.2067],
        [1.0565, 1.1451, 1.9345],
        [1.5496, 1.5229, 1.7395]])
tensor([[0.7448, 0.9305, 0.3424, 0.7032, 0.4505],
        [0.3283, 0.6731, 0.5162, 0.2067, 0.0565],
        [0.1451, 0.9345, 0.5496, 0.5229, 0.7395]])

还有一个常用函数 item(),它可以将一个标量Tensor转换成一个数字。

x = torch.randn(1)
print(x)
print(x.item())
tensor([1.1236])
1.1236071586608887
总结:索引、view操作是不会开辟新内存的,而y=x+y这样的运算是会新开内存的,然后将y指向新内存。

Tensor与Numpy互相转换

Tensor -> Numpy : numpy()
Numpy -> Tensor : from_numpy() or torch.tensor()

numpy()from_numpy() 这两个函数产生的tensor和numpy是共享内存的,改变其中一个时,另一个也会随之改变。

torch.tensor() 总是会进行数据拷贝,所以返回的tensor与原来的数据不再共享内存。

Tensor -> Numpy : numpy()
import torch
import numpy as np
a = torch.ones(5)
b = a.numpy()
print(a, b)
a += 1
print(a, b)
b += 1
print(a, b)
tensor([1., 1., 1., 1., 1.]) [1. 1. 1. 1. 1.]
tensor([2., 2., 2., 2., 2.]) [2. 2. 2. 2. 2.]
tensor([3., 3., 3., 3., 3.]) [3. 3. 3. 3. 3.]
Numpy -> Tensor : from_numpy()
import torch
import numpy as np 
a = np.ones(5)
b = torch.from_numpy(a)
print(a, b)
a += 1
print(a, b)
b += 1
print(a, b)
[1. 1. 1. 1. 1.] tensor([1., 1., 1., 1., 1.], dtype=torch.float64)
[2. 2. 2. 2. 2.] tensor([2., 2., 2., 2., 2.], dtype=torch.float64)
[3. 3. 3. 3. 3.] tensor([3., 3., 3., 3., 3.], dtype=torch.float64)
Numpy -> Tensor : from_numpy()
import torch
import numpy as np 
a = np.ones(5)
c = torch.tensor(a)
a += 1
print(a)
print(c)
[2. 2. 2. 2. 2.]
tensor([1., 1., 1., 1., 1.], dtype=torch.float64)

Tensor on CPU/GPU

用方法 to() 可以将Tensor在CPU/GPU之间相互移动。

# 以下代码只有在Pytorch GPU版本上才会执行
import torch 
x = torch.rand(5,3) # 在CPU上
if torch.cuda.is_available():
	device = torch.device("cuda")
	y = torch.ones_like(x, device=device) # 直接创建一个在GPU上的Tensor
	x = x.to(device) # 将变量移到GPU上
	z = x + y
	print(z)
	print(z.to("cpu", torch.double)) # to()还可以更改数据类型
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值