当前位置:   article > 正文

Docker - 基于Docker的深度学习_affinedocker

affinedocker

基于Docker的深度学习

原文

Docker提供了一种静态链接Linux核到应用程序的方式. 采用Docker容器可以调用GPUs,因此对于Tensorflow或者其它机器学习框架的部署是一种很好的工具.
利用Docker,不需要太多设置就可以重现机器学习项目,而不用再像下面这样:

# 6 hours of installing dependencies
python train.py
> ERROR: libobscure.so cannot open shared object
  • 1
  • 2
  • 3

只需进行类似于下面的操作,即可以执行 train.py 脚本,其集成了所有的依赖项,包括GPU支持:

dockrun tensorflow/tensorflow:0.12.1-gpu python train.py
> TRAINING SUCCESSFUL
  • 1
  • 2

此处, Docker是暂时的,且不会保存容器内的任何数据. 这里把Docker容器想象成一个1GB大小的 tensorflow.exe 应用程序,集成了需要编译的所有依赖项.

Docker的好处

开源软件往往有很多依赖项,造成难以重用,比如不同编译器的版本、丢失头文件、不正确的库路径等等,这些都导致需要浪费很多时间来设置依赖项,以运行软件.

Docker的使用

对于机器学习项目,如果想要分享在GitHub上,项目的依赖项一般是一系列的Linux命令行,复制并粘贴到终端中安装.
Docker通过一个命令行来拉取正确的Docker镜像,可以取代后一部分的操作,运行项目程序. 通过静态的将项目所有依赖项集成进一个3GB的压缩镜像中,重用时只需拉取下载下来即可.

以基于Torch的 pix2pix 项目为例,直接在Ubuntu平台上时:

git clone https://github.com/phillipi/pix2pix.git
cd pix2pix
bash datasets/download_dataset.sh facades
# install dependencies for some time
...
# train
env \
  DATA_ROOT=datasets/facades \
  name=facades \
  niter=200 \
  save_latest_freq=400 \
  which_direction=BtoA \
  display=0 \
  gpu=0 \
  cudnn=0 \
  th train.lua
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

如果依赖项较少时,该训练脚本是不错的,但实际上是有许多比较坑依赖项,如:

安装依赖项时,可能出现各种错误,比如:

luajit: symbol lookup error:
/root/torch/install/lib/lua/5.1/libTHNN.so: undefined symbol: TH_CONVERT_ACCREAL_TO_REAL
  • 1
  • 2

Docker则通过Docker Hub将项目依赖项打包做成二进制镜像形式.

容器化Dockerized

在Linux服务器上安装 dockernvidia-docker,然后Docker容器就可以访问GPUs,且基本上没有性能损失.
如果是Mac平台,可以安装 Docker for Mac,但是不能进行GPU运算,虽然少数Mac可能支持CUDA. 不过,仍可以以CPU模式进行测试,虽然速度很慢.
在Linux平台,下面的脚本可以在Ubuntu16.04安装 docker,可用于云服务商:

curl -fsSL https://affinelayer.com/docker/setup-docker.py | sudo python3
  • 1

Docker安装成功后,可以以容器的方式运行 pix2pix 项目:

sudo docker run --rm --volume /:/host --workdir /host$PWD affinelayer/pix2pix <command>
  • 1

具体过程如下:

git clone https://github.com/phillipi/pix2pix.git
cd pix2pix
bash datasets/download_dataset.sh facades
sudo docker run --rm --volume /:/host --workdir /host$PWD affinelayer/pix2pix \
  env \
    DATA_ROOT=datasets/facades \
    name=facades \
    niter=200 \
    save_latest_freq=400 \
    which_direction=BtoA \
    display=0 \
    gpu=0 \
    cudnn=0 \
    th train.lua
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

这里会下载作者编译的镜像(支持Torch+nvidia-docker),大概3GB的文件.
运行时会打印训练debug信息. 不过这里没有利用GPU. 基于GPU,能够有效提高pix2pix的训练速度.

GPU化

要利用GPU,仅需将 docker 替换为 nvidia-docker.
标准Docker中还未集成 nvidia-docker,因此需要另外安装. 这里提供一种基于Ubuntu16.04 LTS环境的安装脚本:

curl -fsSL https://affinelayer.com/docker/setup-nvidia-docker.py | sudo python3
  • 1

这里大概花费5分钟完成安装,在 Microsoft AzureAWS 测试过.

nvidia-docker 安装完成后,可以打印当前显卡的信息:

sudo nvidia-docker run --rm nvidia/cuda nvidia-smi
  • 1

现在开启 pix2pix 的GPU训练模式:

sudo nvidia-docker run --rm --volume /:/host --workdir /host$PWD affinelayer/pix2pix \
  env \
    DATA_ROOT=datasets/facades \
    name=facades \
    niter=200 \
    save_latest_freq=400 \
    which_direction=BtoA \
    display=0 \
    th train.lua
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

使用了同一个 pix2pix Docker镜像,不过开启了GPU模式.

