关于人工智能:AI-赋能边缘计算在-Kuiper-中运行-TensorFlow-Lite-模型

3次阅读

共计 5332 个字符,预计需要花费 14 分钟才能阅读完成。

EMQ X Kuiper 是一款边缘轻量级物联网数据分析 / 流软件,可在各种资源受限的物联网设施上运行。

TensorFlow Lite 是一组帮忙开发人员在挪动端、嵌入式和物联网设施上运行 TensorFlow 模型的工具,它使得设施上的机器学习预测具备低提早和较小的二进制容量。

通过集成 Kuiper 和 TensorFlow Lite,用户能够通过蕴含事后构建的 TensorFlow 模型的 AI 剖析流中的数据。在本教程中,咱们将疏导您构建一个 kuiper 插件,通过事后训练的图像识别 TensorFlow 模型,标记边缘设施生成的流图片(二进制数据)。

条件筹备

如需运行 TensorFlow Lite 解释器,咱们须要一个经过训练的模型。本篇教程将不介绍如何训练和涵盖这个模型,您能够通过查看 tflite converter 理解详情。咱们既能够训练一个新的模型,也能够在线抉择一个。在本教程中,咱们将应用 mattn/go tflitelabel image 模型。该 repo 为 tflite C API 创立了 golang 绑定。咱们还将应用它来实现咱们的插件。

开发插件

为了集成 Kuiper 和 TensorFlow Lite,咱们将开发一个定制的 Kuiper 函数插件,供 Kuiper 规定应用。例如,咱们将创立 LabelImage 函数,其输出是示意图像的二进制类型数据,输入是示意图像标签的字符串。例如,如果输出图像中有孔雀,LabelImage(col) 将输入“孔雀”。

要开发函数插件,咱们须要:

  1. 创立插件 go 文件。例如,在 kuiper 源代码中,创立 plugins/functions/labelImage/labelImage.go 文件。
  2. 创立一个实现 api. 函数接口 的 struct。
  3. 导出 struct。

实现的要害是 Exec 函数。伪代码如下:

