Fevereiro de 2019

Volume 34 – Número 2

[Machine Learning]

Machine Learning na borda: integração do Azure ML e Azure IoT Edge

Por Ted Way | Fevereiro de 2019

A borda é definida como qualquer plataforma de computação que não seja a nuvem. Sua variação pode incluir o Azure Stack (um cluster de computadores que atua como mini-Azure), um poderoso servidor de gateway ou um dispositivo menor, como um Raspberry Pi ou um sensor. Atualmente, até mesmo refrigeradores e outros eletrodomésticos têm poder de processamento suficiente para serem considerados dispositivos de borda. O desafio é como aplicar a IA (inteligência artificial) e o ML (aprendizado de máquina) em dados que não conseguem chegar à nuvem, independentemente de o motivo ser a soberania de dados, privacidade, largura de banda ou outros problemas.

James McCaffrey escreveu um ótimo artigo — “Machine Learning com dispositivos de IoT na borda” (msdn.com/magazine/mt847186) — na edição de julho de 2018 da MSDN Magazine sobre o treinamento de modelos de ML e o uso da ELL (Biblioteca de Aprendizado Integrado) da Microsoft para implantar um modelo otimizado para dispositivos de borda pequenos. Neste artigo, vamos nos concentrar em ferramentas e serviços corporativos para treinar seu modelo, gerenciá-lo e colocá-lo em contêineres com o Azure Machine Learning. Com o Azure IoT Edge, você aprenderá a configurar um pipeline de dados utilizando um modelo e a implantá-lo no dispositivo de borda. Vamos ver um exemplo onde o serviço de Visão Personalizada pode ser usado para treinar um modelo que é implantado com o Azure IoT Edge. As iterações do modelo podem ser registradas com o Azure ML.

Cenário dos leopardos-das-neves

A Snow Leopard Trust (snowleopard.org) se dedica a “entender melhor o ameaçado leopardo-das-neves e proteger o felino em parceria com as comunidades que vivem em seu habitat”. Para isso, câmeras são espalhadas em mais de 500 quilômetros quadrados para monitorar quais leopardos-das-neves estão na área. Elas são instaladas e, após um determinado tempo, os dados delas são coletados. Essas câmeras são acionadas por movimento, o que pode levar a algumas surpresas, como quando, alguns anos atrás, alguns pesquisadores revelaram um rolo de filme e tudo que tinha nele era uma árvore balançando com o vento.

Com o uso de câmeras digitais, é possível capturar mais imagens, mas, mesmo assim, apenas 5% delas mostram leopardos-das-neves. Um pesquisador humano pode levar mais de 200 horas para analisar todas as imagens e identificar as que contêm esses animais. O tempo dos pesquisadores seria muito mais bem aproveitado no treinamento de um algoritmo de ML para identificar leopardos-das-neves.

Dizem que os algoritmos de ML “aprendem” em vez de serem explicitamente programados. Por exemplo, se você estivesse criando um aplicativo para prever o preço de uma casa com base em fatores como a quantidade de quartos, metros quadrados, entre outros, você poderia explicitamente programá-lo adicionando regras ou fazendo pesquisas em algum banco de dados que já tem as respostas. Caso o usuário insira a quantidade de quartos entre dois e quatro, e a casa tenha uma determinada quantidade de metros quadrados, um determinado preço seria retornado.

Em vez de programar essa resposta, você poderia usar uma equação muito simples, como:

y = w1*x1 + w2*x2 + b

Nesse exemplo, x1 é a quantidade de quartos e x2 é a quantidade de metros quadrados. Com base em dados que apresentam o último preço de venda de determinada quantidade de casas, você pode “treinar” o modelo ao descobrir os valores de w1, w2 e b que melhor atendam aos dados. Após o treinamento, o modelo de ML fica estático, de modo que, se você inserir a mesma entrada duas vezes, ele responderá com a mesma saída nas duas vezes. No entanto, você poderia continuar trabalhando no algoritmo, treinando-o com base em novos dados e atualizando-o, o que basicamente significa encontrar novos valores para w1, w2 e b.

O aprendizado profundo é um subconjunto do ML. Em vez de uma simples equação linear, como a que acabamos de descrever, usamos redes neurais artificiais ou DNNs (redes neurais profundas) que consistem em muitos neurônios ou nós em muitas camadas. O objetivo é simular a forma como nosso cérebro funciona. Cada neurônio executa um cálculo com base em dados — como partes de imagens —, e se o resultado atingir um determinado limite, o neurônio é ativado.

