学习Tensorflow(1)

Tue 28 November 2017

学习Tensorflow (1)

Tensorflow随着AlphaGO变得家喻户晓。这说明Google的宣传能力很强,导致新入坑的人会优先考虑Tensorflow。同样作为转型到这个领域的新入门者,我把我遇到的问题和大家分享。

接下来的系列我大概会介绍的内容包括:

  • 编译安装
  • 从Low level到High level
    • 线性回归, 逻辑回归
    • DNN版本的mnist
  • 特征输入
    • Python和Spark生成tfrecords
    • 特征的解析
    • 特征工程的
  • Wide and Deep综合项目
    • 从高层到底层
    • Embedding
  • 模型的使用
    • Tensorflow Serving
    • 导出模型给其他语言使用
  • 其他补充

本系列内容偏实践,一些算法和DNN理论上的知识请大家自己学习。

大家有什么问题和建议可以发email给我。

怎样学习

先不要买书

现在市面上的书基于的Tensorflow版本都很旧,API发生了很多变化,所以没有必要买书,看书还会带来干扰。另外写那些书的是以写书为目的,只是介绍基本的用法,能捎带上他们实际项目经验的很少。

先不要买GPU

除非你是以实践深度学习为名,以玩游戏为实。目前Tensorflow官方支持的显卡只有Nvidia品牌的,因为底层使用了CUDA的库。

AMD在深度学习这一块也想分杯羹,推出了HIP中间层,已经移植出了cafe的版本,Tensorflow的版本在https://github.com/ROCmSoftwarePlatform/hiptensorflow,建议不要跳进AMD这个大坑。

不是所有的N卡都支持Tensorflow,不同版本的TF对显卡的CUDA capacity score要求不一样,新版的TF存在不支持旧型号的N卡情况。另外想在Mac上使用eGPU显卡的同学要注意,最新版本的TF Mac版已经不再支持GPU了(至少官方不提供包了)。

不要学第三方封装的框架

出于一个原因:

  • Tensorflow的发展比较快

两个表现:

  • 第三方封装跟不上Tensorflow的发展
  • 部分第三方封装已经被Tensorflow吸收了

看文档, 看代码

虽然说API文档都是由代码生成的,但有的时候在线搜API更方便一些。

但你需要看一个函数底层是怎么时间的,这个时候就需要一个编辑器(如VSCode)查阅代码了,这样可以方便跳转。

除了官网,还有http://developers.googleblog.cn/上面有不少Tensorflow的文章值得看。

写代码排错

如果只看,你只能停留在一定的理论阶段。动起手来写代码,你就会遇到各种各样的问题。解决这些问题你对Tensorflow的理解就更深刻一些,也能补充你只看所漏掉的东西。

写代码的原则是组合使用,官方虽然在代码注释里面,example,tutorial里面展示了不少用法。但你把更多代码组合在一起的时候,你可能会遇到意想不到的问题。

学习的过程

  • 从low level的用法学起,对Tensorflow有一个整体的理解;
  • 学习官方推荐的用法,因为low level的东西你用起来效率不够高(编码效率和执行效率);
  • 高低结合,理解高层的内部实现;
  • 从特征工程,到训练模型,到使用模型预测,做一个完整的项目。

怎样安装

从pip安装

在国内可以使用douban的pip镜像进行下载加速。在~/.pip/pip.conf中加入:

[global]
index-url = http://pypi.douban.com/simple
trusted-host = pypi.douban.com

pip install tensorflow进行安装。但通过pip方式安装在比较旧的系统上会存在GLIBCXX版本不兼容的问题,在CentOS6上这个必然出现。通过下面的命令可以看系统限制支持的GLIBCXX版本:

strings /usr/lib64/libstdc++.so.6 | grep GLIBCXX

版本过低的话,下载编译一个gcc-4.9.4。编译出的libstdc++在./x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/目录,但替换的时候要注意:

只能拷贝覆盖,不能先删除再拷贝

如果先删除,你可能接下来任何命令都不能执行了。

从源码安装

