Como ignorar o captcha: rede neural no Tensorflow, Keras, python v numérico noisy captcha

O tema Captcha não é novo, inclusive para Habr. No entanto, os algoritmos captcha estão mudando, assim como os algoritmos para resolvê-los. Portanto, propõe-se lembrar o antigo e operar a seguinte versão do captcha:



Ao longo do caminho, entenda o trabalho de uma simples rede neural na prática e também melhore seus resultados.

Imediatamente faça uma reserva de que não entraremos em pensamentos sobre como o neurônio funciona e o que fazer com tudo isso, o artigo não afirma ser científico, mas fornece apenas um pequeno tutorial.

Dançar do fogão. Em vez de se juntar


Talvez as palavras de alguém sejam repetidas, mas a maioria dos livros sobre Deep Learning começa realmente com o fato de o leitor receber dados pré-preparados com os quais ele começa a trabalhar. De alguma forma MNIST - 60.000 dígitos manuscritos, CIFAR-10, etc. Após a leitura, uma pessoa sai preparada ... para esses conjuntos de dados. Não está totalmente claro como usar seus dados e, o mais importante, como melhorar algo ao criar sua própria rede neural.

É por isso que o artigo no pyimagesearch.com sobre como trabalhar com seus próprios dados, bem como sua tradução, foi muito útil.

Mas, como se costuma dizer, o rabanete não é mais doce: mesmo com a tradução do artigo mastigado sobre keras, há muitos pontos cegos. Novamente, é oferecido um conjunto de dados pré-preparado, apenas com gatos, cães e pandas. Tem que preencher os vazios você mesmo.
No entanto, este artigo e código serão tomados como base.

Coletamos dados no captcha


Não há nada de novo aqui. Precisamos de amostras captcha, como a rede aprenderá com eles sob nossa orientação. Você pode extrair o captcha você mesmo, ou pode levar um pouco aqui - 29.000 captchas . Agora você precisa cortar os números de cada captcha. Não é necessário cortar todos os 29.000 captcha, especialmente porque 1 captcha fornece 5 dígitos. 500 captcha será mais que suficiente.

Como cortar? É possível no Photoshop, mas é melhor ter uma faca melhor.

Então, aqui está o código da faca python - download . (para Windows. Primeiro crie as pastas C: \ 1 \ test e C: \ 1 \ test-out).
A saída será um dump de números de 1 a 9 (não há zeros no captcha).
Em seguida, é necessário analisar esse bloqueio dos números em pastas de 1 a 9 e colocar em cada pasta pelo número correspondente. Mais ou menos ocupação. Mas em um dia você pode obter até 1000 dígitos.

Se, ao escolher uma figura, torna-se dúvida qual dos números, é melhor excluir esta amostra. E tudo bem se os números forem barulhentos ou entrarem incompletamente no "quadro":







Você precisa coletar 200 amostras de cada dígito em cada pasta. Você pode delegar esse trabalho a serviços de terceiros, mas é melhor fazer tudo sozinho para não procurar números correspondentes incorretamente mais tarde.

Rede neural. Teste


Tyat, tyat, nossas redes arrastaram o homem morto

Antes de começar a trabalhar com seus próprios dados, é melhor seguir o artigo acima e executar o código para entender que todos os componentes (keras, tensorflow etc.) estão instalados e funcionando corretamente.

Usaremos uma rede simples cuja sintaxe de inicialização é da linha de comando (!):

python train_simple_nn.py --dataset animals --model output/simple_nn.model --label-bin output/simple_nn_lb.pickle --plot output/simple_nn_plot.png 

* O Tensorflow pode escrever ao trabalhar com erros em seus próprios arquivos e métodos obsoletos, você pode corrigi-lo manualmente ou simplesmente ignorá-lo.

O principal é que, após a conclusão do programa, dois arquivos aparecem na pasta do projeto: simple_nn_lb.pickle e simple_nn.model, e a imagem do animal com uma taxa de inscrição e reconhecimento é exibida, por exemplo:



Rede neural - dados próprios


Agora que o teste de integridade da rede foi verificado, você pode conectar seus próprios dados e começar a treinar a rede.

