树莓派人工智能教程:在 Raspberry Pi 上使用 Go 和 TensorFlow 开发智能应用

这是我在 Raspberry Pi 上建立 libtensorflow 的一个玩法。

步骤0:硬件和软件

所有步骤都是在我的 Raspberry Pi 3 B 模型上进行的:

  • 分配的最小 GPU 内存(16MB)
  • 1GB 的交换内存
  • 外部 USB HDD(作为根分区)

软件版本是:

  • Raspbian(Stretch)/ gcc 6.3.0
  • Tensorflow 1.3.0
  • Protobuf 3.1.0
  • Bazel 0.5.1

在开始之前,我不得不安装依赖关系:

protobuf

$ sudo apt-get install autoconf automake libtool

bazel

$ sudo apt-get install pkg-config zip g++ zlib1g-dev unzip oracle-java8-jdk

步骤1:安装 Protobuf

我 clone protobuf 项目的代码:

$ git clone https://github.com/google/protobuf.git

并开始构建:

$ cd protobuf
$ git checkout v3.1.0
$ ./autogen.sh
$ ./configure
$ make -j 4
$ sudo make install
$ sudo ldconfig

完成这个只需不到一个小时。

我可以看到安装的 protobuf 的版本:

$ protoc --version

libprotoc 3.1.0

步骤2:安装 Bazel

a. 下载

我从这里得到了一个 bazel 的 zip 文件,并解压缩它:

$ wget https://github.com/bazelbuild/bazel/releases/download/0.5.1/bazel-0.5.1-dist.zip
$ unzip -d bazel bazel-0.5.1-dist.zip

b. 编辑 bootstrap 文件

在解压的目录中,我打开了 scripts/bootstrap/compile.sh 文件:

$ cd bazel
$ vi scripts/bootstrap/compile.sh

搜索如下所示的行:

run "${JAVAC}" -classpath "${classpath}" -sourcepath "${sourcepath}" \
      -d "${output}/classes" -source "$JAVA_VERSION" -target "$JAVA_VERSION" \
      -encoding UTF-8 "@${paramfile}"

并在最后一行添加 -J-Xmx500M,以使整行看起来像:

run "${JAVAC}" -classpath "${classpath}" -sourcepath "${sourcepath}" \
      -d "${output}/classes" -source "$JAVA_VERSION" -target "$JAVA_VERSION" \
      -encoding UTF-8 "@${paramfile}" -J-Xmx500M

这是为了扩大 Java 的最大堆大小。

c. 编译

之后,开始构建:

$ chmod u+w ./* -R
$ ./compile.sh

这大概需要一个小时。

d. 安装

编译完成后,我可以在 output 目录中找到已编译的二进制文件。

复制到 /usr/local/bin 目录中:

$ sudo cp output/bazel /usr/local/bin/

步骤3:编译 libtensorflow.so

(以下的过程中,我参考了这个文档

a. 下载

使用下面的代码获取 tensorflow go:

$ go get -d github.com/tensorflow/tensorflow/tensorflow/go

b. 编辑文件

在下载的目录中,我检出了最新的标签,并将 lib64 替换为以下文件中的 lib

$ cd ${GOPATH}/src/github.com/tensorflow/tensorflow
$ git fetch --all --tags --prune
$ git checkout tags/v1.3.0
$ grep -Rl 'lib64' | xargs sed -i 's/lib64/lib/g'

因为树莓派(Raspberry Pi)仍然运行在 32 位的操作系统上,所以他们不得不这样改变。

之后,我在 tensorflow/core/platform/platform.h 中注释了 #define IS_MOBILE_PLATFORM

// Since there's no macro for the Raspberry Pi, assume we're on a mobile
// platform if we're compiling for the ARM CPU.
//#define IS_MOBILE_PLATFORM    // <= commented this line

如果没有注释掉,bazel 将为 iOS 或 Android 等移动平台而不是 Raspberry Pi 构建。

要做到这一点,只需运行:

$ sed -i "s|#define IS_MOBILE_PLATFORM|//#define IS_MOBILE_PLATFORM|g" tensorflow/core/platform/platform.h

最后,是配置和构建 tensorflow 的时候了。

c. 配置和构建

$ ./configure

我不得不在这里回答一些问题,才能继续编译。

然后,我开始构建 libtensorflow.so

$ bazel build -c opt --copt="-mfpu=neon-vfpv4" --copt="-funsafe-math-optimizations" --copt="-ftree-vectorize" --copt="-fomit-frame-pointer" --jobs 1 --local_resources 1024,1.0,1.0 --verbose_failures --genrule_strategy=standalone --spawn_strategy=standalone //tensorflow:libtensorflow.so

在这个过程中,我的 Pi 很多次都没有反应,但是我一直坚持下去。

d. 安装

经过长时间的斗争,(我花了近7个小时!)

我终于得到 libtensorflow.so 文件,它编译在 bazel-bin/tensorflow/ 中。

所以我把它复制到 /usr/local/lib/ 中:

$ sudo cp ./bazel-bin/tensorflow/libtensorflow.so /usr/local/lib/
$ sudo chmod 644 /usr/local/lib/libtensorflow.so
$ sudo ldconfig

全做完了。是时候测试了!

步骤4:Go Test

我运行了一个测试来验证安装:

$ go test github.com/tensorflow/tensorflow/tensorflow/go

然后,我可以看到:

ok      github.com/tensorflow/tensorflow/tensorflow/go  0.350s

Ok, it works!

编辑:正如这个教程说的,我必须在测试之前重新生成操作:

$ go generate github.com/tensorflow/tensorflow/tensorflow/go/op

步骤5: 进一步测试

我想看一个简单的 go 程序运行,所以我写了这个代码:

// sample.go
package main

import (
    "fmt"

    tf "github.com/tensorflow/tensorflow/tensorflow/go"
)

// Sorry - I don't have a good example yet :-P
func main() {
    tensor, _ := tf.NewTensor(int64(42))

    if v, ok := tensor.Value().(int64); ok {
        fmt.Printf("The answer to the life, universe, and everything: %v\n", v)
    }
}

然后运行 run sample.go

The answer to the life, universe, and everything: 42

看到结果?

从现在开始,我可以在树莓派上写出 Tensorflow 应用程序!:-)

步骤98:故障排除

由于 Eigen 问题造成故障

早在 Tensorflow 1.2.0 的时候,我在构建时遇到了这个问题,但在 1.3.0 中仍然没有修复。

所以我必须通过编辑 tensorflow /workspace.bzl 来解决这个问题:

将:

native.new_http_archive(
    name = "eigen_archive",
    urls = [
        "http://mirror.bazel.build/bitbucket.org/eigen/eigen/get/f3a22f35b044.tar.gz",
        "https://bitbucket.org/eigen/eigen/get/f3a22f35b044.tar.gz",
    ],
    sha256 = "ca7beac153d4059c02c8fc59816c82d54ea47fe58365e8aded4082ded0b820c4",
    strip_prefix = "eigen-eigen-f3a22f35b044",
    build_file = str(Label("//third_party:eigen.BUILD")),
)

改成:

native.new_http_archive(
    name = "eigen_archive",
    urls = [
        "http://mirror.bazel.build/bitbucket.org/eigen/eigen/get/d781c1de9834.tar.gz",
        "https://bitbucket.org/eigen/eigen/get/d781c1de9834.tar.gz",
    ],
    sha256 = "a34b208da6ec18fa8da963369e166e4a368612c14d956dd2f9d7072904675d9b",
    strip_prefix = "eigen-eigen-d781c1de9834",
    build_file = str(Label("//third_party:eigen.BUILD")),
)

并从头开始:

$ bazel clean
$ ./configure
$ bazel build -c opt --copt="-mfpu=neon-vfpv4" --copt="-funsafe-math-optimizations" --copt="-ftree-vectorize" --copt="-fomit-frame-pointer" --jobs 1 --local_resources 1024,1.0,1.0 --verbose_failures --genrule_strategy=standalone --spawn_strategy=standalone //tensorflow:libtensorflow.so

...

然后我可以建立它,不会遇到进一步的问题。

我希望这可以在未来的版本上修复。

步骤99:总结

在 Raspberry Pi 上安装 TensorFlow 并不容易。 (这是一个很容易的项目!)

安装 libtensorflow.so 要困难得多,因为构建它需要太多的时间。

但值得尝试; 在 golang 管理 TensorFlow 图表很容易,尤其是那些不喜欢 python 的人来说,就像我一样。

步骤999:如果你需要一个

你没有时间自己构建它,但仍然需要编译的文件?

好,在这里下载

我不能保证是最新的,但是只要有更新版本的tensorflow出来,就会尽量保持最新。

原文链接:https://blog.meinside.pe.kr/TensorFlow-and-Go-on-Raspberry-Pi/

尚未评分
您的评分将帮助我们做出更好的玩法

观光\评论区

Copyright © 2017 玩点什么. All Rights Reserved.