2015年11月9日谷歌开源了人工智能平台TensorFlow,同时成为2015年最受关注的开源项目之一。经历了从v0.1到v0.12的12个版本迭代后,谷歌于2017年2月15日发布了TensorFlow 1.0 版本,并同时在美国加州山景城举办了首届TensorFlow Dev Summit会议。

TensorFlow
1.0及Dev Summit(2017)回顾

和以往版本相比,TensorFlow 1.0 的特性改进主要体现在以下几个方面:

速度更快:TensorFlow 1.0版本采用了XLA的编译技术,改进了TensorFlow的运行性能及内存利用。从Benchmark问题的测试结果来看,对单机Inception v3模型,实现了在单机8 GPUs上7.3倍的运算加速;对分布式Inception
v3模型,实现了在多机64 GPUs上58倍的运算加速。

更加灵活:该版本除了支持tf.layers,tf.metrics及tf.losses模型的High-Level API外,实现了对keras(high-level neural networks library)API的全面兼容。

更产品化:TensorFlow Python API在v1.0版本中趋于稳定,为产品兼容性打下坚实基础。

在TensorFlow 1.0版本发布的当天,谷歌公司还举办了TensorFlow 2017 DEV Summit。该日程(https://events.withgoogle.com/tensorflow-dev-summit/videos-and-agenda/#content)主要包括以下几个方面的主题演讲:

  • XLA (TensorFlow, Compiled)编译技术 :介绍采用XLA技术最小化图计算执行时间和最大化利用计算资源,用于减少数据训练和模型结果推断时间。

  • Hands-on TensorBoard可视化技术:介绍了如何使用TensorBoard,以及TensorFlow图模型、训练数据的可视化等。

  • TensorFlow High-Level API:介绍了使用Layers, Estimators, and Canned Estimators High-Level API定义训练模型。

  • Integrating Keras & TensorFlow: 介绍了如何在TensorFlow中使用Keras API进行模型定义及训练。

  • TensorFlow at DeepMind:介绍了在DeepMind中使用TensorFlow平台的典型案例,包括AlphaGo等应用。

  • Skin Cancer Image Classification:介绍了斯坦福医学院使用TensorFlow分类皮肤癌照片,用于医学诊断。

  • Mobile and Embedded TensorFlow:介绍了如何把TensorFlow模型运行在移动终端、嵌入式设备,包括安卓,iOS等系统。

  • Distributed TensorFlow:系统性地介绍了分布式TensorFlow的相关技术,以及如何应用于大规模模型训练。

  • TensorFlow Ecosystem:讲解了TensorFlow的生态系统,包括生成训练数据,分布式运行TensorFlow和serving models的产品化流程。

  • Serving Models in Production with TensorFlow Serving:系统性讲解了如何在生产环境中应用TensorFlow Serving模型。

  • ML Toolkit:介绍了TensorFlow的机器学习库,如线性回归,KMeans等算法模型的使用。

  • Sequence Models and the RNN API:介绍了如何构建高性能的sequence-to-sequence模型,以及相关API。

  • Wide & Deep Learning: 介绍了如何结合Wide模型和Deep模型构建综合训练模型。

  • Magenta,Music and Art Generation:使用增强型深度学习模型生成音乐声音和艺术图片。

  • Case Study,TensorFlow in Medicine - Retinal Imaging:使用TensorFlow机器学习平台对医学视网膜图片进行分类,辅助医学诊断。

TensorFlow系统架构

TensorFlow作为分布式机器学习平台,主要架构如下图所示。RPC和RDMA为网络层,主要负责传递神经网络算法参数。CPU和GPU为设备层,主要负责神经网络算法中具体的运算操作。Kernel为TensorFlow中算法操作的具体实现,如卷积操作,激活操作等。Distributed Master用于构建子图;切割子图为多个分片,不同的子图分片运行在不同的设备上;Master还负责分发子图分片到Executor/Work端。Executor/Work在设备(CPUs,GPUs,etc.)上,调度执行子图操作;并负责向其它Worker发送和接收图操作的运行结果。C
API把TensorFlow分割为前端和后端,前端(Python/C++/Java Client)基于C API触发TensorFlow后端程序运行。Training libraries和Inference libs是模型训练和推导的库函数,为用户开发应用模型使用。

下图为Client、Master及Worker的内部工作原理。"/job:worker/task:0" 和 "/job:ps/task:0" 表示worker中的执行服务。"job:ps"表示参数服务器,用于存储及更新模型参数。"job:worker"用于优化模型参数,并发参数发送到参数服务器上。Distributed Master和Worker Service只存在于分布式TensorFlow中。单机版本的TensorFlow实现了Local的Session,通过本地进程的内部通讯实现上述功能。

用户编写TensorFlow应用程序生成计算图,Client组件会创建Session,并通过序列化技术,发送图定义到Distributed Master组件。下图中,Client创建了一个 s+=w*x+b的图计算模型。

当Client触发Session运算的时候,Maser构建将要运行的子图。并根据设备情况,切割子图为多个分片。下面为Master构建的运行子图:

接着切割子图,把模型参数分组在参数服务器上,图计算操作分组在运算Worker上。下图为一种可行的图切割策略:

Distributed Master会根据模型参数的分区情况进行切割边,在Task间插入发送和接收Tensor信息的通信节点,如下图所示:

接着Distributed Master通过RegisterGraph方法发送子图分片给Task,如下图所示:

Master通过RunGraph触发子图运算,Worker会使用GPU/CPU运算设备执行TensorFlow Kernel运算。在本节点的CPU和GPU之间,使用cudaMemcpyAsync传输数据;在本节点GPU和GPU之间,使用peer-to-peer DMA传输数据,避免通过CPU复制数据。TensorFlow使用gRPC(TCP)和RDMA (Converged Ethernet)技术,实现Worker间的数据通信及传输,如下图所示:

高性能程序设计

TensorFlow内核采用C/C++开发,并提供了C++,Python,Java,Go语言的Client API。特别是Python API,是目前主流的TensorFlow模型开发接口。但为什么还需要采用C++ API去训练模型呢?本文基于如下两点考虑,首先当我们采用Python API去训练模型的时候,需要不断地用Python
API调用C/C++底层接口,重复的接口调用一定程度上影响了程序的执行性能。更为重要的是,在GPU上训练模型的时候需要大量的内存交换;如果采用C++ API去训练模型,可提供更好的运算性能及更好地控制GPU内存的分配。

下图为Python API的运算架构:在模型训练的每次迭代中,程序通过Python API读取Batch Data,然后通过TensorFlow Session Run接口,传递数据给C++,并触发神经网络训练。如下图所示:

下图为C++ API的运算架构:在模型训练的每次迭代中,通过C++ API读取Batch Data后,直接触发模型训练。减少了不同语言间API接口的循环调用及数据传输。如下图所示:

为了采用C++ API进行模型训练,我们首先需要编写训练模型,这个编写过程可以采用Python语言来完成。我们首先采用Python API编写训练模型,然后把图模型转换为Protobuf的序列化文件。接着通过C++ API加载该模型文件,创建TensorFlow Session,初始化模型变量,以及加载训练数据并执行神经网络训练。程序架构如下图所示:

下面为使用Python API定义训练模型的示例:

with tf.Session() as sess:

    
   #定义Placeholder Tensor接入训练数据
   x = tf.placeholder(tf.float32, [None, 32], name="x")
   y = tf.placeholder(tf.float32, [None, 8], name="y")    #定义训练模型
   w1 = tf.Variable(tf.truncated_normal([32, 16], stddev=0.1))
   b1 = tf.Variable(tf.constant(0.0, shape=[16]))
   w2 = tf.Variable(tf.truncated_normal([16, 8], stddev=0.1))
   b2 = tf.Variable(tf.constant(0.0, shape=[8]))
   a = tf.nn.tanh(tf.nn.bias_add(tf.matmul(x, w1), b1))
   y_out = tf.nn.tanh(tf.nn.bias_add(tf.matmul(a, w2), b2), name="y_out")
   cost = tf.reduce_sum(tf.square(y-y_out), name="cost")
   optimizer = tf.train.AdamOptimizer().minimize(cost, name="train")    #定义变量初始化操作
   init = tf.initialize_variables(tf.all_variables(), name='init_all_vars_op')    #把图模型转换为Protobuf文件
tf.train.write_graph(sess.graph_def, './', 'mlp.pb', as_text=False)

下面为使用C++ API加载Protobuf图模型,并执行训练的示例:

#include "tensorflow/core/public/session.h"
#include "tensorflow/core/graph/default_device.h"
using namespace tensorflow; int main(int argc, char* argv[]) {
   //Protobuf模型文件名
   std::string graph_definition = "mlp.pb";
   //Tensorflow Sesssion
   Session* session;    //定义图模型对象
   GraphDef graph_def;
   SessionOptions opts;    //存储Session会话的运行结果
   std::vector<Tensor> outputs;    #加载Protobuf模型文件到图模型对象中
   TF_CHECK_OK(ReadBinaryProto(Env::Default(), graph_definition, &graph_def));    // 默认在gpu 0上执行模型的训练操作
   graph::SetDefaultDevice("/gpu:0", &graph_def);    //设定GPU显存使用参数
   opts.config.mutable_gpu_options()->set_per_process_gpu_memory_fraction(0.5);
   opts.config.mutable_gpu_options()->set_allow_growth(true);    //创建TensorFlow会话
   TF_CHECK_OK(NewSession(opts, &session));    // 加载图对象到会话中
   TF_CHECK_OK(session->Create(graph_def));    // 执行模型参数初始化操作
   TF_CHECK_OK(session->Run({}, {}, {"init_all_vars_op"}, nullptr));    //定义模型输入数据,包括数据类型和维度信息
   Tensor x(DT_FLOAT, TensorShape({100, 32}));
   Tensor y(DT_FLOAT, TensorShape({100, 8}));    //把Tensor转换为矩阵,并初始化Tensor数据
   auto _XTensor = x.matrix<float>();
   auto _YTensor = y.matrix<float>();
   _XTensor.setRandom();
   _YTensor.setRandom();    for (int i = 0; i < 10; ++i) {
       //执行模型的训练操作,{{"x", x}, {"y", y}}表示输入数据Tensor名称和Tensor对象;{"cost"}表示要获取输出值的操作名称;&outputs表示执行"cost"操作后返回的Tensor对象
       TF_CHECK_OK(session->Run({{"x", x}, {"y", y}}, {"cost"}, {}, &outputs));        //获取执行“cost“操作后的运算结果
       float cost = outputs[0].scalar<float>()(0);
       std::cout << "Cost: " << cost << std::endl;        //执行"train"操作
       TF_CHECK_OK(session->Run({{"x", x}, {"y", y}}, {}, {"train"}, nullptr)); // Train
       outputs.clear();
   }    //关闭Session及删除Session对象
   session->Close();
   delete session;
   return 0;
}

当C++程序写好后,编译时候需要链接的头文件,开源已经帮我们整理好了,存放于目录/usr/lib/python2.7/site-packages/tensorflow/include下。编译和运行的时候需要链接libtensorflow_cc.so,可以按照下面的方式编译该库文件:bazel build -c opt //tensorflow:libtensorflow_cc.so --copt=-m64 --linkopt=-m64 --spawn_strategy=standalone --genrule_strategy=standalone
--verbose_failures。具体可参考TensorFlow源代码的官方编译文档。

总结

本文首先回顾了TensorFlow 1.0主要新特性及TensorFlow 2017 Dev Summit的主要议程。到目前为止TensorFlow的GitHub Star排名为51000+, Fork排名已达24000+,有15000+ commits。并随着TensorFlow新版本的不断发布以及新特性的不断增加,TensorFlow使用更加灵活,运行速度更快,使用方式更产品化,已成为目前主流的深度学习平台之一。

接着介绍了TensorFlow的系统架构,包括Client,Master,Worker,Kernel的相关概念及运行方式,是一种适合大规模分布式训练的机器学习平台。从上述系统架构中可以看到,TensorFlow内核采用C/C++开发,当采用Python API去训练模型的时候,需要不断地用Python调用C/C++底层接口,重复的接口调用一定程度上影响了程序的执行性能。如果有最求高性能运算的朋友,可以尝试用下本文高性能运算章节推荐的方法。

参考文献

[1] http://www.tensorflow.org

[2] 深度学习利器:分布式TensorFlow及实例分析

[3] 深度学习利器:TensorFlow使用实战

深度学习利器: TensorFlow系统架构及高性能程序设计的更多相关文章

  1. 深度学习利器:TensorFlow在智能终端中的应用——智能边缘计算,云端生成模型给移动端下载,然后用该模型进行预测

    前言 深度学习在图像处理.语音识别.自然语言处理领域的应用取得了巨大成功,但是它通常在功能强大的服务器端进行运算.如果智能手机通过网络远程连接服务器,也可以利用深度学习技术,但这样可能会很慢,而且只有 ...

  2. 深度学习(TensorFlow)环境搭建:(一)硬件选购和主机组装

    一.硬件采购 近年来,人工智能AI越来越多被人们所了解,尤其是AlphaGo的人机围棋大战之后,机器学习的热潮也随之高涨.最近,公司采购了几批设备,通过深度学习(TensorFlow)来研究金融行业相 ...

  3. 深度学习(TensorFlow)环境搭建:(三)Ubuntu16.04+CUDA8.0+cuDNN7+Anaconda4.4+Python3.6+TensorFlow1.3

    紧接着上一篇的文章<深度学习(TensorFlow)环境搭建:(二)Ubuntu16.04+1080Ti显卡驱动>,这篇文章,主要讲解如何安装CUDA+CUDNN,不过前提是我们是已经把N ...

  4. 深度学习调用TensorFlow、PyTorch等框架

    深度学习调用TensorFlow.PyTorch等框架 一.开发目标目标 提供统一接口的库,它可以从C++和Python中的多个框架中运行深度学习模型.欧米诺使研究人员能够在自己选择的框架内轻松建立模 ...

  5. 分享《机器学习实战基于Scikit-Learn和TensorFlow》中英文PDF源代码+《深度学习之TensorFlow入门原理与进阶实战》PDF+源代码

    下载:https://pan.baidu.com/s/1qKaDd9PSUUGbBQNB3tkDzw <机器学习实战:基于Scikit-Learn和TensorFlow>高清中文版PDF+ ...

  6. 深度学习(TensorFlow)环境搭建:(二)Ubuntu16.04+1080Ti显卡驱动

    前几天把刚拿到了2台GPU机器组装好了,也写了篇硬件配置清单的文章——<深度学习(TensorFlow)环境搭建:(一)硬件选购和主机组装>.这两台也在安装Ubuntu 16.04和108 ...

  7. 转发——谷歌云官方:一小时掌握深度学习和 TensorFlow

    转发——谷歌云官方:一小时掌握深度学习和 TensorFlow 本文转发自新智元,链接如下: http://mp.weixin.qq.com/s?__biz=MzI3MTA0MTk1MA==& ...

  8. Ubuntu16.04搭建深度学习框架——TensorFlow

    TensorFlow是一个采用数据流图(data flow graphs),用于数值计算的开源软件库,说白了,就是一个库. 小编自己在Ubuntu搭建了深度学习框架TensorFlow,感觉挺简单,现 ...

  9. 深度学习之TensorFlow安装与初体验

    深度学习之TensorFlow安装与初体验 学习前 搞懂一些关系和概念 首先,搞清楚一个关系:深度学习的前身是人工神经网络,深度学习只是人工智能的一种,深层次的神经网络结构就是深度学习的模型,浅层次的 ...

随机推荐

  1. Ajax学习总结(1)——Ajax实例讲解与技术原理

    摘要:AJAX即"Asynchronous Javascript And XML"(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术.AJAX 是一种用 ...

  2. [ES2017] Iterate over properties of an object with ES2017 Object.entries()

    The Object.entries() function is an addition to the ECMAscript scpec in Es2017. This allows us to it ...

  3. 杭电5137How Many Maos Does the Guanxi Worth

    How Many Maos Does the Guanxi Worth Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 512000/5 ...

  4. UVa 10101 - Bangla Numbers

    题目:将数字数转化成数字加单词的表示形式输出. 分析:数论.简单题.直接分成两部分除10000000的商和余数,分别输出就可以. 说明:注意输入为数字0的情况,还有long long类型防止溢出. # ...

  5. Ubuntu中的解压缩文件的方式

    记录Ubuntu下各种压缩和解压方式: .tar 解包:tar xvf FileName.tar 打包:tar cvf FileName.tar DirName (注:tar是打包,不是压缩!) -- ...

  6. 转:IOS的推送。是一个强大的功能

    IOS下我们很多人天天开着 邮件推送 微信推送 QQ推送 微博推送 新浪微博推送,安卓敢吗? 五个后台进程消耗电.流量谁敢这么做?现在安卓也出了推送,但绝对是伪推送.实际是挂了个进程,关掉了就收不到. ...

  7. 【Swift初见】Swift数组(二)

    在苹果的开发文档中对Array还提供了其它的操作算法: 1.Sort函数: 对数组进行排序.依据指定的排序规则,看以下的代码: var array = [2, 3, 4, 5] array.sort{ ...

  8. Android图像处理之熔铸特效

    代码: package com.color; import android.content.Context; import android.graphics.Bitmap; import androi ...

  9. Spark scheduler

    触发Spark scheduler的入口是调用者代码中的action操作,如groupByKey,first,take,foreach等操作.这些action操作最终会调用SparkContext.r ...

  10. wget 指令学习之递归抓取文档技巧

    在线上阅读文档的时候,有没有想将它抓取到本地,以备没有网的时候阅读只需? 先上指令: $ wget --user-agent="Mozilla/5.0 (X11; Linux x86_64) ...