Com isso, essa entrada é inserida na próxima camada. Por exemplo, digamos que nós temos uma imagem com um número escrito à mão e que tenhamos dois neurônios. O primeiro neurônio observa a metade superior da imagem, e o segundo a metade inferior. Se o primeiro neurônio vir um círculo, ele será ativado. Se o da parte inferior vir uma linha vertical, ele será ativado. Caso o número da imagem seja o oito, o primeiro neurônio será ativado, mas o segundo não. Caso o número da imagem seja o nove, o primeiro neurônio será ativado, e o segundo também. Assim, você pode coletar essas informações e concluir que o número da imagem é o nove.

Componentes do Azure

Antes de continuarmos, é importante estar ciente dos componentes das pilhas do Azure e do ML. Estão incluídos:

Serviço de Visão Personalizada: esse serviço é parte da plataforma de Serviços Cognitivos e permite que você treine um modelo de IA facilmente carregando imagens e marcando-as manualmente. O modelo pode ser exportado para muitas plataformas — como iOS (CoreML) ONNX ou o TensorFlow — e salvo no formato .pb, com base em Buffers de protocolo ou protobufs. Os protobufs são descritos pelo Google como seu “mecanismo extensível de plataforma e linguagem neutras para serializar dados estruturados — imagine o XML, mas menor, mais rápido e mais simples” (developers.google.com/protocol-buffers).

Azure Machine Learning: esse serviço é uma plataforma de ciência de dados de ponta a ponta, como um serviço de nuvem que você pode usar para desenvolver e implantar modelos de ML. Ao usar o Serviço do Azure Machine Learning, você pode acompanhar os modelos à medida que os cria, treina, implanta e gerencia, tudo dentro da ampla escala fornecida pela nuvem.

Hub IoT do Azure e Azure IoT Edge: o Hub IoT do Azure é usado para se conectar, monitorar e controlar bilhões de ativos da IoT (Internet das Coisas). O Azure IoT Edge é uma plataforma gerenciada remotamente de um Hub IoT. Ao mover partes da sua carga de trabalho para a borda, ele permite que os dados sejam analisados nos dispositivos em vez de na nuvem. Seus dispositivos conseguem gastar menos tempo enviando mensagens para a nuvem e podem reagir com autonomia e rapidamente a mudanças.

Usando esses componentes, a Snow Leopard Trust consegue instalar 30 câmeras ativadas por movimento, cada uma anexada a computadores de custo relativamente baixo. Usaremos o Azure IoT Edge para implantar o modelo de leopardo-das-neves em um computador que simula um dos dispositivos.

Classificação de imagem na borda

Agora, vamos percorrer as etapas envolvidas no provisionamento dos recursos necessários do Azure e na compilação da solução. Na seção a seguir, forneceremos mais detalhes sobre o que é provisionado e o que está acontecendo no código. Para começar, você precisará de:

• Uma assinatura do Azure. Não tem uma? Crie uma conta gratuita em azure.microsoft.com/free.

• O Visual Studio Code (code.visualstudio.com).

• Uma VM do Ubuntu 16.04 Linux x64 para servir como o dispositivo do IoT Edge.

• Recursos do Azure, incluindo um espaço de trabalho do Azure Machine Learning, um Hub IoT do Azure e uma conta do CustomVision.ai.

• Um exemplo de implantação de modelo em aka.ms/visedge.

A criação de um espaço de trabalho do Azure ML também cria uma conta de armazenamento e o Registro de Contêiner do Azure, que podem ser usados para armazenar as imagens do Docker para implantação em dispositivos do IoT Edge. Comece baixando e instalando as ferramentas do VS Code para IA (aka.ms/vscodetoolsforai). Após a instalação, clique no símbolo do Azure na barra de atividades do VS Code à esquerda.

Agora, instale o SDK do Azure ML. Para isso, abra a paleta de comandos usando o atalho Ctrl+Shift+P e digitando “Install Azure ML SDK” (Instalar o SDK do ML do Azure). Na janela do terminal integrado, especifique qual interpretador do Python deve ser usado; outra opção é pressionar Enter para usar o interpretador de Python padrão.

Depois, crie um espaço de trabalho do Azure ML clicando no ícone do Azure da barra de atividades do Visual Studio Code. Assim que a barra lateral do Azure Machine Learning for exibida, clique com botão do lado direito da assinatura do Azure e selecione Criar espaço de trabalho. Na lista exibida, selecione um grupo de recursos existente na lista ou crie um novo plano usando o assistente na paleta de comandos. Neste exemplo, estamos usando “iot-camera-group”.

