O GitHub possui mais de 300 linguagens de programação, variando de linguagens conhecidas como Python, Java e Javascript a linguagens esotéricas como
Befunge , conhecidas apenas por pequenos grupos de pessoas.
As 10 principais linguagens de programação hospedadas no GitHub por número de repositóriosUm dos problemas que o GitHub enfrenta é o reconhecimento de diferentes linguagens de programação. Quando algum código é colocado no repositório, o reconhecimento de seu tipo é muito importante. Isso é necessário por motivos de pesquisa, alertas de vulnerabilidade, destaque de sintaxe e representação estrutural do conteúdo do repositório para os usuários.
À primeira vista, o reconhecimento de idiomas é uma tarefa simples, mas não é bem assim.
Linguista é a ferramenta que estamos usando atualmente para definir uma linguagem de programação no GitHub. Linguist é um aplicativo Ruby que usa uma variedade de estratégias de reconhecimento de idioma, incluindo informações de nome e extensões de arquivo. Além disso, leva em consideração os modelos Vim ou Emacs, bem como o conteúdo na parte superior do arquivo (shebang). O linguista processa heuristicamente a ambiguidade linguística e, se isso não der certo, usa um classificador bayesiano ingênuo treinado em uma pequena amostra de dados.
Embora o Linguist preveja muito bem no nível do arquivo (precisão de 84%), tudo quebra quando os nomes dos arquivos são estranhos, e mais ainda quando os arquivos não têm extensões. Isso torna o Linguista inútil para conteúdo como GitHub Gists ou trechos de código em README, erros e solicitações pull.
Para tornar a definição da linguagem mais clara a longo prazo, desenvolvemos um classificador de aprendizado de máquina chamado OctoLingua. Baseia-se na arquitetura da Rede Neural Artificial (RNA), que pode lidar com a previsão de linguagem em cenários não triviais. A versão atual do modelo pode fazer previsões para as 50 principais linguagens de programação no GitHub e ultrapassar o Linguist com precisão.
Mais detalhes sobre o OctoLingua
O OctoLingua foi escrito do zero em Python, Keras com o back-end do TensorFlow - foi criado para ser preciso, confiável e fácil de manter. Nesta parte, falaremos sobre nossas fontes de dados, arquitetura de modelo e testes de desempenho do OctoLingua. Também falaremos sobre o processo de adicionar a capacidade de reconhecer um novo idioma.
Fontes de dados
A versão atual do OctoLingua foi treinada em arquivos obtidos do
Rosetta Code e de um conjunto de repositórios de fontes crowds. Limitamos nosso conjunto de idiomas aos 50 mais populares no GitHub.
O Rosetta Code foi um excelente conjunto de dados inicial, pois continha código fonte escrito para executar a mesma tarefa, mas em diferentes linguagens de programação. Por exemplo, o código para gerar
números de Fibonacci foi apresentado em C, C ++, CoffeeScript, D, Java, Julia e outros. No entanto, a cobertura das linguagens era heterogênea: para algumas linguagens de programação, havia apenas alguns arquivos com código; para outros, os arquivos continham pouco código. Portanto, era necessário complementar nosso conjunto de dados de treinamento com algumas fontes adicionais e, assim, melhorar significativamente a cobertura de idiomas e a eficácia do modelo final.
Nosso processo de adição de um novo idioma não é totalmente automatizado. Compilamos programaticamente o código fonte dos repositórios públicos no GitHub. Selecionamos apenas os repositórios que atendem aos critérios mínimos de qualificação, como o número mínimo de garfos que cobrem o idioma de destino e cobrem extensões de arquivos específicas. Nesta fase da coleta de dados, definimos o idioma principal do repositório usando a classificação do Linguista.
Sintomas: Com base em conhecimentos anteriores
Tradicionalmente, arquiteturas baseadas em memória, como Redes Neurais Recorrentes (RNN) e Redes de Memória de Longo Prazo (LSTM), são usadas para resolver problemas de classificação de texto usando redes neurais. No entanto, diferenças nas linguagens de programação no vocabulário, extensões de arquivo, estrutura, estilo de importação de bibliotecas e outros detalhes nos forçaram a apresentar uma abordagem diferente que utiliza todas essas informações, extraindo alguns sinais em forma de tabela para treinar nosso classificador. Os atributos são recuperados da seguinte maneira:
- Os 5 principais caracteres especiais de um arquivo
- Os 20 principais caracteres de um arquivo
- Extensão de arquivo
- A presença de caracteres especiais específicos usados no código fonte dos arquivos, como dois pontos, chaves, ponto e vírgula
Rede Neural Artificial Modelo (RNA)
Utilizamos os fatores acima como entrada para uma rede neural de duas camadas criada usando Keras com um back-end Tensorflow.
O diagrama abaixo mostra que a etapa de extração do recurso cria uma entrada de tabela n-dimensional para o nosso classificador. À medida que as informações se movem pelas camadas da nossa rede, elas são ordenadas pelo abandono e o resultado é uma saída em 51 dimensões, que representa a probabilidade de que esse código seja escrito em cada um dos 50 principais idiomas do GitHub. Também mostra a probabilidade de que o código não seja escrito em nenhum dos 50 idiomas.
Estrutura da RNA do modelo de origem (50 idiomas + 1 para "outros")Utilizamos 90% do nosso banco de dados de origem para treinamento. Além disso, na etapa de treinamento do modelo, parte das extensões de arquivo foi removida para que o modelo pudesse aprender especificamente com o vocabulário dos arquivos, e não com as extensões, que prevêem tão bem a linguagem de programação.
Teste de desempenho
OctoLingua vs Linguist
Na tabela abaixo, mostramos a
pontuação F1 (média harmônica entre precisão e completude) para OctoLingua e Linguist calculada no mesmo conjunto de testes (10% do volume de nossa fonte de dados original).
Três testes são mostrados aqui. No primeiro teste, o conjunto de dados não foi tocado; no segundo, as extensões de arquivo foram excluídas; no terceiro, as extensões de arquivo foram misturadas para confundir o classificador (por exemplo, um arquivo Java pode ter a extensão ".txt" e um arquivo Python pode ter a extensão ".java".
A intuição por trás do embaralhamento ou exclusão de extensões de arquivos em nosso conjunto de testes é avaliar a confiabilidade do OctoLingua na classificação de arquivos quando uma tag de chave é excluída ou enganosa. Um classificador que não seja muito dependente da extensão seria extremamente útil para classificar logs e trechos de código, porque nesses casos as pessoas geralmente não fornecem informações precisas sobre a extensão (por exemplo, muitos logs relacionados a código têm a extensão txt).
A tabela abaixo mostra como o OctoLingua tem bom desempenho sob várias condições, quando assumimos que o modelo aprende principalmente com o vocabulário do código, e não com as meta-informações (por exemplo, a extensão do arquivo). Ao mesmo tempo, o Linguist determina o idioma incorretamente, assim que as informações sobre a extensão correta do arquivo estavam ausentes.
Desempenho do OctoLingua vs. Linguista no mesmo conjunto de testesO efeito da remoção de extensões de arquivo ao treinar um modelo
Como mencionado anteriormente, durante o treinamento, removemos uma certa porcentagem de extensões de arquivo dos dados para fazer o modelo aprender com o vocabulário dos arquivos. A tabela abaixo mostra o desempenho do nosso modelo com várias proporções de extensões de arquivo excluídas durante o treinamento.
Desempenho do OctoLingua com porcentagem diferente de extensões de arquivo excluídasObserve que um modelo treinado em arquivos com extensões é significativamente menos eficaz em arquivos de teste sem extensões ou com extensões mistas do que em dados de teste regulares. Por outro lado, quando um modelo é treinado em um conjunto de dados no qual parte das extensões de arquivo é removida, o desempenho do modelo não diminui muito no conjunto de testes modificado. Isso confirma que a remoção de extensões de parte dos arquivos durante o treinamento solicita que o classificador aprenda mais sobre o vocabulário do código. Também mostra que a extensão do arquivo tendia a dominar e impedia a ponderação do conteúdo em destaque.
Suporte para novos idiomas
Adicionar um novo idioma ao OctoLingua é um processo bastante simples. Começa com as pesquisas e a obtenção de um grande número de arquivos em um novo idioma (podemos fazer isso de forma programática, conforme descrito na seção "Fontes de dados"). Esses arquivos são divididos em conjuntos de treinamento e teste e passam pelo nosso pré-processador e extrator de recursos. Um novo conjunto de dados é adicionado ao pool existente. O kit de teste nos permite garantir que a precisão do nosso modelo permaneça aceitável.
Adicionando um novo idioma ao OctoLinguaNossos planos
O OctoLingua está atualmente em um "estágio avançado de prototipagem". Nosso mecanismo de classificação de idiomas já é confiável, mas ainda não suporta todas as linguagens de programação disponíveis no GitHub. Além de expandir o suporte ao idioma, o que não é tão difícil, nós nos esforçamos para fornecer detecção de idioma com vários níveis de detalhes do código. Nossa implementação atual já nos permite, com uma ligeira modificação de nosso mecanismo de aprendizado de máquina, classificar fragmentos de código. Além disso, não parece difícil levar o modelo ao estágio em que ele pode detectar e classificar de forma confiável as linguagens incorporadas.
Também estamos pensando em publicar o código fonte do nosso modelo, mas precisamos de uma solicitação da comunidade.
Conclusão
Nosso objetivo no desenvolvimento do OctoLingua é criar um serviço que forneça uma definição confiável da linguagem pelo código-fonte em diferentes níveis de detalhe: do nível de arquivos ou fragmentos de código à possível definição e classificação do idioma no nível da linha. Todo o nosso trabalho neste serviço visa apoiar os desenvolvedores em seu trabalho diário de desenvolvimento, bem como criar condições para escrever código de alta qualidade.
Se você estiver interessado em contribuir para o nosso trabalho, não hesite em entrar em contato conosco no Twitter
@github !