简要介绍一下Tensorflow的编译安装,因为官方提供的pip版本没有针对性的优化。从编译配置,你可以对TF有另一个角度的了解。

>>> import tensorflow as tf
>>> sess = tf.Session()
2017-12-02 08:11:21.742387: I tensorflow/core/platform/cpu_feature_guard.cc:137] Your CPU supports instructions that this TensorFlow binary was not compiled to use: SSE4.1 SSE4.2 AVX AVX2 FMA

如果你用官方pip版本,每次创建session的时候必然提示你上面的信息。

编译依赖bazel,从这里https://github.com/bazelbuild/bazel/releases下载dist包,如bazel-0.8.0-dist.zip

bazel的编译安装依赖jdk,所以需要先安装一个JDK:

cd /usr/local/
wget --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/8u131-b11/d54c1d3a095b4ff2b6607d096fa80163/jdk-8u131-linux-x64.tar.gz
tar xf jdk-8u131-linux-x64.tar.gz
rm -f jdk-8u131-linux-x64.tar.gz
ln -s jdk1.8.0_131 jdk
echo 'export JAVA_HOME=/usr/local/jdk' | tee /etc/profile.d/jdk.sh
echo 'export PATH=$JAVA_HOME/bin:$PATH' | tee -a /etc/profile.d/jdk.sh
source /etc/profile.d/jdk.sh

编译bazel:

unzip -d bazel bazel-0.8.0-dist.zip
cd bazel
bash ./compile.sh
export PATH=$(pwd)/output:$PATH

下面安装官方的说明https://www.tensorflow.org/install/install_sources先安装好第三方的依赖,再编译tensorflow。如果编译CUDA支持的Tensorflow,要注意的是你需要版本的CUDA库和cuDNN的库,在nvidia的官网上可能已经找不到链接了,用搜索引擎去找。

Tensorflow编译出来是一个Python的包,一般而言我会在自己的HOME安装一个miniconda,编译的Tensorflow也是针对miniconda。这样做在Mac上可以绕开一些不必要的麻烦,在Linux上新生成环境之间拷贝miniconda的目录就可以了。

alias python=$HOME/miniconda2/bin/python
alias pip=$HOME/miniconda2/bin/pip

这样在配置Tensorflow的时候它就可以自动找到miniconda的路径。

git clone https://github.com/tensorflow/tensorflow
cd tensorflow
git checkout -b v1.4.0 v1.4.0
./configure
Do you wish to build TensorFlow with jemalloc as malloc support? [Y/n]:
jemalloc是一个更好的内存管理组件,当然要。

Do you wish to build TensorFlow with Google Cloud Platform support? [Y/n]:
支持GCP,国内普通用户没这个需求。

Do you wish to build TensorFlow with Hadoop File System support? [Y/n]:
支持HDFS,这个生成环境很有用,训练数据和模型都可以放在HDFS上,避免数据拉来拉去的情况。

Do you wish to build TensorFlow with Amazon S3 File System support? [Y/n]:
支持亚马逊的S3存储,国内普通用户没这个需求。

Do you wish to build TensorFlow with XLA JIT support? [y/N]:
加速线性代数(融合可组合运算来提升性能, 通过极端专门化减小可执行文件大小),这是运行时的优化,理解JVM的JIT就容易理解这个

Do you wish to build TensorFlow with GDR support?
是否支持GDR,如果你不支持CUDA,就不要选这个了。这个是要硬件支持的。如果支持,可以使用grpc+gdr交换参数

Do you wish to build TensorFlow with VERBS support? 
这个和GDR类似,使用verbs库来交换参数,也就是remote direct memory access(RDMA)。如果你使用了InfiniBand的卡,可以启用这个。

Do you wish to build TensorFlow with MPI support?
是否启用MPI支持,和GDR, VERBS的作用是一样的,如果选择需要制定路径。MPI可以选择Open MPI(可以用普通网卡也可以用兼容MPI的专有设备),如果是Intel MPI,可以指定类似 /opt/intel/impi/2018.1.163/intel64 的路径

