非常教程

TensorFlow Guide参考手册

扩展 | Extend

TensorFlow in other languages(TensorFlow其他语言)

背景

本文档旨在为那些对创建或开发其他编程语言中的TensorFlow功能感兴趣的人员提供指导。它描述了TensorFlow的功能以及推荐使用其他编程语言提供的步骤。

Python是TensorFlow支持的第一种客户端语言,目前支持最多的功能。越来越多的功能被移入TensorFlow的核心(用C ++实现)并通过C API公开。客户端语言应该使用该语言的外部函数接口(FFI)来调用此C API以提供TensorFlow功能。

概述

在编程语言中提供TensorFlow功能可以细分为几大类:

  • 运行预定义图:给定GraphDef(或MetaGraphDef)协议消息,能够创建会话,运行查询并获得张量结果。这对于想要在预先训练的模型上运行推理的移动应用或服务器就足够了。
  • 图表构造:每个定义的TensorFlow操作至少有一个函数将操作添加到图形。理想情况下,这些函数会自动生成,以便在操作定义被修改时保持同步。
  • 梯度(AKA自动分化):给定图形和输入和输出操作列表,将相关操作添加到图形中,以计算输入相对于输出的偏导数(梯度)。允许为图形中的特定操作定制梯度函数。
  • 函数:定义一个子图,可以在主要的多个位置调用GraphDef。定义FunctionDefFunctionDefLibrary包含的GraphDef
  • 控制流程:使用用户指定的子图构造“If”和“While”。理想情况下,这些工作与梯度(见上文)。
  • 神经网络库:许多组件支持创建神经网络模型并对它们进行训练(可能在分布式环境中)。虽然以其他语言提供这种方法会很方便,但目前还没有计划用Python以外的其他语言来支持它。这些库通常是对上述功能的封装。

至少,语言绑定应该支持运行预定义的图形,但大多数应该也支持图形构建。TensorFlow Python API提供了所有这些功能。

当前状态

新的语言支持应该建立在C API之上。但是,正如您在下表中看到的,并非所有功能都可用于C语言。在C API中提供更多功能是一个正在进行的项目。

特征

Python

C

运行预定义的图

tf.import_graph_def,tf.Session

TF_GraphImportGraphDef,TF_NewSession

具有生成的操作函数的图构造

Yes

是(C API支持执行此操作的客户端语言)

梯度

tf.gradients

功能

tf.python.framework.function.Defun

控制流

tf.cond,tf.while_loop

神经网络库

tf.train,tf.nn,tf.contrib.layers,tf.contrib.slim

推荐方法

运行预定义的图形

预计语言绑定将定义以下类:

  • Graph:代表TensorFlow计算的图形。由操作组成(用客户端语言表示Operation)并对应TF_Graph于C API中的一个。主要用作创建新Operation对象和启动时的参数Session。还支持遍历graph(TF_GraphNextOperation)中的操作,通过name(TF_GraphOperationByName)查找操作,以及从GraphDef协议消息(TF_GraphToGraphDefTF_GraphImportGraphDef在C API中)进行转换。
  • Operation:表示图中的计算节点。对应TF_Operation于C API中的一个。
  • Output:表示图中操作的输出之一。有DataType(并最终形状)。可以作为输入参数传递给函数,以便将操作添加到图中,或者传递给将该输出作为张量获取SessionRun()方法。对应TF_Output于C API中的一个。
  • Session:表示TensorFlow运行时的特定实例的客户端。它的主要工作是建立一个Graph和一些选项,然后Run()对该图进行现场调用。对应TF_Session于C API中的一个。
  • Tensor:表示元素全部相同的N维(矩形)数组DataType。获取数据流入和流出的SessionRun()电话。对应TF_Tensor于C API中的一个。
  • DataType:具有TensorFlow支持的所有可能张量类型的枚举。对应TF_DataType于C API并且通常在Python API中被称为dtype

图构建

TensorFlow有许多操作,并且列表不是静态的,所以我们建议生成将操作添加到图形的函数,而不是单独手动编写它们(尽管手动编写几个函数是找出生成器应该是什么的好方法生成)。生成函数所需的信息包含在OpDef协议消息中。

有几种方法可以获得OpDef已注册操作的列表:

  • TF_GetAllOpList在C API中检索所有注册的OpDef协议消息。这可用于以客户端语言编写生成器。这要求客户端语言具有协议缓冲区支持才能解释OpDef消息。
  • C ++函数OpRegistry::Global()->GetRegisteredOps()返回所有注册的OpDefs(在中定义tensorflow/core/framework/op.h)的相同列表。这可以用来在C ++中编写生成器(对没有协议缓冲区支持的语言特别有用)。
  • 该列表的ASCII序列化版本通过自动过程定期检入tensorflow/core/ops/ops.pbtxt

