您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關如何在Kuiper 中運行TensorFlow Lite 模型,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
EMQ X Kuiper 是一款邊緣輕量級物聯網數據分析/流軟件,可在各種資源受限的物聯網設備上運行。
TensorFlow Lite 是一組幫助開發人員在移動端、嵌入式和物聯網設備上運行 TensorFlow 模型的工具,它使得設備上的機器學習預測具有低延遲和較小的二進制容量。
通過集成 Kuiper 和 TensorFlow Lite,用戶可以通過包含預先構建的 TensorFlow 模型的 AI 分析流中的數據。 在本教程中,我們將引導您構建一個 kuiper 插件,通過預先訓練的圖像識別 TensorFlow 模型,標記邊緣設備生成的流圖片(二進制數據)。
如需運行 TensorFlow Lite 解釋器,我們需要一個經過訓練的模型。本篇教程將不介紹如何訓練和涵蓋這個模型,您可以通過查看 tflite converter 了解詳情。我們既可以訓練一個新的模型,也可以在線選擇一個。在本教程中,我們將使用 mattn/go tflite 的 label image 模型。該 repo 為 tflite C API 創建了 golang 綁定。我們還將使用它來實現我們的插件。
為了集成 Kuiper 和 TensorFlow Lite,我們將開發一個定制的 Kuiper 函數插件,供 Kuiper 規則使用。例如,我們將創建 LabelImage
函數,其輸入是表示圖像的二進制類型數據,輸出是表示圖像標簽的字符串。例如,如果輸入圖像中有孔雀,LabelImage(col)
將輸出“孔雀”。
要開發函數插件,我們需要:
創建插件 go 文件。例如,在 kuiper 源代碼中,創建 plugins/functions/labelImage/labelImage.go 文件。
創建一個實現 api.函數接口 的 struct。
導出 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 中。
如果使用基于 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/kuiper-plugins/v1.1.2/debian/functions/labelImage_amd64.zip。按如下所示運行 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"}
如果您不使用官方的 Kuiper docker 鏡像運行 Kuiper,由于 golang 插件的限制,預構建的 labelImage 插件將不適用。您需要手動構建插件。手動創建插件 zip 文件有3個步驟:
構建 TensorFlowLite C API。
構建 labelImage 插件。
將插件與安裝腳本打包在一起。
有一個來自 tensorflow repo 的關于構建C API的非常簡單的 說明 。 我們將在本節中逐步詳細展開。 請注意,該插件僅針對 TensorFlow v2.2.0-rc3 進行測試,因此我們將以此版本為基礎進行構建。 以 ubuntu 為例,以下是構建步驟:
安裝 Python 3.
將 requirements.txt 復制到您指定位置。 安裝所需的 python 庫:pip3 install -r requirements.txt
。 requirements 來自相應 TensorFlow 版本的 tensorflow/tensorflow/tools/pip_package/setup.py
。
安裝 TensorFlow 的構建工具 Bazel。
克隆 tesorflow repo,通過 git checkout v2.2.0-rc3 -b mybranch
命令切換到所需的分支。
生成目標 .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
安裝 so 文件。
更新 ldconfig 文件 sudo vi / etc / ld.so.conf.d / tflite.conf
。
將路徑 {{tensorflowPath}}/lib
添加到 tflite.conf,然后保存并退出。
運行 ldconfig: sudo ldconfig
。
檢查安裝結果:ldconfig -p | grep libtensorflow
。 確保列出了兩個so文件。
確保已克隆 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.png 和 frog.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 模型有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。