张量
一个多维数组,是标量,向量,矩阵的高维扩展
- 标量 一个数 0维张量
- 向量 一行/列数 1维张量
- 矩阵 2维张量
- 3维张量 RGB
Varible
是torch中的数据类型,用于封装Tensor,进行自动求导
- data:被包装的Tensor
- grad:data的梯度
- grad_fn:创建Tensor的Function,是自动求导的关键
- requirs_grad:指示是否需要梯度
- is_leaf:指示是否是叶子结点(张量)
Tensor 张量
- dtype:张量的数据类型
- shape:张量的形状
- device:张量所在的设备,GPU/CPU,是加速的关键
Tensor的创建
方法一:直接创建
- torch.tensor() ————功能:从data创建tensor
torch.tensor(
data, //数据,可以是list,numpy
dtype=None, //数据类型,默认与data一致
device=None, //所在设备,cuda/cpu
requires_grad=False, //是否需要梯度
pin_memory=False) //是否存于锁页内存
- torch.from_numpy(ndarray)————从numpy创建tensor
arr=np.array([[1,2,3],[4,5,6]])
t=torch.from_numpy(arr)
array与tensor共享数据类型
方法二:依据数值创建
- torch.zeros——————依size创建全0张量
torch.zeros(
*size, //张量的形状,如(3,3)、(3,224,224)
out=None, //输出的张量
dtype=None,
layout=torch.strided, //内存中的布局形式,strided,sparse_coo
device=None, //所在设备
requires_grad=False) //是否需要梯度
-
torch.zeros_like()——————依input形状创建全0张量
input:创建与input同形状的全0张量 -
torch.ones()————————全1张量
-
torch.ones_like()
-
torch.full()
-
torch.full_like()
size:形状(3,3)
fill_value:张量的值 -
torch.arange——————创建等差的1维张量
数值区间为 [start,end)
torch.arange(start=0,
end,
step=1, //数列长度 差值,默认1
out=None,
dtype=None,
layout=torch.strided,
device=None,
requires_grad=False)
- torch.linspace()————创建均分的1维张量
[start,end]
steps:数列长度,分几步
t=torch.linspace(2,10,6)
结果:tensor([ 2.0000, 3.6000, 5.2000, 6.8000, 8.4000, 10.0000])
10-2=8,分6步,每步长度1.6
-
torch.logspace(start,end,steps,base)————创建对数均分的1维张量
长度为steps,底为base -
torch.eye()————创建单位对角矩阵(2维张量)
n行数
m列数,方阵不填
方法三:依概率分布创建张量
- torch.normal(mean,std,out)————生成正态分布(高斯分布)
mean 均值
std: 标准差
四种模式:mean 标量 std 标量
mean 标量 std 张量
mean 张量 std 标量
mean 张量 std 张量 - torch.randn()
- torch.randn_like()————标准正态分布
- torch.rand()
- torch.rand_like() ————[0,1)均匀分布
- torch.randint()
- torch.randint_like()———[low,high)均匀分布
size张量的形状 - torch.randperm()————0到n-1的随机排列
- torch.bernoulli()——————以input为概率,生成伯努利分布(01分布,两点分布)
input 概率值
张量的操作
张量的拼接与切分
- tensors:张量序列
- dim:要拼接的维度
format
“{} {}”.format(“hello”, “world”) # 不设置指定位置,按默认顺序
‘hello world’
- torch.cat()———————将张量按维度dim拼接
if flag:
t=torch.ones((2,3))
t_0=torch.cat([t,t],dim=0)
t_1= torch.cat([t, t], dim=1)
print("t_0:{} shape{}\nt_1:{} shape{}".format(t_0,t_0.shape,t_1,t_1.shape))
t_0:tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]]) shapetorch.Size([4, 3])
t_1:tensor([[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.]]) shapetorch.Size([2, 6])
- torch.stack()——————在新创建的维度dim上进行拼接
if flag:
t = torch.ones((2, 3))
t_stack= torch.stack([t,t],dim=2)
print("t_stack:{} shape{}\n".format(t_stack, t_stack.shape))
dim=2 是shape2,3,2
dim=3 时shape2,2,3
t_stack:tensor([[[1., 1.],
[1., 1.],
[1., 1.]],[[1., 1.], [1., 1.], [1., 1.]]]) shapetorch.Size([2, 3, 2])
-
切分 torch.chunk() ————将张量按维度dim进行平均切分
返回值:张量列表
注:若不能整除,最后一份张量小于其他张量
input:要切分的张量
chunks:切分的份数
dim:切分的维度 -
切分 torch.split() ————将张量按维度dim切分
可以指定切分长度
tensor:要切分的张量
split_size_or_sections:为int时,表示每一份长度,为list时,按list元素切分
dim
if flag:
a = torch.ones((2, 5))
list_of_tensors=torch.split(a,[2,1,2],dim=1) #2
for idx,t in enumerate(list_of_tensors):
print("第{}个张量:{}, shape is {}".format(idx+1, t, t.shape
第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])
张量索引
- torch.index_select()————在dim上按index索引数据
返回值:依index索引数据拼接的张量
- input
- dim
- index
if flag:
t = torch.randint(0, 9, size=(3, 3))
idx = torch.tensor([0, 2], dtype=torch.long) # float错
t_select = torch.index_select(t, dim=0, index=idx)
print("t:\n{}\nt_select:\n{}".format(t, t_select))
t:tensor([[8, 4, 7],
[2, 0, 8],
[2, 5, 3]])
t_select: tensor([[8, 4, 7],
[2, 5, 3]])
在dim=0 (行)检索第0和第2维度的张量
注意:dtype=torch.long) # float错
- torch.masked_select()————按mask中的TRUE进行索引
返回值:一维张量
- input
- mask:与input同形状的布尔类型的张量
if flag:
t = torch.randint(0, 9, size=(3, 3))
mask = t.le(5) # ge is mean greater than or equal/ gt: greater than le lt
t_select = torch.masked_select(t, mask)
print("t:\n{}\nmask:\n{}\nt_select:\n{} ".format(t, mask, t_select))
- ge : >=
- gt : >
- le : <=
- lt : <
t: tensor([[2, 0, 8],
[3, 2, 4],
[7, 0, 1]])
mask: tensor([[ True, True, False],
[ True, True, True],
[False, True, True]])
t_select: tensor([2, 0, 3, 2, 4, 0, 1])
符合<=5的数
张量变换
- torch.reshape(input,shape)————变换张量形状
input :要变换的张量
shape:新张量形状
if flag:
t = torch.randperm(8)
t_reshape = torch.reshape(t, (-1, 2,2)) # -1代表第0维度数值为8/2/2=2
print("t:{}\nt_reshape:\n{}".format(t, t_reshape))
t:tensor([1, 7, 0, 2, 3, 6, 4, 5])
t_reshape:
tensor([[[1, 7],
[0, 2]],
[[3, 6],
[4, 5]]])
- torch.transpose(input,dim0,dim1)——交换张量的两个维度
相当于是矩阵的转置
# ======================================= example 8 =======================================
# torch.transpose
flag = True
#flag = False
if flag:
# torch.transpose
t = torch.rand((2, 3, 4))
t_transpose = torch.transpose(t, dim0=1, dim1=2) # c*h*w h*w*c
print("t shape:{}\nt_transpose shape: {}".format(t.shape, t_transpose.shape))
t shape:torch.Size([2, 3, 4])
t_transpose shape: torch.Size([2, 4, 3])
- torch.t() ————2维张量的转置
- torch.squeeze()————压缩长度为1的维度(轴)
dim:若为None,移除所有长度为1的轴;否则移除对应dim长度为1的轴
if flag:
t = torch.rand((1, 2, 3, 1))
t_sq = torch.squeeze(t)
t_0 = torch.squeeze(t, dim=0)
t_1 = torch.squeeze(t, dim=1)
print(t.shape)
print(t_sq.shape)
print(t_0.shape)
print(t_1.shape)
torch.Size([1, 2, 3, 1])
torch.Size([2, 3])
torch.Size([2, 3, 1])
torch.Size([1, 2, 3, 1])
- torch.unsqueeze()——依据dim扩展维度
张量的数学运算
加减乘除,对数,指数,幂函数,三角函数
- torch.add(input,alpha=1,other,out=None)——逐元素计算input+alpha*other
input:第一个张量
alpha:乘项因子
other:第二个张量
# ======================================= example 8 =======================================
# torch.add
flag = True
#flag = False
if flag:
t_0 = torch.randn((3, 3))
t_1 = torch.ones_like(t_0)
t_add = torch.add(t_0, 10, t_1)
print("t_0:\n{}\nt_1:\n{}\nt_add_10:\n{}".format(t_0, t_1, t_add))
t_0:
tensor([[-1.4762, -0.9220, -1.0218],
[ 0.7060, -0.4172, 1.1286],
[ 0.5263, 1.4349, 1.1063]])
t_1:
tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]])
t_add_10:
tensor([[ 8.5238, 9.0780, 8.9782],
[10.7060, 9.5828, 11.1286],
[10.5263, 11.4349, 11.1063]])