Os bancos de dados a serem migrados podem ter uma ampla variedade de representações e conteúdos de dados. Desde simples campos de dados numéricos até campos com estrutura e conteúdo complexos, que podem conter arquivos, imagens, tabelas ou até mesmo objetos personalizados complexos (por exemplo, nos formatos XML, CLOB, BLOB etc.).
A descoberta de dados mais simples pode ser feita de forma fácil e muito eficiente usando métodos tradicionais com alguns conhecimentos básicos e conjuntos de valores. Contudo, à medida que os dados se tornam mais complexos, esta eficiência diminui até que os métodos tradicionais não sejam mais suficientes.
Esses dados mais complexos podem ser, por exemplo, texto não estruturado ou ficheiros binários cujo tipo e conteúdo não podem ser claramente identificados e interpretados. Para efeitos de argumentação, vamos ignorar o facto de que a utilização de tais tipos de dados em bases de dados se justifica apenas em alguns casos específicos, uma vez que este problema surge frequentemente durante a migração de sistemas complexos. Esses formatos de dados complexos são geralmente não estruturados, estruturalmente apenas um conjunto de bytes em um determinado campo, sobre o qual o usuário muitas vezes não possui informações confiáveis devido à documentação incompleta. Sem meta-informação é difícil tirar conclusões sobre o tipo de conteúdo e a sua interpretação. Portanto, nossa primeira tarefa é decidir sobre esses campos que tipo de dados eles contêm.
A maneira mais óbvia de identificar os tipos de arquivos seria verificar sua extensão, mas quando armazenada em um banco de dados, essa informação normalmente não está disponível ou, mesmo que estivesse, não poderia ser usada com o máximo de confiança. Supondo que apenas a versão binária dos dados esteja disponível, ou seja, Binary Large Object (BLOB), o primeiro passo é carregá-lo. Todos os metadados são codificados neste BLOB, de acordo com o formato do arquivo.
Dependendo do formato do arquivo ou do tipo de dados, os metadados do arquivo podem aparecer em vários locais do arquivo, no cabeçalho ou no final do arquivo. Além de identificar o formato do arquivo, os cabeçalhos dos arquivos também podem conter metadados sobre o arquivo e seu conteúdo. Arquivos baseados em caracteres (texto) geralmente possuem cabeçalhos baseados em caracteres, enquanto os formatos binários geralmente possuem cabeçalhos binários, embora isso não seja um padrão, apenas uma prática do setor.
A distribuição dos valores de bytes em diferentes tipos de arquivo mostra um padrão diferente para cada tipo. As primeiras tentativas focaram na distribuição de bytes de todo o arquivo, mas métodos mais recentes realizam amostragens diferentes, como analisar apenas amostras do início, fim e meio dos arquivos. Estas amostras podem fornecer uma boa base para aprendizado de máquinaque pode determinar (com alguma probabilidade) o tipo de arquivos desconhecidos usando um modelo construído nas diferentes distribuições. Num procedimento baseado BFD (Byte Frequency Distribution), não é necessário ler o arquivo inteiro, o que economiza tempo. Os valores extraídos de diversas posições do arquivo são analisados estatisticamente para obter uma impressão digital específica do arquivo. Com base nessa impressão digital, o aprendizado de máquina é capaz de encontrar o tipo de arquivo no modelo – aquele que ensinamos com arquivos conhecidos – que melhor se adapta a ele.
A figura abaixo mostra a distribuição de bytes de alguns tipos de arquivos:
Observe que todos os códigos e exemplos de dados de entrada/saída neste artigo são derivados do Clarity Consulting MigNon ferramenta. Este software assistente de migração de dados é o resultado de um projeto plurianual de P&D, parcialmente financiado pela União Europeia.
Aplicando aprendizado de máquina ao reconhecimento de formato de arquivo
O aprendizado de máquina pode ser um método eficaz para reconhecimento de formato de arquivo, especialmente ao trabalhar com grandes conjuntos de dados. Os seguintes modelos podem ser considerados para detecção de formato de arquivo:
- Ingênuo Bayes: Adequado para análise baseada em bytes ou sequências, onde são levadas em consideração características típicas de cada formato de arquivo, como distribuições de bytes ou padrões característicos.
- Máquinas de vetores de suporte (SVM): Uma boa escolha quando os limites entre formatos de arquivo, ou seja, superfícies de decisão, precisam ser definidos com base na frequência de bytes.
- Floresta Aleatória: Entre os métodos de aprendizagem em conjunto, o Random Forest é frequentemente usado porque pode lidar com muitos formatos de arquivo diferentes e lidar com dados ruidosos.
- Redes Neurais Convolucionais (CNNs): CNNs são capazes de reconhecer padrões de distribuição de bytes e podem tratar arquivos como imagens onde a frequência de bytes é interpretada como “pixels”, reconhecendo assim diferentes formatos de arquivo.
- Codificador automático: pode ser usado para aprendizado não supervisionado, especialmente para detecção de anomalias, ao tentar detectar arquivos com padrão de bytes diferente do usual para um determinado formato de arquivo.
- K-vizinhos mais próximos (KNN): para conjuntos de dados pequenos, esta pode ser uma maneira simples, mas eficaz, de identificar formatos de arquivo com base na semelhança de seus vizinhos mais próximos.
- Redes Neurais Recorrentes (RNNs): como os RNNs lidam com dados sequenciais com eficiência, eles podem ser úteis para tarefas em que as sequências de bytes em um arquivo são importantes.
Para reconhecimento automatizado de formato de arquivo, o LightGBM (Light Gradient Boosting Machine) pode ser uma boa escolha por vários motivos. Primeiro, é altamente eficiente em conjuntos de dados grandes e diversos, otimizado para aprendizagem e previsão rápidas e, portanto, tem um bom desempenho para análise de formatos de arquivo com grandes distribuições de bytes ou muitas amostras. Requer pouca memória, o que pode ser uma consideração importante ao detectar e classificar vários formatos de arquivo em um sistema. É um membro da família de modelos de aumento de gradiente, que pode modelar com eficiência superfícies de decisão complexas e essa precisão pode ser crítica na detecção de formatos de arquivo onde a frequência de bytes pode ter distribuições discretas.
A solução LightGBM é orientada por dados e, como precisamos de uma quantidade maior de dados para construir um modelo com a qualidade certa, criamos um sistema de download quase automatizado para isso em nosso exemplo. Para implementar nosso sistema de download automatizado, usamos Selenium em Python para controlar o navegador usando um driver Firefox. Isso nos permitiu pesquisar links e elementos HTML e, em seguida, realizar ações sobre eles, como clicar ou inserir dados. Durante os downloads automáticos, lidamos com tipos de arquivos como CSV, DOC, DOCX, XML, JPG, JSON, PDF, PNG, XLS e XLSX, mas alguns arquivos, como MP3 ou AVI, tiveram que ser coletados e processados manualmente. Os arquivos foram coletados de várias fontes, como kaggle.com para arquivos CSV e JSON, enquanto imagens PNG e JPG foram baixadas de imgur.com. Os vídeos do YouTube foram baixados em formato MP4 de btclod.com e convertidos para AVI usando WinFF. Para arquivos ZIP, a compactação e o download foram feitos por scripts Python separados. Os downloads automatizados foram cuidadosamente organizados em uma estrutura de diretórios apropriada. O volume de download e a qualidade dos dados foram controlados por parâmetros do programa. Alguns dos nossos dados de teste foram coletados manualmente para garantir que havia arquivos diferentes, mas não conseguimos coletar quantidades suficientes de cada tipo de arquivo, portanto, em muitos casos, os downloads automáticos continuaram sendo o principal método de geração de dados.
As quantidades de dados de entrada obtidas foram as seguintes:


