0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

TensorFlow 的功能以及在其他编程语言中的应用

Tensorflowers 来源:fqj 作者:彭涛 2018-04-27 09:38 次阅读

背景

本文档旨在为那些想要用其他编程语言创建或开发 TensorFlow 功能的人员提供指导。本文介绍了 TensorFlow 的功能以及在其他编程语言中实现相同功能应采取的推荐步骤。

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

通过某个编程语言提供 TensorFlow 功能可分为几大类别:

运行预定义图:给定 GraphDef(或 MetaGraphDef)协议消息,能够创建会话,运行查询并获得张量结果。这对于想要在预训练模型上进行推断的移动应用或服务器来说已足够

图构造:每个定义的 TensorFlow 操作至少有一个向图添加操作的函数。理想情况下,这些函数会自动生成,因此在修改操作定义时它们会保持同步

梯度(亦称为自动微分):给定图及输入和输出操作列表,向图添加计算输入相对于输出的偏导数(梯度)的操作。允许针对图中的特定操作自定义梯度函数

函数:定义可在主 GraphDef 中的多个位置调用的子图。在包含在 GraphDef 中的 FunctionDefLibrary 内定义 FunctionDef

控制流:使用用户指定的子图构造 If 和 While 循环。理想情况下,这些控制流支持梯度(参见上文)

神经网络库:一些组件,它们共同支持神经网络模型的创建和训练(可能在分布式设置中)。虽然以其他语言提供此功能会很方便,但目前还没有用除 Python 以外的语言支持此功能的计划。这些库通常是上述功能的封装容器

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

当前状态

应该在 C API 基础之上构建新的语言支持。但是,正如您在下表中所看到的,部分功能尚未在 C 中提供。在 C API 中提供更多功能是一个长期项目。

o4YBAFzCtnqAGsoaAACE6bd57P0296.png

推荐方法

运行预定义的图

语言绑定应该定义以下类:

Graph:表示 TensorFlow 计算的图。包含操作(在客户端语言中由 Operation 表示)并且对应于 C API 中的 TF_Graph。主要在创建新的 Operation 对象和启动 Session 时用作参数。还支持遍历图中的操作 (TF_GraphNextOperation),按名称查询操作 (TF_GraphOperationByName),以及转换为 GraphDef 协议消息或对其进行转换(C API 中的 TF_GraphToGraphDef 和 TF_GraphImportGraphDef)

Operation:表示图中的计算节点。对应于 C API 中的 TF_Operation

Output:表示图中某个操作的一个输出。具有 DataType(最终是一个形状)。可以作为输入参数传递给函数以向图添加操作,或传递给 Session 的 Run() 方法以将该输出提取为张量。对应于 C API 中的 TF_Output

Session:表示 TensorFlow 运行时的特定实例的客户端。它的主要任务是使用 Graph 和一些选项进行构建,然后进行字段调用以对图执行 Run() 操作。对应于 C API 中的 TF_Session

Tensor:表示所有元素都具有相同 DataType 的 N 维(矩形)数组。向 Session 的 Run() 调用提供数据或从中获取数据。对应于 C API 中的 TF_Tensor

DataType:包含受 TensorFlow 支持的所有可能张量类型的枚举。对应于 C API 中的 TF_DataType,在 Python API 中通常称为 dtype

图构造

TensorFlow 有很多操作,并且操作列表不是静态的,因此我们建议生成用于将操作添加到图中的函数,而不是手动逐个编写这些函数(但手动编写一些函数不失为确定生成器应该生成哪些内容的不错方法)。生成函数所需的信息包含在 OpDef 协议消息中。

您可以通过以下几种方法获取已注册操作的 OpDef 列表:

C API 中的 TF_GetAllOpList 会检索所有已注册的 OpDef 协议消息。它可以用于以客户端语言编写生成器。这就要求客户端语言支持协议缓冲区,以便解释 OpDef 消息

C++ 函数 OpRegistry::Global()->GetRegisteredOps() 会返回所有已注册 OpDef(在 tensorflow/core/framework/op.h 中定义)的相同列表。它可以用于以 C++ 编写生成器(对于不支持协议缓冲区的语言特别有用)

该列表的 ASCII 序列化版本通过自动化流程定期检入tensorflow/core/ops/ops.pbtxt

OpDef 会指定以下内容:

驼峰命名法 (CamelCase) 的操作名称。对于生成的函数,请遵循相应语言的惯例。例如,如果该语言使用蛇形命名法 (snake_case),则使用该命名法而不是驼峰命名法表示此操作的函数名称

输入和输出列表。这些内容的类型可以通过引用属性实现多态,如添加操作的输入和输出部分所述

属性列表及其默认值(如果有)。请注意,系统会推断其中一些属性(如果它们由输入确定),一些属性是可选属性(如果它们具有默认值),另一些属性是必需属性(无默认值)

一般操作以及输入、输出和非推断属性的文档

运行时使用的其他一些字段,可以被代码生成器忽略

可以将 OpDef 转换为函数的文本,该函数使用 TF_OperationDescription C 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 的 go get 和适用于 Rust 的 cargo ops)很有用。另一方面,对于某些语言,代码可以从 tensorflow/core/ops/ops.pbtxt 动态生成。

处理常量

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

可选参数

如果语言允许函数具有可选参数(如 Python 中具有默认值的关键字参数),则将它们用于可选属性、操作名称、设备、控制输入等。在某些语言中,可以使用动态作用域设置这些可选参数(如 Python 中的 “with” 块)。如果没有这些功能,库可能会依靠 “编译器模式”,就像在 TensorFlow API 的 C++ 版本中所做的那样。

