Normalmente, cadeias de Markov são usadas para gerar texto, mas também podem ser usadas para prever a similaridade de texto (por CE Shannon 1950 ) para um modelo treinado. Eu recomendo várias cadeias de Markov.
Para cada idioma predominante, treine uma cadeia de Markov em uma amostra grande e representativa de código no idioma. Em seguida, para uma postagem do Stack Overflow para a qual você deseja detectar o código, faça o seguinte para cada uma das cadeias:
- Percorra as linhas no post.
- Declarar duas variáveis: ACTUAL = 1.0 e HIGHEST = 1.0
- Faz um loop por cada caractere na linha.
- Para cada caractere, encontre a probabilidade na cadeia de Markov de que o caractere atual é o seguinte dos caracteres N anteriores. Defina ACTUAL = ACTUAL * PROB 1 . Se o caractere atual não estiver presente na cadeia, use um valor minúsculo para PROB 1 , como 0,000001.
- Agora, encontre o caractere mais provável (ou seja, a maior probabilidade) para seguir os N caracteres anteriores. Defina HIGHEST = HIGHEST * PROB 2 .
- Obviamente, PROB 2 > = PROB 1
Para cada linha, você deve ter um valor ACTUAL e HIGHEST. Divida ACTUAL por MAIS ALTO. Isso lhe dará a pontuação de aptidão para saber se uma determinada linha é o código-fonte. Isso associaria um número a cada uma das linhas no exemplo que você forneceu:
my problem is I need to change the database but I don't won't to create // 0.0032
a new connection. example: // 0.0023
DataSet dsMasterInfo = new DataSet(); // 0.04
Database db = DatabaseFactory.CreateDatabase("ConnectionString"); // 0.05
DbCommand dbCommand = db.GetStoredProcCommand("uspGetMasterName"); // 0.04
Por fim, você precisará selecionar um limite para determinar quando há código na postagem. Isso pode ser simplesmente um número selecionado pela observação que produz alto desempenho. Também pode levar em conta o número de linhas com uma pontuação alta.
Treinamento
Para treinar, obtenha uma amostra grande e representativa do código no idioma. Escreva um programa para fazer um loop sobre o texto do código e associe cada N-grama no arquivo (o intervalo para N deve ser parametrizado) com a frequência estatística do caractere subseqüente. Isso produzirá múltiplos estados possíveis de caracteres que seguem o bigrama, cada um associado a uma probabilidade. Por exemplo, o bigrama "()" poderia ter algumas probabilidades de caracteres a seguir:
"()" 0.5-> ";"
"()" 0.2-> "."
"()" 0.3-> "{"
O primeiro deve ser lido, por exemplo, como "A probabilidade de um ponto-e-vírgula seguir um parênteses vazio é 0,5".
Para treinamento, recomendo N-gramas de tamanho dois a cinco. Quando eu fiz algumas pesquisas sobre isso , descobrimos que N-gramas de tamanho dois a cinco funcionavam bem para o inglês. Como grande parte do código-fonte é do tipo inglês, sugiro começar com esse intervalo e, em seguida, ajustar para encontrar os valores ideais dos parâmetros conforme você encontrar o que funciona.
Uma ressalva: o modelo será afetado por identificadores, nomes de métodos, espaço em branco e etc. No entanto, você pode ajustar o treinamento para omitir certos recursos da amostra de treinamento. Por exemplo, você pode recolher todos os espaços em branco desnecessários. A presença de espaços em branco na entrada (a postagem do Stack Overflow) também pode ser ignorada. Você também pode ignorar o caso alfabético, que seria mais resiliente em face das convenções de nomenclatura de identificadores variáveis.
Durante a minha pesquisa , descobrimos que nossos métodos funcionavam bem para o espanhol e o inglês . Não vejo por que isso também não funcionaria bem para o código-fonte. O código fonte é ainda mais estruturado e previsível que a linguagem humana.