O reconhecimento dos detalhes do padrão de distribuição de frequência de bytes mencionado na introdução é a base para a construção do modelo LightGBM nos dados coletados. O processamento de uma lista completa de bytes é caro, portanto, para determinar a extensão do arquivo, os dados são filtrados através de um BFD, o que pode ser visto como uma espécie de “impressão digital parcial”. Usando isso como dados de entrada, podemos determinar o tipo de alguns arquivos do modelo. Isso é feito criando um HASH-MAP de frequência a partir de um array de bytes, onde as chaves são os bytes e os valores são o número de ocorrências. Como as chaves são números positivos (0 a 255), esse HASH-MAP pode ser facilmente convertido em um array, o que acelera o processo de normalização. A normalização, neste caso, significa construir uma distribuição de probabilidade a partir dos valores de frequência. Como resultado, a soma das frequências normalizadas dará o valor 1. Esta forma normalizada será o BFD.
Testando e ajustando o modelo
O principal problema na definição de extensões de arquivo era que o modelo inicial, que funcionava com 256 bytes, não conseguia distinguir entre formatos semelhantes, como XML, JSON, ZIP, DOCX e XLSX. Destes, o formato ZIP era particularmente confuso porque DOCX e XLSX contêm XML agrupado em um arquivo ZIP. A confusão entre XML e JSON também era comum, pois são muito semelhantes em estrutura. Devido a esses fatores, a precisão do modelo para esses tipos de arquivos permaneceu baixa, sendo necessário aprimorar o modelo e introduzir novas funcionalidades.
Para melhorar a precisão, os seguintes recursos foram adicionados
- Taxas de bytes de 60, 62
- Taxas de bytes de 123, 125
- série de bytes sharedStrings
Para refinar o modelo, introduzimos vários recursos específicos de bytes para identificar diferentes tipos de arquivos. Por exemplo, os bytes 60 e 62, que correspondem aos símbolos ‘<' e '>‘, desempenharam um papel fundamental na identificação precisa dos arquivos XML. Da mesma forma, os bytes 123 e 125, que representam os caracteres ‘{‘ e ‘}’, foram úteis na identificação de arquivos JSON. Para o reconhecimento de arquivos DOCX, utilizamos a proporção da sequência de bytes ‘ Para detecção de arquivos XLSX, a sequência de bytes “sharedStrings” funcionou muito bem porque todos os arquivos XLSX contêm o arquivo sharedStrings.xml, que não é analisado pelo formato ZIP. No entanto, esse recurso acabou sendo descartado porque seu comprimento o tornava muito sensível até mesmo às menores alterações. Embora esses recursos tenham melhorado a eficiência do modelo, a identificação exata dos arquivos ZIP permaneceu problemática e tivemos que utilizar outro método para identificá-los. Como não sabíamos exatamente quais recursos seriam necessários para identificar arquivos ZIP com segurança, decidimos incluir todas as combinações possíveis de 2 bytes no modelo para aumentar a precisão. No entanto, essa abordagem exigia muito memória, tempo e processador porque o processo de aprendizagem precisava lidar com uma enorme quantidade de dados. Para otimizar isso, planejamos usar apenas os 500 recursos mais importantes de 2 bytes, reduzindo significativamente a carga nos recursos computacionais sem comprometer a eficiência do modelo. Com base em nossas análises iniciais, alcançamos mais de 90% de precisão para todas as classes individualmente, exceto para arquivos XML, onde alcançamos apenas 49%. Isso indicou que o modelo pode ter um problema de overfitting. O overfitting pode ocorrer quando o modelo usa muitos recursos, fazendo com que ele tome decisões mais rapidamente, por exemplo, nos pontos finais das árvores de decisão. Isso pode resultar em alta precisão no conjunto de treinamento, mas em pior generalização em dados reais. Uma das maneiras mais eficazes de lidar com o overfitting é reduzir o número de recursos usados. O modelo final contém uma combinação de três recursos. Primeiro, 256 recursos de byte único que examinam a frequência de ocorrência de cada byte. Isto é seguido por um recurso adicional que mede a proporção de símbolos ‘<' e '>‘ (bytes 60 e 62), que são particularmente úteis para reconhecer arquivos XML. Finalmente, o modelo inclui 42 recursos selecionados de dois bytes que, com base em análises anteriores, são mais relevantes para a identificação do tipo de arquivo. Esses recursos combinados ajudam a aumentar a precisão do modelo na identificação de diferentes tipos de arquivos. Após a finalização do modelo, as seguintes precisões foram encontradas na pilha de teste, divididas por tipo de arquivo. Como os elementos de uma coluna em uma tabela são do mesmo tipo, a precisão pode ser aumentada classificando esses pontos de dados binários simultaneamente em um conjunto, pois mesmo que haja um ponto de dados mal classificado no conjunto, os outros pontos de dados irão empurrar o média em direção à classificação correta. As medições de tempo de execução da API para diferentes tamanhos de conjunto para o modelo produziram os seguintes resultados (o tamanho médio do arquivo era de 5 MB e o teste foi feito em uma máquina com processador Intel Core i7-2600 de 3,4 GHz e 1333 MHz de RAM). Os seguintes tempos de execução foram medidos dependendo do uso de memória: – 89,428 segundos com uso máximo de RAM de 7,28 GB – 56,451 segundos com uso máximo de RAM de 4,55 GB – 30,186 segundos com uso máximo de RAM de 2,58 GB A imagem do Docker consiste nos seguintes arquivos: A estrutura do dockerfile é a seguinte: O reconhecimento do formato de arquivo é um desafio na migração de dados, especialmente para sistemas legados não documentados. A estrutura de codificação de arquivos, como BLOBs, dificulta a identificação do formato e são necessários métodos mais avançados. Nossa experiência mostra que combinar aprendizado de máquina com distribuição de frequência de bytes (BFD) pode identificar arquivos com eficiência com base em seus padrões de distribuição de bytes. A precisão do modelo pode ser aumentada adicionando sequências de bytes e recursos específicos para distinguir com segurança entre diferentes formatos. O modelo final resultante, executado em um ambiente Dockerizado, pode ser implementado como um serviço flexível e eficiente que pode ser usado em projetos de migração de dados. .
A figura acima mostra a progressão da precisão para as 3 classes de precisão mais baixas (XLSX, XLS, XML) para diferentes tamanhos de conjuntos. As três classes de precisão mais baixas são escolhidas porque exigem o maior tamanho de conjunto para atingir 100% de precisão geral. O método nos permite determinar o tamanho mínimo do conjunto necessário no pior caso. Pode-se observar que mesmo no pior caso, a precisão média do modelo aumenta para quase 100% ao classificar 7 arquivos por vez.
Implementação de reconhecimento de arquivo baseada em microsserviços
O serviço é conteinerizado usando Docker, baseado nos módulos Python fastAPI e uvicorn. No processo de chamada da API, o sistema primeiro recebe a solicitação e depois converte os dados recebidos para o formato binário (Base64). Os dados binários são então usados para gerar o valor de distribuição de frequência de bytes (BFD) do ponto de dados. Uma vez gerado o BFD, o BFD associado ao ponto de dados e um modelo do tipo lightGBM são usados para classificação da detecção do tipo de arquivo. O sistema registra os eventos e trata quaisquer erros. Por fim, ao final do processo, o sistema envia uma resposta ao usuário.
Na chamada de serviço a estrutura Body contém apenas dois campos “data”, este atributo é uma lista de objetos JSON, e “id”. Esses objetos JSON possuem um campo “bit” (que é uma string contendo a versão codificada em base64 do arquivo).
A resposta do endpoint /predict é um objeto JSON que contém um código de status. A estrutura do objeto JSON é semelhante ao corpo da solicitação. A resposta conterá um campo “dados” cujo valor é uma lista. Esta lista contém objetos JSON adicionais que contêm os campos “id” e “pred”. O valor do campo “id” pode ser o identificador atribuído ao item enviado ou um identificador gerado se não for especificado originalmente para o campo “bit”. O campo de previsão (“pred”) também contém um objeto JSON que contém pares de valores-chave de extensão e probabilidade.
Pensamentos finais





