维度及Pytorch中常用的维度变换与torch.max()

  2018-11-12 


Tensor.view() 扁平化

简单说就是一个把tensor 进行reshape的操作。
常常配合 a.size(0)来取得某一位的维度数

a=torch.randn(3,4,5,7)
b = a.view(1,-1)
print(b.size())
>>torch.Size([1, 420])

其中参数-1表示剩下的值的个数一起构成一个维度。如上例中,第一个参数1将第一个维度的大小设定成1,后一个-1就是说第二个维度的大小=元素总数目/第一个维度的大小,此例中为3*4*5*7/1=420. (由于第一个维度被展为1了,那后面所有元素全部摊开展平了)

#第1,2个维度不变(保持原来的维度),第三个位置写-1表示剩下的维度全部扁平化为一个维度
d = a.view(a.size(0),a.size(1),-1)
print(d.size())
>>torch.Size([3, 4, 35])

 e=a.view(4,-1,5)
 print(e.size())
 >>torch.Size([4, 21, 5])

扁平化批处理的图片的时候(CNN中会出现)
为了扁平化每一张图片的数据,又不想把不同图片的数据混在一起扁平,那么就应该

x = x.view(x.size(0), -1) 

注意:遇到错误RuntimeError: invalid argument 2: view size is not compatible with input tensor's size and stride (at least one dimension spans across two contiguous subspaces). Call .contiguous() before .view().
需要让Tensor连续化,即加一步x = x.contiguous()
原因解释:https://blog.csdn.net/appleml/article/details/80143212使用torch.view()的条件是Tensor是连续的,在对Tensor进行了transpose等操作之后就会变得不连续,就需要这个函数来连续化

unsqueeze降维 和squeeze升维

对于torch:使用unsqueeze降维 和squeeze升维
#升维
unsqueeze(torch1,0)  #在第0个位置增加一个值为1的维度
#(2, 2)->(1,2,2)
    
#降维
squeeze(torch1)  #squeeze给torch删去值为1的维度
#(2, 2, 1)->(2, 2)
    
比如灰度图像只有2,这个时候就需要升维
    
对于numpy array,函数不一样:expand_dims 升维 squeeze 降维
#升维
expand_dims(narray1,0) #在第0个位置增加一个值为1的维度
与torch用法一致

torch.max函数

①torch.max()简单来说是返回一个tensor中的最大值。例如:

si=torch.randn(4,5)  
print(si)  
>>tensor([[ 1.1659, -1.5195, 0.0455, 1.7610, -0.2064],  
[-0.3443, 2.0483, 0.6303, 0.9475, 0.4364],  
[-1.5268, -1.0833, 1.6847, 0.0145, -0.2088],  
[-0.8681, 0.1516, -0.7764, 0.8244, -1.2194]])

print(torch.max(si))  
>>tensor(2.0483) #输出了最大值

②这个函数的参数中还有一个dim参数,使用方法为re = torch.max(Tensor,dim),返回的res为一个二维向量其中res[0]为最大值的Tensor,res[1]为Tensor中最大值对应的index**。例如:

>>> print(torch.max(si,0))
(tensor([1.1659, 2.0483, 1.6847, 1.7610, 0.4364]), tensor([0, 1, 2, 0, 1]))
>>> print(torch.max(si,0)[0])  
tensor([1.1659, 2.0483, 1.6847, 1.7610, 0.4364])

注意,Tensor的维度从0开始算起。在torch.max()中指定了dim之后,比如对于一个3x4x5的 Tensor,指定dim为0后,得到的结果是维度为0的“每一行”对应位置求最大的那个值,此时输出的Tensor的维度是4x5. (在这个二维tensor里,dim=0就是求每行最大值

对于简单的二维Tensor,如上面例子的这个4x5的Tensor。指定dim为0,则给出的结果是4行做比较之后的最大值;如果指定dim为1,则给出的结果是5列做比较之后的最大值,且此处做比较时是按照位置分别做比较,得到一个新的Tensor。(在这个二维tensor里,dim=1就是求每列最大值

eg
_, preds = torch.max(outputs.data, 1)

输出的outputs也是torch.autograd.Variable格式,得到输出后(网络的全连接层的输出)还希望能到到模型预测该样本属于哪个类别的信息,这里采用torch.max。torch.max()的第一个输入是tensor格式,所以用outputs.data而不是outputs作为输入;第二个参数1是代表dim的意思,也就是取每一行的最大值,其实就是我们常见的取概率最大的那个index;第三个参数loss也是

这个函数可以直接处理组

对于python中的维度的理解(tensor array等)

[ [ [ ] ] ]
最外层是第0维,中间层是第1维,最里层是第二维
操作哪一维,就相当于该维以外的维度都固定住,操作只在该维下进行,对于更高维度(外维),都执行相同的操作

对于网络中fc层之后还要返回计算softmax的值的时候,应该选择return F.los_softmax(x,dim=1)
因为经过fc层之后的矩阵结构为[[a1,a2],[b1,b2]] (假设二分类,batch=2)
则要对[a1,a2]求softmax,再对[b1,b2]求softmax,所以是固定第0维,操作第1维,对第一维的每组求softmax


且听风吟