RPN 预备编程知识(一) : Numpy VS Pytorch ( Anchor_target_layer )

25 篇文章 1 订阅
18 篇文章 8 订阅

目录

1.  np.where(x>4) ) 知道返回[0] [1]

2. np.meshgrid 构造xy轴

3.  np.ravel( ) VS np.flatten() 拉成一维

4.  x.reshape( )  了解填充方式

5.  np.squeeze(a,axis=none) & b.squeeze(0) [ b是torch.data ]

6.  np.view & tensor.view 区别很大

7.  np.argmax(a,axis = none) & torch.max(a,1) 注意np中有关键字

8.  np.shape VS tensor.size() 一个属性 一个方法

9.  vstack( ) take 1 position argument but 2 were given[an error] 需要的是一个元组

10. np.empty([2,2]) & np.empty(2) & np.empty(2,) VS tensor.new(2,3)

11. np.fill & np.full 默认值 VS tensor.fill_(-1)

12. np.linspace(2,3,5)从2到3有5个数

13. nplogspace(2,3,4,base = 2)

14. np.full_like(a,fill_value) & np.empty_like(a) & np.zeros_like(a) 类似维度的数组

15.  np.ascontiguousarray VS tensor.contiguous() → Tensor  地址连续的需要

16. 广播(重要)

17. torch.stack((a,b,c),dim)

18. expand_as(tensor)

19. torch.equal(a,b) & a.eq(b)

20. dx = deltas[:, 0::4] #!4表示步长,每隔4个选一个(proposal layer)

21.  pred_boxes = np.zeros(deltas.shape, dtype=deltas.dtype)  VS

       pred_boxes = deltas.clone() 返回一个新的与某一个输出同样类型大小的变量。(proposal layer)


由于我自己之前编程很少利用np,这个算一个补习吧。如果想要尝试理解一个np函数什么时候用,可以看anchor_target_layer解析里面的应用。还有就是  numpy&pytorch 总是有时候晕,你比方  np.squeeze(a,axis=none) & a.squeeze() [ a是torch.data ],首先np中没有unsqueeze,pytorch有;  再有就是np.view()和torch中的x.view(x.size[0],-1);还有torch中直接x.size()类似与x.shape(注意后者没有()),但是np没有np.size()。

 

---------------------  

1. np.where(x>4)

返回一个行向量,一个列向量。

所以大多后面加一个[0] np.where(x>4)[0]

---------------------  

2.np.meshgrid

类似于坐标轴一样的感觉,所以rpn生成anchor平移的时候,就可以用到坐标轴,也就是np.meshgrid。

z,s=np.meshgrid(x,y)  z就是x轴,z的每一列就是x轴=-2,1,0,1s的每一行y轴=0,1,2

x=np.array([-2,1,0,1])  4
y=np.array([0,1,2])   3
z,s=np.meshgrid(x,y)   3*4
              列数,行数
>>> z=array([[-2,  1,  0,  1],
             [-2,  1,  0,  1],
             [-2,  1,  0,  1]])
>>> s= array([[0, 0, 0, 0],
              [1, 1, 1, 1],
              [2, 2, 2, 2]])

meshgrid is very useful to evaluate functions on a grid.下面是caffe中的Anchor_target_layer的shift实现过程。

#算出box的偏移量
# 1. 构造原图上的一个grid,看成xy轴
shift_x = np.arange(0, width) * self._feat_stride          
shift_y = np.arange(0, height) * self._feat_stride 
# shift_x 变成 height行np.arange(0, width)
# shift_y 变成 width列np.arange(0, height)两者用ravel展开的时候就是在图片上一行一行读取。
shift_x, shift_y = np.meshgrid(shift_x, shift_y) 
# 用来算偏移量, 原始的anchor只要+shifts就是了,一行一行读取。
shifts = np.vstack((shift_x.ravel(), shift_y.ravel(),  
                    shift_x.ravel(), shift_y.ravel())).transpose() 

shifts.ndim=(H*W,4),注意我写的是H*W,而不是W*H。因为它是逐行添加的,具体可看下面x对应w,y对应h,填充y=0第一行,所有列,然后填充第二行。

---------------------  

3. np.ravel( ) VS np.flatten() 变成1维处理节省空间

相同点都是返回一维度。

np.ravel( )  返回view(视图),共享内存。之前的变了,他也变。更节省!

