DeepVAC / deepvac

PyTorch Project Specification.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

DeepVAC

DeepVAC提供了基于PyTorch的AI项目的工程化规范。为了达到这一目标,DeepVAC包含了:

诸多PyTorch AI项目的内在逻辑都大同小异,因此DeepVAC致力于把更通用的逻辑剥离出来,从而使得工程代码的准确性、易读性、可维护性上更具优势。

如果想使得AI项目符合DeepVAC规范,需要仔细阅读DeepVAC标准。 如果想了解deepvac库的设计,请阅读deepvac库的设计

如何基于DeepVAC构建自己的PyTorch AI项目

1. 阅读DeepVAC标准

可以粗略阅读,建立起第一印象。

2. 环境准备

DeepVAC的依赖有:

  • Python3。不支持Python2,其已被废弃;
  • 依赖包:torch, torchvision, tensorboard, scipy, numpy, cv2, Pillow;

这些依赖使用pip命令(或者git clone)自行安装,不再赘述。

对于普通用户来说,最方便高效的方式还是使用MLab HomePod作为DeepVAC的使用环境,这是一个预构建的Docker image,可以帮助用户省掉不必要的环境配置时间。 同时在MLab组织内部,我们也使用MLab HomePod进行日常的模型的训练任务。

3. 安装deepvac库

可以使用pip来进行安装:
pip3 install deepvac
或者
python3 -m pip install deepvac

如果你需要使用deepvac在github上的最新代码,就需要使用如下的开发者模式:

开发者模式

  • 克隆该项目到本地:git clone https://github.com/DeepVAC/deepvac
  • 在你的入口文件中添加:
import sys
#replace with your local deepvac directory
sys.path.insert(0,'/home/gemfield/github/deepvac')

或者设置PYTHONPATH环境变量:

export PYTHONPATH=/home/gemfield/github/deepvac

4. 创建自己的PyTorch项目

  • 初始化自己项目的git仓库;
  • 在仓库中创建第一个研究分支,比如分支名为 LTS_b1_aug9_movie_video_plate_130w;
  • 切换到上述的LTS_b1分支中,开始工作;

5. 编写配置文件

配置文件的文件名均为 config.py,位于你项目的根目录。在代码开始处添加from deepvac import new, AttrDict; 所有用户的配置都存放在这个文件里。config模块提供了6个预定义的作用域:config.core,config.aug,config.cast,config.datasets,config.backbones,config.loss。使用方法如下:

  • 所有和trainer相关(包括train、val、test)的配置都定义在config.core.<my_train_class>中;
  • 所有和deepvac.aug中增强模块相关的配置都定义在config.aug.<my_aug_class>中;
  • 所有和模型转换相关的配置都定义在config.cast.<the_caster_class>中;
  • 所有和Datasets相关的配置都定义在config.datasets.<my_dataset_class>中;
  • 所有和loss相关的配置都定义在config.loss.<my_loss_class>中;
  • 用户可以开辟自己的作用域,比如config.my_stuff = AttrDict(),然后config.my_stuff.name = 'gemfield';
  • 用户可以使用new()来初始化config实例,使用clone()来深拷贝config配置项。

更多配置:

  • 预训练模型加载;
  • checkpoint加载;
  • tensorboard使用;
  • TorchScript使用;
  • 转换ONNX;
  • 转换NCNN;
  • 转换CoreML;
  • 转换TensorRT;
  • 转换TNN;
  • 转换MNN;
  • 开启量化;
  • 开启EMA;
  • 开启自动混合精度训练(AMP);

以及关于配置文件的更详细解释,请阅读config说明.

项目根目录下的train.py中用如下方式引用config.py文件:

from config import config as deepvac_config
from deepvac import DeepvacTrain

class MyTrain(DeepvacTrain):
    ......

my_train = MyTrain(deepvac_config)
my_train()

项目根目录下的test.py中用如下方式引用config.py文件:

from config import config as deepvac_config
from deepvac import Deepvac

class MyTest(Deepvac)
    ......

my_test = MyTest(deepvac_config)
my_test()

