reconhecimento de Imagem com Aprendizado de Máquina em Python, Convolucionais Rede Neural

fonte: irish times, Pól — Muirí

Após o pré-processamento dos dados, é hora de construir o nosso modelo para executar a tarefa de reconhecimento de Imagem. Uma das técnicas é usar a rede Neural de convolução.

este artigo segue o artigo que escrevi sobre o processamento de imagens. Depois de disponibilizar os dados para a tarefa de reconhecimento de imagens, é hora de criar um algoritmo que irá executar a tarefa. Entre muitas técnicas usadas para reconhecer imagens como modelo perceptron de camadas múltiplas, a rede Neural de convolução (CNN) aparece como uma rede muito eficiente. Neste artigo, veremos como construir um CNN e como aplicá-lo em um conjunto de dados de imagens.

Quando começamos a construir um modelo de reconhecimento de imagem pela primeira vez, geralmente é uma boa ideia treiná-lo e avaliá-lo em um conjunto de dados relativamente simples.

uma das tarefas mais simples que podemos realizar é o reconhecimento de dígitos manuscritos. Dada uma imagem de um manuscrito dígitos (por exemplo,, 0, 1, …, 9), nós queremos que o nosso modelo para ser capaz de classificar corretamente o seu valor numérico. Embora esta tarefa pareça relativamente simples, ela é realmente usada com bastante frequência na vida real, como a extração automática de números de cartão de crédito de uma imagem. O conjunto de dados que usaremos para o reconhecimento de dígitos é o conjunto de dados MNIST, que é o conjunto de dados usado para o reconhecimento de dígitos baseados na aprendizagem por máquina.

a base de dados do MNIST (Instituto Nacional de normas e Tecnologia modificado) contém 60.000 exemplos de treino e 10.000 exemplos de testes. O banco de dados contém dígitos manuscritos em tons de cinza que foram redimensionados para caber em uma caixa de 20×20 pixels, que foi então centrado em uma imagem 28×28 (almofadado com espaço em branco). O banco de dados MNIST é acessível via Python.

neste artigo, vou mostrar-lhe como codificar a sua rede Neural convolucional usando keras, a API de alto nível do TensorFlow. Estou usando o tensorflow 2.0 neste artigo.

1 – inicialização

Uma vez que cada imagem de tons de cinzento tem dimensões 28×28, existem 784 pixels por imagem. Portanto, cada imagem de entrada corresponde a um tensor de 784 valores normalizados de vírgula flutuante entre 0.0 e 1.0. O rótulo de uma imagem é um tensor de um a quente com 10 classes (cada classe representa um dígito). Em termos de nosso Código, temos img_rows = 28, img_cols = 28 e num_classes = 10. Assim, a entrada tem forma (numero_examples, img_rows, img_cols), daí 60000x28x28. outro elemento importante a ser configurado é a semente aleatória, pois queremos manter o ponto de partida quando um computador gera uma sequência de números aleatórios.

também importamos o conjunto de dados MNIST.

import tensorflow as tf # tensorflow 2.0
from keras.datasets import mnist
import numpy as npseed=0
np.random.seed(seed) # fix random seed
tf.random.set_seed(seed)# input image dimensions
num_classes = 10 # 10 digits
img_rows, img_cols = 28, 28 # number of pixels
# the data, shuffled and split between train and test sets
(X_train, Y_train), (X_test, Y_test) = mnist.load_data()

2 – remodelação e revisão de

conforme mencionado na secção anterior, as entradas têm forma (numero_ exemplos, img_rows, img_cols). No entanto, para usar os dados com nossa rede neural convolucional, precisamos colocá-los no formato NHWC.

NHWC formato tem uma forma com quatro dimensões:

  1. Número de dados de imagem de amostras (tamanho do lote)
  2. Altura de cada imagem
  3. Largura de cada imagem
  4. Canais por imagem

a altura e A largura de cada imagem do conjunto de dados é img_rows e img_cols, enquanto o número de canais é de 1 (uma vez que as imagens são em tons de cinza).