Agora, no campo, digite um nome único e claro para seu novo espaço de trabalho. Ao pressionar Enter, o novo espaço de trabalho será criado e aparecerá na árvore abaixo do nome da assinatura.

Vamos criar um Hub IoT abrindo o VS Code e clicando no botão Extensões no painel à esquerda (Ctrl+Shift+X). Pesquise por “Kit de ferramentas do Azure IoT” e instale a extensão. Você precisará de um computador Linux, que atuará como o dispositivo de borda. Você pode usar uma VM em seu computador, no Azure ou em qualquer outro lugar ao qual tenha acesso.

Comece clicando no botão Explorer na barra de atividades à esquerda e localize a entrada “Dispositivos do Hub IoT do Azure”. Clique em “Mais ações” (as reticências) e selecione “Criar Hub IoT”.

Escolha uma assinatura e, em seguida, o selecione o mesmo grupo de recursos (“iot-camera-group”) anterior ou crie um novo. A seguir, escolha uma região e uma camada. É possível usar a camada gratuita F1, mas caso ela já exista no Hub IoT, você precisará criar uma camada S1. Por fim, dê um nome ao Hub IoT, como “iot-camera-hub”.

Agora é hora de registrar um dispositivo IoT Edge por meio da adição de uma entrada ao Hub IoT. Isso gerará uma cadeia de conexão que você deve inserir no seu dispositivo IoT Edge (nesse caso, sua VM do Linux) para que ele possa se conectar ao Hub IoT.

Para isso, clique no menu “Mais ações” (as reticências) em “Dispositivos Hub IoT do Azure” e escolha “Criar dispositivo do IoT Edge”. Não clique em “Criar dispositivo”. Depois, insira um nome para o dispositivo de borda, como “camera-pc-01”. Por fim, copie o valor connectionString para a entrada que acabou de criar. Você precisará inseri-la em seu dispositivo de borda.

No futuro, você poderá clicar em “Dispositivos de Hub IoT do Azure” e depois em “Selecionar Hub IoT”. Você precisará entrar no Azure, escolher a assinatura que você provisionou ao Hub IoT e, em seguida, selecionar seu Hub IoT, mas você pode exibir todas as cadeias de conexão associadas a seus dispositivos.

Configurar um dispositivo do IoT Edge

A maneira mais fácil de simular um dispositivo de borda é usando uma VM pré-configurada (aka.ms/edgevm). Quando a VM é iniciada, ela instala o tempo de execução e as dependências mais recentes do Azure IoT Edge. Depois de provisionar a VM, conecte-se a ela e execute o comando a seguir na linha de comando com a cadeia de conexão para o dispositivo registrado com o IoT Edge (a cadeia de conexão é o connectionString.value que você copiou anteriormente):

/etc/iotedge/configedge.sh "<your_iothub_edge_connection_string>"

Caso queira configurar sua própria VM do Ubuntu 16.04 x64 como o dispositivo de borda, confira as informações em: aka.ms/edgevm.

Solução da classificação de imagens

Agora é hora de compilar a solução de classificação de imagens. Clone o exemplo do Git (aka.ms/visedge). Vamos usar o computador com Linux x64 como a máquina de borda. Siga estas etapas:

• Atualize o arquivo .env com os valores do registro de contêiner e verifique se o mecanismo do Docker tem acesso a ele.

• Renomeie o arquivo deployment.template.json para deployment.template.RPI.json.

• Renomeie o arquivo deployment.template.test-amd64.json para deployment.template.json.

• Compile a solução inteira clicando com o botão direito do mouse no arquivo deployment.template.json e selecionando Compilar a solução do IoT Edge (isso pode demorar um pouco, especialmente para compilar numpy e pillow).

• Implante a solução em seu dispositivo clicando com o botão direito no arquivo config/deployment.json, selecionando Criar implantação do dispositivo do IoT Edge e escolhendo seu dispositivo de destino.

• Monitore as mensagens sendo enviadas à nuvem clicando com o botão direito no dispositivo na Extensão do IoT Edge do VS Code e selecionando Iniciar o monitoramento de mensagens D2C.

Para a versão x64 da solução, essas etapas implantam dois módulos:

Captura da câmera: captura o stream de vídeo de uma câmera USB e envia os quadros para o módulo de classificação de imagens. O resultado é enviado ao edgeHub, que pode retransmiti-lo como uma mensagem ao Hub IoT.

Visão Personalizada: esse serviço Web é executado localmente com o HTTP, incorporando uma imagem e classificando-a. Ele foi criado usando o site da Visão Personalizada (customvision.ai). O modelo da solução classifica se uma imagem contém uma maçã ou uma banana.

