Efficient research work environment setup for Computer Science and general workflow for Deep Learning experiments. Contribute to our lab VCL.
- Work environment setup
- Deep Learning Experiments Workflow
- Commonly used CG software
- Blender
- MeshLab
- Unity
系统自带的terminal往往比较简单,不支持多窗口和各种定制。而在实验中经常需要开多个terminal窗口(比如我需要同时连多台服务器),所以系统自带的原始terminal使用起来会比较不方便。建议使用以下的terminal软件,以支持多窗口、分屏和快捷切换的特性。
安装完毕之后不需要掌握太多的功能,一般只需要用到多窗口、分屏的功能,掌握切换窗口/分屏的快捷键即可。能用键盘的操作就别用鼠标去点!此外,背景半透明等额外特性看个人需要是否使用。
Shell对于工作效率可以说是重中之重了,一个好的shell能成倍提高工作效率!一般系统自带的shell都是未经配置的bash,功能比较简略。
在此,强烈推荐使用zsh及其插件管理工具oh-my-zsh!!! 其功能极大的简便了命令行操作,相信用过了都会觉得真香(看看Github 9万多star就知道了)。
-
安装与(推荐)配置过程:
- 按照这里按照zsh和机器插件管理包oh-my-zsh。注意oh-my-zsh是zsh的一个插件管理包,我们还需要通过它来安装其他插件来实现各种强大的功能。
- 安装插件zsh-autosuggestions,注意按照这里的命令通过oh-my-zsh来方便安装。这个插件的功能是更强大的命令补全。
- 安装插件zsh-syntax-highlighting,注意按照这里的命令通过oh-my-zsh来方便安装。这个插件的功能是命令行的语法高亮,方便阅读命令的同时也会让你的命令行更加酷炫。
- 安装插件extract,只需要在zsh的配置文件
~/.zshrc
里加一行即可。这个插件的功能是简化各类解压操作。 - 安装插件git,可选,简化git的相关操作。
-
常用特性:
DL的实验基本都需要在服务器上跑,所以一些针对服务器的操作简化是很必要的。
-
Connection
通过ssh username@server_ip
命令连接服务器是大家常用的操作,然而每次都需要输入用户名、服务器ip和密码是不是很麻烦。强烈推荐一个ssh xxx
一键登录的操作-
免密登录.
原理是通过公私钥登录。我们先通过ssh-keygen
生成一个rsa公私钥对:$ ssh-keygen -t rsa
这样会在
~/.ssh
文件夹下生成一个公私钥对,id_rsa
和id_rsa.pub
(或者其他你命的名字)。接下来把公钥拷贝到服务器上:$ ssh-copy-id -i ~/.ssh/id_rsa.pub username@server_ip
这样配置之后再通过
ssh username@server_ip
登录就不需要输密码了。 -
配置连接的别名. 我们进一步配置
ssh
连接,通过vim ~/.ssh/config
创建(打开)ssh的配置文件,写入:Host lab Hostname 111.222.333.4 User myname Port 22 LocalForward 16008 127.0.0.1:6008 IdentityFile ~/.ssh/id_rsa
这样我们就为
myname@111.222.333.4
建立了一个别名叫做lab
,并且关联上了之前配置好的rsa的私钥。同时LocalForward
将服务器6008
端口转发到本地的16008
端口,免去了通常使用tensorboard时ssh的-L
参数。
以后只需要通过ssh lab
即可直接登录服务器,比原来简便了很多。
-
-
tmux
tmux是一个unix-like系统下的命令行多路复用工具,可以帮助我们在命令行中同时开多个窗口,并且保证在其中跑的程序不会因为服务器连接的中断而停止,这对于长时间运行的实验(如神经网络训练)尤为重要。大多数人对tmux应该不陌生,也听过有用其他类似软件的。- 安装与推荐配置:
- 常用操作:
推荐阅读这个指南来熟悉tmux的常用操作和概念。推荐用一个session来管理一个project,里面的每一个window(或者panel)来管理一个实验,多个实验同时用不同的window(或者panel)来跑。
-
python
强推PyCharm!!通过学校邮箱注册即可获得免费的专业版。常用特性:
- 远程服务器直连/同步。按官方指南creating-a-remote-server-configuration操作即可。本地ide修改代码,文件即刻同步到服务器上,对于在服务器上跑实验但是又想本地改代码的人来说十分方便。
- 使用远程服务器的python解释器。依旧官方指南configuring-remote-interpreters-via-ssh。本地修改代码可以按照远程服务器的python解释器来进行补全和提示,不必再担心本地和远程环境不一样的问题。
- 快捷键
crtl+B
(command+B
for Mac)进行函数或变量声明的一键查询。 - 快捷键
crtl+W
(command+W
for Mac)快速关闭当前页。 - 在pycharm内对一个project进行git管理。官方指南写的比较复杂。
-
- Vim的自动补全插件:YouCompleteMe
待补充。
这一部分针对有python和深度学习基础但实战经验不是很丰富的同学。
若没有深度学习基础,推荐学习斯坦福公开课CS231n。
若不熟悉深度学习框架,建议先学习一遍其官网的官方教程:PyTorch,TensorFlow,TensorLayer.
硬件环境(nvidia-driver+CUDA+cudnn)的搭建:yixin.
一个深度学习的项目往往需要进行大量的调试和对比实验,而且debug往往比较困难,所以代码和实验的组织特别重要,特别要关注可复现性、易扩展性。
不同的项目可能需要用到不同的python环境,所以用一些虚拟环境/python包管理工具将它们相互之间隔离开来是非常有好处的。
-
Anaconda
Anaconda提供了强大而方便的包管理与环境管理的功能。个人习惯于将不同深度学习框架配置到不同的环境中,如PyTorch, TensorFlow各自单独一个环境,以及为git上有些久远的python2项目单开一个python2环境,基本就能满足需求。
使用anaconda完成不同cuda版本环境并存->这里。 -
virtualenv 待补充。
大多数深度学习的代码可以按照以下结构划分,将各个功能分割开来(便于debug和调试):
config.py
定义实验的超参数和全局变量,例如网络结构的超参数、learning rate、epoch数、实验/数据路径等。dataset.py
定义数据的供应流,提供获取数据的接口给train.py
使用,例如pytorch里的DataLoader对象。network.py
定义模型的网络结构。agent.py
定义一个控制训练过程的容器,提供train.py
需要的接口,特别是训练中间过程的保存与恢复。tensorflow V1里叫做session,pytorch里需要我们自己写。train.py
执行训练的主文件,尽量简短。evaluate.py
执行evaluatoin/prediction的主文件,尽量简短。utils.py
常用的工具函数和对象。- 其他(如
visualization
等)
样例代码:PyTorch_Template
- 每一个实验开一个文件夹
在项目总目录下,每一次实验单开一个文件夹,作有意义的命名,这是为了实验的可复现和对比。
例如,第一次写好了一份代码并跑了一次完整的实验,该实验名为baseline
放在项目总目录下。那么若我想把网络层数增加一倍再试试看,那么则先拷贝baseline
的内容到一个新的文件夹baseline_layer2x
下,然后在baseline_layer2x
修改网络层数,之后再在该文件夹下跑新的实验。
- 代码和数据分离
一般来说,服务器上的硬盘空间会进行划分,会有很大的空间专门划分给数据存储,另外有一部分用于常规文件。因此我们应尽量将数据放在大的硬盘分区内,与代码分离。这里说的数据既包括用于训练数据,也包括训练过程中产生的数据(训练日志,模型文件)等。所以训练过程中产生的数据train_log
需要我们的代码将他们放到硬盘的数据分区中,但为了方便访问,我们可以在实验文件夹下建立一个软连接索引到实际存放的位置:
- 使用git进行版本控制
使用git进行版本控制是很好的习惯,结合PyCharm的功能,可以很方便的让我们看到代码相对于之前的commit改动了什么:
网络训练过程中非常有必要对loss和中间结果进行可视化,tensorboard基本算是标配的工具。一键安装:
$ pip install tensorboard
TensorBoard 通过读取 TensorFlow 的事件文件(看作日志文件)来运行。TensorFlow 的事件文件包含运行 TensorFlow 时生成的总结数据。
- 在TensorFlow中,通过
tf.summary
api生成事件文件,参见官方文档。 - 对于PyTorch,我们可以通过一个第三方的包tensorboardX来生成事件文件。看完其样例代码就肯定会用了。
假设我们在服务器上/mnt/username/project/baseline/log
位置生成了一次实验的事件文件:
接着我们运行tensorboard读取上述事件文件:
$ tensorboard --logdir /mnt/username/project/baseline/log --port 6006
运行后,我们可以在localhost:6006
(即127.0.0.1/6006
)查看可视化结果。但是由于服务器上一般没有图形化界面,我们没办法通过浏览器打开该地址。解决方法是,我们在ssh登录服务器的时候建立一个通道,将服务器端口6006
的数据转发到一个本地端口上:
$ ssh -L 16006:127.0.0.1:6006 lab
参数-L 16006:127.0.0.1:6006
建立了一个通道(也可写在ssh配置文件中),将服务器端口6006
的数据转发到了本地16006
端口上,于是我们可以通过本地的网页浏览器访问127.0.0.1:16006
查看可视化结果。
- 模块测试代码
DL程序debug很容易让人头大,我们最好以模块化的思维去考虑问题出在哪一个模块:数据、网络结构、后处理等等。为了预防bug的产生,我们可以在按照前述代码结构,在每写好一个模块后,就可以写一个简单的测试函数,来看看代码是否产生了期望的行为。比如,关于数据处理部分dataset.py
,简单打印一个batch的结果,看看是否符合期望:
- 数据供应速度
在GPU上跑程序的时候,用nvidia-smi
查看GPU使用情况的时候,出了关注显存占用情况,还应去关注一下Volatile GPU-Util
这一信息。一般来说,使用率越高越好;如果一直比较低,说明程序有很多时间花在了CPU上,很有可能是数据供应的速度没有跟上模型计算的速度,造成了GPU资源的浪费,程序运行速度慢。解决方法一是优化数据供应dataset.py
部分的代码,二是增加数据供应的线程数(如pytorch里的num_workers
),三是检查其他部分比如后处理/可视化部分代码是否可以优化。特别地,python里尽量避免显式for循环。 - 分析可视化结果
- 经验之谈
- 增大batch size的同时适当增大learning rate,保持两者的平衡。原因是增大batch size之后,一个epoch内梯度下降的次数减少了,所以可以让每一步可以走得长一点(增大learning rate)。
- 对learning rate做动态调整,常用exponential decay或者step decay(每隔一定step减小lr)。原因是通常训练初期使lr较大加快收敛,训练后期使lr较小能够在局部收敛得更好。
- dropout/BatchNorm在训练/测试时的不同行为的切换。
- 对于回归任务,网络最后一层尽量不用非线性激活单元。
- BN层前的卷积层尽量不要加bias项。原因是BN层会做normalization。
- ...