1. 简单说说 TensorFlow
TensorFlow 是 Google 大脑团队开源的一套机器学习框架,我对这个东西也是刚刚接触,所以更多的信息请你参考官网:https://www.tensorflow.org。
TensorFlow 目前支持的最完善的语言是 Python ,不过对于大型项目,Python 这样的动态语言让代码维护的成本指数级增长。我在国外的一些社区上面看到不少人讨论这个问题,Kotlin 社区中也有人对 Kotlin 未来在这方面的表现给予厚望。
这篇文章就是带大家先去一探究竟,结合现状和我们自己的脑洞,展望一下 Kotlin 将来究竟能如何活跃在机器学习这个领域。
2. 用 Kotlin 基于 TensorFlow 开发的几种可能
2.1 Java Api
毫无疑问,最初想到使用 Kotlin 写这类程序的时候,我首先想到了 TensorFlow 的 Java Api,Java Api,尽管还是 Experimental 阶段,不过这都不叫事儿,Java 生态那么大,将来肯定会支持得比较好的。
WARNING: The API is currently experimental and is not covered by TensorFlow API stability guarantees. See README.md for installation instructions.
基于只要 Java 能干的,Kotlin 一定能干的原则,这条路行得通,也几乎没有什么接入成本,所以我就按下不表啦。
2.2 Native
Kotlin 其实从最初作为 Java 的小弟隐忍至今,已经不是 Java 能罩得住的了。前不久 Kotlin Native 0.4 preview 发布,已经可以用 CLion 尝鲜了,虽然编译时间还是一如既往的长,单步调试也不是那么完美,不过,代码提示已经有了,随便用 C 接口写点儿程序都不再是什么问题。
TensorFlow 提供了一套 C Api,旨在为各种语言提供最基础的支持。换句话说,其他各类语言的 Api 本质上都是从这儿来的,这里当然不会有什么 Session 类,你在 Python 里面看到的无非也是基于这些最基本的 Api 的封装。
那么,是不是说只要 Kotlin 基于这套 Api 做一些封装就可以了呢?答案是必须滴。
3. 开始写点儿代码
3.1 官方的 Demo
好啦,下面我们准备写点儿 Kotlin Native 的代码来庆祝一下这个伟大的想法。等等,我好想在 Kotlin Native 官方的 Sample 里面发现了一个叫 “TensorFlow” 的目录!
https://github.com/JetBrains/kotlin-native/tree/master/samples/tensorflow
TensorFlow demo Small Hello World calculation on the TensorFlow backend, arranging simple operations into a graph and running it on a session. Like other TensorFlow clients (e. g. for Python), this example is built on top of the TensorFlow C API, showing how a TensorFlow client in Kotlin/Native could look like.
有兴趣的话大家可以去看下这个工程,工程采用 Gradle 和 shell 两种方式构建,如果大家之前对 Kotlin Native 有了解,搞懂它是很容易的。
3.2 CMake 版的 Demo
这是一件很纠结的事情。我终于等到了 Kotlin Native 的 IDE 支持,结果它却是用 CMake 构建的。最重要的 JetBrains 也没有推出一款叫 “IntelliK” 的 IDE,而是直接用 CLion,我去,哪怕改名叫 “KLion” 也行啊,我们这些 Kotlin 的粉丝不答应啊。
好吧,其实最重要的是之前 Kotlin Native 的工程都是 Gradle 构建的,想要体验一下 CLion 的螃蟹味,还得改造下构建脚本,也是没谁了。
不过倒也不麻烦,TensorFlow Demo 的代码是现成的,我们只需要改造下构建脚本,这又有何难。我们直接用 CLion 创建一个 Kotlin Native 的工程(选项里面找不到的,Kotlin Native 插件都不下载还来凑什么热闹):
工程创建完,我们就把前面提到的官方 Demo 的代码复制过来,把类做下拆分和整理(当然这也不是必须的啦),如下图:
首先运行
代码语言:javascript复制./downloadTensorflow.sh
把 TensorFlow 的 C Api 依赖下载下来,目标目录是你的 用户目录下面的 .konan/thirdparty/tensorflow,原脚本用的是 1.1,我在我的 Mac 上面编译有个函数无法链接,于是我修改为最新的 1.4 顺利编译通过。当然这些你可以随意修改啦,我们就按照上面的配置继续往下讲。
接着就是修改 CMakeList.txt 这个文件了。
代码语言:javascript复制# 配置 CMake 最低版本,这个默认就好啦,我用的是 CMake 3.9.4
cmake_minimum_required(VERSION 3.8)
# Kotlin Native 构建需要一些脚本配置,下面这行就有点儿类似 Gradle 当中的 buildscript 当中的 classpath 配置
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/KotlinCMakeModule)
# 设置 TensorFlow 的位置
set(TENSORFLOW_HOME $ENV{HOME}/.konan/third-party/tensorflow)
# 定义工程,<工程名> <语言名>
project(TensorflowKonan Kotlin)
# 这个是我们刚刚引入的 KotlinCMakeModule 当中定义的函数,大家有兴趣可以点进去看下它的实现
# 目的与 Gradle 当中的 interop(...){ ... } 一样,配置 C Api
cinterop(
# C Api 兼容模块的名称
NAME tensorflow
# C Api 兼容配置文件路径
DEF_FILE src/main/cinterop/tensorflow.def
# 编译选项,要指定 TensorFlow 的 c_api.h 文件的目录
COMPILER_OPTS "-I ${TENSORFLOW_HOME}/include"
)
# 配置构建目标
konanc_executable(
# 模块名,随便写啦
NAME HelloTensorFlow
# 源码路径,写目录就可以
SOURCES src/main/kotlin
# 我们依赖了前面的配置的叫 tensorflow 的 interop 模块
LIBRARIES tensorflow
# 链接 tensorflow 的库:libtensorflow.so
LINKER_OPTS "-L${TENSORFLOW_HOME}/lib -ltensorflow"
)
哇塞,写这么详细的注释,我都被自己感动了好伐。。
好啦, 由于源代码都是官方 Demo 当中抄来的,我就不贴啦,完整的工程见 Github:https://github.com/enbandari/TensorflowDemo
运行结果:
代码语言:javascript复制Hello, TensorFlow 1.4.0!
3 2 is 5.
这样用 CLion 打开这个工程,还可以享受到自动补全和单步调试之类的待遇(尽管还不是很完美):
4. 小结
Tensorflow 对于每个语言的支持,基本上都源自于对 C Api 的封装,Python 的 Api 好用那完全是因为人家封装的好,所以我们是不是现在立刻马上就应该去了解下,然后去贡献一个 Kotlin 版本的 Api 封装呢?