também, cada pixel contém um valor em escala de cinzentos quantificado por um inteiro entre 0 e 255. Assim, a base de dados é normalizada para ter valores de ponto flutuante entre 0.0 e 1.0. Neste caso, 0.0 corresponde a um valor de pixels de tons de cinza de 255 (branco puro), enquanto 1.0 corresponde a um valor em pixel em tons de cinzento de 0 (preto puro).

X_train = X_train.reshape(X_train.shape, img_rows, img_cols, 1) 
X_test = X_test.reshape(X_test.shape, img_rows, img_cols, 1)input_shape = (img_rows, img_cols, 1)# cast floats to single precision
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')# rescale data in interval
X_train /= 255
X_test /= 255

3 – Casting label vectors Y

precisamos transformar nossas classes em vetores. Fazemos esta tocando a seguinte linha:

Y_train = keras.utils.to_categorical(Y_train, num_classes)
Y_test = keras.utils.to_categorical(Y_test, num_classes)

Para ter uma melhor explicação para essa etapa, você deve ver este artigo.

Agora que temos o processo de nossos dados, podemos começar a construir o modelo.

modelo de rede Neural de convolução

como mencionado no final do artigo que escrevi sobre o processamento de imagens, os filtros desempenham um papel enorme no reconhecimento de imagens. Usamos filtros para transformar Entradas e extrair recursos que permitem ao nosso modelo reconhecer certas imagens. Um exemplo muito alto disto seria um filtro de detecção de curvas, que permite ao nosso modelo distinguir entre dígitos com curvas e dígitos sem curvas.como todos os pesos da rede neural, os pesos do filtro são variáveis treináveis. Treinamos nossa rede neural (através dos pesos da matriz do núcleo) para produzir filtros que são capazes de extrair as características ocultas mais úteis.

Quando os dados de entrada têm vários canais, um filtro terá uma matriz de kernel separada por canal. O conjunto de dados MNIST tem apenas um canal, mas para outros tipos de dados de imagem (por exemplo, RGB), nós treinaríamos o modelo para obter pesos ideais para a matriz de kernel de cada canal.

2-convolução

chegamos agora ao ponto focal das redes neurais convolucionais: a convolução. A convolução representa como aplicamos nossos pesos de filtro aos dados de entrada. A operação principal usada por uma convolução é o produto de ponto de matriz, isto é, uma soma sobre o produto Elemento-sábio de duas matrizes.

O número de matrix dot produtos em uma convolução depende da dimensão dos dados de entrada e de kernel matriz, bem como o tamanho da passada. O tamanho do stride é o deslocamento vertical/horizontal da matriz do núcleo à medida que se move ao longo dos dados de entrada.

3-preenchimento

às vezes, quando fazemos a operação de produto Ponto como visto antes, não usamos uma linha ou uma coluna. Para evitar este fenômeno podemos usar estofamento.

assim, se quisermos usar todos os dados de entrada na nossa convolução, podemos preencher a matriz de dados de entrada com 0’s. isto significa que adicionamos linhas / colunas feitas inteiramente de 0’s às bordas da matriz de dados de entrada. Uma vez que 0 multiplicado por qualquer número resulta em 0, o enchimento não afeta os produtos matrix dot. Isto é importante porque não queremos adicionar distorções à nossa convolução.

4-camada de convolução

uma camada de convolução numa CNN aplica múltiplos filtros ao tensor de entrada. Enquanto cada filtro tem uma matriz de kernel separada para cada um dos canais de entrada, o resultado geral da convolução de um filtro é a soma das convoluções em todos os canais de entrada.

adicionar mais filtros a uma camada de convolução permite que a camada extraia melhor as características ocultas. No entanto, isso vem ao custo de tempo de treinamento adicional e complexidade computacional, uma vez que os filtros adicionam pesos extras ao modelo. O número de canais para os dados de saída é igual ao número de filtros que a camada de convolução usa.

Pooling

