『PyTorch』Tensor
文章目录
- 1. 张量
- 2. Variable类型(PyTorch 0.4之前)
- 3. Tensor类型(PyTorch 0.4之后)
- 4. 创建Tensor
- 4.1 直接创建
- 4.2 依据数值创建
- 4.2.1 torch.zeros()
- 4.2.2 torch.zeros_like()
- 4.2.3 torch.ones()
- 4.2.4 torch.ones_like()
- 4.2.5 torch.full()
- 4.2.6 torch.full_like()
- 4.2.7 torch.arrange()
- 4.2.8 torch.linspace()
- 4.2.9 torch.logspace()
- 4.2.10 torch.eye()
- 4.3 依据概率分布创建
- 5. 张量的常用操作
- 6. 张量的数学运算
- 6. 张量的数学运算
1. 张量
2. Variable类型(PyTorch 0.4之前)
Variable
是torch.autograd
中的数据类型,主要用于封装Tensor,进行自动求导
-
data
被包装的张量 -
grad
data的梯度 -
grad_fn
创建Tensor的function,是自动求导的关键 -
requires_grad
指示是否需要梯度,True表示需要计算梯度,False表示不需要计算梯度 -
is_leaf
指示是否是叶子结点(张量)
3. Tensor类型(PyTorch 0.4之后)
Variable
从PyTorch 0.4之后开始并入Tensor
,多了3个主要属性
-
dtype
张量的数据类型,如torch.FloatTensor
,torch.cuda.FloatTensor
-
shape
张量的形状,类似NumPy数组的shape -
device
张量所在设备,GPU/CPU,是加速的关键
4. 创建Tensor
4.1 直接创建
4.1.1 torch.tensor()
- 函数
torch.tensor(data, dtype=None, device=None,requires_grad=False, pin_memory=False)
-
功能
从data创建Tensor -
参数
- data:数据,可以是list,numpy的ndarray
- dtype:数据类型,默认与data一致
- device:所在设备,GPU/CPU
- requires_grad:是否需要计算梯度
- pin_memory:是否存于锁业内存,通常就是False,与转换效率有关
import torch
import numpy as np
# 通过torch.tensor()创建张量
ary = np.ones((3,3))
print(f"ndarray的数据类型:{ary.dtype}")
t = torch.tensor(ary)
print(t)
s = torch.tensor(ary,device="cuda")
print(s)
输出结果:
ndarray的数据类型:float64
tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]], dtype=torch.float64)
tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]], device=‘cuda:0’, dtype=torch.float64)
4.1.2 torch.from_numpy()
- 函数
torch.from_numpy(ndarray)
-
功能
从NumPy创建Tensor
从torch.from_numpy创建的Tensor与原ndarray共享内存,当修改其中一个数据,另一个也将会被改动
import torch
import numpy as np
# 通过torch.from_numpy()创建张量
ary = np.random.randint(0, 20, size=9).reshape(3, 3)
t = torch.from_numpy(ary)
print(f"ndarray的数据类型为:{ary.dtype}")
print(t)
输出结果:
ndarray的数据类型为:int32
tensor([[13, 17, 3],
[18, 11, 1],
[17, 8, 4]], dtype=torch.int32)
4.2 依据数值创建
4.2.1 torch.zeros()
- 函数
torch.zeros(*size,out=None,dtype=None,layout=torch.strided,device=None,requires_grad=False)
-
功能
根据size创建全0张量 -
参数
- size:张量的形状
- out:输出的张量
- layout:内存中布局形式,有strided,sparse_coo等,一般默认值
import torch
import numpy as np
# 通过torch.zeros()创建全0张量
out_t = torch.tensor([1])
t = torch.zeros((3,3),out=out_t)
print(t)
print(out_t)
print(id(t)==id(out_t))
输出结果:
tensor([[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])
tensor([[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])
True
4.2.2 torch.zeros_like()
- 函数
torch.zeros_like(input,dtype=None,layout=None,device=None,requires_grad=False)
-
功能
根据input的形状创建全0张量 -
参数
- input:张量,创建的全0张量形状与此一致
4.2.3 torch.ones()
参考torch.zeros()
4.2.4 torch.ones_like()
参考torch.zeros_like()
4.2.5 torch.full()
- 函数
torch.full(size,fill_value,out=None,dtype=None,
layout=torch.strided,device=None,requires_grad=False)
-
功能
根据fill_value的值创建shape为size的张量
4.2.6 torch.full_like()
方法类似
4.2.7 torch.arrange()
- 函数
torch.arange(end, *, out=None, dtype=None, device:=None, requires_grad=False)
torch.arange(start, end, *, out=None, dtype=None, device=None, requires_grad=False)
torch.arange(start, end, step, *, out=None, dtype=None, device=None, requires_grad=False)
-
功能
创建等差的一维张量
注意区间为
4.2.8 torch.linspace()
- 函数
torch.linspace(start, end, steps=100, *, out=None, dtype=None,
layout=strided, device: =None, requires_grad=False)
-
功能
创建均分的一维张量,数值区间为,steps是该张量元素个数,步长要自己算
4.2.9 torch.logspace()
- 函数
torch.logspace(start, end, steps=100, base=10.0, *, out=None,
dtype=None, layout=strided, device=None, requires_grad=False)
-
功能
创建对数均分的一维张量,数值区间为,steps是该张量元素个数,步长要自己算
import torch
t = torch.logspace(2, 6, 5, base=2)
print(t)
输出结果:
tensor([ 4., 8., 16., 32., 64.])
从这可以看出,是把 进行等分,得到指数序列 L,然后,输出的Tensor每个元素是
4.2.10 torch.eye()
- 函数
torch.eye(n, m, *, out=None, dtype=None, layout=strided, device=None, requires_grad=False)
torch.eye(n, *, out=None, dtype=None, layout=strided, device=None, requires_grad=False)
-
功能
创建单位矩阵(二维张量),默认方阵
import torch
t = torch.eye(4)
print(t)
s = torch.eye(3, 4)
print(s)
输出结果:
tensor([[1., 0., 0., 0.],
[0., 1., 0., 0.],
[0., 0., 1., 0.],
[0., 0., 0., 1.]])tensor([[1., 0., 0., 0.],
[0., 1., 0., 0.],
[0., 0., 1., 0.]])
4.3 依据概率分布创建
4.3.1 torch.normal()
-
均值和标准差都是标量
-
函数
torch.normal(mean, std, size, *, generator=None, out=None, dtype=None, layout=strided, device=None, requires_grad=False)
-
功能
根据均值mean,标准差std采样,返回的张量shape为sizet_normal = torch.normal(0, 1., size=(2,3)) print(t_normal)
输出结果:
tensor([[ 0.4256, -0.6451, -0.2785],
[-0.7766, -1.0419, -0.0259]])
-
-
均值和标准差都是张量
-
函数
torch.normal(mean, std, *, generator=None, out=None)
-
功能
返回张量,mean和std的shape必须一致,且返回结果的shape和mean以及std的shape一致,返回结果对应位置的元素值,是根据mean和std的对应位置的值作为均值和标准差采样的mean = torch.arange(1, 5, dtype=torch.float) std = torch.arange(1, 5, dtype=torch.float) t_normal = torch.normal(mean, std) print(f"mean:{mean}") print(f"std:{std}") print(t_normal)
输出结果:
mean:tensor([1., 2., 3., 4.])
std:tensor([1., 2., 3., 4.])
tensor([1.6039, 3.3902, 5.8297, 1.5644])
-
-
均值和标准差有一个是张量
标量会做broadcast处理,参考都是张量的情况
4.3.2 torch.randn()
-
函数
torch.rand(size, *, generator=None, out=None, dtype=None, layout=strided, device=None, requires_grad=False)
-
功能
从均匀分布中采样,返回shape为size的张量torch.rand_like()参考前面类似的like函数
4.3.3 torch.randint()
-
函数
torch.randint(low, high, size, *, generator=None, out=None, dtype=None, layout=strided, device=None, requires_grad=False) torch.randint(high, size, *, generator=None, out=None, dtype=None, layout=strided, device=None, requires_grad=False)
-
功能
从均匀分布中采样,返回shape为size的张量,第二种定义从均匀分布采样torch.randint_like()参考前面类似的like函数
4.3.4 torch.randperm()
-
函数
torch.randperm(n, *, generator, out=None, dtype=None, layout=strided, device=None, requires_grad=False)
-
功能
生成从 到 的随机排列
4.3.5 torch.bernoulli()
-
函数
torch.bernoulli(p, *, generator=None, out=None)
-
功能
以 为概率,生成伯努利分布(分布,两点分布)
5. 张量的常用操作
有些方法是可以直接用Tensor对象.方法的
5.1 张量的拼接与切分
5.1.1 torch.cat()
-
函数
torch.cat(tensors, dim=0, *, out)
-
功能
将张量按照指定维度拼接import torch t = torch.ones(2, 3) t_0 = torch.cat([t, t], dim=0) t_1 = torch.cat([t, t], dim=1) t_2 = torch.cat([t, t, t], dim=1) print(t) print(t_0) print(t_1) print(t_2)
输出结果:
tensor([[1., 1., 1.],
[1., 1., 1.]])tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]])tensor([[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.]])tensor([[1., 1., 1., 1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1., 1., 1., 1.]])
5.1.2 torch.stack()
-
函数
torch.stack(tensors, dim=0, *, out=None)
-
功能
在新创建的维度dim上进行拼接,用到时先实验一下,别想当然,记不住的import torch t = torch.ones(2, 3) t_stack_0 = torch.stack([t, t, t, t], dim=0) t_stack_1 = torch.stack([t, t, t, t], dim=1) t_stack_2 = torch.stack([t, t, t, t], dim=2) print(f"t 的shape:{t.shape}") print(f"t_stack_0的shape:{t_stack_0.shape}") print(f"t_stack_1的shape:{t_stack_1.shape}") print(f"t_stack_2的shape:{t_stack_2.shape}")
输出结果:
t 的shape:torch.Size([2, 3])
t_stack_0的shape:torch.Size([4, 2, 3])
t_stack_1的shape:torch.Size([2, 4, 3])
t_stack_2的shape:torch.Size([2, 3, 4])
5.1.3 torch.chunk()
-
函数
torch.chunk(chunks, dim=0)
-
功能
将张量按维度dim进行平均切分,返回张量列表
【注意】若不能整除,最后一个张量小于其他张量import torch t = torch.ones(2, 7) tensors = torch.chunk(t, dim=1, chunks=3) for index, tensor in enumerate(tensors): print(f"第{index + 1}个张量:{tensor},shape is {tensor.shape}")
输出结果:
第1个张量: tensor([[1., 1., 1.],
[1., 1., 1.]]),shape is torch.Size([2, 3])
第2个张量: tensor([[1., 1., 1.],
[1., 1., 1.]]),shape is torch.Size([2, 3])
第3个张量: tensor([[1.],
[1.]]),shape is torch.Size([2, 1])
5.1.4 torch.split()
-
函数
torch.split(tensor, split_size_or_sections, dim=0)
-
功能
将张量按维度dim进行切分,返回张量列表 -
参数
-
split_size_or_sections
- int时,表示每一份的长度
- list时,按list元素大小切分(元素和要和切割的维度上元素数一致)
import torch t = torch.ones(2, 5) tensors = torch.split(t, 3, dim=1) tensors1 = torch.split(t, [2, 1, 2], dim=1) for index, tensor in enumerate(tensors): print(f"第{index + 1}个张量:{tensor},shape is {tensor.shape}") for index, tensor in enumerate(tensors1): print(f"第{index + 1}个张量:{tensor},shape is {tensor.shape}")
输出结果:
第1个张量: tensor([[1., 1., 1.],
[1., 1., 1.]]),shape is torch.Size([2, 3])
第2个张量: tensor([[1., 1.],
[1., 1.]]),shape is torch.Size([2, 2])第1个张量: tensor([[1., 1.],
[1., 1.]]),shape is torch.Size([2, 2])
第2个张量: tensor([[1.],
[1.]]),shape is torch.Size([2, 1])
第3个张量: tensor([[1., 1.],
[1., 1.]]),shape is torch.Size([2, 2]) -
split_size_or_sections
5.2 张量的索引
5.2.1 torch.index_select()
-
函数
torch.index_select(tensor, dim, index, *, out=None)
-
功能
在维度dim上,按照index索引数据,返回搜索结果拼接而成的张量
【注意】index必须是long类型的一维Tensorimport torch t = torch.randint(0, 9, size=(3, 3)) idx = torch.tensor([0, 2], dtype=torch.long) # 作为索引,这里必须是long t_select = torch.index_select(t, dim=1, index=idx) print(t) print(t_select)
输出结果:
tensor([[4, 7, 2],
[7, 3, 7],
[7, 5, 7]])
tensor([[4, 2],
[7, 7],
[7, 7]])
5.2.2 torch.mask_select()
-
函数
torch.masked_select(tensor, mask, *, out=None)
-
功能
按mask中的True进行索引,返回一维张量import torch t = torch.randint(0, 9, size=(3, 3)) mask = t.ge(5) # ge:>= , gt:> , le , lt t_select = torch.masked_select(t, mask) print(t) print(mask) print(t_select)
输出结果:
tensor([[0, 4, 8],
[2, 7, 5],
[6, 7, 6]])tensor([[False, False, True],
[False, True, True],
[ True, True, True]])tensor([8, 7, 5, 6, 7, 6])
5.3 张量变换
5.3.1 torch.reshape()
-
函数
torch.masked_select(tensor, mask, *, out=None)
-
功能
重塑形状,但是元素个数要对的上import torch t = torch.randint(0, 9, size=(3, 3)) print(t) t = t.reshape(1, -1) s = torch.reshape(t, (1, -1)) print(t) print(s)
输出结果:
tensor([[3, 4, 8],
[7, 8, 1],
[1, 3, 0]])
tensor([[3, 4, 8, 7, 8, 1, 1, 3, 0]])
tensor([[3, 4, 8, 7, 8, 1, 1, 3, 0]]) -
注意——内存共享
import torch t = torch.randint(0, 9, size=(3, 3)) print(t) s = t.reshape(1, -1) s[0][2] = 100 # 内存共享,更改它也会影响原Tensor print(s) print(t)
输出结果:
tensor([[5, 3, 7],
[0, 4, 5],
[3, 0, 7]])tensor([[ 5, 3, 100, 0, 4, 5, 3, 0, 7]])
tensor([[ 5, 3, 100],
[ 0, 4, 5],
[ 3, 0, 7]])
5.3.2 torch.transpose()
-
函数
torch.transpose(dim0, dim1)
-
功能
交换两个维度,比如一般卷积神经网络输入channel×height×width,交换0和1维,然后交换1和2维,得到height×width×channelimport torch t = torch.randint(0, 24, size=(2, 3, 4)) print(t.shape) s = t.transpose(0, 2) print(s.shape)
输出结果:
torch.Size([2, 3, 4])
torch.Size([4, 3, 2])
5.3.3 torch.t()
- 功能:转置二维张量
5.3.4 torch.squeeze()
-
功能
压缩长度为1的轴
- 不输入参数,则移除所有长度为1的维度
- 若指定维度,则当且仅当该维度长度为1时,可以删除该维度
5.3.5 torch.unsqueeze()
-
功能
扩充张量维度import torch t = torch.ones(2, 3, 4) print(t.shape) s = t.unsqueeze(2) p = t.unsqueeze(0) print(s.shape) print(p.shape)
输出结果:
torch.Size([2, 3, 4])
torch.Size([2, 3, 1, 4])
torch.Size([1, 2, 3, 4])
6. 张量的数学运算
需要用到时查询使用
print(s.shape)
> 输出结果:
>
> torch.Size([2, 3, 4])
> torch.Size([4, 3, 2])
### 5.3.3 torch.t()
- <font size=5 color = gree>功能</font>:转置二维张量
### 5.3.4 torch.squeeze()
- <font size=5 color = gree>功能</font>
压缩长度为1的轴
- 不输入参数,则移除所有长度为1的维度
- 若指定维度,则当且仅当该维度长度为1时,可以删除该维度
### 5.3.5 torch.unsqueeze()
- <font size=5 color = gree>功能</font>
扩充张量维度
```python
import torch
t = torch.ones(2, 3, 4)
print(t.shape)
s = t.unsqueeze(2)
p = t.unsqueeze(0)
print(s.shape)
print(p.shape)
输出结果:
torch.Size([2, 3, 4])
torch.Size([2, 3, 1, 4])
torch.Size([1, 2, 3, 4])
6. 张量的数学运算
需要用到时查询使用