O módulo de captura da câmera pode enviar mensagens para o edgeHub usando o SDK do Azure IoT Edge. Você pode compilar seus próprios módulos como contêineres do Docker e usar o SDK para se comunicar com o edgeHub.

Para o Serviço de Visão Personalizada, você pode trabalhar com o modelo existente na solução ou acessar customvision.ai e treinar seu próprio modelo. Para criar seu classificador de leopardos-das-neves, faça o upload de fotos desses animais no Serviço de Visão Personalizada. Você também pode fazer upload de imagens de outros animais encontrados no mesmo habitat. Basta marcar as imagens e clicar no botão Treinar para treinar o modelo. Os arquivos de modelo e de rótulo são exportados como arquivos .pb e. txt, respectivamente, que podem ser usados para substituir o que está na solução.

A Visão Personalizada usa o aprendizado por transferência, que usa uma rede neural profunda existente e extrai os recursos de sua imagem. Depois, ela treina um classificador baseado nos seus dados (nesse caso, as imagens do upload e as marcas atribuídas a elas).

Para ilustrar o aprendizado por transferência, imagine que você deseja treinar um cão farejador de bombas — um pastor-alemão, por exemplo. Se você pegar um pastor-alemão com 2 anos de idade, ele não saberá nada sobre bombas. Mas ele possui a “infraestrutura” para detectar bombas com seu ótimo olfato. Você pode começar a treinar seu pastor-alemão fazendo-o farejar uma bomba e dizendo a ele que se trata de uma bomba; depois, faça-o farejar outra coisa, uma flor por exemplo, e diga que não é uma bomba. Repita isso com vários tipos de bombas e outros odores e, depois de alguns meses e muita ração, você terá um cão farejador de bombas. Não é tão difícil treinar um pastor-alemão; a parte difícil é criar um.

DNNs como ResNet 50, Inception v3, YOLO e VGG são, basicamente, pastores-alemães. Tratam-se de modelos complexos de IA que pegam uma imagem e extraem os recursos dela, tal qual um pastor-alemão extrai os sinais de um odor. Assim como a quantidade de quartos e de metros quadrados de uma casa são recursos que podem ser usados para prever um preço, os recursos extraídos são enviados para um classificador. É esse classificador que precisa ser treinado, o qual, em seguida, preverá se um leopardo-das-neves está presente na imagem ou não. O classificador pode ser uma regressão logística simples, um computador do vetor de suporte ou qualquer outro classificador. A beleza do aprendizado por transferência é a extração de recursos com a DNN, o que resulta em recursos úteis que podem ser usados para classificar imagens com bastante precisão.

A Figura 1 fornece o código para capturar uma imagem e prever o que está presente nela usando o modelo de IA.

Figura 1 Código de previsão

from urllib.request import urlopen

import tensorflow as tf

from PIL import Image
import numpy as np
# import scipy
# from scipy import misc
import sys
import os  

filename = 'model.pb'
labels_filename = 'labels.txt'

network_input_size = 227
mean_values_b_g_r = (0,0,0)

size = (256, 256)
output_layer = 'loss:0'
input_node = 'Placeholder:0'

graph_def = tf.GraphDef()
labels = []

def initialize():
  print('Loading model...',end=''),
  with tf.gfile.FastGFile(filename, 'rb') as f:
    graph_def.ParseFromString(f.read())
    tf.import_graph_def(graph_def, name='')
  print('Success!')
  print('Loading labels...', end='')
  with open(labels_filename, 'rt') as lf:
    for l in lf:
      l = l[:-1]
      labels.append(l)
  print(len(labels), 'found. Success!')
  
def crop_center(img,cropx,cropy):
  y,x,z = img.shape
  startx = x//2-(cropx//2)
  starty = y//2-(cropy//2)
  print('crop_center: ', x, 'x', y, 'to', cropx, 'x', cropy)
  return img[starty:starty+cropy,startx:startx+cropx]

def predict_url(imageUrl):
  print('Predicting from url: ',imageUrl)
  with urlopen(imageUrl) as testImage:
    # image = scipy.misc.imread(testImage)
    image = Image.open(testImage)
    return predict_image(image)