Do you wish to build TensorFlow with OpenCL support? 
OpenCL不建议启用, 这是一个开发的计算框架,但异构计算的事实标准是CUDA,如果你启用了OpenCL,还要安装下面的ConputeCPP for SYCL 1.2

Do you wish to build TensorFlow with CUDA support? 
如果有较新的N卡就选择支持,训练预测快不快这是一个关键。

Please specify the CUDA SDK version you want to use, e.g. 7.0. [Leave empty to default to CUDA 8.0]:
建议你使用CUDA 8.0版本

Please specify optimization flags to use during compilation when bazel option "--config=opt" is specified [Default is -march=native]:
优化选项,这里指CPU指令集优化,建议默认,也就是march=native,尤其是在生成环境,这会针对你的CPU扩展指令优化(sse4.1 sse4.2 avx avx2 fma)

Add "--config=mkl" to your bazel command to build with MKL support.

告诉你还可以开启mkl,MKL是Intel® MKL-DNN,类似于cuDNN,可以发挥Intel® Xeon®和Intel® Xeon Phi™系统处理器的潜力,在桌面级的i5, i7 CPU上也有效
这个优化目前仅在Linux系统上有效,和CUDA的支持也是互斥的。这个优化对于大部分的用户可以有,生产环节用AMD CPU的真不多见

总结一下抛开你的代码,让Tensorflow快起来的东西有:

  • 硬件

    • Intel CPU
    • Nvidia Tesla计算卡或者GPU
  • 编译对硬件的支持

    • 计算加速
      • CUDA
      • MKL
      • native指令
    • 通信加速
      • grpc+gdr
      • grpc+verbs
      • grpc+mpi
  • 软件优化
    • jemalloc
    • JIT

PS: 通信加速不是全都依赖硬件

编译配置会保存在.tf_configure.bazelrc这个文件中。

我用下面的命令,开始编译:

bazel build --config=mkl -c opt //tensorflow/tools/pip_package:build_pip_package

MKL更多的信息可以查看: https://software.intel.com/en-us/articles/build-and-install-tensorflow-on-intel-architecturehttps://software.intel.com/en-us/articles/tensorflow-optimizations-on-modern-intel-architecture

你也可以选择针对CPU的扩展指令进行优化:

bazel build --config=opt //tensorflow/tools/pip_package:build_pip_package

安装自己编译出的pip包:

pip install /tmp/tensorflow_pkg/tensorflow-1.4.0-cp27-cp27mu-linux_x86_64.whl

在安装完,你很兴奋的开启python import tensorflow,然后出现了ImportError: No module named platform不要惊慌,因为你在tensorflow的源码目录,切出来就没问题了。

其他注意:

  • 一个已知的问题,如果开启了MPI的支持,必然依赖CUDA。如果没开启CUDA,在编译到stream_executor的时候就会出错;这算一个bug。

  • 启用MKL支持的话,不要下载安装Intel MKL并指定TF_MKL_ROOT,会自动下载依赖,如果你指定的话不一定能编译得过。

  • 如果遇到一些诡异的问题,怎么都解决不了,可以清一次bazel的cache,在$HOME/.cache目录下面。

  • 遇到Error: no such instruction: shlx %edi,%ecx,%ecx那是因为你的binutils的版本太低,在CentOS6上会遇到。

  • 安装的时候可能会出现提示miniconda的libstdc++.so.6版本不兼容,把编译好的libstdc++.so.6给miniconda的lib目录覆盖拷贝一下就OK了。

  • 启用MKL后还会报Your CPU supports instructions that this TensorFlow binary was not compiled to use: SSE4.1 SSE4.2 AVX AVX2 FMA,这个问题可以忽略,因为实际上编译报错的shlx的指令就属于AVX2指令集。

如果启用了MKL,ldd $HOME/miniconda/lib/python2.7/site-packages/tensorflow/python/_pywrap_tensorflow_internal.so会看到libmklml_intel.so,libiomp5.so这两个依赖。

至此编译安装就介绍完了。

Category: 机器学习 Tagged: Tensorflow 深度学习 DNN

Comments