np.flatten() 返回copy,开辟内存。

--------------------- 

4. x.reshape( )

注意:返回的是view,没有copy。

c = a.reshape(1,3)
>>> a = array([[1],[2],[3]])
>>> a[2] = 4
>>> a
array([[1],[2],[4]])
>>> c
array([[1, 2, 4]])

首先看几个常用的 :

    x.reshape( -1) 变成维度为1的数组。ndim = (n,)

    x.reshape( 1,-1) _>ndim = (1,n) ,-1 可以用到增加维度上。也可以将ndim = (n,)的数组,变成ndim = (1,n) or(n,1)的向量时。

然后通过下面的3维的数组看一下,reshape填充的顺序,从最后一个维度开始赋值。

c = np.arange(8).reshape(2,2,2)
>>> c[0,:,:]
>>> array([[0, 1],
          [2, 3]])
>>> c[0,0,0]= 0  c[0,0,1]= 1  c[0,1,0]= 2  c[0,1,1]= 3

--------------------- 

5. np.squeeze(a,axis=none) & b.squeeze(0) [ b是torch.data ]

首先np中没有unsqueeze。 squeeze的作用,是把axis轴的维度压缩,去掉,前提是axis的维度为 1,如果不是就报错。

a=array([[[1],[2],[3]]])
a.shape
>>>(1,3,1)
np.squeeze(a,axis=0)
>>>array([[1],[2],[3]])
np.squeeze(a,axis=1)
>>>报错
np.squeeze(a,axis=2)
array([[1,2,3]])

但是在pytorch中,有unsqueeze,相当于增加维度。squeeze相当于压缩维度。

tensor.squeeze(0)把第0个轴压缩,如果维度是1则压缩,不是不压缩,也不报错!

--------------------- 

6. np.view & tensor.view

np.view是一个视图,但是在torch中你经常看到x = x.view(x.size(0), -1) 作用是改变维度[n,c,h,w]_>[n,c*h*w]

当需要对输入图像三个通道进行相同的处理时使用cv2.split和cv2.merge是相当浪费资源的,因为任何一个通道的数据对处理来说都是一样的,我们可以用view来将其转换为一维矩阵后再做处理,这要不需要额外的内存开销和时间开销。
代码如下:

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

--------------------- 

7. np.argmax(a,axis = none) & torch.max(a,1)

np.argmax返回的索引 如果axis=1,二维表示在每一行里面找列最大的,只返回索引。高维度的可以这样理解:在axis轴对应的维数里寻找最大。你比如:a.shape=(2,3,4), np.argmax(a,axis=2),按4个数4个数的找最大,返回(2,3)。

torch.max(a,1)[0]  返回最大值

torch.max(a,1)[1]   返回索引

---------------------

8. np.shape VS tensor.size()

首先torch中也有tensor.shape类似于tensor.size(),但是shape是一个属性,而size是一个方法,所以size有()需要参数。

np中没有size()的方法!

---------------------

9. Vstack( ) take 1 position argument but 2 were given[an error]

例:np.row_stack(a,b)

改为:np.row_stack(a,b) -----别忘了括号,里面需要的是一个元组。

---------------------

10. np.empty([2,2]) & np.empty(2) & np.empty(2,) VS tensor.new(2,3)

首先后两个是一样的,其次np.empty([2,2]) 出来每次都一样。然后出来的是无限接近于0的数。

tensor.new()随机建立和tensor一种类型的数据

---------------------

11. np.fill & np.full VS tensor.new().fill_()

创造一列的,有默认值的那种,np.fill & np.full这两个没分清,感觉差不多,之后再说吧。

# label: 1 is positive, 0 is negative, -1 is dont care 

labels = np.empty((len(inds_inside), ), dtype=np.float32)#默认float64 
labels.fill(-1) 

 

 #没有找到new函数,创建和gt_boxes同一类型的new
        labels = gt_boxes.new(batch_size, inds_inside.size(0)).fill_(-1)

---------------------

12. np.linspace(2,3,5)从2到3有5个数

---------------------

13. nplogspace(2,3,4,base = 2)

默认,base = 10 ,4 ...8从2**2到2***3有四个数

---------------------

14. np.full_like(a,fill_value) & np.empty_like(a) & np.zeros_like(a)

创造一个类似于a的但填充了其他value的array

