Basic Workflow
下面的代码首先安装 dvc 工具,然后为一个 Git 代码库添加数据文件版本控制支持,
conda create -n dvcPandas python=3.6
conda activate dvcPandas
pip install pandas numpy ipython 'dvc[all]'
take dvcEx
git clone git@github.com:leetschau/pv-current.git
cd pv-current
dvc init
cp .../comb1122.csv . # add a data file
dvc add comb1122.csv
git add .dvc/config .gitignore
git commit -m'add input file of deviation operator to dvc'
dvc remote add -d algo ssh://leo@192.168.100.1/opt/dvcrepo
git add -A
git commit -m'add a dvc remote'
dvc push
dvc unprotect comb1122.csv
echo "some new data" >> comb1122.csv
dvc add comb1122.csv
git add comb1122.csv.dvc
git commit -m'update data file'
dvc push
git checkout 0a0e0b9c50 -- comb1122.csv.dvc # 0a0e0b9c50 is the uuid of the old version
dvc pull
git reset --hard HEAD # get the newest version of the data file
dvc pull
DVC 管理的文件发生变化时,需要先 unprotect
再 add
,所以不要用 DVC 管理文件夹,而应该管理一个一个具体的数据文件。
每次数据文件需要更新时,DVC 再次 add
时创建新的 .dvc 文件,加入到版本控制系统中。
需要回溯旧版本时(包括程序和数据文件),先 git checkout <old-version>
,再 dvc checkout
;
如果只回溯数据文件,不回溯程序文件,则先 git checkout <old-version-dvc-file>
,再 dvc checkout <data-file.dvc
,
详见 Data and Model Files Versioning。
.gitignore
文件中不用写 **/*.csv
,因为 dvc 会自动将被管理文件加进去:
pip install dvc[all]
中的 [all]
提供了 DVC remote 对 SSH, Amazon S3 等云服务的支持。
目前云服务中不包含阿里云,Remote 的 HTTP 类型只能读,不支持写操作,暂不考虑。
在现有代码基础上添加一个计算流程 (pipeline):
dvc run -d comb1122.csv -d app.py -o devires.csv python app.py comb1122.csv devires.csv false
git add ...
gci -m'add a dvc pipeline of app.py'
dvc push
Reproduce Codes and Data
由于 DVC 配置信息已经保存到了 VCS 中,clone 新的代码库时直接 dvc pull
就可以了:
git clone git@github.com:leetschau/pv-current.git
cd pv-current
conda activate dvcPandas
dvc pull
dvc repro devires.csv.dvc
Backup and Restore
Backup remote DVC repository to local host:
cd ~/Documents
take dvcBackup
rsync -av algo:/opt/dvcrepo algo
algo
is defined in ~/.ssh/config whose IP is 192.168.100.1,
the same host specifed in dvc remote add
above.
Now you can use this backup remote:
dvc remote add -d loc1 ~/Documents/dvcBackup/algo/dvcrepo
dvc pull
Backgrouds
离散度算子的Python实现有个问题:算法实现严重依赖输入数据,包括数据的格式 (schema of data frame) 和一定的数据量(算法需要做相关性和分布特性分析时, 数据量需要足够大才能计算出有意义的结果,从而对结果的正确性进行评价), 但这两点都没有办法体现在算法实现代码中,最直接的办法是将数据文件包含在代码库中, 但测试数据经常是几十 MB 到上百 MB,且变化比较频繁, 所以直接放到代码库中不是理想的解决方案(但也不是不可接受)。
只能写在文档里,或者定义在测试用例里。
定义在文档中,没办法保证实现逻辑变化后开发者会同步修改文档。
定义在测试用例里有几个问题:
-
与文档类似,算法实现逻辑变化后,很难保证开发者同步修改测试用例;
-
随着数据格式的变化,之前的测试用例需要随之修改,这部分工作量也不小,且比较枯燥;
-
随着测试用例的增多,需要不断筛选哪些测试用例价值比较大值得保留(有维护成本);
-
部分测试用例是否能够完全自己创建数据,不依赖于外部数据仍然是个问题;
解决方案:
-
为算法实现添加类型定义,例如在 Python 中加类型标注,或者使用强类型语言, 如 Scala(Breeze, Spark), Julia, Haskell, F# 等;
数据版本控制参考了 How should a data scientist handle versioning, both for pipeline code and models?, 其中提到另外两个解决方案 Pachyderm 和 datmo, 但都没有 dvc 理想。