Determinando a maturidade de uma melancia usando Keras: um ciclo completo, de uma ideia a um programa no Google Play

Como tudo começou


Tudo começou com o Apple Market - descobri que eles têm um programa para determinar a maturidade de uma melancia. O programa ... é estranho. O que vale, pelo menos, a oferta de bater na melancia não com os nós dos dedos, mas ... por telefone! No entanto, eu queria repetir essa conquista em uma plataforma Android mais familiar.

Seleção de ferramenta


Nosso problema é resolvido de várias maneiras e, para ser sincero, tive que fazer um esforço considerável para não seguir o caminho "simples". Ou seja, faça transformadas de Fourier, wavelets e um editor de sinais. No entanto, eu queria ganhar experiência com redes neurais, então deixe as redes fazerem análise de dados.

Keras, o complemento do Google para TensorFlow e Theano, foi escolhido como uma biblioteca para criar e treinar redes neurais. Em geral, se você está apenas começando com redes de aprendizado profundo, é melhor não encontrar uma ferramenta. Por um lado, o Keras é uma ferramenta poderosa e otimizada para velocidade, memória e hardware (sim, pode funcionar em placas de vídeo e seus clusters). Por outro lado, tudo o que pode ser "oculto" do usuário fica oculto lá, para que você não precise se preocupar com o encaixe de camadas de uma rede neural, por exemplo. Muito confortável

Como Keras, e redes neurais em geral, exigem conhecimento de Python - essa linguagem, como uma cobra enrolada ... desculpe, reprimida. Em resumo, você não deve se intrometer no moderno Deep Learning sem o Python. Felizmente, o Python pode ser estudado em duas semanas, em casos extremos - em um mês.

Você precisará de mais algumas bibliotecas para Python, mas essas são trivialidades - quero dizer, se você já lidou com o próprio Python. Isso requer conhecimento (muito superficial) do NumPy, PyPlot e, possivelmente, de algumas bibliotecas, das quais assumimos literalmente algumas funções. Não é difícil. A verdade é

Bem, concluindo, observo que não precisamos dos clusters de placas de vídeo mencionados acima - nossa tarefa normalmente é resolvida com a ajuda da CPU de um computador - lentamente, mas não de forma crítica.

Plano de trabalho


Primeiro, você precisa criar uma rede neural - em Python e Keras, no Ubuntu. Você pode - no emulador Ubunta. Você pode - para Windows, mas o tempo extra gasto é suficiente para você estudar o Ubuntu mencionado e depois trabalhar com ele.

O próximo passo é escrever um programa. Eu pretendo fazer isso em Java no Android. Este será um protótipo do programa, no sentido de que ele terá uma interface de usuário, mas ainda não existe uma rede neural.

Qual é o significado de escrever "chupetas", você pergunta. Mas eis o seguinte: qualquer tarefa relacionada à análise de dados, mais cedo ou mais tarde, repousa na pesquisa de dados - para treinar nosso programa. De fato, quantas melancias devem ser aproveitadas e provadas para que a rede neural possa construir um modelo confiável nesses dados? Cem? Mais?

Aqui, nosso programa nos ajudará a: enviá-lo para o Google Play, distribuir (tudo bem, impor, torcer os braços) a todos os amigos que não têm sorte de ter um telefone com Android e dados, um pequeno fluxo, começar a fluir ... e, a propósito, para onde?

O próximo passo é escrever um programa de servidor que receba dados do nosso cliente Android. É verdade que este programa de servidor é muito simples, terminei tudo em cerca de vinte minutos. Mas, no entanto, este é um estágio separado.

Finalmente, dados suficientes. Nós treinamos uma rede neural.

Portamos a rede neural em Java e lançamos uma atualização para o nosso programa.

Lucro Embora não. O programa foi gratuito. Apenas experiência e solavancos de pelúcia.

Criando uma rede neural


Trabalhar com áudio, que, é claro, está tocando em uma melancia, é uma rede neural recorrente ou a chamada rede evolutiva unidimensional. Além disso, nos últimos anos, as redes evolutivas têm liderado inequivocamente, substituindo as recorrentes. A idéia de uma rede convolucional é que a janela deslize sobre o conjunto de dados - o gráfico “intensidade do som - tempo” - e, em vez de analisar centenas de milhares de amostras, trabalhamos apenas com o que entra na janela. As camadas a seguir combinam e analisam os resultados dessa camada.