While the convolution layer extracts important hidden features, the number of features can still be pretty large. Podemos usar o pooling para reduzir o tamanho dos dados nas dimensões de altura e largura. Isso permite que o modelo para executar menos computações e, em última análise, treinar mais rápido. Também evita a sobrefunção, extraindo apenas as características mais salientes e ignorando potenciais distorções ou características pouco comuns encontradas em apenas alguns exemplos.

como funciona o agrupamento?

semelhante a uma convolução, usamos matrizes de filtro em pooling. No entanto, o filtro de pooling não tem pesos, nem executa produtos de pontos de matriz. Em vez disso, aplica uma operação de redução às subsecções dos dados de entrada.

O tipo de agrupamento que é normalmente utilizado nas CNN é referido como agrupamento máximo. Os filtros da agregação máxima utilizam a operação máxima para obter o número máximo em cada submatriz dos dados de entrada.

múltiplas camadas

1 – adicionando camadas extras

Como todas as redes neurais, as CNNs podem beneficiar de camadas adicionais. As camadas adicionais permitem que uma CNN basicamente empilhe vários filtros juntos para uso nos dados da imagem. No entanto, semelhante à construção de qualquer rede neural, precisamos ter cuidado com quantas camadas adicionais adicionamos. Se adicionarmos muitas camadas a um modelo, corremos o risco de o sobrecarregar com os dados de treinamento e, portanto, generalizar muito mal. Além disso, cada camada adicional adiciona complexidade computacional e aumenta o tempo de treinamento para o nosso modelo.

2 – aumentar os filtros

usualmente aumentamos o número de filtros em uma camada de convolução quanto mais profundo é em nosso modelo. Neste caso, a nossa segunda camada de convolução tem 64 filtros, em comparação com os 32 filtros da primeira camada de convolução. Quanto mais profunda a camada de convolução, mais detalhados se tornam os recursos extraídos. Por exemplo, a primeira camada de convolução pode ter filtros que extraem características como linhas, arestas e curvas. Quando chegamos ao segundo nível, os filtros da camada de convolução poderiam agora extrair mais características distintivas, tais como o ângulo agudo de um 77 ou as curvas de intersecção de um 88.

camada totalmente conectada

1-camada totalmente conectada

aplicamos uma camada totalmente conectada de tamanho 1024 (ou seja, o número de neurônios na camada) aos dados de saída da segunda camada agregante. O número de unidades é um pouco arbitrário. O suficiente para ser poderoso, mas não tanto para ser demasiado intensivo em recursos. O objetivo da camada totalmente conectada é agregar as características de dados antes de convertê-las em classes. Isso permite que o modelo Faça melhores previsões do que se tivéssemos convertido a saída de pooling diretamente para classes.

2-achatamento

os dados que temos usado em nosso modelo são do formato NHWC. No entanto, para usar uma camada totalmente conectada, precisamos que os dados sejam uma matriz, onde o número de linhas representa o tamanho do lote e as colunas representam as características dos dados. Desta vez precisamos remodelar na direção oposta e converter de NHWC para uma matriz 2-D.

Dropout

1-Co-adaptação

Co-adaptação refere-se a quando múltiplos neurónios em uma camada extraem as mesmas, ou muito semelhantes, características ocultas dos dados de entrada. Isso pode acontecer quando os pesos de conexão para dois neurônios diferentes são quase idênticos.quando uma camada totalmente conectada tem um grande número de neurônios, a co-adaptação é mais provável de ocorrer. Isto pode ser um problema por duas razões. Primeiro, é um desperdício de computação quando temos neurônios redundantes computando a mesma saída. Em segundo lugar, se muitos neurônios estão extraindo as mesmas características, acrescenta mais significado a essas características para o nosso modelo. Isto leva a sobrefitting se as características extraídas duplicadas são específicas apenas para o conjunto de treinamento.

2-Gota

a forma como minimizamos a co-adaptação para camadas totalmente conectadas com muitos neurônios é através da aplicação de gota durante o treinamento. Em desistência, desligamos aleatoriamente uma fração dos neurônios de uma camada em cada passo de treinamento, zerando os valores dos neurônios.

camada Soft-max