之后,train.py/test.py代码中通过如下方式来读写config.core中的配置项

print(self.config.log_dir)
print(self.config.batch_size)
......

此外,鉴于config的核心作用,deepvac还设计了如下的API来方便对config模块的使用:

  • AttrDict
  • new
  • interpret
  • fork
  • clone
from deepvac import AttrDict, new, interpret, fork

关于这些API的使用方法,请访问config API 说明.

6. 编写synthesis/synthesis.py(可选)

编写该文件,用于产生本项目的数据集,用于对本项目的数据集进行自动化检查和清洗。 这一步为可选,如果有需要的话,可以参考Deepvac组织下Synthesis2D项目的实现。

7. 编写aug/aug.py(可选)

编写该文件,用于实现数据增强策略。 deepvac.aug模块为数据增强设计了特有的语法,在两个层面实现了复用:aug 和 composer。比如说,我想复用添加随机斑点的SpeckleAug:

from deepvac.aug.base_aug import SpeckleAug

这是对底层aug算子的复用。我们还可以直接复用别人写好的composer,并且是以直截了当的方式。比如deepvac.aug提供了一个用于人脸检测数据增强的RetinaAugComposer:

from deepvac.aug import RetinaAugComposer

以上说的是直接复用,但项目中更多的是自定义扩展,而且大部分情况下也需要复用torchvision的transform的compose,又该怎么办呢?这里解释下,composer是deepvac.aug模块的概念,compose是torchvision transform模块的概念,之所以这么相似纯粹是因为巧合。

要扩展自己的composer也是很简单的,比如我可以自定义一个composer(我把它命名为GemfieldComposer),这个composer可以使用/复用以下增强逻辑:

  • torchvision transform定义的compose;
  • deepvac内置的aug算子;
  • 我自己写的aug算子。

更详细的步骤请访问:deepvac.aug模块使用

8. 编写Dataset类

代码编写在data/dataloader.py文件中。继承deepvac.datasets类体系,比如FileLineDataset类提供了对如下train.txt这种格式的封装:

#train.txt,第一列为图片路径,第二列为label
img0/1.jpg 0
img0/2.jpg 0
...
img1/0.jpg 1
...
img2/0.jpg 2
...

有时第二列是字符串,并且想把FileLineDataset中使用Image读取图片对方式替换为cv2,那么可以通过如下的继承方式来重新实现:

from deepvac.datasets import FileLineDataset

class FileLineCvStrDataset(FileLineDataset):
    def _buildLabelFromLine(self, line):
        line = line.strip().split(" ")
        return [line[0], line[1]]

    def _buildSampleFromPath(self, abs_path):
        #we just set default loader with Pillow Image
        sample = cv2.imread(abs_path)
        sample = self.compose(sample)
        return sample

哦,FileLineCvStrDataset也已经是deepvac.datasets中提供的类了。

9. 编写训练和验证脚本

在Deepvac规范中,train.py就代表了训练范式。模型训练的代码写在train.py文件中,继承DeepvacTrain类:

from deepvac import DeepvacTrain

class MyTrain(DeepvacTrain):
    pass

继承DeepvacTrain的子类可能需要重新实现以下方法才能够开始训练:

类的方法(*号表示用户一般要重新实现) 功能 备注
preEpoch 每轮Epoch之前的用户操作,DeepvacTrain啥也不做 用户可以重新定义(如果需要的话)
preIter 每个batch迭代之前的用户操作,DeepvacTrain啥也不做 用户可以重新定义(如果需要的话)
postIter 每个batch迭代之后的用户操作,DeepvacTrain啥也不做 用户可以重新定义(如果需要的话)
postEpoch 每轮Epoch之后的用户操作,DeepvacTrain啥也不做 用户可以重新定义(如果需要的话)
doFeedData2Device DeepvacTrain把来自dataloader的sample和target(标签)移动到device设备上 用户可以重新定义(如果需要的话)
doForward DeepvacTrain会进行网络推理,推理结果赋值给self.config.output成员 用户可以重新定义(如果需要的话)
doLoss DeepvacTrain会使用self.config.output和self.config.target进行计算得到此次迭代的loss 用户可以重新定义(如果需要的话)
doBackward 网络反向传播过程,DeepvacTrain会调用self.config.loss.backward()进行BP 用户可以重新定义(如果需要的话)
doOptimize 网络权重更新的过程,DeepvacTrain会调用self.config.optimizer.step() 用户可以重新定义(如果需要的话)
doSchedule 更新学习率的过程,DeepvacTrain会调用self.config.scheduler.step() 用户可以重新定义(如果需要的话)
* doValAcc 在val模式下计算模型的acc,DeepvacTrain啥也不做 用户一般要重新定义,写tensorboard的时候依赖于此

