ИИ на границе является одним из самых популярных пограничных сценариев. Реализация этого сценария включает классификацию изображений, обнаружение объектов, тело, лицо и анализ жестов, а также манипуляцию с изображениями. В этом руководстве по архитектуре описывается, как использовать Azure IoT Edge для поддержки этих сценариев.
Вы можете повысить точность ИИ, обновив модель ИИ, но в некоторых сценариях сетевая среда пограничных устройств не хороша. Например, в отрасли ветровой энергии и нефти оборудование может находиться в пустыне или океане.
Двойники модулей IoT Edge используются для реализации динамически загруженной модели ИИ. Модули IoT Edge основаны на Docker. Изображение модуля IoT Edge в среде ИИ обычно имеет размер не менее 1 ГБ, поэтому добавочное обновление модели ИИ важно в сети с узкой пропускной способностью. Это основное внимание в этой статье. Идея заключается в создании модуля искусственного интеллекта IoT Edge, который может загружать модели обнаружения объектов LiteRT (ранее TensorFlow Lite) или Open Neural Network Exchange (ONNX). Вы также можете включить модуль как веб-API, чтобы использовать его для преимущества других приложений или модулей.
Решение, описанное в этой статье, поможет вам следующим образом:
- Включение вывода искусственного интеллекта на пограничных устройствах.
- Свести к минимуму затраты на развертывание и обновление моделей искусственного интеллекта на пограничном сервере. Решение может сэкономить деньги для вас или клиентов, особенно в сетевой среде с узкой пропускной способностью.
- Создайте репозиторий моделей ИИ и управляйте ими в локальном хранилище устройства IoT Edge.
- Достигает почти нулевого простоя, когда пограничное устройство переключает модели искусственного интеллекта.
TensorFlow и LiteRT являются товарным знаком Google Inc. Никакое подтверждение не подразумевается использованием этого знака.
Архитектура
Скачайте файл Visio для этой архитектуры.
Поток данных
- Модель ИИ отправляется в Хранилище BLOB-объектов Azure или веб-службу. Модель может быть предварительно обученной моделью LiteRT или ONNX или моделью, созданной в Машинное обучение Azure. Модуль IoT Edge может получить доступ к этой модели и скачать его на пограничное устройство позже. Если вам нужна более эффективная безопасность, рассмотрите возможность использования подключений к частной конечной точке между хранилищем BLOB-объектов и пограничным устройством.
- Центр Интернета вещей Azure автоматически синхронизирует двойники модулей устройства с сведениями о модели ИИ. Синхронизация возникает, даже если IoT Edge отключена. (В некоторых случаях устройства Интернета вещей подключены к сетям по расписанию, ежедневно или еженедельно для экономии питания или уменьшения сетевого трафика.)
- Модуль загрузчика отслеживает обновления двойников модулей через API. При обнаружении обновления он получает маркер SAS модели машинного обучения, а затем загружает модель ИИ.
- Дополнительные сведения см. в разделе "Создание маркера SAS для контейнера или большого двоичного объекта".
- Свойство ExpiresOn можно использовать для задания даты окончания срока действия ресурсов. Если устройство будет работать в автономном режиме в течение длительного времени, можно продлить срок действия.
- Модуль загрузчика сохраняет модель ИИ в общем локальном хранилище модуля IoT Edge. Необходимо настроить общее локальное хранилище в JSON-файле развертывания IoT Edge.
- Модуль загрузчика загружает модель ИИ из локального хранилища с помощью API LiteRT или ONNX.
- Модуль загрузчика запускает веб-API, который получает двоичную фотографию с помощью запроса POST и возвращает результаты в JSON-файле.
Чтобы обновить модель ИИ, вы можете отправить новую версию в хранилище BLOB-объектов и синхронизировать двойники модуля устройства еще раз для добавочного обновления. Нет необходимости обновлять весь образ модуля IoT Edge.
Подробности сценария
В этом решении модуль IoT Edge используется для скачивания модели ИИ, а затем включения вывода машинного обучения. В этом решении можно использовать предварительно обученные модели LiteRT или ONNX.
LiteRT
Файл
.tflite
— это предварительно обученная модель ИИ. Вы можете скачать один из TensorFlow.org. Это универсальная модель ИИ, которую можно использовать в кроссплатформенных приложениях, таких как iOS и Android. LiteRT поддерживает модели из TensorFlow, PyTorch, JAX и Keras. Дополнительные сведения о метаданных и связанных полях (например,labels.txt
) см. в разделе "Чтение метаданных из моделей".Модель обнаружения объектов обучена обнаруживать наличие и расположение нескольких классов объектов. Например, модель может быть обучена изображениями, содержащими различные куски фруктов, а также метку, указывающую класс фруктов, которые они представляют (например, apple) и данные, указывающие, где каждый объект отображается на изображении.
При предоставлении изображения модели выводится список объектов, обнаруженных им, расположение ограничивающего прямоугольника для каждого объекта и оценка, указывающая достоверность обнаружения.
Если вы хотите создать или настроить модель ИИ, см. статью LiteRT Model Maker.
Вы можете получить более бесплатные предварительно обученные модели обнаружения с различными характеристиками задержки и точности в зоопарке обнаружения. Каждая модель использует входные и выходные сигнатуры, показанные в следующих примерах кода.
ONNX
ONNX — это открытый стандартный формат для представления моделей машинного обучения. Она поддерживается сообществом партнеров, которые реализовали его во многих платформах и средствах.
- ONNX поддерживает средства для создания и развертывания моделей и выполнения других задач. Дополнительные сведения см. в разделе "Поддерживаемые средства ONNX".
- Среду выполнения ONNX можно использовать для запуска предварительно обученных моделей ONNX. Сведения о предварительно обученных моделях см . в зоопарке моделей ONNX.
- Для этого сценария можно использовать модель обнаружения объектов и сегментации изображений: Tiny YOLOv3.
Сообщество ONNX предоставляет средства для создания и развертывания модели глубокого обучения.
Скачивание обученных моделей ИИ
Чтобы скачать обученные модели ИИ, рекомендуется использовать двойники устройств для получения уведомлений о готовности новой модели. Даже если устройство находится в автономном режиме, сообщение может быть кэшировано в Центр Интернета вещей до тех пор, пока пограничное устройство не вернется в сеть. Сообщение будет синхронизировано автоматически.
Ниже приведен пример кода Python, который регистрирует уведомления для двойников устройств, а затем загружает модель ИИ в ZIP-файл. Он также выполняет дальнейшие операции с скачанным файлом.
Код выполняет следующие задачи:
- Получение уведомления двойников устройства. Уведомление включает имя файла, адрес скачивания файла и маркер проверки подлинности MD5. (В имени файла можно включить сведения о версии, например 1.0.)
- Скачайте модель ИИ в виде ZIP-файла в локальное хранилище.
- При необходимости выполните контрольную сумму MD5. Проверка MD5 помогает предотвратить изменение ZIP-файлов во время сетевой передачи.
- Распакуйте ZIP-файл и сохраните его локально.
- Отправьте уведомление в Центр Интернета вещей или сообщение маршрутизации, чтобы сообщить о готовности новой модели ИИ.
# define behavior for receiving a twin patch
async def twin_patch_handler(patch):
try:
print( "######## The data in the desired properties patch was: %s" % patch)
if "FileName" in patch:
FileName = patch["FileName"]
if "DownloadUrl" in patch:
DownloadUrl = patch["DownloadUrl"]
if "ContentMD5" in patch:
ContentMD5 = patch["ContentMD5"]
FilePath = "/iotedge/storage/" + FileName
# download AI model
r = requests.get(DownloadUrl)
print ("######## download AI Model Succeeded.")
ffw = open(FilePath, 'wb')
ffw.write(r.content)
ffw.close()
print ("######## AI Model File: " + FilePath)
# MD5 checksum
md5str = content_encoding(FilePath)
if md5str == ContentMD5:
print ( "######## New AI Model MD5 checksum succeeded")
# decompressing the ZIP file
unZipSrc = FilePath
targeDir = "/iotedge/storage/"
filenamenoext = get_filename_and_ext(unZipSrc)[0]
targeDir = targeDir + filenamenoext
unzip_file(unZipSrc,targeDir)
# ONNX
local_model_path = targeDir + "/tiny-yolov3-11.onnx"
local_labelmap_path = targeDir + "/coco_classes.txt"
# LiteRT
# local_model_path = targeDir + "/ssd_mobilenet_v1_1_metadata_1.tflite"
# local_labelmap_path = targeDir + "/labelmap.txt"
# message to module
if client is not None:
print ( "######## Send AI Model Info AS Routing Message")
data = "{\"local_model_path\": \"%s\",\"local_labelmap_path\": \"%s\"}" % (filenamenoext+"/tiny-yolov3-11.onnx", filenamenoext+"/coco_classes.txt")
await client.send_message_to_output(data, "DLModelOutput")
# update the reported properties
reported_properties = {"LatestAIModelFileName": FileName }
print("######## Setting reported LatestAIModelName to {}".format(reported_properties["LatestAIModelFileName"]))
await client.patch_twin_reported_properties(reported_properties)
else:
print ( "######## New AI Model MD5 checksum failed")
except Exception as ex:
print ( "Unexpected error in twin_patch_handler: %s" % ex )
Вывод
После скачивания модели ИИ следующий шаг — использовать модель на пограничном устройстве. Вы можете динамически загружать модель и выполнять обнаружение объектов на пограничных устройствах. В следующем примере кода показано, как использовать модель искусственного интеллекта LiteRT для обнаружения объектов на пограничных устройствах.
Код выполняет следующие задачи:
- Динамически загружайте модель искусственного интеллекта LiteRT.
- Выполнение стандартизации изображений.
- Обнаружение объектов.
- Оценки обнаружения вычислений.
class InferenceProcedure():
def detect_object(self, imgBytes):
results = []
try:
model_full_path = AI_Model_Path.Get_Model_Path()
if(model_full_path == ""):
raise Exception ("PLEASE SET AI MODEL FIRST")
if '.tflite' in model_full_path:
interpreter = tf.lite.Interpreter(model_path=model_full_path)
interpreter.allocate_tensors()
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()
input_shape = input_details[0]['shape']
# bytes to numpy.ndarray
im_arr = np.frombuffer(imgBytes, dtype=np.uint8)
img = cv2.imdecode(im_arr, flags=cv2.IMREAD_COLOR)
im_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
im_rgb = cv2.resize(im_rgb, (input_shape[1], input_shape[2]))
input_data = np.expand_dims(im_rgb, axis=0)
interpreter.set_tensor(input_details[0]['index'], input_data)
interpreter.invoke()
output_data = interpreter.get_tensor(output_details[0]['index'])
detection_boxes = interpreter.get_tensor(output_details[0]['index'])
detection_classes = interpreter.get_tensor(output_details[1]['index'])
detection_scores = interpreter.get_tensor(output_details[2]['index'])
num_boxes = interpreter.get_tensor(output_details[3]['index'])
label_names = [line.rstrip('\n') for line in open(AI_Model_Path.Get_Labelmap_Path())]
label_names = np.array(label_names)
new_label_names = list(filter(lambda x : x != '???', label_names))
for i in range(int(num_boxes[0])):
if detection_scores[0, i] > .5:
class_id = int(detection_classes[0, i])
class_name = new_label_names[class_id]
# top, left, bottom, right
results_json = "{'Class': '%s','Score': '%s','Location': '%s'}" % (class_name, detection_scores[0, i],detection_boxes[0, i])
results.append(results_json)
print(results_json)
except Exception as e:
print ( "detect_object unexpected error %s " % e )
raise
# return results
return json.dumps(results)
Ниже приведена версия ONNX предыдущего кода. Действия в основном одинаковы. Единственное различие заключается в том, как обрабатывается оценка обнаружения, так как Labelmap
выходные параметры модели отличаются.
class InferenceProcedure():
def letterbox_image(self, image, size):
'''resize image with unchanged aspect ratio using padding'''
iw, ih = image.size
w, h = size
scale = min(w/iw, h/ih)
nw = int(iw*scale)
nh = int(ih*scale)
image = image.resize((nw,nh), Image.BICUBIC)
new_image = Image.new('RGB', size, (128,128,128))
new_image.paste(image, ((w-nw)//2, (h-nh)//2))
return new_image
def preprocess(self, img):
model_image_size = (416, 416)
boxed_image = self.letterbox_image(img, tuple(reversed(model_image_size)))
image_data = np.array(boxed_image, dtype='float32')
image_data /= 255.
image_data = np.transpose(image_data, [2, 0, 1])
image_data = np.expand_dims(image_data, 0)
return image_data
def detect_object(self, imgBytes):
results = []
try:
model_full_path = AI_Model_Path.Get_Model_Path()
if(model_full_path == ""):
raise Exception ("PLEASE SET AI MODEL FIRST")
if '.onnx' in model_full_path:
# input
image_data = self.preprocess(imgBytes)
image_size = np.array([imgBytes.size[1], imgBytes.size[0]], dtype=np.float32).reshape(1, 2)
labels_file = open(AI_Model_Path.Get_Labelmap_Path())
labels = labels_file.read().split("\n")
# Loading ONNX model
print("loading Tiny YOLO...")
start_time = time.time()
sess = rt.InferenceSession(model_full_path)
print("loaded after", time.time() - start_time, "s")
input_name00 = sess.get_inputs()[0].name
input_name01 = sess.get_inputs()[1].name
pred = sess.run(None, {input_name00: image_data,input_name01:image_size})
boxes = pred[0]
scores = pred[1]
indices = pred[2]
results = []
out_boxes, out_scores, out_classes = [], [], []
for idx_ in indices[0]:
out_classes.append(idx_[1])
out_scores.append(scores[tuple(idx_)])
idx_1 = (idx_[0], idx_[2])
out_boxes.append(boxes[idx_1])
results_json = "{'Class': '%s','Score': '%s','Location': '%s'}" % (labels[idx_[1]], scores[tuple(idx_)],boxes[idx_1])
results.append(results_json)
print(results_json)
except Exception as e:
print ( "detect_object unexpected error %s " % e )
raise
# return results
return json.dumps(results)
Если устройство IoT edge включает предыдущий код и функции, пограничное устройство имеет обнаружение объектов ИИ и поддерживает динамическое обновление моделей ИИ. Если вы хотите, чтобы пограничный модуль предоставлял функции искусственного интеллекта другим приложениям или модулям через веб-API, вы можете создать веб-API в модуле.
Платформа Flask — это один из примеров инструмента, который можно использовать для быстрого создания API. Изображения можно получать в виде двоичных данных, использовать модель ИИ для обнаружения, а затем возвращать результаты в формате JSON. Дополнительные сведения см. в руководстве flask: Flask в Visual Studio Code.
Соавторы
Эта статья поддерживается корпорацией Майкрософт. Первоначально он был написан следующими участниками.
Автор субъекта:
- Бо Ван | Старший инженер по программному обеспечению
Другой участник:
- Фредди Айала | Архитектор облачных решений
Чтобы просмотреть недоступные профили LinkedIn, войдите в LinkedIn.
Следующие шаги
- Общие сведения о двойниках модулей и их использование в Центре Интернета вещей
- Сведения о развертывании модулей и настройке маршрутов в IoT Edge
- Предоставление модулям доступа к локальному хранилищу устройства
- Общие сведения об автоматическом развертывании IoT Edge для отдельных устройств или в масштабе
- Открытие exchange нейронной сети
- Учебники ONNX
- Развертывание модели машинного обучения на устройствах Интернета вещей и пограничных устройствах