Apêndice A — Pacotes

Este apêndice foi construído para mostrar a estrutura dos pacotes {captchaDownload} e {captchaOracle}, utilizados como auxiliares para implementação do WAWL, orquestradas pelo pacote {captcha}. Os pacotes {captchaDownload} e {captchaOracle} foram desenvolvidos para facilitar a obtenção dos resultados da tese, enquanto o pacote {captcha} pode ser utilizado por qualquer pessoa interessada em visualizar, anotar e resolver Captchas. As próximas subseções do apêndice descrevem os pacotes {captchaDownload} e {captchaOracle}.

Pacote captchaDownload

O pacote {captchaDownload} foi construído para armazenar os códigos de baixar dados de Captchas de forma consistente. O pacote também inclui funções para trabalhar com oráculos.

O pacote não foi criado para ser usado pelo público geral. O intuito de criar o pacote foi o de organizar as funções utilizadas para realizar as simulações e obter os resultados empíricos da tese. Apesar disso, o código está disponível publicamente para quem tiver interesse em usar como referência para construir funções que acessam o oráculo.

As funções do pacote {captchaDownload} são organizadas em dois tipos principais. As funções de acesso, identificadas pelo termo _access, fazem o download da imagem do Captcha e retornam todas as informações necessárias para fazer a verificação do oráculo, como, por exemplo, cookies e dados da sessão do usuário. Já as funções de teste, identificadas pelo termo _test, servem para verificar se um rótulo fornecido para o Captcha está correto ou não.

As funções ficam mais claras através de um exemplo. No caso do TRF5, por exemplo, o acesso é feito pela página do sistema PJe. A função captcha_access_trf5() recebe o parâmetro path=, que é a pasta para salvar a imagem, retornando uma lista com o caminho da imagem que foi salva e de componentes da sessão do usuário.

Código
acesso <- captchaDownload:::captcha_access_trf5("assets/img")
acesso
$f_captcha
assets/img/trf5ac031dafbd.jpeg

$j_id
[1] "j_id1"

$u
[1] "https://pje.trf5.jus.br/pjeconsulta/ConsultaPublica/listView.seam"

Em seguida, obtém-se o rótulo do modelo. Isso pode ser feito manualmente ou através de um modelo.

Código
library(captcha)
captcha <- read_captcha(acesso$f_captcha)
plot(captcha)
modelo_trf5 <- captcha_load_model("trf5")
(lab <- decrypt(acesso$f_captcha, modelo_trf5))
#> [1] "969588"

Figura A.1: Exemplo de Captcha baixado diretamente do TRF5

Agora, aplica-se a função captcha_test_trf5() para verificar se o rótulo está correto ou incorreto. A verificação é feita de forma automática, diretamente da internet, através do oráculo. A função recebe dois parâmetros: obj= com as informações obtidas da função de acesso; e label=, o rótulo obtido. A função retorna TRUE se o rótulo está correto e FALSE caso contrário.

Código
(acertou <- captchaDownload:::captcha_test_trf5(acesso, lab))
[1] TRUE

Cada Captcha possui uma função de acesso e uma função de teste. Na prática, se uma pessoa desejar resolver um novo Captcha usando a técnica do oráculo, são essas funções que ela precisaria desenvolver. Todas as outras operações podem ser generalizadas para diferentes casos de uso e estão implementadas nos pacotes {captchaDownload} e {captchaOracle}. Vale notar que a construção dessas funções geralmente é necessária para a construção de web scrapers, ou seja, elas não criam dificuldades adicionais para pessoas interessadas em resolver Captchas para acessar dados da internet.

A função principal do pacote {captchaDownload} é a captcha_oracle(). A função é responsável por realizar a anotação parcial automática dos Captchas utilizando um modelo inicial e o oráculo. A função possui os seguintes parâmetros:

  • path=: caminho em que os arquivos serão salvos.
  • model=: modelo para predizer o rótulo de uma imagem.
  • max_ntry=: quantidade máxima de chutes até desistir.
  • manual=: caso o máximo de tentativas seja alcançado, abrir o prompt para anotar manualmente? Por padrão, sim.
  • captcha_access=: função que baixa um Captcha e retorna dados da sessão para validar o Captcha, como mostrada anteriormente.
  • captcha_test=: função que testa se um Captcha está correto a partir de um rótulo específico, como mostrado anteriormente.