Para tornar mais claro, imagine que você precisa encontrar uma gaivota na foto de uma paisagem marítima. Você digitaliza uma imagem - a “janela” de sua atenção se move ao longo de linhas e colunas imaginárias, em busca de uma marca de seleção branca. É assim que uma rede convolucional 2D funciona, enquanto uma rede unidimensional varre ao longo de uma coordenada - a melhor opção se estivermos lidando com um sinal de áudio.

Observo, no entanto, que não é necessário focar nas redes 1D. Como exercício, plotei o som e analisei o bitmap resultante como uma imagem - usando uma rede de convolução 2D. Para minha surpresa, o resultado não foi pior do que ao analisar dados "unidimensionais brutos".

A rede usada tinha a seguinte estrutura:

model = Sequential() model.add(Conv1D(filters=32, kernel_size=512, strides=3, padding='valid', use_bias=False, input_shape=(nSampleSize, 1), name='c1d', activation='relu')) model.add(Activation('relu', input_shape=(nSampleSize, 1))) model.add(MaxPooling1D(pool_size=(2))) model.add(Conv1D(32, (3))) model.add(Activation('relu')) model.add(MaxPooling1D(pool_size=(2))) model.add(Conv1D(64, (3))) model.add(Activation('relu')) model.add(MaxPooling1D(pool_size=(2))) model.add(Flatten()) model.add(Dense(64)) model.add(Activation('relu')) model.add(Dropout(0.5)) model.add(Dense(nNumOfOutputs)) #1)) model.add(Activation('sigmoid')) model.compile(loss='mean_squared_error', optimizer='adam', metrics=['accuracy']) 

Essa rede possui dois valores de saída (prevê dois valores): doçura e maturação. A doçura é 0 (sem açúcar), 1 (normal) e 2 (excelente), e a maturação, respectivamente, 0 é muito dura, 1 é o que você precisa e 2 é madura demais, como algodão com areia.

As notas para a amostra de teste são definidas pela pessoa, exatamente como - falaremos na seção do programa para Android. A tarefa da rede neural é prever qual a classificação que uma pessoa dará para uma determinada melancia (de acordo com uma torneira).

Escrevendo um programa


Eu já mencionei que o programa deveria sair em duas versões. A primeira, preliminar, alerta honestamente o usuário de que suas previsões são um absurdo completo. Mas permite ao usuário gravar uma batida em uma melancia, avaliar o sabor dessa melancia e enviá-la ao autor do programa pela Internet. Ou seja, a primeira versão simplesmente coleta dados.

Aqui está a página do programa no Google Play, é claro, o programa é gratuito.

O que ela faz:

1. Pressione o botão com o microfone e a gravação inicia. Você tem cinco segundos para acertar a melancia três vezes - bate, bate, bate. Um botão com melancia faz uma “previsão” e ainda não o tocamos.

Nota - se o Google tiver uma versão antiga, a gravação e a previsão serão combinadas em um botão com uma melancia, mas não haverá um botão com um microfone.

imagem

2. O arquivo salvo é temporário e será substituído na próxima vez que você pressionar o botão de gravação. Isso permite que você repita a batida se alguém falar de braços dados (você não pode imaginar como é difícil fazer as pessoas calarem a boca por cinco segundos!) Ou a água está barulhenta - a louça está tocando - o vizinho está perfurando ...

Mas agora a melancia é selecionada e comprada. Você trouxe para casa, gravou um som e cortou. Agora você está pronto para avaliar seu sabor. Selecione a guia Salvar.

Nesta guia, vemos duas caixas de combinação para classificação - doçura e maturação (doçura e maturidade, o trabalho de tradução está em andamento). Coloque uma marca - clique em Salvar.

Atenção! Salvar pode ser clicado apenas uma vez. Então, primeiro coloque uma marca. Com o toque de um botão, o arquivo de som é renomeado e agora não será apagado na próxima vez que for gravado.

imagem

3. Finalmente, depois de gravar (e, portanto, comer) uma dúzia de melancias, você voltou da casa de campo, onde não tinha Internet. Agora a Internet é. Abra a guia Enviar e pressione o botão O pacote (com uma dúzia de melancias) vai para o servidor do desenvolvedor.

imagem

Escrevendo um programa servidor


Tudo é simples aqui, então é melhor definir o código completo para esse script. O programa “captura” arquivos, fornece nomes exclusivos e os coloca em um diretório acessível apenas ao proprietário do site.

 <?php if (is_uploaded_file($_FILES['file']['tmp_name'])) { $uploads_dir = './melonaire/'; $tmp_name = $_FILES['file']['tmp_name']; $pic_name = $_FILES['file']['name']; $filename = md5(date('Ymd H:i:s:u')); move_uploaded_file($tmp_name, $uploads_dir.$filename); } else { echo "File not uploaded successfully."; } ?> 

