深度学习领域目前主流的语言是Python,但一些深度学习框架也推出了其他语言的版本或适配方法。以谷歌(Google)公司著名的TensorFlow平台为例,虽然训练神经网络的过程还需要使用Python语言,但对于已经训练好的神经网络模型,已经可以在Java、Javascript、C++、Go等语言中调用,以便利用这些模型进行计算并获取神经网络对于需解决问题的预测结果。下面我们来给出一个具体的实例帮助理解这种方式,实例将使用Go语言(Golang)。
1. 搭建Go语言调用TensorFlow模型所需的环境
TensorFlow目前仅支持在Linux和MacOS下由Go语言调用,因此,如果想在Windows下使用,建议在Windows 10上安装Ubuntu子系统(Ubuntu是Linux系统中的一种,Windows 10中支持以子系统的方式安装Ubuntu,可以在Microsoft Store中搜索安装,是免费的),或者使用VirtualBox等免费的虚拟机软件安装Linux的虚拟机。本节中演示的将是在Ubuntu系统中搭建Go语言调用TensorFlow模型所需的环境以及具体调用的过程与方法,其他操作系统中方法是类似的,命令名称可能略有不同。
首先,虽然是在Go语言中调用TensorFlow模型,但仍然需要先安装TensorFlow框架,而由于TensorFlow框架是基于Python的,所以还是要先安装Python。TensorFlow需要Python 3.x系列版本,目前最好使用3.5或3.6大版本号下最新小版本,例如我们示例中使用的是Ubuntu 16.04版本,最新只能安装到Python 3.5.2版本。更新Python版本可以用下面的命令(后面所有示例都是用root账户来进行的,如果使用其他账户,需要在命令前加上sudo来获取超级用户权限):
apt-get upgrade python3
或直接:
apt upgrade python3
之后用下面的命令安装TensorFlow:
pip3 install -U TensorFlow
安装完毕之后,可以启动python3的交互式界面,然后输入下面的命令来检查是否正确安装了TensorFlow。
import tensorflow
print(tensorflow.__version__)
如果看到类似下图的输出结果,就说明安装正常。
然后要保证Go语言在该系统中也正常安装并设置好了GOPATH环境变量。之后需要再安装TensorFlow的C语言API库,这个库用于与其他语言(包括Go语言)的绑定。从官网“Install”页面的C语言下载页面下载对应操作系统的最新版本,例如我们下载的是名为libtensorflow-cpu-linux-x86_64-1.12.0.tar.gz的文件。用下面的命令将其安装到/usr/local目录:
tar -xzf libtensorflow-cpu-linux-x86_64-1.12.0.tar.gz -C /usr/local
再运行ldconfig命令配置好链接器,然后可以用下面的C语言程序验证是否正确安装了TensorFlow的C语言库。
#include <stdio.h>
#include <tensorflow/c/c_api.h>
int main() {
printf("Hello from TensorFlow C library version %s\n", TF_Version());
return 0;
}
将这段程序保存为名为hello_tf.c或其他任何名字的C语言源代码文件,然后用g++或gcc命令来编译:
编译时如果出现错误,要加上 -ltensorflow参数就可以编译通过,运行编译出来的hello_tf可执行文件看到如上图的输出,就说明安装正确了。
再往后就可以正式开始安装所需的Go语言第三方包,需要安装两个:
go get -v github.com/tensorflow/tensorflow/tensorflow/go
go get -v github.com/galeone/tfgo
安装成功后就完成了所有的环境搭建,可以正式开始测试了。
2. 在Python中训练TensorFlow模型并保存
为了演示需要,我们先在Python中训练一个基于神经网络的深度学习模型用于测试。
import tensorflow as tf
import random
import os
import sys
import shutil
random.seed()
x = tf.placeholder(tf.float32, name="x")
yTrain = tf.placeholder(tf.float32)
w1 = tf.Variable(tf.random_normal([4, 32], mean=0.5, stddev=0.1), dtype=tf.float32)
b1 = tf.Variable(0, dtype=tf.float32)
xr = tf.reshape(x, [1, 4])
n1 = tf.nn.tanh(tf.matmul(xr, w1) + b1)
w2 = tf.Variable(tf.random_normal([32, 32], mean=0.5, stddev=0.1), dtype=tf.float32)
b2 = tf.Variable(0, dtype=tf.float32)
n2 = tf.nn.sigmoid(tf.matmul(n1, w2) + b2)
w3 = tf.Variable(tf.random_normal([32, 2], mean=0.5, stddev=0.1), dtype=tf.float32)
b3 = tf.Variable(0, dtype=tf.float32)
n3 = tf.matmul(n2, w3) + b3
y = tf.nn.softmax(tf.reshape(n3, [2]), name="y")
loss = tf.reduce_mean(tf.square(y - yTrain))
optimizer = tf.train.RMSPropOptimizer(0.01)
train = optimizer.minimize(loss)
sess = tf.Session()
sess.run(tf.global_variables_initializer())
lossSum = 0.0
for i in range(10000):
xDataRandom = [int(random.random() * 10), int(random.random() * 10), int(random.random() * 10), int(random.random() * 10)]
if xDataRandom[2] % 2 == 0:
yTrainDataRandom = [0, 1]
else:
yTrainDataRandom = [1, 0]
result = sess.run([train, x, yTrain, y, loss], feed_dict={x: xDataRandom, yTrain: yTrainDataRandom})
lossSum = lossSum + float(result[len(result) - 1])
print("i: %d, loss: %10.10f, avgLoss: %10.10f" % (i, float(result[len(result) - 1]), lossSum / (i + 1)))
if os.path.exists("export"):
shutil.rmtree("export")
print("Saving model...")
builder = tf.saved_model.builder.SavedModelBuilder("export")
builder.add_meta_graph_and_variables(sess, ["tag"])
builder.save()
代码 18‑1 testtf/savemodel.py
代码 18‑1是在Python语言中使用TensorFlow框架来训练一个神经网络的示例代码,该神经网络主要用于根据身份证的后四位数字推断持有者的性别。具体神经网络的实现我们在本书中不做过多解释,仅需要了解运行这段Python程序后将在运行目录下新建一个export目录,其中保存了该神经网络的训练结果,下面我们介绍如何在Go语言中调用该神经网络来进行预测。所谓的“预测”,指的是神经网络根据大量数据和对应的正确结果训练出一套算法,当再遇到新的数据时就可以根据该算法来计算出结果,这就是预测。
3. 使用Go语言调用TensorFlow模型进行预测
首先要获得TensorFlow中保存的神经网络模型,本例中就是export目录及其中所有的文件。然后用下面的Go语言程序就可以进行载入、调用和预测。
package main
import (
"fmt"
tg "github.com/galeone/tfgo"
tf "github.com/tensorflow/tensorflow/tensorflow/go"
)
func main() {
model := tg.LoadModel("/root/py/export", []string{"tag"}, nil)
inputArray := [][]float32{{1, 2, 3, 4}}
fmt.Printf("input: %v\n", inputArray)
fakeInput, _ := tf.NewTensor(inputArray)
results := model.Exec([]tf.Output{
model.Op("y", 0),
}, map[tf.Output]*tf.Tensor{
model.Op("x", 0): fakeInput,
})
predictions := results[0].Value().([]float32)
fmt.Printf("predict: %v\n", predictions)
}
代码 18‑2 testtf/testtf.go
代码 18‑2中,从“/root/py/export”目录载入了我们之前保存的TensorFlow模型(注意参数中的tag是在保存模型时指定的标记,两边必须一致才能正确载入模型),然后传入正确形式的输入参数(本例中是一个二维数组,但只有第一维有一个四个数字组成的向量)后调用model.Exec函数即可运行该神经网络模型获得预测的值。代码 18‑2的运行结果是:
root@txVPC02:~/goprjs/src/testtf# go run testtf.go
2019-03-06 23:50:37.066663: I tensorflow/cc/saved_model/reader.cc:31] Reading SavedModel from: /root/py/export
2019-03-06 23:50:37.101462: I tensorflow/cc/saved_model/reader.cc:54] Reading meta graph with tags { tag }
2019-03-06 23:50:37.102592: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to
use: SSE4.1 SSE4.2 AVX AVX2 FMA
2019-03-06 23:50:37.258481: I tensorflow/cc/saved_model/loader.cc:162] Restoring SavedModel bundle.
2019-03-06 23:50:37.771518: I tensorflow/cc/saved_model/loader.cc:138] Running MainOp with key legacy_init_op on SavedModel bundle.
2019-03-06 23:50:37.771576: I tensorflow/cc/saved_model/loader.cc:259] SavedModel load for tags { tag }; Status: success. Took 704924 microseconds.
input: [[1 2 3 4]]
predict: [0.5751267 0.42487338]
可以看到,程序成功根据输入数据获得了预测值(我们暂时不用去管预测值的准确程度,因为训练该模型时的训练轮数并不够),说明Go语言中调用神经网络模型进行预测是成功的。
有疑问加站长微信联系(非本文作者)