Protips 小贴士

对于基于Python的Tensorflow,可能用到一组命令行选项:

--env PYTHONUNBUFFERED=x # 即时打印所有的输出
  • 1
--env CUDA_CACHE_PATH=/host/tmp/cuda-cache #每次调用重新编译CUDA核,可避免每次启动Tensorflow的1分钟延迟
  • 1

即:

sudo nvidia-docker run --rm --volume /:/host --workdir /host$PWD \
  --env PYTHONUNBUFFERED=x \
  --env CUDA_CACHE_PATH=/host/tmp/cuda-cache \
  <image> \
  <command>
  • 1
  • 2
  • 3
  • 4
  • 5

若觉得命令行太长,可以定义一个别名(alias):

alias dockrun="sudo nvidia-docker run --rm --volume /:/host --workdir /host\$PWD --env PYTHONUNBUFFERED=x --env CUDA_CACHE_PATH=/host/tmp/cuda-cache"
  • 1

利用别名 dockrun,运行 pix2pix-tensorflow

git clone https://github.com/affinelayer/pix2pix-tensorflow.git
cd pix2pix-tensorflow
python tools/download-dataset.py facades
dockrun affinelayer/pix2pix-tensorflow python pix2pix.py \
  --mode train \
  --output_dir facades_train \
  --max_epochs 200 \
  --input_dir facades/train \
  --which_direction BtoA
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

pix2pix-tensorflow 项目除了需要Tensorflow 0.12.1外,没有其它依赖项. 即便这样,在Github issue中还是有人遇到Tensorflow版本不对的问题.

Docker项目设置

使用Docker镜像来进行项目开发是很简单的.
只需在一个空路径中建立一个文件,命名为Dockerfile,内容类似于下面的形式:

FROM nvidia/cuda:8.0-cudnn5-devel  # 父镜像
WORKDIR /root   # 类似于 cd /root,进入到/root路径

# 在shell终端运行命令,以安装training dependencies
RUN apt-get update
RUN apt-get install -y --no-install-recommends git ca-certificates sudo

# torch 深度学习框架
RUN git clone https://github.com/torch/distro.git torch --recursive && \
    cd torch && \
    git checkout 49c5b4fd478cb2e7f87ba5853510d26bf28a3d83 && \
    bash install-deps && \
    bash install.sh -b

ENV PATH="/root/torch/install/bin/:${PATH}" # 指定torch环境变量

# 安装tool dependencies
# datasets/download_dataset.sh and models/download_model.sh
# wget
RUN apt-get install -y --no-install-recommends wget

# scripts/combine_A_and_B.py and scripts/edges/batch_hed.py
# opencv
RUN apt-get install -y --no-install-recommends python python-dev
RUN curl -O https://bootstrap.pypa.io/get-pip.py && python get-pip.py
RUN pip install numpy scipy

RUN curl -OL https://github.com/Itseez/opencv/archive/2.4.13.zip && \
    unzip 2.4.13.zip && \
    cd opencv-2.4.13 && \
    mkdir release && \
    cd release && \
    cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local .. && \
    make && \
    make install