func (f *labelImage) Exec(args []interface{}, ctx api.FunctionContext) (interface{}, bool) {
    
    //... 初始化和验证

    // 解码输出图像
    img, _, err := image.Decode(bytes.NewReader(arg[0]))
    if err != nil {return err, false}
    var outerErr error
    f.once.Do(func() {// 加载标签、tflite 模型并初始化 tflite 解释器})

        // 对输出图像运行解释器
        // 返回可能性最大的标签
         return result, true
}

此外还须要留神插件的导出。该函数是无状态的,因而咱们将仅导出一个 struct 实例。所有应用此函数的规定都会共享一个实例,以防止创立实例和加载模型的开销。模型和标签门路将在实例化时指定。

var LabelImage = labelImage{
    modelPath: "labelImage/mobilenet_quant_v1_224.tflite",
    labelPath: "labelImage/labels.txt",
}

查阅 本教程 以取得创立 Kuiper 插件的具体步骤。请参阅 labelImage.go 以获取残缺的源代码。

构建并装置插件

要应用该插件,咱们须要在运行 Kuiper 的环境中对其进行构建,而后将其装置在 Kuiper 中。

通过预构建的 zip 装置

如果应用基于 debian 的带有 1.1.1 或 1.1.1-slim 标签的 Kuiper docker 镜像,咱们能够装置预构建的 labelImage 插件。例如,要在 docker image emqx/kuiper:1.1.2-slim 中装置 Kuiper 1.1.2 插件,则预构建的 zip 文件位于 https://www.emqx.io/downloads…。按如下所示运行 rest 命令以进行装置。

POST http://{{kuiperHost:kuiperRestPort}}/plugins/functions
Content-Type: application/json

{"name":"labelImage", "file": "https://www.emqx.io/downloads/kuiper-plugins/v1.1.2/debian/functions/labelImage_amd64.zip"}

手动构建

  1. 如果您不应用官网的 Kuiper docker 镜像运行 Kuiper,因为 golang 插件的限度,预构建的 labelImage 插件将不实用。您须要手动构建插件。手动创立插件 zip 文件有 3 个步骤:

    1. 构建 TensorFlowLite C API。
    2. 构建 labelImage 插件。
    3. 将插件与装置脚本打包在一起。

构建 TensorFlowLite C API

有一个来自 tensorflow repo 的对于构建 C API 的非常简单的 阐明。咱们将在本节中逐渐具体开展。请留神,该插件仅针对 TensorFlow v2.2.0-rc3 进行测试,因而咱们将以此版本为根底进行构建。以 ubuntu 为例,以下是构建步骤:

  1. 装置 Python 3.
  2. 将 requirements.txt 复制到您指定地位。装置所需的 python 库:pip3 install -r requirements.txt。requirements 来自相应 TensorFlow 版本的 tensorflow/tensorflow/tools/pip_package/setup.py
  3. 装置 TensorFlow 的构建工具 Bazel。
  4. 克隆 tesorflow repo,通过 git checkout v2.2.0-rc3 -b mybranch 命令切换到所需的分支。
  5. 生成指标 .so 文件,输入将位于 ./bazel-bin 中。将两个 so 文件复制到 tensorflow/lib 文件夹中。

    $ cd $tensorflowSrc
    $ bazel build --config monolithic -c opt //tensorflow/lite:libtensorflowlite.so
    $ bazel build --config monolithic -c opt //tensorflow/lite/c:libtensorflowlite_c.so
    $ mkdir lib
    $ cp bazel-bin/tensorflow/lite/libtensorflowlite.so lib
    $ cp bazel-bin/tensorflow/lite/c/libtensorflowlite_c.so lib
  6. 装置 so 文件。

    1. 更新 ldconfig 文件 sudo vi / etc / ld.so.conf.d / tflite.conf
    2. 将门路 {{tensorflowPath}}/lib 增加到 tflite.conf,而后保留并退出。
    3. 运行 ldconfig: sudo ldconfig
    4. 查看装置后果:ldconfig -p | grep libtensorflow。确保列出了两个 so 文件。

构建 labelImage 插件

确保已克隆 Kuiper github repo。插件源文件位于 plugins/functions/labelImage/labelImage.go 中。在构建插件之前,导出 tensorflow repo 和构建库的门路。

$ cd {{kuiperRepoPath}}
$ export CGO_CFLAGS=-I/root/tensorflow
$ export CGO_LDFLAGS=-L/root/tensorflow/lib
$ go build -trimpath --buildmode=plugin -o plugins/functions/LabelImage.so plugins/functions/labelImage/*.go

通过这些命令,插件将构建到 plugins/functions/LabelImage.so 中。出于开发目标,您能够重新启动 Kuiper 以主动加载此插件并进行测试。测试实现后,咱们应该将其打包为一个 zip 文件,该文件可供 Kuiper 插件装置 API 应用,以便能够在其余计算机(例如生产环境)中应用。

打包插件

plugins/functions/labelImage 目录中的所有文件和目录与构建的 LabelImage.so 一起打包到一个 zip 文件中。zip 文件的文件构造应相似于:

  • etc

    • labels.txt
    • mobilenet_quant_v1_224.tflite
  • lib

    • libtensorflowlite.so
    • libtensorflowlite_c.so
  • install.sh
  • LabelImage.so
  • tflite.conf

将打包的插件装置到指标零碎,如 通过预构建 zip 装置 所示。

运行插件

插件装置后,咱们就能够在规定中应用它了。咱们将创立一个规定用于接管来自 mqtt 主题的图像字节数据,并通过 tflite 模型标记该图像。

定义流

通过 Kuiper rest API 定义流。咱们创立一个名为 tfdemo 的流,其格局为二进制,主题为 tfdemo。

POST http://{{host}}/streams
Content-Type: application/json

{"sql":"CREATE STREAM tfdemo () WITH (DATASOURCE=\"tfdemo\", FORMAT=\"BINARY\")"}

定义规定

通过 Kuiper rest API 定义规定。咱们将创立一个名为 ruleTf 的规定。咱们只是从 tfdemo 流中读取图像,而后对其运行自定义函数 labelImage。返回后果将是 AI 辨认的图像的标签。

POST http://{{host}}/rules
Content-Type: application/json

{
  "id": "ruleTf",
  "sql": "SELECT labelImage(self) FROM tfdemo",
  "actions": [
    {"log": {}
    }
  ]
}

输出数据

在这里,咱们创立了一个 go 程序,用于将图像数据发送到 tfdemo 主题以便由规定进行解决。

package main

import (
    "fmt"
    mqtt "github.com/eclipse/paho.mqtt.golang"
    "io/ioutil"
    "time"
)

func main(){
    const TOPIC = "tfdemo"

    images := []string{
        "peacock.png",
        "frog.jpg",
        // 其余你须要的图像
    }
    opts := mqtt.NewClientOptions().AddBroker("tcp://yourownhost:1883")
    client := mqtt.NewClient(opts)
    if token := client.Connect(); token.Wait() && token.Error() != nil {panic(token.Error())
    }
    for _, image := range images {fmt.Println("Publishing" + image);
        payload, err := ioutil.ReadFile(image)
        if err != nil{fmt.Println(err)
            continue
        }
        if token := client.Publish(TOPIC, 0, false, payload); token.Wait() && token.Error() != nil {fmt.Println(token.Error())
        } else {fmt.Println("Published" + image);
        }
        time.Sleep(1 * time.Second)
    }
    client.Disconnect(0)
}

运行 pub.go,它将开始将图像输出 tfdemo 主题。

查看后果

因为咱们的规定定义只有一个指标:log,所以后果将被写入日志文件。咱们用 peacock.pngfrog.png 两个图像填充流。查看日志文件,咱们会发现:

time="2021-02-05 16:23:29" level=info msg="sink result for rule ruleTf: [{\"labelImage\":\"peacock\"}]" file="sinks/log_sink.go:16" rule=ruleTf
time="2021-02-05 16:23:30" level=info msg="sink result for rule ruleTf: [{\"labelImage\":\"bullfrog\"}]" file="sinks/log_sink.go:16" rule=ruleTf

图像标记正确。

论断

通过本篇教程,您能够构建自定义的 Kuiper 插件,以应用事后训练好的 TensorFlow Lite 模型。如果须要应用其余模型,则只需依照规定步骤创立另一个函数即可。请留神,如果在同一环境中运行,构建的 TensorFlow C API 能够在所有函数之间共享。心愿本文能帮忙您更好地在边缘计算中利用 AI,让 AI 为您的边缘设施赋能。

版权申明:本文为 EMQ 原创,转载请注明出处。

原文链接:https://www.emqx.cn/blog/run-tensorflow-lite-model-with-kuiper-function-plugin

正文完
 0