Coloque nas pastas da pasta dat com números que contêm amostras selecionadas para cada dígito.
Por conveniência, colocaremos a pasta dat na pasta do projeto (por exemplo, ao lado da pasta animals).
Agora, a sintaxe para iniciar o aprendizado em rede será:

 python train_simple_nn.py --dataset dat --model output/simple_nn.model --label-bin output/simple_nn_lb.pickle --plot output/simple_nn_plot.png 

No entanto, é muito cedo para começar o treinamento.

Você precisa corrigir o arquivo train_simple_nn.py.

1. No final do arquivo:

 #model.summary() score = model.evaluate(testX, testY, verbose=1) print("\nTest score:", score[0]) print('Test accuracy:', score[1]) 

Isso adicionará informações.

2)

 image = cv2.resize(image, (32, 32)).flatten() 

mude para

 image = cv2.resize(image, (16, 37)).flatten() 
Aqui redimensionamos a imagem de entrada. Por que exatamente esse tamanho? Como a maioria dos dígitos cortados tem esse tamanho ou é reduzida a ele. Se você dimensionar para 32x32 pixels, a imagem ficará distorcida. Sim, e por que fazer isso?

Além disso, colocamos essa alteração em teste:

 try: image = cv2.resize(image, (16, 37)).flatten() except: continue 

Porque o programa não pode digerir algumas fotos e problemas Nenhum, portanto, elas são ignoradas.

3. Agora, a coisa mais importante. Onde há um comentário no código
definir arquitetura 3072-1024-512-3 com Keras

A arquitetura de rede no artigo é definida como 3072-1024-512-3. Isso significa que a rede recebe 3072 (32 pixels * 32 pixels * 3) na entrada, depois na camada 1024, na camada 512 e na saída 3 opções - um gato, um cachorro ou um panda.

No nosso caso, a entrada é 1776 (16 pixels * 37 pixels * 3), depois a camada 1024, a camada 512, na saída de 9 variantes de números.

Portanto, nosso código:

 model.add(Dense(1024, input_shape=(1776,), activation="sigmoid"))model.add(Dense(512, activation="sigmoid")) 

* 9 saídas não precisam ser indicadas adicionalmente, porque o próprio programa determina o número de saídas pelo número de pastas no conjunto de dados.

Lançamos


 python train_simple_nn.py --dataset dat --model output/simple_nn.model --label-bin output/simple_nn_lb.pickle --plot output/simple_nn_plot.png 

Como as imagens com números são pequenas, a rede aprende muito rapidamente (5 a 10 minutos), mesmo em hardware fraco, usando apenas a CPU.

Depois de executar o programa na linha de comandos, consulte os resultados:



Isso significa que, no conjunto de treinamento, a fidelidade foi alcançada - 82,19%, no controle - 75,6% e no teste - 75,59%.

Precisamos nos concentrar no último indicador em sua maior parte. Por que os outros também são importantes, será explicado mais adiante.

Vamos também ver a parte gráfica do trabalho da rede neural. Está na pasta de saída do projeto simple_nn_plot.png:



Mais rápido, mais alto, mais forte. Melhorando resultados


Um pouco sobre como configurar uma rede neural, veja aqui .

A opção autêntica é a seguinte.

Adicione eras.
No código, mudamos

 EPOCHS = 75 

em

 EPOCHS = 200 

Aumente o "número de vezes" em que a rede passará por treinamento.

Resultado:



Assim, 93,5%, 92,6%, 92,6%.

Nas imagens:



Aqui é perceptível que as linhas azul e vermelha após a 130ª era começam a se dispersar, e isso diz que um aumento adicional no número de épocas não funcionará. Veja isso.

No código, mudamos

 EPOCHS = 200 

em

 EPOCHS = 500 

e fugir novamente.

Resultado:



Então nós temos:
99%, 95,5%, 95,5%.

E no gráfico:



Bem, o aumento no número de épocas foi claramente para a rede. No entanto, esse resultado é enganoso.

Vamos verificar a operação da rede usando um exemplo real.

Para esses fins, o script predict.py está na pasta do projeto. Antes de começar, prepare.

Na pasta de imagens do projeto, colocamos os arquivos com as imagens dos números do captcha, que a rede não havia encontrado anteriormente no processo de aprendizado. I.e. é necessário obter dígitos que não sejam do dat dataset dat.