典型的写法如下:

class MyTrain(DeepvacTrain):
    ...
    #因为基类不能处理list类型的标签,重写该方法
    def doFeedData2Device(self):
        self.config.target = [anno.to(self.config.device) for anno in self.config.target]
        self.config.sample = self.config.sample.to(self.config.device)

    #初始化config.core.acc
    def doValAcc(self):
        self.config.acc = your_acc
        LOG.logI('Test accuray: {:.4f}'.format(self.config.acc))


train = MyTrain(deepvac_config)
train()

10. 编写测试脚本

在Deepvac规范中,test.py就代表测试范式。测试代码写在test.py文件中,继承Deepvac类。

和train.py中的train/val的本质不同在于:

  • 舍弃train/val上下文;
  • 网络不再使用autograd上下文;
  • 不再进行loss、反向、优化等计算;
  • 使用Deepvac的*Report模块来进行准确度、速度方面的衡量;

继承Deepvac类的子类必须(重新)实现以下方法才能够开始测试:

类的方法(*号表示必需重新实现) 功能 备注
preIter 每个batch迭代之前的用户操作,Deepvac啥也不做 用户可以重新定义(如果需要的话)
postIter 每个batch迭代之后的用户操作,Deepvac啥也不做 用户可以重新定义(如果需要的话)
doFeedData2Device Deepvac把来自dataloader的sample和target(标签)移动到device设备上 用户可以重新定义(如果需要的话)
doForward Deepvac会进行网络推理,推理结果赋值给self.config.output成员 用户可以重新定义(如果需要的话)
doTest 用户完全自定义的test逻辑,可以通过report.add(gt, pred)添加测试结果,生成报告 看下面的测试逻辑

典型的写法如下:

class MyTest(Deepvac):
    ...
    def doTest(self):
        ...

test = MyTest(deepvac_config)
test()
#test(input_tensor)

当执行test()的时候,DeepVAC框架会按照如下的优先级进行测试:

  • 如果用户传递了参数,比如test(input_tensor),则将针对该input_tensor进行doFeedData2Device + doForward,然后测试结束;
  • 如果用户重写了doTest()函数,则将执行doTest(),然后测试结束;
  • 如果用户配置了config.my_test.test_loader,则将迭代该loader,对每个sample进行doFeedData2Device + doForward,然后测试结束;
  • 以上都不符合,报错退出。

DeepVAC的社区产品

产品名称 简介 当前版本 获取方式/部署形式
DeepVAC 独树一帜的PyTorch工程规范 0.6.0 pip install deepvac
libdeepvac 独树一帜的PyTorch模型部署框架 1.9.0 SDK,下载 & 解压
MLab HomePod 迄今为止最先进的容器化PyTorch模型训练环境 2.0 docker run / k8s
MLab RookPod 迄今为止最先进的成本10万人民币以下的存储解决方案 NA 硬件规范 + k8s yaml
pyRBAC 基于Keycloak的RBAC python实现 NA pip install(敬请期待)
DeepVAC版PyTorch 为MLab HomePod pro版本定制的PyTorch包 1.9.0 conda install -c gemfield pytorch
DeepVAC版LibTorch 为libdeepvac定制的LibTorch库 1.9.0 压缩包,下载 & 解压

About

PyTorch Project Specification.

License:GNU General Public License v3.0


Languages

Language:Python 100.0%