A função amarra todos os conceitos necessários para criar bases de dados de forma automática. Primeiro, considera o caminho para salvar os dados. Em seguida, considera o modelo e formas de lidar com o oráculo. Por último, recebe as funções de acesso e de teste do Captcha. A função escreve um arquivo de log com os resultados dos testes. O arquivo contém max_ntry linhas, podendo ter uma linha adicional se manual=TRUE, já que, se o modelo errar todos os chutes, a anotação manual deve ser adicionada.

No exemplo do TRF5, a chamada da função captcha_oracle() com um chute ficaria da seguinte forma:

Código
modelo_trf5 <- captcha_load_model("trf5")

captchaDownload::captcha_oracle(
  path = "assets/img/",
  model = modelo_trf5, 
  max_ntry = 1,
  manual = TRUE, 
  captcha_access = captchaDownload:::captcha_access_trf5,
  captcha_test = captchaDownload:::captcha_test_trf5
)
✔ Acertou!!!

No teste do exemplo, a função acertou, salvando o seguinte arquivo de log1.

ntry, label , type, result
1,    569328, auto, TRUE

Abaixo, foi colocado um modelo ruim para o TRT, para forçar o modelo a errar todos os chutes. O resultado é o log abaixo

Código
modelo <- captcha_load_model("assets/modelo_ruim.pt")

captchaDownload::captcha_oracle(
  path = "assets/img/",
  model = modelo, 
  max_ntry = 10,
  manual = TRUE, 
  captcha_access = captchaDownload:::captcha_access_trt,
  captcha_test = captchaDownload:::captcha_test_trt
)
ℹ Temos 10 candidatos...
ℹ Errou! O chute foi: v2su7w
ℹ Errou! O chute foi: t2su7w
ℹ Errou! O chute foi: v2su7y
ℹ Errou! O chute foi: t2su7y
ℹ Errou! O chute foi: y2su7w
ℹ Errou! O chute foi: v2su7h
ℹ Errou! O chute foi: t2su7h
ℹ Errou! O chute foi: y2su7y
ℹ Errou! O chute foi: v2wu7w
Label: v2xu7w

No novo exemplo, a função errou todos os dez chutes, salvando o seguinte arquivo de log2. O último valor é um rótulo inserido manualmente.

ntry,  label,   type, result
   1, v2su7w,   auto,  FALSE
   2, t2su7w,   auto,  FALSE
   3, v2su7y,   auto,  FALSE
   4, t2su7y,   auto,  FALSE
   5, y2su7w,   auto,  FALSE
   6, v2su7h,   auto,  FALSE
   7, t2su7h,   auto,  FALSE
   8, y2su7y,   auto,  FALSE
   9, v2wu7w,   auto,  FALSE
  10, 92su7w,   auto,  FALSE
  NA, v2xu7w, manual,   TRUE

Se o parâmetro manual=FALSE e o modelo não consegue acertar o rótulo, a função também adiciona a mensagem:

✖ Errado depois de todas as tentativas...

Em alguns casos, é possível que a função realize menos do que max_ntry chutes. Isso acontece quando a probabilidade do melhor rótulo depois do chute errado é muito pequena, segundo o modelo. Isso é feito pela função captcha_candidates(), que considera como padrão o corte de 0.01 de probabilidade. Ou seja, na prática, a função testa no máximo os max_ntry rótulos com probabilidades maiores que 0.01 segundo o modelo.

Em resumo, o pacote {captchaDownload} contém toda a parte de web scraping utilizada no desenvolvimento da tese. Adicionalmente, o pacote contém funções para orquestrar o download automático de Captchas parcialmente rotulados, a partir de um modelo inicial e um oráculo.

Os dados fornecidos pelo pacote ficam tanto na forma de imagens rotuladas quanto na forma de arquivos de log, disponibilizados em arquivos CSV. Para lidar com essa estrutura de dados, mais um pacote foi desenvolvido: o {captchaOracle}, definido a seguir.

Pacote captchaOracle