OpDef指定如下:

  • CamelCase中的操作名称。对于生成的函数,遵循该语言的约定。例如,如果语言使用snake_case,那么使用该字符而不是使用CamelCase作为操作的函数名称。
  • 输入和输出的列表。正如添加操作的输入和输出部分所述,这些参数的类型可能会通过引用属性而呈现多态。
  • 属性列表及其默认值(如果有的话)。请注意,其中一些将被推断(如果它们由输入确定),一些将是可选的(如果它们具有默认值),并且一些将是必需的(无默认值)。
  • 一般操作的文档以及输入,输出和非推断属性。
  • 运行时使用的一些其他字段,可由代码生成器忽略。

一个OpDef可被转换为附加操作,运算图表的功能的文本TF_使用OperationDescriptionC API(包裹在该语言的FFI):

  • 开始TF_NewOperation()创建TF_OperationDescription*
  • 调用TF_AddInput()TF_AddInputList()每个输入一次(取决于输入是否具有列表类型)。
  • 调用TF_SetAttr*()函数来设置非推断的属性。如果您不想覆盖默认值,可以跳过默认值的属性。
  • 必要时设置可选字段:
    • TF_SetDevice():强制操作到特定设备上。
    • TF_AddControlInput():在此操作开始运行之前添加其他操作完成的要求
    • TF_SetAttrString("_kernel") 设置内核标签(很少使用)
    • TF_ColocateWith() 将另一个作业与另一个作​​业共同作业
  • TF_FinishOperation()完成时调用。这将操作添加到图形中,之后不能修改。

现有示例运行代码生成器作为构建过程的一部分(使用Bazel genrule)。或者,代码生成器可以通过自动cron进程运行,可能会检查结果。这会在生成的代码和OpDef检入到存储库中的代码之间产生分歧,但对于预期会像go getGo和cargo opsRust 那样预先生成代码的语言而言非常有用。另一方面,对于某些语言,代码可以从中tensorflow/core/ops/ops.pbtxt动态生成。

处理常量

如果用户可以为输入参数提供常量,调用代码将更加简洁。生成的代码应该将这些常量转换为添加到图的操作,并用作实例化操作的输入。

可选参数

如果语言允许一个函数的可选参数(例如Python中带有默认值的关键字参数),请将它们用于可选属性,操作名称,设备,控制输入等。在某些语言中,可以使用动态范围来设置这些可选参数(如“与”在Python中的块)。如果没有这些功能,库可能采取“构建器模式”,就像在TensorFlow API的C ++版本中所做的那样。

名称范围

支持使用某种范围层次结构命名图操作是个好主意,特别是考虑到TensorBoard依靠它以合理的方式显示大图的事实。现有的Python和C ++ API采用不同的方法:在Python中,名称的“目录”部分(到最后一个“/”的所有内容都来自with块)。实际上,有一个线程本地堆栈,范围定义了名称层次结构。名称的最后一个组件由用户明确提供(使用可选的name关键字参数)或默认为要添加的操作的类型的名称。在C ++中,名称的“目录”部分存储在明确的Scope对象中。NewSubScope()方法附加到名称的那部分并返回一个新的Scope。该名称的最后一个组件是使用该WithOpName()方法设置的,并且像Python一样默认为要添加的op类型的名称。Scope对象显式传递以指定上下文的名称。

封装

将生成的函数保留为某些私有操作可能是有意义的,以便可以使用执行一点额外工作的封装函数。这也提供了一个外部孵化器来支持生成代码范围之外的功能。

封装的一个用途是支持SparseTensor输入和输出。SparseTensor是3个稠密张量的元组:索引,值和形状。值是矢量大小n,形状是矢量大小等级,而索引是矩阵大小n,等级。有一些稀疏操作使用这个三元组来表示单个稀疏张量。

使用包装的另一个原因是拥有状态的操作。有几个这样的操作(例如一个变量)附带随从操作保持该状态。Python API为构造函数创建操作的这些操作符提供了类,并且该类上的方法向操作该状态的图上添加操作。

其他考虑事项

  • 最好有一个关键字列表,用于重命名与语言关键字(或其他会导致问题的符号,如生成的代码中引用的库函数或变量的名称)相冲突的操作函数和参数。
  • Const由于生成的函数通常会具有冗余DataType输入,因此将操作添加到图形的功能通常是一个封装器。

梯度,功能和控制流程

此时,除Python以外的语言不支持梯度,函数和控制流操作(“if”和“while”)。这将在C API提供必要的支持时更新。

TensorFlow Guide

TensorFlow是谷歌基于DistBelief进行研发的第二代人工智能学习系统,其命名来源于本身的运行原理。Tensor(张量)意味着N维数组,Flow(流)意味着基于数据流图的计算,TensorFlow为张量从流图的一端流动到另一端计算过程。TensorFlow是将复杂的数据结构传输至人工智能神经网中进行分析和处理过程的系统。

主页 https://www.tensorflow.org/
源码 https://github.com/tensorflow/tensorflow
版本 Guide
发布版本 1.4

TensorFlow Guide目录

1.指南 | Guide
2.教程 | Tutorials
3.配置 | Deploy
4.扩展 | Extend
5.开始 | Get Started
6.表现 | Performance