本文记录我从事机器视觉工作积累下来的一点习惯和经验。
文件夹管理
在服务器的数据盘建立model
, data
, output
三个文件夹,model
用于存放预训练模型和Deployment-Ready的模型,data
用于存放训练和测试所用数据,output
用于存放训练时产生的checkpoints和log。
新建项目时,将这三个文件夹通过symlink链接到项目的根目录下。
依赖管理
依赖管理主要依靠Python库Pipenv。它结合了Pypi包管理和VirtualEnvs的环境管理,为每个项目单独建立Python环境,并通过PipFile和PipFile.lock实现更新和迁移。具体的workflow为:
- 建立项目文件夹,并使用
pipenv install
命令初始化其独立的Python环境 - 按需要通过
pipenv install package-name
来安装需要的依赖 - 使用
pipenv run
或激活pipenv shell
运行、Debug相应的项目程序 - 需要迁移环境时,将
PipFile.lock
拷贝至新的目录下,通过pipenv install
来还原Python的运行环境;通过Git等版本控制工具来还原代码。
更多有关环境搭建和管理的内容,参见博文PyCharm+PipEnv本地Python开发环境配置。
项目组织
对于某一项目,我的习惯是将其分为三个不同的子项目:训练、部署、评测/结果分析。
训练过程单独保存一份代码,这份代码会经常更新,并做好配置文件的管理,一般一次训练即对应一个配置文件和一份log,记录这次训练所使用的所有超参数(参见我对深度学习模型中数据的分类)。
部署所用代码也会制定一份配置文件格式,跟训练代码保持同步(尤其是网络结构),主要区别是网络中loss层等的去除,生成的结果是所用框架支持的实例化格式(如deploy.prototxt文件)。
评测部分单独使用一份代码,输入测试数据和部署代码得到的实例化模型,执行推断并得到结果,根据结果文件再以数据ground truth作评测。也可以包括对测试结果的分析脚本(如bad case,画PR曲线等)。
这样的设计,关键之处有两点,一是配置文件保证训练和部署模型的一致性,二是实例化模型和保存测试结果让三个子项目之间的交互仅以文件形式传递,再配合最早文件夹管理和依赖管理的内容,三个子项目完全可以在不同的机器和环境下同步操作。
数据管理
对于数据,我有如下划分:
- 原始图片数据和标注,通常只读,按照标注规范,跟标注组进行交互
- 训练/评测集列表,这一部分单独保存,并保持灵活性,以随着新数据的加入和糟糕数据的清理等不断更新
- 框架所用二进制格式,如caffe的lmdb等,可以由训练项目直接使用,常由原始图片数据和列表文件生成
- 评测数据及结果,评测数据可由原始数据和评测集列表制作,用于评测项目,结果文件也以约定格式保存
框架维护
自己维护两套所用框架的源码,一份用于稳定版本编译,另一份用于新特性的开发。新特性测试通过后,拷贝至稳定版本重新编译。对于新特性版本,可单独建立一个前端环境(Python环境),用动态链接的方式快速调用和测试。
实用工具推荐
tmux
tmux的引入有两个重要作用:
- 窗口划分,可以在一个终端窗口里同时进行多个任务
- session管理,不同session执行不同的项目,且在SSH退出登陆后,session内任务依然进行
我通常会将终端分为4个Panel,左上用于执行训练程序和打印log,右上用于监测GPU运行情况,左下用于执行文件操作和少量代码编辑,右下用于监测CPU运行情况。
gpustat/nvidia-smi/htop
配合watch
命令,实时检测测GPU和CPU的运行情况
sshfs
挂载文件夹,有两个用途:
- 原始数据挂载到工作服务器上
- 服务器上代码挂载到本地,利用本地的文本编辑器更新
此外,也可以建立FTP,用FileZilla将本地和服务器代码进行同步。(某些IDE实际上继承了这一功能,参见博文PyCharm+PipEnv本地Python开发环境配置)
GitKraken
Git的可视化客户端,相比命令行工具更为直观,用于管理代码
meld
文件比较工具,可以直观方便地比较代码间的改动和变化,某些文本编辑器和IDE集成了这一功能,但不够强大
Netron/Netscope/TensorBoard
网络结构可视化工具
vim/emacs/nano
命令行文本编辑工具,我自己不够熟练,仅用来做少量的代码修改
Evernote/Git
用于记录工作日志、数据存放、训练模型、代码修改等等备忘
Spotify/Pithos
用于放松和保持专注,后者是Pandora的Linux第三方客户端