O pacote {captchaOracle}, assim como o {captchaDownload}, foi desenvolvido para a construção da tese. O pacote, portanto, não apresenta documentação extensiva e suas funções podem não estar com a sintaxe final. Futuramente, o pacote poderá funcionar como novo backend para o pacote {captcha}, aplicando o WAWL como uma alternativa no fluxo de resolução de Captchas definido na Subseção 3.2.3.

O pacote possui quatro funções principais: a captcha_dataset_oracle(), a net_captcha_oracle(), a oracle_loss() e a captcha_accuracy_oracle(). Cada função desempenha um papel similar a seus pares do pacote {captcha}, mas conseguem lidar com a estrutura de dados fornecida pelo oráculo.

A primeira função a ser utilizada é a captcha_dataset_oracle(). Trata-se de uma função similar à captcha_dataset() do pacote {captcha}, mas com um parâmetro adicional, path_logs=, que recebe o caminho dos arquivos de log.

A estrutura de dados no caso do oráculo é mais complexa do que no caso canônico. Na resposta, ao invés de guardar uma matriz one hot para cada Captcha, é armazenada uma lista com várias matrizes one hot, uma para cada tentativa do Captcha. Além disso, é armazenado um vetor z, com zeros e uns, informando se algum rótulo está correto ou se todos os rótulos estão incorretos. A variável z é construída a partir dos nomes dos arquivos, que contém um _1 caso o rótulo esteja correto e _0 caso contrário. Por último, a imagem de entrada é armazenada da mesma forma que na função captcha_dataset().

O módulo net_captcha_oracle() faz poucos ajustes à estrutura inicial fornecida pelo módulo net_captcha() do pacote {captcha}. A única modificação da função é que ela recebe um modelo inicial de entrada, transferindo os pesos ajustados do modelo ao novo módulo. O módulo net_captcha_oracle(), inclusive, poderia ser utilizado fora do contexto do WAWL, já que só utiliza os dados de input, que não são alterados.

A função captcha_accuracy_oracle() é utilizada para estimar a acurácia do modelo. Para isso, a função precisa lidar com o fato de que os dados de validação apresentam uma estrutura diferente dos dados de treino, já que estão completamente anotados. No treino, a acurácia é calculada considerando apenas os casos em que a resposta é conhecida. Na validação, a acurácia é calculada considerando-se todas as observações.

Por último, a função oracle_loss() é a que contém a proposta de função de perda do método WAWL. Nos casos corretos, a função de perda é obtida calculando-se uma entropia cruzada simples. Nos casos incorretos, a perda é calculada pela estratégia 1-p, ou seja, considerando o complementar da probabilidade de observar os chutes que foram apresentados segundo o modelo.

Em resumo, o pacote {captchaOracle} é o que contém os principais avanços da tese do ponto de vista estatístico. Na prática, é utilizado como backend computacional para ajuste dos modelos que utilizam o oráculo, dentro de um fluxo de trabalho igual ao que é construído para ajuste dos modelos canônicos.

Os códigos para realizar as simulações do modelo foram adicionados na pasta data-raw do pacote {captchaOracle}. Os códigos foram organizados da seguinte forma:

  • passo_01_*.R. Contêm os códigos utilizados para ajustar os modelos iniciais. Os códigos são organizados de forma a permitir que vários modelos sejam rodados em paralelo, aproveitando o máximo do poder computacional da máquina utilizada para realizar os ajustes.
  • passo_02_*.R. Contêm os códigos utilizados para construir as bases de treino e validação para o passo 03. Foi o passo mais demorado da simulação, já que envolveu acessar os sites dos tribunais pela internet para obtenção dos Captchas anotados automaticamente. Para realizar a simulação, foram baixados mais de 500.000 Captchas da internet.
  • passo_03_*.R. Contêm os códigos utilizados para ajustar os modelos finais. Os códigos foram organizados de forma similar ao passo 01, mas utilizando as funções desenvolvidas no pacote {captchaOracle} para considerar os dados fornecidos pelo oráculo.

Por fim, foi adicionado também um script report.R, que monta as bases principais e os resumos dos modelos ajustados. As bases fornecidas pelo último script foram adicionadas ao repositório da tese.


  1. Espaços foram adicionados manualmente para facilitar a visualização.↩︎

  2. Espaços foram adicionados para facilitar a visualização.↩︎