名称作用域

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

封装容器

可以保留生成的函数专用于某些操作,这样可以改用执行一些额外工作的封装容器函数。这也为支持所生成代码作用域之外的功能提供了一个应急路径。

封装容器的一个用途是支持 SparseTensor 输入和输出。SparseTensor 是一个包含 3 个密集张量(索引、值和形状)的元组。值是向量大小 [n],形状是向量大小 [秩],索引是矩阵大小 [n, 秩]。有一些稀疏操作使用此三元组表示单个稀疏张量。

使用封装容器的另一个原因是用于保留状态的操作。有一些此类操作(例如变量)有几个用于处理该状态的伴随操作。Python API 为这些操作提供了类,其中构造函数会创建操作,并且此类上的方法会向处理该状态的图添加操作。

其他注意事项

最好添加一个关键字列表,用于重命名与语言关键字冲突的操作函数和参数(或其他会导致问题的符号,如生成的代码中引用的库函数或变量的名称)。

用于向图添加 Const 操作的函数通常是封装容器,因为生成的函数通常具有冗余的 DataType 输入。

梯度、函数和控制流

目前,对梯度、函数和控制流操作(“if” 和 “while”)的支持并未在除 Python 以外的其他语言中提供。当 C API 提供必要的支持时,将会更新这方面的功能。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 编程语言
    +关注

    关注

    10

    文章

    1942

    浏览量

    34711
  • 函数
    +关注

    关注

    3

    文章

    4329

    浏览量

    62576

原文标题:采用其他编程语言的 TensorFlow

文章出处:【微信号:tensorflowers,微信公众号:Tensorflowers】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    C语言中的基本数据类型

    C语言是非常重要的一门程序设计语言,学好C语言再去学习其他编程语言将变得很轻松,因为大部分
    发表于 04-26 17:33 2006次阅读
    C<b class='flag-5'>语言中</b>的基本数据类型

    嵌入式C语言中的goto语句详解

    goto语句被称为C语言中的跳转语句。用于无条件跳转到其他标签。它将控制权转移到程序的其他部分。
    发表于 07-19 16:08 3376次阅读
    嵌入式C<b class='flag-5'>语言中</b>的goto语句详解

    C语言中多级指针的概念和使用方法

    多级指针在C语言中是一种特殊的指针类型,它可以指向其他指针的指针。
    发表于 08-16 16:16 1095次阅读

    编程语言中一个奇怪的代码结构

    在C语言和C++等编程语言中,我们常常会遇到一个奇怪的代码结构。
    发表于 11-01 10:24 439次阅读
    <b class='flag-5'>编程</b><b class='flag-5'>语言中</b>一个奇怪的代码结构

    Python与其他编程语言有何不同?

    。  此外,IEEE Spectrum连续第二年将Python评为顶级语言。  Python的快速增长很大程度上归功于其诱人的功能,而其他编程语言中
    发表于 09-16 15:54

    C语言和汇编语言混合编程方法和C语言中断处理方法

    C语言和汇编语言混合编程方法和C语言中断处理方法,new
    发表于 01-06 14:36 36次下载

    c语言中typedef的用法

    C语言是一门通用计算机编程语言,应用广泛。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码
    发表于 11-09 15:23 9232次阅读

    C语言中变量和常量的关系

    AC编程语言中的变量是指定的存储器位置,用户可以在程序执行期间存储相同数据类型的不同值。
    发表于 07-29 14:17 2880次阅读

    热门编程语言中哪个的安全性更高

    编程语言之争,一直以来是开发者社区的热议问题,因为开发者喜欢证明自己所使用的编程语言占据主导地位,尤其是安全性,只不过讨论的过程往往都伴随着双方的愤怒,最后不了了之。那么,你可知在众多
    的头像 发表于 02-06 12:37 3154次阅读

    C语言中驱动法编程的代码案例

    是稳定的。 本文例举的编程实现多为代码片段,但不影响描述的完整性。 本文例举的编程虽然基于C语言,但其编程思想也适用于其他
    的头像 发表于 10-12 09:21 1989次阅读

    go语言中怎么使用HTTP代理

    go语言中怎么使用HTTP代理。
    的头像 发表于 09-01 14:41 2412次阅读

    c语言中逻辑真等价于什么

    在C语言中,逻辑真等价于1。逻辑真可以理解为一个表达式、语句或条件的结果为真,即满足条件。在计算机科学和编程中,逻辑真在控制流语句、循环和条件语句中具有重要的作用。 逻辑真等价于条件为真的情况。在C
    的头像 发表于 11-30 14:10 2147次阅读

    如何解决C语言中的“访问权限冲突”异常?C语言引发异常原因分析

    如何解决C语言中的“访问权限冲突”异常?C语言引发异常原因分析  在C语言中,访问权限冲突异常通常是由于尝试访问未授权的变量、函数或其他数据结构而引起的。这种异常是
    的头像 发表于 01-12 16:03 5650次阅读

    verilog与其他编程语言的接口机制

    Verilog是一种硬件描述语言,用于描述数字电路的行为和结构。与其他编程语言相比,Verilog具有与硬件紧密结合的特点,因此其接口机制也有一些与众不同之处。本文将详细介绍Veril
    的头像 发表于 02-23 10:22 693次阅读

    C语言中的socket编程基础

    Socket编程简介 Socket是一种通信机制,允许程序之间进行通信。在C语言中,socket编程是网络编程的基础。通过使用socket,程序可以发送和接收数据,实现不同计算机之间的
    的头像 发表于 11-01 16:51 304次阅读