11创建tensor02
randn一般是均值为0,方差为1的正态分布N(0,1),也可以自定义N(u,std)用torch.normal
torch.normal(mean=torch.full([10],0),std=torch.arange(1,0,-0.1))
#比如先把一个2*5的矩阵打平变成1*10,然后normal后再reshape为2*5
#torch.full先构建一个一维长度为10全是0的tensor,这样他们的mean就都是0
#torch.arange使得标准差std分布为[1,0.9,0.8....]
full
默认类型是FloatTensor
torch.full([2,3],7)#dim=2,即两行三列的tensor
torch.full([],7)#dim=0,即标量
torch.full([1],7)#dim=1,一维一个元素的向量
torch.full([2],7)#dim=1, 一维两个元素的向量
tensor([7.,7.])
arange等差数列
[start,end) 左闭右开
linspace按照steps等分切割 等差数列
[start,end]左闭右闭
/logspace按照steps等分切割
按照step^start ——>step^end等分
[start,end]左闭右闭
例:torch.logspace(0,1,steps=10)
10^0=1 到 10^1=10 间按10^0.1 10^0.2…划分
ones:所有元素为1
zero:所有元素为1
eye:对角线赋值为1如果不是对角矩阵后面赋值为0
以上接收的都是shape
torch.eye(3)#3*3的对角矩阵
torch.zeros(3*3)#3*3的0矩阵
torch.ones_like(a)#和a一样形状的3*3的1矩阵
a=torch.ones(3,3)#dim=2 因为还是一个二维的平面矩阵
print(a)
'''
tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]])
'''
randperm 打散
idx=torch.randperm(2)#因为a、b都有两行,所以参数是2,
a[idx]
b[idx]必须是同一索引
import torch
a=torch.rand(2,3)
b=torch.rand(2,2)
idx=torch.randperm(2)#因为a、b都有两行,所以参数是2
print(a)
print(b)
print(idx)#[1,0]
print(a[idx])#对于a,bidx必须是同一索引
print(b[idx])
print(a)
print(b)
'''
tensor([[0.2436, 0.6611, 0.8526],
[0.1075, 0.2996, 0.2687]])
tensor([[0.9829, 0.6718],
[0.0802, 0.7499]])
tensor([1, 0])#表示dim=1,这样行互换,如果是[0,1]保持不变
tensor([[0.1075, 0.2996, 0.2687],
[0.2436, 0.6611, 0.8526]])
tensor([[0.0802, 0.7499],
[0.9829, 0.6718]])
'''
12索引与切片1
indexing
dim 0 first
a=toch.rand(4,3,28,28)#b c h w b表示batchsize就是几张图片
a[0].shape#取第一个维度的 就是第一张图片 包含三个维度:通道,长,宽
a[0,0].shape#取dim=0,dim=1的shape即第0张图片的第0通道
a[0,0,2,4]#第0张图片的第0通道的第二行第四列的像素点 打印出来是一个常量,标量,dim=0
select first/last N
取连续的片段
a[:2].shape
#0->2,即0,1不包含2,所以包含的是前两张图片的shape
#结果是[2,3,28,28]
a[:2,:1,:,:].shape
#即第0,1张图片的第0个通道的所有图片的数据,
#:默认取全部即从0-28全部都取
a[:2,1:,:,:].shape
#:2即第0,1张图片,两张图片
#1:从第1个通道开始到全部的通道即第1,2两个通道
#正向索引0,1,2
#反向索引-3,-2,-1
a[:2,-1:,:,:].shape
#:2即第0,1张图片,两张图片
#-1:从最后一个通道开始到结束,所以只有一个通道
select by steps
写两个:表示隔行采样
a[:,:,0:28:2,0:28:2].shape
#0:28:2表示[0,28)且每隔2取一次,所以是14
a[:,:,::2,::2].shape
#::2取所有,每隔2取一次, 所以是14,与上同
冒号总结:
:
all,只有冒号取所有[0,n)
:x
[0,x)
x:
[x,n)
start:end:step
[start,end)隔step取一次
13索引与切片2
select by specific index
具体的索引
先定义了一个tensor,这里用到了linspace和view方法.
1第一个参数是索引的对象
2第二个参数0表示按行索引,1表示按列进行索引
3第三个参数是一个tensor,就是索引的序号,比如b里面tensor[0, 2]表示第0行和第2行,c里面tensor[1, 3]表示第1列和第3列。
返回切片后的张量tensor.
import torch
a = torch.linspace(1, 12, steps=12).view(3, 4)
print(a)
#tensor([[ 1., 2., 3., 4.],
# [ 5., 6., 7., 8.],
# [ 9., 10., 11., 12.]])
b = torch.index_select(a, 0, torch.tensor([0, 2]))
print(b)
#tensor([[ 1., 2., 3., 4.],
# [ 9., 10., 11., 12.]])
c = torch.index_select(a, 1, torch.tensor([1, 3]))
print(c)
#tensor([[ 2., 4.],
# [ 6., 8.],
# [10., 12.]])
a=torch.rand(4,3,28,28)
print(a)
b=a.index_select(0,torch.tensor([0,2]))#0表示是第0个维度,[0,2]表示指定的是第0张和第2张图片
#其他三个维度的数全取 所以打印的是一个[2,3,28,28]的tensor
print(b)
print(b.shape)
c=a.index_select(1,torch.tensor([1,2]))#1表示是第1个维度,[1,2]表示指定的是第1和第2通道
#其他三个维度的数全取 所以打印的是一个[4,2,28,28]的tensor 四张图片,取rgb的gb两个通道,其他全取
print(c)
print(c.shape)#torch.Size([4, 2, 28, 28])
d=a.index_select(2,torch.arange(8))#对第2个维度操作,就是对行操作,取[0,8)即0-7行共8行,其他全取
print(d.shape)#torch.Size([4, 3, 8, 28])
…
表示任意多的维度可以取代任意多的:,:,:,
,根据实际情况判断是取多少维度
print(a[...].shape)#其实就是a torch.Size([4, 3, 28, 28])
print(a[0,...].shape)#其实就是a[0] ...代表chw 取的是第0张图片,其他全取 torch.Size([3, 28, 28])
print(a[0,...,::2].shape)#其实就是a[0,:,:,::2] ...代表ch 取第0张图片,在列上隔2取 torch.Size([3, 28, 14])
print(a[:,1,...,:].shape)#其实就是a[:,1]或者a[:,1,:,:] 取第1个通道其他全取 torch.Size([4, 28, 28])
print(a[...,:2].shape)#其实就是a[:,:,:,:2]前三维度全取,最后列只取0和1列 torch.Size([4, 3, 28, 2]) torch.Size([4, 3, 28, 2])
select by mask
用掩码,但是把数据打平处理
mask=x.ge(0.5)#值大于0.5的将对应位置索引的矩阵置TRUE
掩码为TRUE的值取出来
但是会把34的矩阵打平成112的向量,再取出符合的值,最后的shape 维度是1
import torch
x=torch.randn(3,4)
print(x)
mask=x.ge(0.5)
print(mask)
a=torch.masked_select(x,mask)
print(a)
print(a.shape)
'''
tensor([[ 1.3789, -1.8209, 0.9027, 1.6865],
[ 0.3729, -0.6339, 0.5470, 0.6969],
[-0.3212, 0.0666, -1.2894, -2.0430]])
tensor([[ True, False, True, True],
[False, False, True, True],
[False, False, False, False]])
tensor([1.3789, 0.9027, 1.6865, 0.5470, 0.6969])
torch.Size([5])
'''```
**select by flatten index**
比较index_select(dim,torch.tensor([x1,x2]))
把2*3的tensor打平成1*6的vector所以索引变了
```bash
src=torch.randn(2,3)
print(src)
c=torch.take(src,torch.tensor([0,2,5]))
print(c)
'''
tensor([[-2.6371, 1.2871, -0.6298],
[-0.7618, -1.1859, 0.4471]])
tensor([-2.6371, -0.6298, 0.4471])
'''
14维度变换1
Operation
▪ View/reshape
▪ Squeeze/unsqueeze
▪ Transpose/t/permute
▪ Expand/repeat
View/reshape
缺点是维度丢失,因为b可能是a.view(4,784)而来,但是b不知道原来a怎么存储的,即不知道[B,C,W,H]是什么具体的值
a=torch.rand(4,1,28,28)#load进4张图片,通道为1表示灰度单色图,长28,宽28
a.view(4,28*28)#chw后三个维度合在一起,变成[4,784]就是每张图片忽略位置信息上下信息,合成784,这使用于全连接层
a.view(4*28,28)#前三个维度合并在一起bch合并,变成[N,28]表示只关注每行的28个像素点的信息
a.view(4*1,28,28)#前两个维度b和c合在一起,表示四个方框框,只关注features map这个属性,不关注灰度是单色还是彩色,不关注features map是来自哪个通道
view的时候必须保证size是一样
prod(a.size)==prod(a’.size)
15维度变换2
squeeze v.s unsqueeze挤压维度和展开维度
unsqueeze(pos/index) 表示在pos/index这个位置插入一个维度,对数据本身没影响,只是增加维度,换个角度理解数据的存储
a的torch.Size([4,1,28,28])
a.unsqueeze(0).shape#torch.Size([1,4,1,28,28]) 可以理解成在batch之前添加了一组或一个集合,里面有四张照片,但是本身的数据没变化,只是理解方式变化了
a.unsqueeze(-1).shape#torch.Size([4,1,28,28,1]) 可以理解成在最后面增加了一个方差或者均值的维度,但是本身的数据没变化,只是理解方式变化了
index的范围是[-a.dim()-1,a.din()+1] 即[-5,5)
索引的对应如下
0 1 2 3 4 正的索引是在当前索引前插入
-5 -4 -3 -2 -1 负的索引是在当前索引后插入
总的来说就是放在index所指的位置上即可
a=torch.tensor([1.2,2.3])
print(a)
print(a.dim())
print(a.shape)
b=a.unsqueeze(-1)
print(b)
print(b.shape)
c=a.unsqueeze(0)
print(c)
print(c.shape)
'''
tensor([1.2000, 2.3000])
1
torch.Size([2])
tensor([[1.2000],
[2.3000]])
torch.Size([2, 1])
tensor([[1.2000, 2.3000]])
torch.Size([1, 2])
'''