No próprio arquivo, corrigimos duas linhas para o tamanho padrão da imagem:

 ap.add_argument("-w", "--width", type=int, default=16, help="target spatial dimension width") ap.add_argument("-e", "--height", type=int, default=37, help="target spatial dimension height") 

Execute a partir da linha de comando:

 python predict.py --image images/1.jpg --model output/simple_nn.model --label-bin output/simple_nn_lb.pickle --flatten 1 


E vemos o resultado:



Outra foto:



No entanto, ele não funciona com todos os números ruidosos:



O que pode ser feito aqui?

  1. Aumente o número de cópias de números nas pastas para treinamento.
  2. Tente outros métodos.

Vamos tentar outros métodos


Como você pode ver no último gráfico, as linhas azul e vermelha divergem em torno da 130ª era. Isso significa que o aprendizado após a 130ª era é ineficaz. Fixamos o resultado na 130ª época: 89,3%, 88%, 88% e verificamos se outros métodos para melhorar a rede funcionam.

Reduza a velocidade do aprendizado.

 INIT_LR = 0.01 
em
 INIT_LR = 0.001 

Resultado:
41%, 39%, 39%

Bem, por.

Adicione uma camada oculta adicional.

 model.add(Dense(512, activation="sigmoid")) 
em
 model.add(Dense(512, activation="sigmoid")) model.add(Dense(258, activation="sigmoid")) 

Resultado:
56%, 62%, 62%

Melhor, mas não.

No entanto, se você aumentar o número de eras para 250:
84%, 83%, 83%

Ao mesmo tempo, as linhas vermelha e azul não se separam após a 130ª era:



Economize 250 eras e aplique o desbaste :

 from keras.layers.core import Dropout 

Insira o desbaste entre as camadas:

 model.add(Dense(1024, input_shape=(1776,), activation="sigmoid")) model.add(Dropout(0.3)) model.add(Dense(512, activation="sigmoid")) model.add(Dropout(0.3)) model.add(Dense(258, activation="sigmoid")) model.add(Dropout(0.3)) 

Resultado:
53%, 65%, 65%

O primeiro valor é mais baixo que o restante, isso indica que a rede não está aprendendo. Para fazer isso, é recomendável aumentar o número de eras.

 model.add(Dense(1024, input_shape=(1776,), activation="sigmoid")) model.add(Dropout(0.3)) model.add(Dense(512, activation="sigmoid")) model.add(Dropout(0.3)) 

Resultado:
88%, 92%, 92%

Com 1 camada extra, desbaste e 500 eras:

 model.add(Dense(1024, input_shape=(1776,), activation="sigmoid")) model.add(Dropout(0.3)) model.add(Dense(512, activation="sigmoid")) model.add(Dropout(0.3)) model.add(Dense(258, activation="sigmoid")) 

Resultado:
92,4%, 92,6%, 92,58%

Apesar de uma porcentagem menor em comparação com um simples aumento de eras para 500, o gráfico parece mais uniforme:



E a rede processa imagens que caíram anteriormente:



Agora, coletaremos tudo em um arquivo, que cortará a imagem com o captcha na entrada em 5 dígitos, executará cada dígito na rede neural e enviará o resultado ao intérprete python.

Aqui é mais simples. No arquivo que nos cortou os números do captcha, adicione o arquivo que lida com previsões.

Agora, o programa não apenas corta o captcha em 5 partes, mas também exibe todos os números reconhecidos no intérprete:



Novamente, é preciso lembrar que o programa não fornece 100% do resultado e, geralmente, um dos 5 dígitos está incorreto. Mas este é um bom resultado, considerando que no conjunto de treinamento existem apenas 170-200 cópias para cada número.

O reconhecimento Captcha dura de 3 a 5 segundos em um computador de potência média.

De que outra forma você pode tentar melhorar a rede? Você pode ler no livro "Biblioteca Keras - uma ferramenta de aprendizado profundo" A. Dzhulli, S. Pala.

O script final que corta o captcha e reconhece está aqui .
Começa sem parâmetros.
Scripts reciclados para treinamento e teste da rede.
Captcha para o teste, inclusive com falsos positivos - aqui .
O modelo para o trabalho está aqui .
Os números nas pastas estão aqui .

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


All Articles