Treinamento em redes neurais


Os dados são divididos em treinamento e teste, 70 e 30 por cento, respectivamente. Rede neural - converge. Não há surpresas aqui, no entanto, para iniciantes: não se esqueça de normalizar os dados de entrada, isso economizará muitos nervos. Algo assim:

 for file_name in os.listdir(path): nSweetness, nRipeness, arr_loaded = loadData(file_name) arr_data.append(arr_loaded / max(abs(arr_loaded))) # 2 stands for num. of inputs of a combo box - 1 arr_labels.append([nSweetness / 2.0, nRipeness / 2.0]) 

Portando uma rede neural


Existem várias maneiras de portar uma rede de um ambiente Python para Java. Recentemente, o Google tornou esse processo mais conveniente; portanto, se você ler os livros, verifique se eles não estão desatualizados. Aqui está como eu fiz isso:

 from keras.models import Model from keras.models import load_model from keras.layers import * import os import sys import tensorflow as tf # ------------------- def print_graph_nodes(filename): g = tf.GraphDef() g.ParseFromString(open(filename, 'rb').read()) print() print(filename) print("=======================INPUT=========================") print([n for n in g.node if n.name.find('input') != -1]) print("=======================OUTPUT========================") print([n for n in g.node if n.name.find('output') != -1]) print("===================KERAS_LEARNING=====================") print([n for n in g.node if n.name.find('keras_learning_phase') != -1]) print("======================================================") print() # ------------------- def get_script_path(): return os.path.dirname(os.path.realpath(sys.argv[0])) # ------------------- def keras_to_tensorflow(keras_model, output_dir, model_name,out_prefix="output_", log_tensorboard=True): if os.path.exists(output_dir) == False: os.mkdir(output_dir) out_nodes = [] for i in range(len(keras_model.outputs)): out_nodes.append(out_prefix + str(i + 1)) tf.identity(keras_model.output[i], out_prefix + str(i + 1)) sess = K.get_session() from tensorflow.python.framework import graph_util, graph_io init_graph = sess.graph.as_graph_def() main_graph = graph_util.convert_variables_to_constants(sess, init_graph, out_nodes) graph_io.write_graph(main_graph, output_dir, name=model_name, as_text=False) if log_tensorboard: from tensorflow.python.tools import import_pb_to_tensorboard import_pb_to_tensorboard.import_to_tensorboard( os.path.join(output_dir, model_name), output_dir) model = load_model(get_script_path() + "/models/model.h5") #keras_to_tensorflow(model, output_dir=get_script_path() + "/models/model.h5", # model_name=get_script_path() + "/models/converted.pb") print_graph_nodes(get_script_path() + "/models/converted.pb") 

Preste atenção na última linha: no código Java, você precisará especificar os nomes de entrada e saída da rede. Essa "impressão" apenas as imprime.

Então, colocamos o arquivo recebido coordted.pb no diretório de ativos do projeto no Android Studio, conectamos a biblioteca tensorflowinferenceinterface (veja aqui , ou melhor, aqui ), e é isso.

Só isso. Quando fiz isso pela primeira vez, esperava que fosse difícil, mas ... funcionou na primeira tentativa.

Veja como é uma chamada de rede neural a partir do código Java:

  protected Void doInBackground(Void... params) { try { //Pass input into the tensorflow tf.feed(INPUT_NAME, m_arrInput, 1, // batch ? m_arrInput.length, 1); // channels ? //compute predictions tf.run(new String[]{OUTPUT_NAME}); //copy the output into the PREDICTIONS array tf.fetch(OUTPUT_NAME, m_arrPrediction); } catch (Exception e) { e.getMessage(); } return null; } 

Aqui m_arrInput é uma matriz com dois elementos contendo - sim! - nossa previsão, normalizada de zero a um.

Conclusão


Aqui, ao que parece, deve-se agradecer pela atenção e expressar esperança de que foi interessante. Em vez disso, observo que o Google é a primeira versão do programa. O segundo está completamente pronto, mas não há dados suficientes. Então, se você gosta de melancia - coloque um programa no seu Android. Quanto mais dados você enviar, melhor será a segunda versão ...

Claro, será grátis.

Boa sorte e sim: obrigado por assistir. Espero que tenha sido interessante.

Atualização importante: uma nova versão com análise aprimorada foi lançada. Obrigado a todos que enviaram as melancias e envie mais!

Source: https://habr.com/ru/post/pt424099/


All Articles