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. caioj 1063 动态规划入门(一维一边推1:美元和马克)

    这道题一开始我是这么想的 最后的答案肯定是某次的马克换回来的,但这个该怎么确定?? 实际上应该把范围缩小,只看最后一次和倒数第二次之间有什么联系. 可以发现,只有两种可能,最后一天换或者不换.换的话就 ...

  2. OpenCV —— HighGUI

    分为:硬件相关部分,文件部分以及图形用户接口部分 创建窗口 —— cvNamedWindow 若设置成 CV_WINDOW_AUTOSIZE 窗口大小会随着图像的载入而根据图像大小调整,用户没办法手动 ...

  3. Java_Learn

    20180417 集合类 Collection 如果是实现了list接口的集合类,具备的特点是有序,可重复: 如果是实现了set接口的集合类,具备的特点是无序,不可重复: Collection中的方法 ...

  4. spring webSocket The HTTP response from the server [200] did not permit the HTTP upgrade to WebSocket

    在springboot 1.5.9版本 WebSocketConfig配置 registry.addEndpoint("/webSocket").withSockJS();在加了. ...

  5. coverage python 代码覆盖率工具使用(django 使用)

    1. 安装包 pip install coverage 2.启动程序 coverage run -m pytest 3.获取html格式的报告文件 coverage html 4.创建配置文件 .co ...

  6. POJ——T 2891 Strange Way to Express Integers

    http://poj.org/problem?id=2891 Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 16849   ...

  7. 68.qq号索引结构体写入内存,并实现快速排序

    //两个步骤,第一步读取文件,并且初始化索引结构体,把初始化的索引结构体写入到文件,第二步,读取这个文件到索引结构体 //并对这个结构体进行快速排序,得到顺序的索引,再写入文件 #define _CR ...

  8. jquery如何阻止子元素相应mouseout事件

    jquery如何阻止子元素相应mouseout事件:mouseout有一个特点,当鼠标移入子元素的时候,也会触发此事件,但是在实际应用中这个特点往往不是我们想要的,下面就通过代码实例介绍一下如何实现此 ...

  9. Logstash读写性能调整优化

    继续

  10. ArcGIS小技巧——多图层情况下交互显示效果

    在使用ArcMap处理数据的过程中,通常需要对比不同图层之间的差异.或者查看影像配准情况,这时我通常会怀念ENVI中的强大的拉幕显示.闪烁.亮度和透明度显示工具...... 直到有一天,闲着没事干捣鼓 ...