docker配置深度学习环境
版权声明:本文为博主原创文章,转载注明出处便可。 http://www.javashuo.com/article/p-vsqghqsm-mw.htmlhtml
序
阅读本篇文章能够帮你解决的问题是:提供一套解决方案,可以在支持Docker的任何版本Ubuntu系统下,搭建出完美运行各类深度学习框架、各类版本、各类环境依赖(NAIVID显卡)深度学习工程的开发环境。不只如此,还要像在本机同样方便的修改代码运行计算。python
搭建深度学习计算平台,通常须要咱们在本机上安装一些必要的环境,安装系统、显卡驱动、cuda、cudnn等。而随着Docker的流行,每每可以帮咱们轻松的进行环境搭建、复制与隔离,因此官方也利用容器技术与深度学习相结合,所以也出现了如下方案。linux
容器方案比传统方案带来更多的随意性,装系统前不须要考虑Ubuntu哪个版本符合不符合咱们的代码运行要求,咱们只须要安装一个本身喜欢的(18.04彻底能够),再在官网下载一下显卡驱动,或者软件源附加驱动更新一下就好了,剩下都不须要咱们继续考虑。这些也很是的轻松,由于Nvidia对Ubuntu的支持愈来愈友好,咱们只须要下载deb包,一行命令便可安装成功。git
系统 | 显卡驱动 | Cuda | Cudnn | |
---|---|---|---|---|
传统方案 | 一种版本 | 必需 | 一种版本 | 必需 |
容器方案 | 各类版本 | 必需 | 非必需 | 非必需 |
安装显卡驱动能够参照:https://blog.csdn.net/bskfnvjtlyzmv867/article/details/80102000github
正式进入正文以前,确保你已经安装好趁手的系统和显卡驱动。docker
I. 安装Docker
关于Docker教程,详见:Docker——入门实战shell
安装指定版本Docker CE
这里的版本由第二部分的Nvidia Docker依赖决定,笔者在写此文时须要的版本是18.03.1,若是在安装Nvidia Docker时依赖的Docker CE版本已经变动,能够卸载从新安装须要的版本。json
sudo apt install curl curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - echo "deb [arch=amd64] https://download.docker.com/linux/ubuntu xenial edge" | sudo tee /etc/apt/sources.list.d/docker.list sudo apt-get update && sudo apt-get install -y docker-ce=18.03.1~ce-0~ubuntu1234
执行这个命令后,脚本就会自动的将一切准备工做作好,而且把Docker CE 的Edge版本安装在系统中。ubuntu
启动Docker CE
sudo systemctl enable docker
sudo systemctl start docker12
创建docker 用户组
默认状况下,docker 命令会使用Unix socket 与Docker 引擎通信。而只有root 用户和docker 组的用户才能够访问Docker 引擎的Unix socket。出于安全考虑,通常Ubuntu系统上不会直接使用root 用户。所以,更好地作法是将须要使用docker 的用户加入docker用户组。vim
# 创建docker组
sudo groupadd docker
# 将当前用户加入docker组
sudo usermod -aG docker $USER1234
注销当前用户,从新登陆Ubuntu,输入docker info,此时能够直接出现信息。
配置国内镜像加速
在/etc/docker/daemon.json 中写入以下内容(若是文件不存在请新建该文件)
{
"registry-mirrors": [
"https://registry.docker-cn.com"
]
}12345
从新启动服务
sudo systemctl daemon-reload sudo systemctl restart docker12
II. 安装Nvidia Docker2
Nvidia Docker2项目的主页:https://github.com/NVIDIA/nvidia-docker
# If you have nvidia-docker 1.0 installed: we need to remove it and all existing GPU containers
ocker volume ls -q -f driver=nvidia-docker | xargs -r -I{} -n1 docker ps -q -a -f volume={} | xargs -r docker rm -f
sudo apt-get purge -y nvidia-docker
# Add the package repositories
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/ubuntu16.04/amd64/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
# Install nvidia-docker2 and reload the Docker daemon configuration
sudo apt-get update && sudo apt-get install -y nvidia-docker2
sudo pkill -SIGHUP dockerd
# Test nvidia-smi with the latest official CUDA image
docker run --runtime=nvidia --rm nvidia/cuda nvidia-smi1234567891011121314
III. 搭建环境
拉取镜像
Nvidia官网在DockerHub中提供了关于深度学习的各个版本环境,点我…有Ubuntu14.04-18.04,Cuda6.5-9.2,Cudnn4-7,基本含盖了咱们所须要的各类版本的深度学习环境,咱们直接拉取镜像,在已有的镜像基础上配置咱们的深度学习环境。
下载镜像,这里以ubuntu16.0四、cuda8.0、cudnn5.1的版本为例,咱们找到知足版本要求的TAG为8.0-cudnn5-devel-ubuntu16.04。
# 拉取镜像
docker pull nvidia/cuda:8.0-cudnn5-devel-ubuntu16.04
# 查看镜像
docker images -a1234
建立启动容器
利用下载好的镜像,建立一个交互式的容器。容器须要使用nvidia显卡,须要设置额外的参数。-p 8022:22
docker run -it --name 自定义容器名 -v /home/你的用户名/mnist/:/home/你的用户名/mnist/ --runtime=nvidia -e NVIDIA_VISIBLE_DEVICE=0,1 nvidia/cuda:8.0-cudnn5-devel-ubuntu16.041
NVIDIA_VISIBLE_DEVICE参数指定对容器分配几块GPU资源;-v参数用于挂载本地目录,冒号前为宿主机目录,冒号后为容器目录,两个能够设置为同样比较方便代码书写。配置目录挂载是为了方便本文下一部分测试Mnist服务。容器启动完毕,此时,能够像正常本机配置的深度学习环境同样,测试各个软件的版本。
nvidia-smi
nvcc -V
# 查看cudnn版本
cd /usr/lib/x86_64-linux-gnu/
ll |grep cudnn12345
IV. 构建环境
安装环境
在上一部分咱们搭建了深度学习计算的必要环境,包括CUDA和CUDNN。然而大多数深度学习环境都是须要执行Python编写的深度学习代码的,甚至须要一些经常使用的深度学习框架,如TensorFlow、PyTorch等。在上一部分咱们拉取的Nvidia官方提供的镜像中并无包含Python运行环境以及任何的深度学习框架,须要咱们本身安装。
附上安装环境的全部命令:
apt-get update
# 安装Python2.7环境 3.+版本自行添加
apt-get install -y --no-install-recommends build-essential curl libfreetype6-dev libpng12-dev libzmq3-dev pkg-config python python-dev python-pip python-qt4 python-tk git vim
apt-get clean
## 安装深度学习框架 自行添加
pip --no-cache-dir install setuptools
pip --no-cache-dir install tensorflow-gpu==1.2 opencv-python Pillow scikit-image matplotlib1234567
构建镜像
安装好环境后,其实已经能够开始运行咱们的深度学习代码了。若是你想马上测试本身的Docker深度学习环境搭建成功与否,能够直接开始下一部分的Mnist数据集测试。
若是此时,项目组另外一位小伙伴也想跑深度学习,刚好须要和你同样的环境依赖,咱们彻底能够“拷贝”一份配好的环境给他,他能够直接上手去使用。Docker的方便之处也体如今这,咱们能够将本身定制的容器构建成镜像,能够上传到Docker Hub给别人下载,也能够生成压缩包拷贝给别人。
利用commit命令,生成一个名为homography1.0的新镜像。
# docker commit -a "做者信息" -m "提交信息" 以前启动的容器名 自定义镜像名
docker commit -a "wangguoping" -m "deep homography environment" tensorflow1.2 homography1.012
至于将镜像提交Hub和拷贝就不是本文重点,也就不介绍了。
另外,这里生成镜像还有一个好处,就是第六部分结合PyCharm使用。PyCharm里面配Docker选择的是镜像(IMAGE),而不是容器(Container),它会根据咱们选择的镜像本身帮咱们启动一个容器,用来运行PyCharm里面的代码。我一开始没有搞清楚这个概念,也走了很多弯路。
V. 测试Mnist
进入上一部分挂载的目录:
cd /home/test/mnist # test是个人用户名 vim mnist.py # 建立mnist的tensorflow代码12
代码内容能够参考:Tensorflow——nn、cnn、rnn玩mnist
# coding=utf-8
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
train_img = mnist.train.images
train_lab = mnist.train.labels
test_img = mnist.test.images
test_lab = mnist.test.labels
dim_input = 784
dim_output = 10
x_data = tf.placeholder(tf.float32, [None, dim_input])
y_real = tf.placeholder(tf.float32, [None, dim_output])
stddev = 0.1
weights = {"w_conv1": tf.Variable(tf.random_normal([3, 3, 1, 64], stddev=stddev)),
"w_conv2": tf.Variable(tf.random_normal([3, 3, 64, 128], stddev=stddev)),
"w_fc1": tf.Variable(tf.random_normal([7 * 7 * 128, 1024], stddev=stddev)),
"w_fc2": tf.Variable(tf.random_normal([1024, dim_output], stddev=stddev))}
biases = {"b_conv1": tf.Variable(tf.zeros([64])),
"b_conv2": tf.Variable(tf.zeros([128])),
"b_fc1": tf.Variable(tf.zeros([1024])),
"b_fc2": tf.Variable(tf.zeros([dim_output]))}
def forward_prop(_input, _w, _b, keep_prob):
_input_r = tf.reshape(_input, shape=[-1, 28, 28, 1])
_conv1 = tf.nn.conv2d(_input_r, _w["w_conv1"], strides=[1, 1, 1, 1], padding="SAME")
_conv1 = tf.nn.relu(tf.nn.bias_add(_conv1, _b["b_conv1"]))
_pool1 = tf.nn.max_pool(_conv1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")
# dropout
_pool_dr1 = tf.nn.dropout(_pool1, keep_prob=keep_prob)
_conv2 = tf.nn.conv2d(_pool_dr1, _w["w_conv2"], strides=[1, 1, 1, 1], padding="SAME")
_conv2 = tf.nn.relu(tf.nn.bias_add(_conv2, _b["b_conv2"]))
_pool2 = tf.nn.max_pool(_conv2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")
_pool_dr2 = tf.nn.dropout(_pool2, keep_prob=keep_prob)
flatten = tf.reshape(_pool_dr2, shape=[-1, _w["w_fc1"].get_shape().as_list()[0]])
_fc1 = tf.nn.relu(tf.add(tf.matmul(flatten, _w["w_fc1"]), _b["b_fc1"]))
_fc_dr1 = tf.nn.dropout(_fc1, keep_prob=keep_prob)
_out = tf.nn.relu(tf.add(tf.matmul(_fc_dr1, _w["w_fc2"]), _b["b_fc2"]))
return {"input_r": _input_r, "conv1": _conv1, "pool1": _pool1, "pool_dr1": _pool_dr1, "conv2": _conv2,
"pool2": _pool2, "pool_dr2": _pool_dr2, "flatten": flatten, "fc1": _fc1, "fc_dr1": _fc_dr1, "out": _out}
keep_prob = tf.placeholder(tf.float32)
y_pred = forward_prop(x_data, weights, biases, keep_prob)["out"]
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=y_pred, labels=y_real))
op = tf.train.GradientDescentOptimizer(learning_rate=0.001).minimize(loss)
correct = tf.equal(tf.arg_max(y_pred, 1), tf.arg_max(y_real, 1))
accuracy = tf.reduce_mean(tf.cast(correct, tf.float32))
training_epoch = 100
batch_size = 128
display_step = 2
init = tf.global_variables_initializer()
total_batch = mnist.train.num_examples // batch_size
print("have %d batchs,each batch size is:%d" % (total_batch, batch_size))
saver = tf.train.Saver(max_to_keep=2)
is_training = True
with tf.Session() as sess:
sess.run(init)
if is_training:
for epoch in range(training_epoch):
avg_loss = 0
for i_batch in range(total_batch):
batch_xs, batch_ys = mnist.train.next_batch(batch_size)
feed_dict = {x_data: batch_xs, y_real: batch_ys, keep_prob: 0.5}
sess.run(op, feed_dict=feed_dict)
avg_loss += sess.run(loss, feed_dict=feed_dict)
avg_loss = avg_loss / total_batch
if epoch % display_step == 0:
print("Epoch:%3d/%3d, loss:%.6f" % (epoch, training_epoch, avg_loss))
feed_dict = {x_data: batch_xs, y_real: batch_ys, keep_prob: 0.5}
train_accuracy = sess.run(accuracy, feed_dict=feed_dict)
print("train accuracy:%.6f" % train_accuracy)
saver.save(sess, "MNIST_model/model.ckpt-" + str(epoch))
else:
saver.restore(sess, tf.train.latest_checkpoint(checkpoint_dir="MNIST_model/"))
feed_dict = {x_data: mnist.test.images, y_real: mnist.test.labels, keep_prob: 1.0}
test_accuracy = sess.run(accuracy, feed_dict=feed_dict)
print("test accuracy:%.6f" % test_accuracy)
print("end!")
下载Mnist数据集,保存在/home/test/mnist/MNIST_data目录下。这里须要咱们修改目录权限,Docker共享目录默认只读。注意,这里切换到宿主机的终端下进行操做,可能你会问为何不直接容器内下载,由于之后咱们要跑的数据集不可能只是mnist大小,难道你要在docker里下载几十个G的数据集吗。
sudo chmod -R a+rw /home/test/mnist mkdir -p /home/test/mnist/MNIST_data wget http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz wget http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz wget http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz wget http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz123456
切换至Docker的终端下,运行mnist.py脚本文件,便可发现已经能够跑起来了。
python mnist.py1
此时会在/home/test/mnist下产生MNSIT_model文件夹,里面保存着训练生成的模型。
VI. PyCharm+Docker
Mnist已经测试成功,基本的Docker+Deep Learning方案演示已经完成。然而,我一直不喜欢命令行修改代码,运行脚本,查看结果,我十分推崇PyCharm去调试Python。好比,当Mnist训练完毕,我须要修改第80行的is_training = False来测试我训练出的模型,没有PyCharm,我须要经过vim修改mnist.py,而后再输入python来运行。可能你会以为也不是很麻烦,若是须要修改模型,更换网络,甚至重构代码呢?
因此能用IDE尽可能仍是让PyCharm来开发咱们代码,咱们只须要编码,点击运行,剩下的其余操做我都不太愿意去干,一行命令都懒得敲,毕竟懒嘛!
PyCharm在2018的Profession版本以后都是提供Docker的功能的,能够利用容器中的Python解释器为咱们的代码提供运行条件。利用PyCharm,你能够像在使用本机的深度学习环境同样,无需考虑因容器带来的过多的繁琐操做。官方关于Docker的使用文档参见:http://www.jetbrains.com/help/pycharm/run-debug-configuration-docker.html
在Settings的Build下有一个Docker选项,右侧添加,PyCharm默认会给咱们设置好选择Unix Socket的方式与Docker守护进程进行通讯。出现Connection successful便可,点击OK。
添加成功后,PyCharm下方会出现docker的窗口,能够可视化的查看镜像与容器的相关信息。其中的homography1.0:latsest是咱们上一步构建的镜像。
下面新建一个Python的解释器,相似于本地的Python建立虚拟环境。
按照图示新建,点击OK,便可发现导入容器的Python解释器已经拥有了所有的第三方Python库以及深度学习框架。
等待PyCharm导入容器的解释器成功,理论上咱们即可以开始点击运行按钮跑起咱们的代码了。但实际还有两个问题须要解决。
首先,PyCharm会根据咱们的镜像来启动一个容器运行咱们的代码,然而PyCharm并不知道咱们是要运行深度学习程序,须要利用Nvidia Docker使用GPU资源。咱们以前是经过配置–runtime=nvidia参数来启动一个可使用GPU的容器,那咱们只要指定PyCharm启动一个容器的时候也带上这个参数就好。
另外一个问题就是,咱们如今跑的程序是读取宿主机上某个目录下的几十个G的数据集,好像Docker也不知道数据在哪里,毕竟咱们没有挂载。一样,模型它也不会帮咱们保存,一旦程序运行结束,PyCharm启动的容器销毁,全部的结果都没了,程序白跑了,因此咱们也要指定-v参数告诉PyCharm挂载什么目录。
解决这两个问题,在PyCharm的Run/Debug Configuration中,能够配置。
点击Docker Container settings右边的按钮,添加上面所说的两个参数便可。
坑的是,你发现无法加入–runtime参数。然而,仍是找到了解决方案。把default-runtime”: “nvidia”添加到/etc/docker/daemon.json文件中。这个文件也是咱们配置国内镜像加速的文件。
{
"registry-mirrors": [
"https://registry.docker-cn.com"
],
"default-runtime": "nvidia",
"runtimes": {
"nvidia": {
"path": "/usr/bin/nvidia-container-runtime",
"runtimeArgs": []
}
}
}123456789101112
修改完毕,须要重启docker服务。
sudo systemctl daemon-reload sudo systemctl restart docker12
好了,大功告成,点击运行,跑起来~~
VII. 结语
Docker仍是有不少技巧的,短暂几天也只学了个皮毛,用于深度学习也十分不错。官方也有不少构建好的深度学习环境镜像,包含了主流的深度学习框架,能够再Docker Hub自行搜索。实验室电脑有时候仍是很奇葩的,须要耐心解决,积极的去利用一些新的技术解决难题应该是更应该考虑的事情。
昵称:
退出 订阅评论
[Ctrl+Enter快捷键提交]
【活动】华为云12.12会员节 云产品1折起 满额送Mate20 点击抢购
【推荐】服务器100%基准CPU性能,1核1G首年168元,限时特惠!
· 包含深度学习经常使用框架的Docker环境
· Windows10 利用 Docker 配置 TensofFlow 深度学习工具
· docker配置环境
· Ubuntu 深度炼丹环境配置
· Docker学习---ubuntu环境
· 华硕董事长施崇棠坦诚手机失败:拼到最后已经没办法
· 用户谈ofo押金之殇:一个失败的资本游戏
· NASA自爆服务器遭入侵 过去12年员工的信息恐遭外泄
· 印度外卖创企Swiggy融资10亿美圆 腾讯参投
· UP ing,做为技术公司的联想
» 更多新闻...