深度学习 与 C++ 的爱恨情仇

论坛 期权论坛 期权     
CVer   2019-6-9 21:24   3404   0
点击上方“CVer”,选择加"星标"或“置顶”
重磅干货,第一时间送达
作者:花花
https://zhuanlan.zhihu.com/p/55249369
已授权转载
本文涉及的相关教程和代码:
  • CPP-Call-Tensorflow
    • C++ 调用Python(TensorFlow)程序
    • https://github.com/BIGBALLON/CPP-Call-Tensorflow


  • Caffe2-Tutorial
    • 使用Caffe2 Python API建立并训练LeNet,并正确存weight
    • 使用Caffe2 Python API建立并训练ResNet, 不使用lmdb, 并正确存取带有BN的weight
    • 使用Caffe2 C++ API 读取预训练model并进行预测
    • 使用Caffe2 Python API 进行 Multi-GPU训练
    • 将 Caffe 的 weight 转化为 Caffe2 的 weight, 并使用Caffe2 C++进行读取与预测
    • 将 PyTorch 的 weight 转化为 Caffe2 的 weight, 并使用Caffe2 C++进行读取与预测
    • https://github.com/BIGBALLON/Caffe2-Tutorial


  • PyTorch-CPP
    • 使用PyTorch C++ API (Libtorch) 读取预训练model并进行预测
    • https://github.com/BIGBALLON/PyTorch-CPP
OK,下面开始讲故事, 不想听故事的可以直接把代码抱走,不用客气,请随意啦。
[h1]0. 初识 Deep Learning[/h1]大约1年半前至2年前的样子,选修了学校的 Deep Learning and Practice,第一次接触深度学习,记得那时候大家用的多半是TensorFlow,第一个作业是实现 NIN(Network In Network),弄了半天因为initial的问题死活train不起来,神奇的舍友推荐我加一下BN试试,搞了半天TensorFlow有N个batch_normal的函数就是不知道怎么用,于是神奇的舍友又推荐我用一个叫做Keras的东西,我靠,BN只要一行。更神奇的是,加完BN后train得飞起,于是乎就寄信去问助教,可不可以用BN,第二天助教课得到得答复是,BN是 homework2 要求使用的trick,当时没别的,就觉得舍友好猛,啥都懂。
噢,跑偏了,回来回来。后来我们有一个需求,需要在C++中调用keras(tf),查了一下有好多种方法,选了原生支持的方法,就加个头文件
  1. Python.h
复制代码
,然后瞎一顿搞就好了,代码见 CPP-Call-Tensorflow:https://github.com/BIGBALLON/CPP-Call-Tensorflow
[h1]1. Caffe2 与 C++[/h1]不经意间,身边的朋友几乎清一色都转向了PyTorch,而因为对 C++ 有特殊的需求,Lab的学长们还在使用Caffe。唔,然后Caffe2就出来了,原生支持 Python 和 C++。 于是我们就转向了 Caffe2
三种做法:
  • 最直接的是用Caffe2 Python API 建network并完成训练,导出model,再用 C++ 进行加载与使用
  • 当然,后来也会用Caffe2 Python API 拉出network,直接导出,在C++ 端完成所有的后续工作,包括训练,以及训练好后的导出model,inference等等。
  • 最暴力的是直接放弃Caffe2 Python API, 完全使用 C++ 完成 建network,training,inference等所有的工作。

中间也遇到些许小坑,说出来你可能不信,Caffe2刚出来的时候,整个issue区问最多的问题就是weight怎么存和weight怎么读。后来都在问带有BN的network weight怎么存,当然更多的人是在问Caffe2为什么那么难装,哈哈。



当然Caffe2 还有一个好处, 能够将 Caffe的 weight 轻易地转化为 Caffe2 的 weight
不知不觉,Caffe2 猛然间和PyTorch合并了,PyTorch0.4 出现了, 与此同时一个叫做ONNX(Open Neural Network Exchange)的东西,它也lei le。 于是我们可以将weight 在不同的DL framework间相互转换。其中ONNX对Caffe2的支持也非常好。 于是我们又有了新的做法:
  • 在PyTorch下进行训练,然后通过ONNX导出model,再将onnx model 转化为Caffe2 model。
值得吐槽的地方是,自从Caffe2 与 PyTorch合并后,官方的文档也长期不更新了,可以观察到Github上面关于Caffe2的issue也常常没有人回复,Caffe2的C++端进行了很大幅度的修改,官方也没有任何的文档说明,你想用的话就自己遇坑自己解决就对了。
在此期间也学会了一个小技巧:
通常情况下,你的程序就算是编译好,也无法直接从copy到其他机器上运行,因为你的程序需要用到cuda,cudnn,caffe2等等。怎么办,把它们打包起来,一起带走:
以Ubuntu16.04为例,首先先安装这两个工具:
  1. sudo apt install chrpath patchelf
复制代码
然后进行打包操作,假设你的程序名字叫做
  1. test
复制代码
, shell文件
  1. pack.sh
复制代码
如下
  1. ldd test | grep "=> /" | awk '{print $3}' | xargs -I '{}' cp -v '{}' .rm libcuda.so*rm libnvidia-fatbinaryloader.so*rm libc.so.6ls -1 lib* | xargs -t -n1 patchelf --set-rpath .cp /lib/x86_64-linux-gnu/libc.so.6 .strip testchrpath -r . test