def predict_image(image):
  print('Predicting image')
  tf.reset_default_graph()
  tf.import_graph_def(graph_def, name='')
  
  with tf.Session() as sess:
    prob_tensor = sess.graph.get_tensor_by_name(output_layer)

    # w = image.shape[0]
    # h = image.shape[1]
    w, h = image.size
    print('Image size',w,'x',h)

    # scaling
    if w > h:
      new_size = (int((float(size[1]) / h) * w), size[1], 3)
    else:
      new_size = (size[0], int((float(size[0]) / w) * h), 3)

    # resize
    if  not (new_size[0] == w and new_size[0] == h):
      print('Resizing to', new_size[0],'x',new_size[1])
      #augmented_image = scipy.misc.imresize(image, new_size)
      augmented_image = np.asarray(image.resize((new_size[0], new_size[1])))
    else:
      augmented_image = np.asarray(image)

    # crop center
    try:
      augmented_image = crop_center(augmented_image, network_input_size, 
        network_input_size)
    except:
      return 'error: crop_center'

    augmented_image = augmented_image.astype(float)

    # RGB -> BGR
    red, green, blue = tf.split(axis=2, num_or_size_splits=3, value=augmented_image)

    image_normalized = tf.concat(axis=2, values=[
      blue - mean_values_b_g_r[0],
      green - mean_values_b_g_r[1],
      red - mean_values_b_g_r[2],
    ])

    image_normalized = image_normalized.eval()
    image_normalized = np.expand_dims(image_normalized, axis=0)

    predictions, = sess.run(prob_tensor, {input_node: image_normalized})

    result = []
    idx = 0
    for p in predictions:
      truncated_probablity = np.float64(round(p,8))
      if (truncated_probablity > 1e-8):
        result.append({'Tag': labels[idx], 'Probability': truncated_probablity })
      idx += 1
    print('Results: ', str(result))
    return result

Azure Machine Learning

Você pode usar a Visão Personalizada para criar seu modelo de IA; mas e se você quiser treinar vários modelos ou colaborar com uma equipe de cientistas de dados? Os rigores do desenvolvimento de software, especialmente quanto ao controle do código-fonte, estão ausentes no fluxo de trabalho da ciência de dados. O Azure ML junta tudo isso com a preparação, a experimentação, o gerenciamento de modelos e a operacionalização de dados.

Neste exemplo, se você estiver fazendo vários experimentos com a Visão Personalizada, pode registrar o modelo .pb e outros arquivos para monitorá-los. Este é o código:

from azureml.core.model import Model
model = Model.register(model_path = "custom-vision-model/",
                       model_name = "model.pb",
                       tags = {"area": "vision", "type": "classification", 
                         "version": "1.0"},
                       description = "Snow leopard classification model",
                       workspace = ws)

Se quiser ver todos os modelos registrados, insira este código:

models = Model.list(workspace=ws)
for m in models:
  print("Name:", m.name,"\tVersion:", m.version, "\tDescription:", 
  m.description, m.tags)

Se quiser treinar seus próprios modelos, confira os blocos de anotações de exemplo do Azure Machine Learning (github.com/Azure/MachineLearningNotebooks). Você pode treinar seu modelo, registrá-lo e criar imagens do Docker com ele. As imagens do Docker podem ser implantadas na nuvem em uma Instância de Contêiner do Azure ou um Serviço de Kubernetes do Azure. Uma API REST é exposta no contêiner a ser chamado ao classificar os dados. A imagem do Docker também contém o SDK do Azure IoT Edge, que agenciará as mensagens com o agente do IoT Edge em execução no dispositivo de borda. Isso permite criar e implantar o contêiner na nuvem ou na borda.

Conclusão

Há muitos componentes durante a compilação de uma solução empresarial, começando com a Visão Personalizada para treinar os modelos, o Azure ML para gerenciá-los (e treinar outros tipos de modelos) e o Azure IoT Edge para implantá-los. A configuração desses serviços demorará um pouco, mas você colherá os frutos da facilidade de treinar novos modelos e atualizá-los em vários dispositivos de borda.


Ted Wa é gerente de programas sênior da equipe do Azure ML que está trabalhando para acelerar a IA na nuvem e na borda em hardware especializados. Seu Ph.D. na Universidade de Michigan foi sobre “verificação ortográfica para radiologistas”, um sistema de diagnósticos auxiliado por computador para estimar a nocividade em exames de TC torácica.

Emmanuel Bertrand é gerente de programas sênior da equipe do Azure IoT Edge, auxiliando a habilitar implantações fáceis de módulos da IoT por meio do Azure Marketplace. Bertrand entrou na Microsoft como especialista em experiência de usuários e clientes e, antes disso, havia digitalizado os processos de várias empresas usando ferramentas tradicionais.

Agradecemos aos seguintes especialistas técnicos pela revisão deste artigo: Rakesh Kelkar, Chipalo Street


Discuta esse artigo no fórum do MSDN Magazine