Uma vez que existem 10 dígitos possíveis uma imagem MNIST pode ser, usamos uma camada de 10 neurônios totalmente conectados para obter as classes para cada classe de dígitos. A função Softmax é aplicada às classes para convertê-las em probabilidades de classe.

construir o modelo

Agora estamos prontos para construir o nosso modelo. Aqui está o código:

from keras.models import Sequential
from keras.layers import Dense, Conv2D, Flatten
from keras.layers import MaxPooling2D, Dropoutmodel = Sequential()#add model layers
model.add(Conv2D(32, kernel_size=(5, 5),
activation='relu',
input_shape=input_shape))
model.add(MaxPooling2D(pool_size=(2, 2)))# add second convolutional layer with 20 filters
model.add(Conv2D(64, (5, 5), activation='relu'))
# add 2D pooling layer
model.add(MaxPooling2D(pool_size=(2, 2)))
# flatten data
model.add(Flatten())
# add a dense all-to-all relu layer
model.add(Dense(1024, activation='relu'))
# apply dropout with rate 0.5
model.add(Dropout(0.5))
# soft-max layer
model.add(Dense(num_classes, activation='softmax'))

o tipo de modelo que vamos usar é sequencial. Sequencial é a maneira mais fácil de construir um modelo em Keras. Ele permite que você construa um modelo camada por camada.

usamos o método add() para anexar camadas ao nosso modelo. Para os propósitos de nosso exemplo introdutório, basta focar em camadas densas por simplicidade. Toda camada densa() aceita como seu primeiro argumento requerido um inteiro que especifica o número de neurônios. O tipo de função de ativação para a camada é definido usando o argumento opcional de ativação, cuja entrada é o nome da função de ativação em formato de cadeia de caracteres. Exemplos incluem relu, tanh, elu, sigmoid, softmax.nesta rede neural, temos 2 camadas de convolução seguidas de cada vez por uma camada comum. Então nós achatamos os dados para adicionar uma camada densa na qual aplicamos o dropout com uma taxa de 0,5. Finalmente, adicionamos uma camada densa para alocar cada imagem com a classe correta.

compilando o modelo

a seguir, precisamos compilar o nosso modelo. Compilar o modelo leva três parâmetros: otimizador, perda e métricas.

o Optimizador controla a taxa de aprendizagem. Vamos usar ‘adam’ como nosso otimizador. Adam é geralmente um bom otimizador para usar em muitos casos. O Optimizador adam ajusta a taxa de aprendizagem ao longo do treino.

a taxa de aprendizagem determina a rapidez com que são calculados os pesos ideais para o modelo. Uma menor taxa de aprendizagem pode levar a pesos mais precisos (até um certo ponto), mas a redução é o tempo de computação.

usaremos ‘categorical_crossentropy’ para a nossa função de perda. Esta é a escolha mais comum para classificação. Uma pontuação mais baixa indica que o modelo está se apresentando melhor.

para tornar as coisas ainda mais fáceis de interpretar, vamos usar a métrica de ‘precisão’ para ver a pontuação de precisão no conjunto de validação quando treinamos o modelo.

#compile model using accuracy to measure model performance
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=)

Training the model

Now we will train our model. Para treinar, usaremos a função’ fit () ‘ em nosso modelo com os seguintes parâmetros: dados de treinamento (X_train), dados de destino (Y_train), dados de validação, e o número de epochs.

para os nossos dados de validação, utilizaremos o conjunto de testes que nos foi fornecido no nosso conjunto de dados, que dividimos em X_test e Y_test.

O número de epochs é o número de vezes que o modelo circulará através dos dados. Quanto mais epochs corremos, mais o modelo vai melhorar, até um certo ponto. Depois desse ponto, o modelo vai parar de melhorar durante cada época. Para o nosso modelo, vamos definir o número de epochs para 3.

#train the model
model.fit(X_train, Y_train, validation_data=(X_test, Y_test), epochs=3)

Avaliar o modelo

Agora temos treinado nosso modelo, podemos avaliar o seu desempenho:

# evaluate the model
score = model.evaluate(X_test, Y_test, verbose=1)
# print performance
print()
print('Test loss:', score)
print('Test accuracy:', score)