# scripts/edges/batch_hed.py
# Caffe 深度学习框架
# based on https://github.com/BVLC/caffe/blob/master/docker/gpu/Dockerfile # Caffe 官方镜像源
# 安装Caffe依赖项
RUN apt-get update && apt-get install -y --no-install-recommends \
        build-essential \
        cmake \
        git \
        wget \
        libatlas-base-dev \
        libboost-all-dev \
        libgflags-dev \
        libgoogle-glog-dev \
        libhdf5-serial-dev \
        libleveldb-dev \
        liblmdb-dev \
        libopencv-dev \
        libprotobuf-dev \
        libsnappy-dev \
        protobuf-compiler \
        python-dev \
        python-numpy \
        python-pip \
        python-setuptools \
        python-scipy && \
    rm -rf /var/lib/apt/lists/*

ENV CAFFE_ROOT=/opt/caffe # 指定Caffe环境变量

RUN mkdir -p $CAFFE_ROOT && \
    cd $CAFFE_ROOT && \
    git clone --depth 1 https://github.com/s9xie/hed . && \
    git checkout 9e74dd710773d8d8a469ad905c76f4a7fa08f945 && \
    pip install --upgrade pip && \
    cd python && for req in $(cat requirements.txt) pydot; do pip install $req; done && cd .. && \像不一致. 另外,如果 docker build指定了CPU,也会导致在另一台机器上不能运行.
    # https://github.com/s9xie/hed/pull/23
    sed -i "s|add_subdirectory(examples)||g" CMakeLists.txt && \
    mkdir build && cd build && \
    # /opt/caffe/include/caffe/util/cudnn.hpp(123): error: argument of type "int" is incompatible with parameter of type "cudnnNanPropagation_t" => -DUSE_CUDNN=OFF 
    # /usr/bin/ld: cannot find -lopencv_dep_cudart => -DCUDA_USE_STATIC_CUDA_RUNTIME=OFF 
    cmake -DUSE_CUDNN=OFF -DCUDA_USE_STATIC_CUDA_RUNTIME=OFF .. && \
    make -j"$(nproc)"

ENV PYCAFFE_ROOT $CAFFE_ROOT/python  # 指定Caffe的python API
ENV PYTHONPATH $PYCAFFE_ROOT:$PYTHONPATH
ENV PATH $CAFFE_ROOT/build/tools:$PYCAFFE_ROOT:$PATH # 指定Caffe的C++ API
RUN echo "$CAFFE_ROOT/build/lib" >> /etc/ld.so.conf.d/caffe.conf && ldconfig

RUN cd $CAFFE_ROOT && curl -O http://vcl.ucsd.edu/hed/hed_pretrained_bsds.caffemodel

# scripts/edges/PostprocessHED.m

RUN apt-get update && \
    apt-get install -y --no-install-recommends octave liboctave-dev && \
    octave --eval "pkg install -forge image" && \
    echo "pkg load image;" >> /root/.octaverc

RUN curl -O https://pdollar.github.io/toolbox/archive/piotr_toolbox.zip && \
    unzip piotr_toolbox.zip && \
    octave --eval "addpath(genpath('/root/toolbox')); savepath;" && \
    echo "#include <stdlib.h>" > wrappers.hpp && \
    cat /root/toolbox/channels/private/wrappers.hpp >> wrappers.hpp && \
    mv wrappers.hpp /root/toolbox/channels/private/wrappers.hpp && \
    mkdir /root/mex && \
    cd /root/toolbox/channels/private && \
    mkoctfile --mex -DMATLAB_MEX_FILE -o /root/mex/convConst.mex convConst.cpp && \
    mkoctfile --mex -DMATLAB_MEX_FILE -o /root/mex/gradientMex.mex gradientMex.cpp && \
    mkoctfile --mex -DMATLAB_MEX_FILE -o /root/mex/imPadMex.mex imPadMex.cpp && \
    mkoctfile --mex -DMATLAB_MEX_FILE -o /root/mex/imResampleMex.mex imResampleMex.cpp && \
    mkoctfile --mex -DMATLAB_MEX_FILE -o /root/mex/rgbConvertMex.mex rgbConvertMex.cpp && \
    octave --eval "addpath('/root/mex'); savepath;" && \
    # gradient2 causes a segfault, use builtin gradient instead
    echo "function [a, b] = gradient2(x)\n[a, b] = gradient(x, 1);\nend" > /root/mex/gradient2.m

RUN curl -O https://raw.githubusercontent.com/pdollar/edges/master/private/edgesNmsMex.cpp && \
    octave --eval "mex edgesNmsMex.cpp" && \
    mv edgesNmsMex.mex /root/mex/

RUN apt-get install -y --no-install-recommends python-imaging
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115

基于该Dockerfile,编译:

mkdir docker-build
cd docker-build
curl -O https://affinelayer.com/docker/Dockerfile
sudo docker build --rm --no-cache --tag pix2pix .
  • 1
  • 2
  • 3
  • 4

花费一段时间完成后,即可新建Docker镜像,查看Docker镜像:

sudo docker images pix2pix
  • 1
output:
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
pix2pix             latest              bf5bd6bb35f8        3 seconds ago       11.38 GB
  • 1
  • 2
  • 3

设置Docker Hub账户,docker login登录,即可推送镜像:

sudo docker tag pix2pix <accountname>/pix2pix
sudo docker push <accountname>/pix2pix
  • 1
  • 2

这样即可使用该镜像来运行分享的软件和项目,很方便快捷.

也可以不用把Docker镜像推送到Docker Hub中,直接保存到本地:

# save image to disk, this took about 18 minutes 保存到磁盘
sudo docker save pix2pix | gzip > pix2pix.image.gz

# load image from disk, this took about 4 minutes 从磁盘加载
gunzip --stdout pix2pix.image.gz | sudo docker load
  • 1
  • 2
  • 3
  • 4
  • 5

可重现性 Reproducibility

Docker镜像便于复制,不必每次都利用Dockerfile重复创建镜像. 查看创建镜像历史:

sudo docker history --no-trunc pix2pix
  • 1

采用Dockerfile重复创建镜像可能导致版本不一样. 例如,如果Dockerfile中有 git clone 或者 apt-get update 命令,在不同的时间编译相同的Dockerfile,就可能导致创建的镜像不一致. 另外,如果 docker build指定了CPU,也会导致在另一台机器上不能运行.

因此,Docker镜像的目的是为了便于复用和部署,如果需要直接从Dockerfile复用镜像,则需要仔细对待Dockerfile文件内容,否则可能出现问题.

如果从零开始编译Dockerfile,并添加 –network none,断开网络链接,则可重现性更好,但推荐直接从镜像进行复用.

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/652760
推荐阅读
相关标签
  

闽ICP备14008679号