---------------------

15.  np.ascontiguousarray VS tensor.contiguous() → Tensor

主要用在vstack transpose 这种,还有 anchors = all_anchors[inds_inside:]经过索引返回部分结果。打乱了数据内存的情况。而之后要用到torch.view()转换维度 这种需要数据内存连续,才不报错,或者不copy节省空间

 

判断是否contiguous用torch.Tensor.is_contiguous()函数。

import torch
x = torch.ones(10, 10)
x.is_contiguous()  # True
x.transpose(0, 1).is_contiguous()  # False
x.transpose(0, 1).contiguous().is_contiguous()  # True

另外,在pytorch的最新版本0.4版本中,增加了torch.reshape(), 这与 numpy.reshape 的功能类似。它大致相当于 tensor.contiguous().view()

 #bbox_overlaps里有vastck
overlaps = bbox_overlaps( #返回大小连续的overlaps,等同于排序
            np.ascontiguousarray(anchors, dtype=np.float),  
            np.ascontiguousarray(gt_boxes, dtype=np.float)) 
#返回一个内存连续的有相同数据的tensor,如果原tensor内存连续则返回原tensor
#shifts.view need 内存连续
#type_as(tesnor)将tensor投射为参数给定tensor类型并返回。 如果tensor已经是正确的类型则不会执行操作。等效于:self.type(tensor.type())
#shifts int_>float

shifts = shifts.contiguous().type_as(rpn_cls_score).float()
A = self._num_anchors
K = shifts.size(0)
#int_tensor_>float_tensor
self._anchors = self._anchors.type_as(gt_boxes) # move to specific gpu.
#board
all_anchors = self._anchors.view(1, A, 4) + shifts.view(K, 1, 4)
#k,a,4_>k*a,4
all_anchors = all_anchors.view(K * A, 4)

---------------------

16. 广播(重要)

广播的原则:如果两个数组的后缘维度(trailing dimension,即从末尾开始算起的维度)的轴长度相符,或其中的一方的长度为1,则认为它们是广播兼容的。广播会在缺失和(或)长度为1的维度上进行。(3,2)(2,)两者的后缘维度是相同的。

更加通俗的说法:

规则1: 如果两个数组在维度的数量上有差异,那么维度较少的数组的形状就会被用1填充在它的前导(左)边
规则2: 如果两个数组的形状在任何维度上都不匹配,但等于1,那么在这个维度中,形状为1的数组将被拉伸以匹配另一个形状规则3: 如果在任何维度上,大小都不一致,且两者都不等于1,就会出现错误。

下面看例子:

In[1]: import numpy as np
In[2]: M = np.ones((2, 3))
       a = np.arange(3)

In [3]: M.shape
Out[3]: (2, 3)
In [4]: a.shape
Out[4]: (3,)


根据规则1,数组a的维数更少,所以我们用1填充在它的左边。

M.shape -> (2, 3)
a.shape -> (1, 3)

根据规则2,我们现在看到第一个维度不匹配,所以我们扩展这个维度来匹配。

M.shape -> (2, 3)
a.shape -> (2, 3)

现在就可以相加了,而且最终的shape是(2, 3)。我们验证一下:

In [5]: (M + a).shape
Out[5]: (2, 3)

 

下面看一个满足规则3的例子:

In [15]: M = np.ones((3, 2))
In [16]: a = np.arange(3)

In [16]: M.shape
Out[16]: (3, 2)
In [17]: a.shape
Out[17]: (3,)

根据规则1,

M.shape -> (3, 2)
a.shape -> (1, 3)

根据规则2,a的第一个维度被拉伸到与M匹配:

M.shape -> (3, 2)
a.shape -> (3, 3)

现在根据规则3,如果我们进行加的操作,会出现错误,验证下:

In [18]: M + a
Traceback (most recent call last):

  File "<ipython-input-18-8cac1d547906>", line 1, in <module>
    M + a

ValueError: operands could not be broadcast together with shapes (3,2) (3,)

注意这里可能出现的混淆:你可以想象出a和M的兼容性,比方说,用1在右边而不是左边填充a。但这不是广播规则的工作方式!还要注意的是,虽然我们一直在关注+运算符,但是这些广播规则适用于任何二元ufunc。

---------------------

17. torch.stack((a,b,c),dim)

沿着一个新维度对输入张量序列进行连接。 序列中所有的张量都应该为相同形状。