Assim, temos uma precisão de 99,3% e uma perda de 0,025 no conjunto de teste, o que é muito bom. Ainda podemos melhorar o modelo aumentando o número de épocas e introduzindo um tamanho de lote.

faça previsões

Se quiser ver as previsões reais que o nosso modelo fez para os dados de teste, podemos usar a função predict_classes. Nós também podemos fazer isso usando a função predict dará um array com 10 números. Estes números são as probabilidades de a imagem de entrada representar cada dígito (0-9). O índice array com o maior número representa a previsão do modelo. A soma de cada array é igual a 1 (uma vez que cada número é uma probabilidade).

para mostrar isto, vamos mostrar as previsões para as primeiras 4 imagens no conjunto de testes.

Nota: Se tivermos novos dados, podemos introduzir os nossos novos dados na função de Previsão para ver as previsões que o nosso modelo faz sobre os novos dados. Uma vez que não temos quaisquer novos dados invisíveis, vamos mostrar previsões usando o conjunto de testes para agora.

#predict first 4 images in the test set
model.predict_classes(X_test)

#predict first 4 images in the test set
model.predict(X_test)

We can see that our model predicted 7, 2, 1 and 0 for the first four images.

Let’s compare this with the actual results.

#actual results for first 4 images in test set
y_test

Os resultados mostram que as primeiras quatro imagens também são 7, 2,1 e 0. O nosso modelo previu correctamente!

modelo inteiro

import tensorflow as tf # tensorflow 2.0
from keras.datasets import mnist
import numpy as np
seed=0
np.random.seed(seed) # fix random seed
tf.random.set_seed(seed)
# input image dimensions
num_classes = 10 # 10 digitsimg_rows, img_cols = 28, 28 # number of pixels# the data, shuffled and split between train and test sets
(X_train, Y_train), (X_test, Y_test) = mnist.load_data()X_train = X_train.reshape(X_train.shape, img_rows, img_cols, 1)
X_test = X_test.reshape(X_test.shape, img_rows, img_cols, 1)
input_shape = (img_rows, img_cols, 1)# cast floats to single precision
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')# rescale data in interval
X_train /= 255
X_test /= 255Y_train = keras.utils.to_categorical(Y_train, num_classes)
Y_test = keras.utils.to_categorical(Y_test, num_classes)from keras.models import Sequential
from keras.layers import Dense, Conv2D, Flatten
from keras.layers import MaxPooling2D, Dropout
model = Sequential()#add model layers
model.add(Conv2D(32, kernel_size=(5, 5),
activation='relu',
input_shape=input_shape))
model.add(MaxPooling2D(pool_size=(2, 2)))
# add second convolutional layer with 20 filters
model.add(Conv2D(64, (5, 5), activation='relu'))
# add 2D pooling layer
model.add(MaxPooling2D(pool_size=(2, 2)))
# flatten data
model.add(Flatten())
# add a dense all-to-all relu layer
model.add(Dense(1024, activation='relu'))
# apply dropout with rate 0.5
model.add(Dropout(0.5))
# soft-max layer
model.add(Dense(num_classes, activation='softmax'))#compile model using accuracy to measure model performance
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=)#train the model
model.fit(X_train, Y_train, validation_data=(X_test, Y_test), epochs=3)# evaluate the model
score = model.evaluate(X_test, Y_test, verbose=1)# print performance
print()
print('Test loss:', score)
print('Test accuracy:', score)#predict first 4 images in the test set
model.predict(X_test)model.predict_classes(X_test)#actual results for first 4 images in test set
Y_test

a continuar…

neste artigo, abordei a segunda parte do reconhecimento de imagens que está a construir uma rede Neural de convolução.espero que tenha encontrado o que veio buscar neste artigo e fique comigo para os próximos episódios desta viagem de reconhecimento de imagens!

PS: atualmente sou um mestre de engenharia em Berkeley, e se você quiser discutir o tema, sinta-se à vontade para me contactar. Aqui está o meu e-mail.

Deixe uma resposta

O seu endereço de email não será publicado.