EMQ X Kuiper— это упрощенное программное обеспечение для анализа/потоковой передачи данных Интернета вещей, которое может работать на различных устройствах Интернета вещей с ограниченными ресурсами.
TensorFlow LiteЭто набор инструментов, которые помогают разработчикам запускать модель Tensorflow на мобильных, встроенных устройствах и устройствах Интернета вещей, что позволяет машинному обучению прогнозировать на устройстве с малой задержкой и меньшей двоичной емкостью.
Интегрируя Kuiper и TensorFlow Lite, пользователи могут анализировать данные в потоках с помощью ИИ, который включает в себя предварительно созданные модели TensorFlow. В этом руководстве мы познакомим вас с созданием подключаемого модуля kuiper для маркировки потоковых изображений (двоичных данных), созданных пограничными устройствами, с помощью предварительно обученной модели распознавания изображений TensorFlow.
условная подготовка
Для запуска интерпретатора TensorFlow Lite нам нужна обученная модель. В этом руководстве не рассказывается, как тренировать и охватывать эту модель, вы можете проверить это, посмотревtflite converter Выучить больше. Мы можем либо обучить новую модель, либо выбрать ее онлайн. В этом уроке мы будем использоватьmattn/go tfliteиз label image Модель. Этот репозиторий создает привязки golang для API tflite C. Мы также будем использовать его для реализации нашего плагина.
Разработать плагины
Чтобы интегрировать Kuiper и TensorFlow Lite, мы разработаем собственный подключаемый модуль функции Kuiper для использования по правилам Kuiper. Например, мы создадимLabelImage
Функция, вход которой — двоичные данные, представляющие изображение, и выход — строка, представляющая метку изображения. Например, если на входном изображении есть павлины,LabelImage(col)
выведет "павлин".
Для разработки функционального плагина нам потребуется:
- Создайте файл запуска плагина. Например, в исходном коде kuiper создайтеplugins/functions/labelImage/labelImage.goдокумент.
- Создать реализациюинтерфейс функции API структура.
- Экспорт структуры.
Ключом к достижению является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
}
Кроме того, нужно обратить внимание на экспорт плагинов. Функция не имеет состояния, поэтому мы будем экспортировать только экземпляр структуры. Все правила, использующие эту функцию, имеют общий экземпляр, чтобы избежать дополнительных затрат на создание экземпляров и загрузку моделей. Пути модели и метки будут указаны во время создания экземпляра.
var LabelImage = labelImage{
modelPath: "labelImage/mobilenet_quant_v1_224.tflite",
labelPath: "labelImage/labels.txt",
}
Проверитьэтот учебникподробные инструкции по созданию плагина Kuiper. видетьlabelImage.goдля полного исходного кода.
Соберите и установите плагин
Чтобы использовать плагин, нам нужно собрать его в среде, где работает Kuiper, а затем установить его в Kuiper.
Установить через готовый zip
Если вы используете образ докера Kuiper на основе Debian с метками 1.1.1 или 1.1.1-slim, мы можем установить готовый плагин labelImage. Например, чтобы установить подключаемый модуль Kuiper 1.1.2 в образе докера emqx/kuiper:1.1.2-slim, предварительно созданный zip-файл находится по адресуWoohoo.Дыхание демона.IO/downloads/can…остальная команда для установки.
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 с официальным образом докера Kuiper, предварительно созданный плагин labelImage не будет работать из-за ограничений плагина golang. Вам нужно собрать плагин вручную. Чтобы вручную создать zip-файл плагина, нужно выполнить 3 шага:
- Создайте API TensorFlowLite C.
- Соберите плагин labelImage.
- Упакуйте плагин вместе со сценарием установки.
Создание API TensorFlowLite C
В репозитории tensorflow есть очень простое руководство по созданию C API.инструкция. Мы будем расширять это шаг за шагом в этом разделе. Обратите внимание, что этот плагин тестируется только на TensorFlow v2.2.0-rc3, поэтому мы будем использовать эту версию. отubuntuВ качестве примера, вот этапы сборки:
-
УстановитьPython 3.
-
будетrequirements.txtСкопируйте в указанное вами место. Установите необходимые библиотеки Python:
pip3 install -r requirements.txt
. требования из соответствующей версии TensorFlowtensorflow/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
. Убедитесь, что оба файла указаны в списке.
- Обновите файл ldconfig
Создайте плагин labelImage
Убедитесь, что вы клонировали репозиторий Kuiper на github. Исходные файлы плагина находятся по адресуplugins/functions/labelImage/labelImage.goсередина. Перед сборкой плагина экспортируйте репозиторий tensorflow и путь к библиотеке сборки.
$ 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-файл, который может использоваться API-интерфейсом установки плагина Kuiper, чтобы его можно было использовать на других машинах (например, в рабочей среде).
Плагины упаковки
будетplugins/functions/labelImageВсе файлы и каталоги в каталоге упакованы в zip-файл вместе со встроенным LabelImage.so. Файловая структура zip-файла должна быть примерно такой:
- etc
- labels.txt
- mobilenet_quant_v1_224.tflite
- lib
- libtensorflowlite.so
- libtensorflowlite_c.so
- install.sh
- LabelImage.so
- tflite.conf
Установите упакованный плагин в целевую систему, напримерУстановить через готовый zipпоказано.
Запустите плагин
После установки плагина мы можем использовать его в наших правилах. Мы создадим правило для получения байтовых данных изображения из темы mqtt и пометим изображение с помощью модели tflite.
определить поток
Потоки определяются через API отдыха Kuiper. Мы создаем поток с именем tfdemo с бинарным форматом и темой tfdemo.
POST http://{{host}}/streams
Content-Type: application/json
{"sql":"CREATE STREAM tfdemo () WITH (DATASOURCE=\"tfdemo\", FORMAT=\"BINARY\")"}
определить правила
Определите правила через API отдыха Kuiper. Мы создадим правило с именем ruleTf. Мы просто читаем изображение из потока tfdemo и запускаем на нем пользовательскую функцию.labelImage. Возвращаемым результатом будет метка изображения, распознанная ИИ.
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.
результат испытаний
Поскольку наше определение правила имеет только одну цель: журнал, результаты будут записаны в файл журнала. мы используем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. Если вам нужно использовать другую модель, просто следуйте предписанным шагам, чтобы создать другую функцию. Обратите внимание, что встроенный API TensorFlow C может использоваться всеми функциями, если они работают в одной среде. Я надеюсь, что эта статья поможет вам лучше использовать ИИ в периферийных вычислениях и позволит ИИ расширить возможности ваших периферийных устройств.
Уведомление об авторских правах: эта статьяEMQОригинал, при перепечатке указывать источник.
Оригинальная ссылка:Woohoo. Дыхание демона. Talent/blog/Run-spec…