注意这个函数和concatenate是不同的,torch的concatenate函数是torch.cat,是在已有的维度上拼接,而stack是建立一个新的维度,然后再在该纬度上进行拼接。

参数:

  • sqequence (Sequence) – 待连接的张量序列
  • dim (int) – 插入的维度。必须介于 0 与 待连接的张量序列数之间。要看合成后的

类似的维度的操作,可以看我上面reshape的说明,必须要理解填充的顺序。从后缘维度开始填充。

你比如:a=[[1,2,3],[4,5,9],[7,8,9]] b=[[1,2,3],[4,5,9],[7,8,9]] ,c=-[[1,2,3],[4,5,9],[7,8,9]] ,

torch.stack((a,b,c),0)0是最后一个填充的,从最大层次也就是最外面的括号看

>>>【[[1,2,3],[4,5,9],[7,8,9]],[[1,2,3],[4,5,9],[7,8,9]],-[[1,2,3],[4,5,9],[7,8,9]] 】

torch.stack((a,b,c),1)从中间的括号开始看

>>> [[[1,2,3],[1,2,3],-[1,2,3]],[4,5,9],[4,5,9],-[4,5,9]...]

torch.stack((a,b,c),2)从最里面的一个元素一个元素竖着开始看

>>> [[[1,1,-1],[2,2,-2],[3,3,-3]],[....]

在比如一维度数组stack

a=([1,2,3]) b=([1,2,3])

torch.stack((a,b),0)

>>>[[1,2,3],[1,2,3]]

torch.stack((a,b),1)

>>>[[1,1][2,2],[3,3]]

---------------------

18. expand_as(tensor)

torch版本的bbox_transform_batch有用。将tensor扩展为参数tensor的大小。类似于人为广播操作。但必须只有一个维度是不相等的。

>>> a=torch.rand(2,1,4)
>>> b=torch.rand(2,4,4)
>>> a
tensor([[[ 0.1828,  0.9803,  0.4630,  0.7553]],

        [[ 0.3949,  0.8661,  0.8884,  0.3982]]])
>>> b
tensor([[[ 0.5678,  0.7193,  0.6781,  0.9207],
         [ 0.4690,  0.4737,  0.2638,  0.9247],
         [ 0.9315,  0.8202,  0.5217,  0.8444],
         [ 0.5279,  0.5673,  0.6443,  0.4649]],

        [[ 0.3587,  0.8476,  0.6263,  0.1106],
         [ 0.4531,  0.0974,  0.9504,  0.6684],
         [ 0.5585,  0.9721,  0.1965,  0.3138],
         [ 0.6662,  0.2503,  0.9760,  0.0737]]])
>>> a.expand_as(b)
tensor([[[ 0.1828,  0.9803,  0.4630,  0.7553],
         [ 0.1828,  0.9803,  0.4630,  0.7553],
         [ 0.1828,  0.9803,  0.4630,  0.7553],
         [ 0.1828,  0.9803,  0.4630,  0.7553]],

        [[ 0.3949,  0.8661,  0.8884,  0.3982],
         [ 0.3949,  0.8661,  0.8884,  0.3982],
         [ 0.3949,  0.8661,  0.8884,  0.3982],
         [ 0.3949,  0.8661,  0.8884,  0.3982]]])

19.torch.equal(a,b) & a.eq(b)

a.eq(b)

torch.eq(input, other, out=None) → Tensor

比较元素相等性。第二个参数可为一个数或与第一个参数同类型形状的张量。

参数:

  • input (Tensor) – 待比较张量
  • other (Tensor or float) – 比较张量或数
  • out (Tensor, optional) – 输出张量,须为 ByteTensor类型 or 与input同类型

返回值: 一个 torch.ByteTensor 张量,包含了每个位置的比较结果(相等为1,不等为0 )

返回类型: Tensor

例子:

>>> torch.eq(torch.Tensor([[1, 2], [3, 4]]), torch.Tensor([[1, 1], [4, 4]]))
1  0
0  1
[torch.ByteTensor of size 2x2]

torch.equal

torch.equal(tensor1, tensor2) → bool

如果两个张量有相同的形状和元素值,则返回True ,否则 False

例子:

>>> torch.equal(torch.Tensor([1, 2]), torch.Tensor([1, 2]))
True
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值