
# 使用Tensorflow训练神经网络
#### 应用场景
当前主流的大数据、AI训练和推理等应用（如Tensorflow、Caffe）均采用容器化方式运行，并需要大量GPU、高性能网络和存储等硬件加速能力，并且都是任务型计算，需要快速申请大量资源，计算任务完成后快速释放。本文将演示在云容器实例中创建GPU类型的负载，以tensorflow的图像分类为示例，演示在容器中直接使用GPU训练一个简单的神经网络。
#### 优势
使用容器化的方式做此类人工智能训练与推理有如下优势：
- 容器化消除环境差异，不需要自己安装各种软件和配套版本，如python，tensorflow，cuda toolkit等软件。
- GPU驱动免安装。
- 低成本，按秒计费。
- serverless带来的免VM运维。
#### 镜像制作
tensorflow社区有tensoflow的基础镜像，已经装好了基础的tensorflow库，它分支持GPU和支持CPU两个版本，在镜像中心即可下载。
- GPU版本地址为 tensorflow/tensorflow:1.15.0-gpu
- CPU版本地址为 tensorflow/tensorflow:1.13.0
本文采用tensorflow官网中一个已经训练好的模型，对图片进行分类，模型名称Inception-v3。Inception-v3是在2012年ImageNet视觉识别挑战赛上训练出的模型，它将一个非常大的图片集进行了1000个种类的图片分类。Github有使用Inception-v3进行图片分类的代码。
训练模型的代码，均在工程<https://gpu-demo.obs.cn-north-1.myhuaweicloud.com/gpu-demo.zip>中，您需要将代码下载解压，并将代码工程打入镜像中。下面附上制作镜像的Dockerfile文件内容：
```
FROM tensorflow/tensorflow:1.15.0-gpu
ADD gpu-demo /home/project/gpu-demo
```
其中ADD将gpu-demo工程拷贝到镜像的/home/project目录下，可以根据自己需要修改。
执行**docker build -t tensorflow/tensorflow:v1 .**命令制作镜像（.表示当前目录，即Dockerfile文件所在目录）。
镜像制作好后需要上传到容器镜像服务，具体步骤请参见<https://support.huaweicloud.com/usermanual-swr/swr_01_0009.html>。
#### 创建Tensorflow负载
1. 登录云容器实例管理控制台。
2. 创建GPU型命名空间，填写命名空间名称，设置好VPC和子网网段后，单击"创建"。
   
   图1GPU型命名空间   
   ![](https://support.huaweicloud.com/bestpractice-cci/zh-cn_image_0268097429.png "点击放大")
   
   
3. 左侧导航栏中选择"工作负载 \> 无状态（Deployment）"，在右侧页面中单击"镜像创建"。
4. 配置负载信息。 
   1. 填写基本信息，选择[2]创建的命名空间，Pod数量选择为"1"，选择Pod规格为"GPU加速型"，显卡的驱动版本选择"418.126"，如下所示。
      GPU Pod的详细规格和显卡驱动的说明请参见[Pod规格](https://support.huaweicloud.com/productdesc-cci/cci_03_0007.html)。
      图2选择GPU容器规格   
      ![](https://support.huaweicloud.com/bestpractice-cci/zh-cn_image_0268097502.png "点击放大") 
   
   2. 选择需要的容器镜像，这里选择的上传到镜像容器仓库的tensorflow镜像。
   
   3. 在容器设置下面的高级设置中，挂载一个NFS类型的文件存储卷，用于保存训练后的数据。
      图3挂载NFS存储   
      ![](https://support.huaweicloud.com/bestpractice-cci/zh-cn_image_0268098155.png "点击放大") 
   
   4. 在启动命令中输出执行命令和参数。
      - 可执行命令：/bin/bash
      
      - 参数1：-c
      
      - 参数2：python /home/project/gpu-demo/cifar10/cifar10_multi_gpu_train.py --num_gpus=1 --data_dir=/home/project/gpu-demo/cifar10/data --max_steps=10000 --train_dir=/tmp/sfs0/train_data; while true; do sleep 10; done 此处 **--train_dir** 表示训练结果存储路径，其前缀**/tmp/sfs0** 需要与[4.c]中设置的NFS"容器内挂载路径"路径保持一致，否则训练结果无法写入NFS中。
        **--max_steps**表示训练迭代的次数，这里指定了10000次迭代，完成模型训练大概耗时3分钟，如果不指定，默认是1000000次迭代，耗时会比较长。max_steps数值越大，训练时间越久，结果越精确。
        
      
      
      该命令是训练图片分类模型，然后单击"下一步"。
      图4设置容器启动命令   
      ![](https://support.huaweicloud.com/bestpractice-cci/zh-cn_image_0268098248.png "点击放大") 
   
   5. 配置负载访问信息。 本例中选择"不启用"，单击"下一步"。
      
   
   6. 单击"提交"，然后单击"返回工作负载列表"。 在负载列表中，待负载状态为"运行中"时，负载创建成功。
      
   
   
   
   
 
#### 使用已有模型分类图片
1. 单击负载名称，进入负载详情界面，选择"Pod列表\>终端"Tab页。当黑色区域文本框中出现#号时，说明已登录。 
   图5Pod终端访问   
   ![](https://support.huaweicloud.com/bestpractice-cci/zh-cn_image_0268100158.png "点击放大")
   
   
2. 进入到工程所在目录，执行python classify_image.py --model_dir=model命令，可以看到分类结果。 
   ```
   # cd /home/project/gpu-demo                                                     
   # ls -l                                                                         
   total 96                                                                        
   -rw-r--r-- 1 root root  6874 Aug 30 08:09 airplane.jpg                          
   drwxr-xr-x 3 root root  4096 Sep  4 07:54 cifar10                               
   drwxr-xr-x 3 root root  4096 Aug 30 08:09 cifar10_estimator                     
   -rw-r--r-- 1 root root 30836 Aug 30 08:09 dog.jpg                               
   -rw-r--r-- 1 root root 43675 Aug 30 08:09 flower.jpg                            
   drwxr-xr-x 4 root root  4096 Sep  4 02:14 inception                             
   # cd inception                                                                  
   # python classify_image.py --model_dir=model --image_file=/home/project/gpu-demo/airplane.jpg                                  
   …
   2019-01-02 08:05:24.891201: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1084] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 15131 MB memory) -> physical GPU (device: 0, name: Tesla P100-PCIE-16GiB, pci bus id: 0000:00:0a.0, compute capability: 6.0)           
   airliner (score = 0.84250)                                                      
   wing (score = 0.03228)                                                          
   space shuttle (score = 0.02524)                                                 
   warplane, military plane (score = 0.00691)                                      
   airship, dirigible (score = 0.00664)
   ```
   这里通过**--image_file** 指定了要分类的图片，图片如下。执行结果最后几行是分类的label和对应的打分，其中有一行显示airliner(score = 0.84250)，分数越高越准确，可见模型认为这个图片是一架客机。
   图6airliner   
   ![](https://support.huaweicloud.com/bestpractice-cci/zh-cn_image_0148336460.jpg)
   也可以不指定要分类的图片，默认将使用下面这张图片分类。
   图7熊猫   
   ![](https://support.huaweicloud.com/bestpractice-cci/zh-cn_image_0148335215.jpg)
   执行命令**python classify_image.py ----model_dir=mode**
   ```
   # python classify_image.py --model_dir=model
   …
   2019-01-02 08:02:33.271527: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1084] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 15131 MB memory) -> physical GPU (device: 0, name: Tesla P100-PCIE-16GiB, pci bus id: 0000:00:0a.0, compute capability: 6.0)                                   
   giant panda, panda, panda bear, coon bear, Ailuropoda melanoleuca (score = 0.89107)                                                                             
   indri, indris, Indri indri, Indri brevicaudatus (score = 0.00779)               
   lesser panda, red panda, panda, bear cat, cat bear, Ailurus fulgens (score = 0.00296)                                                                           
   custard apple (score = 0.00147)                                                 
   earthstar (score = 0.00117)
   ```
   执行结果显示模型认为这是一只大熊猫。
   
   
 
#### 使用训练的图片分类模型
tensorflow官网中给了一个深度卷积网络的模型代码和训练数据：CIFAR-10。这是个简化的图片分类模型，将图片分成以下10类：airplane, automobile, bird, cat, deer, dog, frog, horse, ship和truck。当然给模型的图，也就是训练数据，也是这10种类型的图片。
1. 单击负载名称，进入负载详情界面，选择"Pod列表\>终端"Tab页，使用代码中提供的cifar10_eval.py校验模型的准确性，这里的checkpoint_dir指定使用刚刚训练出来的模型进行准确性校验。 
   ```
   # cd /home/project/gpu-demo/cifar10
   # python cifar10_eval.py --data_dir=data --checkpoint_dir=/tmp/sfs0/train_data --run_once
   …
   2019-01-02 08:25:43.914186: precision @1 = 0.817
   ```
   
   
2. 继续使用上面的飞机图片进行测试，这里的checkpoint_dir指定使用刚刚训练出来的模型进行图片分类，test_file指定用哪张图片测试。 
   ```
   # python label_image.py --checkpoint_dir=/tmp/sfs0/train_data --test_file=/home/project/gpu-demo/airplane.jpg
       …
   2019-01-02 08:36:42.149700: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1084] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 15131 MB memory) -> physical GPU (device: 0, name: Tesla P100-PCIE-16GiB, pci bus id: 0000:00:0a.0, compute capability: 6.0)                                   
   airplane (score = 4.28143)                                                      
   ship (score = 1.92319)                                                          
   cat (score = 0.03095)
   ```
   可见它准确识别出图中是架飞机。label_image.py是使用刚刚训练的模型来进行图片分类的代码。
   同时，在"Pod列表\>监控"Tab页中，可以看到各种资源的使用率。
   ![](https://support.huaweicloud.com/bestpractice-cci/zh-cn_image_0148312561.jpg "点击放大")
   
   
 
