update一下performance:
coco的resnet101到了34.3,比tf-faster-rcnn还要高那么一丢丢了,所以我就假装这个代码是Ok的了。(vgg的coco结果差超多。。。。但是我也懒得管了,vgg是什么,能吃吗)
每年夏天我都要做一下faster-rcnn。。。。我也不懂了。
去年做torch的faster rcnn的起因,是想做来提升captioning结果的。然后就从densecap出发,做了一个faster rcnn。
原本以为会很简单,因为感觉大体的结构一毛一样嘛,densecap就是从faster-rcnn来的结构嘛。。。结果改成傻逼了。各种改。。最终也没复现出来。(现在感觉可能是因为用了spatial transformer network啊。。。。。)
至今我好像也没有看到成功的torch上的faster-rcnn的复现。fast-rcnn倒是有。。。。真奇怪。。。
今年又重新做faster-rcnn。起因是,同实习的小伙伴要用faster-rcnn,我问那你用什么,他说用tensorflow,我说为啥不用pytorch,他说因为现在pytorch实现的结果都一般,都没有认真调;我想,哎哟我去,这怎么行,然后就自己开始写了。。。
当然也没有从头开始造轮子;小伙伴跟我说他用的tf-faster-rcnn,里面结果很好,所以我就是直接tf-faster-rcnn clone,然后开始改。
其实主要的代码并没有改多久,基本上还是很简单的,但是一开始结果不行。一会就nan。
结果发现是没有zero_grad。。。。。。。
反正又遇到一些问题,一个是vgg取的layer取错了。。。取成了pool5,应该是conv5_3,导致nan。。。。。。第二个是resnet固定参数固定batch norm乱七八糟的。其实都不难,都是细节。
anyway,现在的版本至少在pascal voc的结果差不多和tf-faster-rcnn match了。。。。。。。虽然就是差那么1。。。。。。
coco结果似乎差很多。。。。。。不知道为啥~~~~讲道理嘛如果voc结果差不多的话,也不应该coco差这么多啊?????
github在这,ruotianluo/pytorch-faster-rcnn,pretrained模型都有,虽然coco上的只有非常弱的版本。(长的最近还在训练。。。。。。太慢了。。。。。)
强迫症部分:
1. tensorboard
虽然我非常讨厌tensorflow,但是我非常喜爱tensorboard!
visdom看起来也不错,但是总感觉差了这么一点。(最近好像有看到对visdom有类tensorboard的分装,可以看看。但是tensorboard确实做的真的好啊)
由于原本的tensorflow版本都是对图中的node做summary operation,最后session run的时候一起跑,但是我由于没有内部节点,所以没法直接获得summary op。结果我就专门开了一个计算图,这个图没有别的,只有placeholders(所以其实不是图),然后所有的operations都是summary。。。。session run只干一件事,收集summary。。。。。
虽然很傻逼,但是至少给了我tensorboard可视化的结果。
然后。。。。后来我看到了一个东西叫tensorboard-pytorch。。。。。。。。
(其实之前不是没有tensorboard普适版,什么crayon啊,mxnet也有一个tensorboard。。。但是。。。功能貌似都不全)反正tensorboard-pytorch是我第一个看到几乎支持所有tensorboard功能的(甚至还可以展示pytorch 的计算图),虽然他其实就是对tensorboard做了一个封装——所以你还是要装tensorflow。(但是装tensorflow还是很方便的)
但是我现在github里面的code还没改成用tensorboard_pytorch,因为最近冒出了一系列类似的东西。tensorboard_logger(这个好像很垃圾功能很少), inferno(除了tensorboard还有trainer什么的)
所以,再观望一段时间好了。
2. python layer
py-faster-rcnn还有tf-faster-rcnn都是中间有python layer的。就是要把网络当中结果拿出来,放到python下运算。
其实py-faster-rcnn还好。。。。tf-faster-rcnn那个py_func真的是超级麻烦。。。。。。
pytorch其实就跟py-faster-rcnn差不多,不需要弄个啥py_func,直接拿出来中间接过来放进去,非常顺畅,就是一个普通的python function。
其实好好的不要去动它挺好的。。。。。。但是我心有不甘。。。。。
怎么可以这么几层用python,用numpy呢!!!!!
而且,因为我的crop_and_resize使用stn实现的(crop_and_resize是roi pooling的替代品,说比roi pooling效果好),所以我就想如果全部在pytorch下,就可以从stn也获得offset的gradient了(事实上,stn获得gradient之后效果差了很多。。。。妈蛋。(所以去年densecap写失败是因为这个原因吗。。。。))。
于是我就试图把这几层改成torch的。。。。。。。踏上了一条不归路。(浪费了超多生命)
1 )gpu下做nms
一开始想法是follow densecap的做法,他也是在gpu下做的nms,用的torch
然后我就直接按照他的做。(他比一般的c下的nms算法有点区别,为了避免indexing的耗时) jcjohnson/densecap 可以看一下。
然而还是巨慢
然后我就想,算了反正py-faster-rcnn本来就有gpu的nms_kernel就用那个了。(诶,既然有gpu version,为啥还要自己写,因为原本的gpu_nms接收的是numpy array;所有对我们的code来说,其实很脑残,我们先把cudatensor转成了cpu numpy,然后在gpu_nms里面又把这个numpy放会了gpu里。。虽然其实时间上差得好像没那么多,但是。。不爽)
然后我就用cffi手写了好几个。原本的nms_kernel分成两部分,一个是算overlap,用cuda写的,一个根据overlap做supression,在cpu下做的。
我第一个版本就是把suppression也放在了gpu下做,开了一个单线程的kernel。。。。慢。。。。。(但是就算这样也比densecap那种方法快了无数倍;只是比原本得拷来拷去的gpu_nms要慢)
然后我就把supression放回了cpu。速度快了一些。
(把代码改成TH api研究了很久。。。感觉自己又会写c了(各种不打分号。。。。))
2 )numpy的argsort和torch.sort
其实还有一个提速的点是排序。用gpu下的torch.sort就会快很多。然而一开始调试的时候,为了match faster-rcnn的nms结果。。。。。怎么都不match。。。。
后来发现。。。原来是sort的结果不一样妈蛋。torch.sort对于值相同的element,顺序是随机的。。。。。。
Order of equal elements after torch.sort
可以试一下我上面的代码。。。。大概是因为并行的原因吧。。。。。
但是这浪费了我超级超级久的时间。。。。。。一步一步测试啊。。。。。真是坑爹。。。
3 )np.random.choice vs torch.multinomial
proposal_target_layer有一步是sample roi,需要uniform随机选取proposal。一开始我使用了torch.multinomial,输入就是一个每个点都概率一样。结果超级超级慢(平均一个iteration要花0.02秒)(可想而知又是各种看每个步骤的时间,贼麻烦)。
然后我就用np.random.choice。。。。。(0.003秒。。。)
差的也太多了吧。。。。。
4 )其它一些
虽然现在的nms层快了(大概0.01秒一个iteration),换了np.random.choice快乐,但是proposal_target_layer还是要比原来慢0.003秒一个iteration。。。。。。
还得再细分看每个步骤的时间。。。。再说吧。。。(cudatensor的indexing是真的慢!!!!!!!能不做就别做!!!!)
5) bbox_overlap
之前的代码用的是一个cython实现的bbox overlap的代码,然后我改成了numpy,和torch,都用的是np和th里面的计算部件,照理说应该如果有多线程的话是可以更快的吧。。。。。。以为cython哪个是单线程的。。。然而慢了10倍。。。。。。虽然这个也不是bottleneck,但是特别迷
~~(然而这部分都还在本地,没有传到github上,还要改的再好看一点)~~已经放到master了。
faster-rcnn一不小心写多了;
那另外的一句带过了:
又重新好好修改了我的neuraltalk2.pytorch的代码,readme应该干净和谐了很多,加了pretrained的model;另外100行不到写了一个非常屌的model(一篇paper里的),cross entropy training能到1.07的karparthy test split CIDER score。虽然SCST之后效果就不是最好了,但是我也还没怎么调。
我也不知道为什么我要莫名其妙撸代码。。。。。。我的志向不是software engineer啊,。。。