复制代码
  1. 打包前┌─[bg@bg-cgi] - [~/Documents/czf/debug] - [2019-01-19 01:49:54]└─[0] lspack.sh  test打包后┌─[bg@bg-cgi] - [~/Documents/czf/debug] - [2019-01-19 01:50:21]└─[0] lslibatk-1.0.so.0           libfontconfig.so.1        libgraphite2.so.3         libk5crypto.so.3            libopencv_highgui.so.2.4  libschroedinger-1.0.so.0   libusb-1.0.so.0     libXcursor.so.1libavcodec-ffmpeg.so.56   libfreetype.so.6          libgsm.so.1               libkeyutils.so.1            libopencv_imgproc.so.2.4  libselinux.so.1            libutil.so.1        libXdamage.so.1libavformat-ffmpeg.so.56  libgcc_s.so.1             libgssapi_krb5.so.2       libkrb5.so.3                libopenjpeg.so.5          libshine.so.3              libuuid.so.1        libXdmcp.so.6libavutil-ffmpeg.so.54    libgcrypt.so.20           libgtkglext-x11-1.0.so.0  libkrb5support.so.0         libopen-pal.so.13         libSM.so.6                 libv4l1.so.0        libXext.so.6libbluray.so.1            libgdkglext-x11-1.0.so.0  libgtk-x11-2.0.so.0       libleveldb.so.1             libopen-rte.so.12         libsnappy.so.1             libv4l2.so.0        libXfixes.so.3libbz2.so.1.0             libgdk_pixbuf-2.0.so.0    libHalf.so.12             liblmdb.so.0                libopus.so.0              libsoxr.so.0               libv4lconvert.so.0  libXinerama.so.1libcaffe2_gpu.so          libgdk-x11-2.0.so.0       libharfbuzz.so.0          libltdl.so.7                liborc-0.4.so.0           libspeex.so.1              libva.so.1          libXi.so.6libcaffe2.so              libgflags.so.2            libhogweed.so.4           liblzma.so.5                libp11-kit.so.0           libssh-gcrypt.so.4         libvorbisenc.so.2   libxml2.so.2libcairo.so.2             libgio-2.0.so.0           libhwloc.so.5             libmodplug.so.1             libpango-1.0.so.0         libstdc++.so.6             libvorbis.so.0      libXmu.so.6libcom_err.so.2           libglib-2.0.so.0          libibverbs.so.1           libmp3lame.so.0             libpangocairo-1.0.so.0    libswresample-ffmpeg.so.1  libvpx.so.3         libXrandr.so.2libcrystalhd.so.3         libglog.so.0              libICE.so.6               libmpi_cxx.so.1             libpangoft2-1.0.so.0      libswscale-ffmpeg.so.3     libwavpack.so.1     libXrender.so.1libc.so.6                 libGL.so.1                libicudata.so.55          libmpi.so.12                libpangox-1.0.so.0        libtasn1.so.6              libwebp.so.5        libXt.so.6libcublas.so.8.0          libGLU.so.1               libicuuc.so.55            libm.so.6                   libpcre.so.3              libtbb.so.2                libX11.so.6         libxvidcore.so.4libcudnn.so.7             libgme.so.0               libidn.so.11              libnettle.so.6              libpixman-1.so.0          libthai.so.0               libx264.so.148      libz.so.1libcurand.so.8.0          libgmodule-2.0.so.0       libIex-2_2.so.12          libnuma.so.1                libpng12.so.0             libtheoradec.so.1          libx265.so.79       libzvbi.so.0libdatrie.so.1            libgmp.so.10              libIlmImf-2_2.so.22       libnvidia-glcore.so.410.78  libpthread.so.0           libtheoraenc.so.1          libXau.so.6         pack.shlibdc1394.so.22           libgnutls.so.30           libIlmThread-2_2.so.12    libnvidia-tls.so.410.78     libraw1394.so.11          libtiff.so.5               libxcb-render.so.0  testlibdl.so.2                libgobject-2.0.so.0       libjasper.so.1            libnvrtc.so.8.0             libresolv.so.2            libtwolame.so.0            libxcb-shm.so.0libexpat.so.1             libgomp.so.1              libjbig.so.0              libogg.so.0                 librtmp.so.1              libudev.so.1               libxcb.so.1libffi.so.6               libgpg-error.so.0         libjpeg.so.8              libopencv_core.so.2.4       librt.so.1                libunwind.so.8             libXcomposite.so.1
复制代码
可以看到需要的库文件都打包进来了,而且程序执行的时候不会再去系统的路径中找,而是直接在当前目录找,把整个文件夹copy到其他机器去吧,现在你可以随意地执行它了。
上述Caffe2的使用(C++ inference,caffe转caffe2,pytorch转caffe2),代码见 Caffe2-Tutorial
[h1]2. PyTorch 与 C++[/h1]随着PyTorch不断的完善,身边弃坑TF,投奔PyTorch的朋友就没有再回来的了。随着PyTorch1.0的发布,C++ 似乎有了新的曙光,现在我们可以这么做:
  • 在PyTorch python 端训练model,并通过jit导出,然后使用PyTorch C++ API 编写需要的应用,编译即可上线。代码见 PyTorch-CPP
  • 完全在PyTorch C++ API中拉net,training,inference等,say goodbye for python 。

[h1]3. Deep Learning 与 C++ 的 未来[/h1]Deep Learning 发展到现在,C++ 方面还是不能够随心所欲地coding, 希望在未来半年到一年内还会有新的突破。 期待一下能像写python一样随心所欲地写 C++ 程序!!

CVer学术交流群

扫码添加CVer助手,可申请加入CVer-目标检测交流群、图像分割、目标跟踪和GAN等群。一定要备注:研究方向+地点+学校/公司+昵称(如目标检测+上海+上交+卡卡)


▲长按加群

这么硬的论文速递,麻烦给我一个好看


▲长按关注我们
麻烦给我一个好看!
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:10
帖子:2
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP