l= torch.arange(0,10) * 2
print(l.view(2,5))
print(l.view(2,-1))
result:
tensor([[ 0, 2, 4, 6, 8],
[10, 12, 14, 16, 18]])
tensor([[ 0, 2, 4, 6, 8],
[10, 12, 14, 16, 18]])
把tensor扩展成size的形状
x = torch.tensor([1, 2, 3])
print(x.expand(3, 3))
print(x) # 没有分配新的内存
tensor([[1, 2, 3],
[1, 2, 3],
[1, 2, 3]])
tensor([1, 2, 3])
把tensor_1扩展成和tensor_2一样的形状
mat1 = torch.randn((2,1,1))
mat2 = torch.randn((2,4,2))
mat1 = mat1.expand_as(mat2)
print(mat1.shape)
torch.Size([2, 4, 2])
print(x.repeat(2,4))
print(x)
tensor([[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3],
[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]])
tensor([1, 2, 3])
感觉就是对第 i 维度重复 n 次
import torch
tensor = torch.randn(3, 4)
print('tensor size:', tensor.size())
tensor_1 = tensor[:, None]
print('tensor_1 size:', tensor_1.size())
tensor_2 = tensor[:, :, None]
print('tensor_2 size', tensor_2.size())
tensor size: torch.Size([3, 4])
tensor_1 size: torch.Size([3, 1, 4])
tensor_2 size torch.Size([3, 4, 1])
从实验结果可以看出, None 功能类似torch.unsqueeze(),方便扩展维度,而不改变数据排列顺序。
沿着一个新的维度对张量进行拼接
T1 = torch.tensor([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
T2 = torch.tensor([[10, 20, 30],
[40, 50, 60],
[70, 80, 90]])
print(torch.stack((T1,T2),dim=0).shape)
print(torch.stack((T1,T2),dim=1).shape)
print(torch.stack((T1,T2),dim=2).shape)
print(torch.stack((T1,T2),dim=-1).shape) # 按照最后一维度进行拼接
print(torch.stack((T1,T2),dim=3).shape) # 报错!
# outputs:
torch.Size([2, 3, 3])
torch.Size([3, 2, 3])
torch.Size([3, 3, 2])
torch.Size([3, 3, 2])
将两个张量(tensor)拼接在一起
A = torch.ones((2,3))
B = torch.ones((4,3)) * 2
print(A)
print(B)
C = torch.cat((A,B),dim=0) # shape:6,3
print(C)
# D = torch.cat((A,B),dim=1) # 报错,2 and 4 dimension error
# print(D)
D = torch.cat((A,torch.ones(2,4) * 3),dim=1)
print(D)
tensor([[1., 1., 1.],
[1., 1., 1.]])
tensor([[2., 2., 2.],
[2., 2., 2.],
[2., 2., 2.],
[2., 2., 2.]])
tensor([[1., 1., 1.],
[1., 1., 1.],
[2., 2., 2.],
[2., 2., 2.],
[2., 2., 2.],
[2., 2., 2.]])
tensor([[1., 1., 1., 3., 3., 3., 3.],
[1., 1., 1., 3., 3., 3., 3.]])
any() 函数用于判断给定的可迭代参数 iterable 是否全部为 False,则返回 False,如果有一个为 True,则返回 True。
注:元素除了是 0、空、FALSE 外都算 TRUE。
tmp = torch.randn((2,1,2))
print(torch.zeros_like(tmp))
print(torch.zeros_like(tmp).shape)
tensor([[[0., 0.]],
[[0., 0.]]])
torch.Size([2, 1, 2])
tmp = torch.randn((2,3,2))
t = tmp.new_full((2,),100)
print(t)
print(tmp.device == t.device)
tensor([100., 100.])
True
维度换位
tmp = torch.randn((1,3,2))
print(tmp.shape)
print(tmp.permute(2,0,1).shape)
torch.Size([1, 3, 2])
torch.Size([2, 1, 3])
输入通道被分成num_groups组,每个组包含num_channels / num_groups个通道。分别计算每组的平均值和标准差。
mat = torch.randn((2,6,10,10))
bn1 = nn.GroupNorm(3,6) # 划分成3组,每组进行batchnorm
print(bn1(mat))
bn2 = nn.GroupNorm(6,6)
print(bn2(mat))
bn3 = nn.GroupNorm(1,6)
print(bn3(mat))
返回一个内存连续的有相同数据的tensor,如果原tensor内存连续,则返回原tensor
contiguous一般与transpose,permute,view搭配使用:使用transpose或permute进行维度变换后,调用contiguous,然后方可使用view对维度进行变形(如:tensor_var.contiguous().view() ),如下:
mat = torch.Tensor(5,6)
y = mat.permute(1,0) # 等价于 transpose
# y.view(-1) # 会报错
y = mat.permute(1,0).contiguous()
y.view(-1)
print(y.shape)
报错原因分析:
1.transpose、permute等维度变换操作后,tensor在内存中不再是连续存储的,而view操作要求tensor的内存连续存储,所以需要contiguous来返回一个contiguous copy;
2.维度变换后的变量是之前变量的浅拷贝,指向同一区域,即view操作会连带原来的变量一同变形,这是不合法的,所以也会报错;---- 这个解释有部分道理,也即contiguous返回了tensor的深拷贝contiguous copy数据
返回一个新的张量,对输入的既定位置插入维度 1
注意: 返回张量与输入张量共享内存,所以改变其中一个的内容会改变另一个
x = torch.Tensor(range(24))
x = torch.reshape(x,(2,3,4))
print(x.shape)
x1 = torch.unsqueeze(x,0)
print(x1.shape)
print(x1)
x2 = torch.unsqueeze(x,1)
print(x2.shape)
torch.Size([2, 3, 4])
torch.Size([1, 2, 3, 4])
tensor([[[[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.]],
[[12., 13., 14., 15.],
[16., 17., 18., 19.],
[20., 21., 22., 23.]]]])
torch.Size([2, 1, 3, 4])
对数据的维度进行压缩,去掉维数为1的的维度
x = torch.randn(8).reshape(2,1,1, 4)
print(x.shape)
y = torch.squeeze(x)
x[0][0] = 100
print(x)
print(y.shape)
print(y) # 可见两者共享同一块内存
torch.Size([2, 1, 1, 4])
tensor([[[[ 1.0000e+02, 1.0000e+02, 1.0000e+02, 1.0000e+02]]],
[[[ 7.9778e-01, -6.9345e-01, 7.1565e-03, 3.3529e-01]]]])
torch.Size([2, 4])
tensor([[ 1.0000e+02, 1.0000e+02, 1.0000e+02, 1.0000e+02],
[ 7.9778e-01, -6.9345e-01, 7.1565e-03, 3.3529e-01]])
x = torch.Tensor(range(120))
x = torch.reshape(x,(4,3,2,5)) # 可以看成 4张图片 每张图片3个通道 每个通道的(维度)size是2*5
print(x[0].shape)
print(x[0,0].shape)
print(x[0,0,0].shape)
print(x[0,0,0,0])
print('-' * 40)
# 采用切片
print(x[2:,:,:,:].shape)
print(x[1:2,2:,-2:,:].shape)
print(x[:,:,::2,::2].shape)
print('-' * 40)
# 采用 ... 索引任意多的维度
print(x[...].shape)
print(x[0,...].shape) # 第一张图片的所有维度
print(x[:,1,...].shape) # 所有图片第2通道的所有维度
print(x[...,:2].shape) # 所有图片所有通道所有行的第一、二列
print(x[...,::2].shape) # 所有图片所有通道所有行的奇数列
torch.Size([3, 2, 5])
torch.Size([2, 5])
torch.Size([5])
tensor(0.)
----------------------------------------
torch.Size([2, 3, 2, 5])
torch.Size([1, 1, 2, 5])
torch.Size([4, 3, 1, 3])
----------------------------------------
torch.Size([4, 3, 2, 5])
torch.Size([3, 2, 5])
torch.Size([4, 2, 5])
torch.Size([4, 3, 2, 2])
torch.Size([4, 3, 2, 3])
重新修改Tensor的形状,但是依旧是原来的哪一块内存
x = torch.Tensor(range(24))
y = x.reshape(-1, 6)
print(x.shape)
x[0]= 100
print(y.shape)
print(x)
print(y) # 共用同一块内存
torch.Size([24])
torch.Size([4, 6])
tensor([100., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11.,
12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23.])
tensor([[100., 1., 2., 3., 4., 5.],
[ 6., 7., 8., 9., 10., 11.],
[ 12., 13., 14., 15., 16., 17.],
[ 18., 19., 20., 21., 22., 23.]])
对输入的数据应用线性变换 y = x A T + b y = xA^T+b y=xAT+b
x = torch.Tensor(range(24))
y = x.reshape(-1, 6)
print(y.shape)
linear = nn.Linear(6,8)
out = linear(y)
print(out.shape)
torch.Size([4, 6])
torch.Size([4, 8])
x = torch.randn(8).reshape(-1, 4)
x[0][2] = x[1][3] = x[1][1] = 0
print(x)
# nonzero_idx = x.nonzero() # 官方建议 使用 torch.nonzero()代替
nonzero_idx = torch.nonzero(x)
print(nonzero_idx)
tensor([[-0.0937, 0.6384, 0.0000, -0.3853],
[-0.7973, 0.0000, 0.4418, 0.0000]])
tensor([[0, 0],
[0, 1],
[0, 3],
[1, 0],
[1, 2]])