Este artigo foi traduzido por máquina.

Clustering de dados

Dados de cluster usando Naive Bayes inferência

James McCaffrey

Baixar o código de exemplo

Dados de cluster são uma técnica de aprendizado de máquina que possui muitos importantes aplicações práticas, tais como agrupar dados de vendas para revelar o comportamento de compra do consumidor, ou Agrupamento de dados de rede dar insights sobre padrões de comunicação. Dados de cluster também são útil para identificar pontos de dados anômalos. Neste artigo eu apresento um programa completo c# que você pode usar como base para a adição de recursos de clusters para um sistema de software ou para a criação de um utilitário cluster autônomo poderoso.

Existem muitos algoritmos de clusters diferentes, em parte porque a eficácia de um algoritmo de clustering depende em certa medida as características dos dados sendo agrupados. O algoritmo mais comum é chamado de k-means clustering. Infelizmente, este algoritmo é aplicável somente para itens de dados numéricos. Em contraste, o algoritmo de clustering, que vou apresentar neste artigo é baseado em uma técnica chamada Naive Bayes inferência, que trabalha com dados categóricos ou numéricos. Apesar de todas as idéias utilizadas no algoritmo de clustering aqui apresentado são bem conhecidas, o algoritmo geral e implementação específica não, o melhor de meu conhecimento, foram publicados antes. Eu chamo esse algoritmo e sua implementação iterativa Naive Bayesian inferência aglomerativo Clustering (INBIAC) para a distinguir de outras técnicas de clusters. Naive Bayes inferência é uma técnica muito comum para a realização de classificação de dados, mas geralmente não sabe que Naive Bayes também pode ser usado para Agrupamento de dados.

A melhor maneira de entender onde eu estou indo neste artigo é dar uma olhada no Figura 1. O programa de demonstração começa gerando oito tuplas de dados aleatórios que descrevem a localização (urbana, suburbana ou rural), renda (baixa, média, alta ou muito alta) e política (liberal ou conservador) oito pessoas hipotéticas. O programa, em seguida, carrega os dados brutos de seqüência de caracteres na memória e converte os dados em valores int para habilitar o processamento eficiente. Por exemplo, a última tupla de ("Rural", "Low," "conservador") é armazenada como (2, 0, 1).

Data Clustering Using Naive Bayes Inference
Figura 1 dados Clustering usando Naive Bayes inferência

Muitos algoritmos de clusters, incluindo INBIAC, exigem o número de clusters deve ser especificado. Aqui, a variável numClusters é definido como 3. O programa de demonstração clusters de dados e, em seguida, exibe o agrupamento final de [0, 2, 2, 1, 1, 2, 1, 0]. Nos bastidores, o algoritmo de sementes clusters 0, 1 e 2 com tuplas, 1, 6 e 0, respectivamente. Em seguida, cada um dos restantes cinco tuplas é atribuído, um de cada vez, para um cluster. Este tipo de algoritmo é chamado aglomerativo.

Porque nenhuma intervenção do usuário ou dados de treinamento é necessária, o cluster é às vezes denominada "aprendizado não supervisionado". Cada índice da matriz de cluster representa uma tupla e o valor na matriz é um ID de cluster. Então tupla 2 ("Subterrâneo", "VeryHigh", "conservador") é atribuída ao cluster 0, tupla 1 ("Rural", "médio," "Conservador") é atribuído ao cluster 2 e assim por diante.

O programa de demonstração termina exibindo os dados raw originais em forma de cluster. Como você pode ver, a clusterização final parece razoável. E se você olhar para os dados originais, acho que você vai concordar que a tentativa de dados de cluster manualmente, mesmo para conjuntos de dados muito pequenos, seria extremamente difícil.

Este artigo pressupõe que você tem avançadas habilidades de programação com uma linguagem C-família, mas não se que você tem experiência com Naive Bayes inferência ou algoritmos de clustering. O programa de demonstração mostrado na Figura 1 é um único aplicativo de console c#. Eu codifiquei-lo sem o uso de técnicas OOP para que você mais facilmente pode refatorar para idiomas que não suportam totalmente a OOP.

Eu removi todos os erros de verificação para manter as idéias tão claras quanto possível. O código para o programa de demonstração é muito longo para apresentar na íntegra este artigo, então vou me concentrar em explicar as partes chaves do algoritmo. O código-fonte completo para o programa de demonstração está disponível em archive.msdn.microsoft.com/mag201303INBIAC.

Estrutura do programa

A estrutura geral do programa, com alguns comentários e WriteLine instruções removidas, está listada em Figura 2.

Figura 2 estrutura de programa de agrupamento

using System;
using System.Collections.Generic;
namespace ClusteringBayesian
{
  class ClusteringBayesianProgram
  {
    static Random random = null;
    static void Main(string[] args)
    {
      try
      {
        Console.WriteLine("\nBegin data clustering using Naive Bayes demo\n");
        random = new Random(6); // Seed of 6 gives a nice demo
        int numTuples = 8;
        Console.WriteLine("Generating " + numTuples +
          "tuples of location-income-politics data");
        string[] rawData = MakeData(numTuples);
        Console.WriteLine("\nRaw data in string form is:\n");
        ShowData(rawData, numTuples);
        string[] attNames = new string[] { "Location", "Income", "Politics" };
        string[][] attValues = new string[attNames.Length][];
        attValues[0] = new string[] { "Urban", "Suburban", "Rural" };
        // Location
        attValues[1] = new string[] { "Low", "Medium", "High", "VeryHigh" };
        // Income
        attValues[2] = new string[] { "Liberal", "Conservative" };
        // Politics
        Console.WriteLine("Loading raw data into memory\n");
        string[][] tuples = LoadData(rawData, attValues);
        Console.WriteLine("Converting raw data to int form and" +
          "storing in memory\n");
        int[][] tuplesAsInt = TuplesToInts(tuples, attValues);
        Console.WriteLine("Data in int form is:\n");
        ShowData(tuplesAsInt, numTuples);
        int numClusters = 3;
        int numTrials = 10;  // Times to get good seed indexes (different tuples)
        Console.WriteLine("\nSetting numClusters to " + numClusters);
        Console.WriteLine("\nInitializing Naive Bayes joint counts with " +
          "Laplacian smoothing");
        int[][][] jointCounts = InitJointCounts(tuplesAsInt, attValues,
          numClusters);
        int[] clusterCounts = new int[numClusters];
        Console.WriteLine("\nBegin clustering data using Naive Bayes " +
          "(with equal priors) ");
        int[] clustering = Cluster(tuplesAsInt, numClusters, numTrials,
          jointCounts, clusterCounts, true);
        Console.WriteLine("Clustering complete");
        Console.WriteLine("\nClustering in internal form is:\n");
        for (int i = 0; i < clustering.Length; ++i)
          Console.Write(clustering[i] + " ");
        Console.WriteLine("Raw data displayed in clusters is:\n");
        DisplayClustered(tuplesAsInt, numClusters, clustering, attValues);
        Console.WriteLine("\nEnd demo\n");
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.Message);
      }
    } // Main
    // Other methods go here
  } // class
} // ns

Eu usei Visual Studio 2010 para criar um aplicativo de console c# chamado ClusteringBayesian. Na janela Solution Explorer renomeei o arquivo Program. cs para o ClusteringBayesian mais descritivo­Program, que automaticamente renomeado a única classe. Eu removi desnecessárias gerados pelo modelo de referências aos namespaces .NET; Observe que o programa tem algumas dependências e precisa somente o namespace Systems.Collections.Generic.

Eu declaro um objeto de Random classe-escopo denominado aleatório. Este objeto é usado para gerar dados brutos semi-aleatório e para determinar quais tuplas usar para propagar cada cluster. No método Main, instancio aleatórios usando um valor de semente de 6, só porque isso gera uma demo de boa aparência.

As próximas linhas do programa demo usam métodos auxiliares MakeData e ShowData para gerar e exibir oito linhas de dados fictícios. MakeData chama os métodos sub-helper, MakeParty, MakeLocation, MakeIncome e MakePolitics. Se você deseja experimentar com tuplas de dados específicos codificados, você pode substituir esse código com, por exemplo:

int numTuples = 4;
string[] rawData = new string[] { "Urban,VeryHigh,Liberal",
  "Rural,Medium,Conservative", "Urban,Low,Liberal",
  "Suburban,Medium,Liberal" };

Em seguida, a demo programa codifica o atributo nomes local, a renda e a política. Em alguns cenários, por exemplo, se seus dados brutos em um arquivo de texto com um cabeçalho ou em uma tabela do SQL com nomes de coluna, você pode querer verificar os seus dados e determinar programaticamente os nomes de atributo.

Demo programa também codifica os valores de atributo, urbano, suburbano e Rural para localização; Low, média, alta e VeryHigh para renda; e liberais e os conservadores para a política. Novamente, em alguns cenários você pode querer analisar seus dados brutos para programaticamente determinar os valores de atributo.

O programa de demonstração chama auxiliar método LoadData para carregar os dados brutos de seqüência de caracteres em uma matriz de matrizes na memória. Para grandes conjuntos de dados, isso não seria possível. Em tais situações, você precisará carregar blocos de dados em um tempo ou iterar por meio de dados crus armazenados externamente uma linha ou linha por vez.

Embora seja possível trabalhar com dados de seqüência cru diretamente, é muito mais eficiente para trabalhar com os dados codificados como tipo int. Assim, em seguida, método auxiliar TuplesToInts aceita a matriz de matrizes de seqüências de caracteres, verifica-se através dessa matriz, converte cada seqüência de caracteres em um índice baseado em zero e armazena todos os dados em uma matriz de matrizes do tipo int. Novamente, para conjuntos de dados muito grandes você pode precisa ler uma linha de dados brutos em um momento e converter valores de atributo para ints na mosca.

O programa de demonstração prepara a cluster rotina definindo dois valores de parâmetro. Parâmetro numClusters é o número de clusters para gerar. Em geral, dados de cluster são um processo exploratório, e você deve experimentar com diferentes valores de numClusters (apesar de existirem algumas técnicas fascinantes para determinar programaticamente um número ideal de clusters). Parâmetro numTrials é usado pela rotina clustering ao gerar o agrupamento inicial, como explicarei em breve.

O método de cluster requer duas matrizes para manter as contagens de tuplas atribuídas a qualquer momento do algoritmo de INBIAC. JointCounts de matriz contém o número de tuplas clusterizados que têm um valor de atributo específico e um determinado cluster. A matriz de jointCounts é um pouco complicada, e explicarei isso em mais detalhes em breve. Mas cada valor em jointCounts é inicializado com 1 como parte de um importante passo na técnica Bayesiana chamado Laplaciano suavização. A segunda matriz, clusterCounts, contém o número de tuplas atribuídos para cada cluster em um determinado momento. O índice de clusterCounts representa um cluster, e o valor é a contagem de associado.

O agrupamento é realizado pelo método de Cluster. Cluster de método retorna uma matriz que codifica a qual cluster é atribuído a cada tupla. O programa de demonstração conclui, mostrando a matriz de clustering e exibindo os dados agrupados por cluster usando o método auxiliar DisplayClustered.

Naive Bayes inferência

A chave para compreender o algoritmo INBIAC para que você vai ser capaz de modificar o código de demonstração para suas próprias necessidades é o entendimento Naive Bayes inferência. Naive Bayes é melhor explicada por exemplo. Suponha que você tenha as oito tuplas mostradas na Figura 1 e deseja colocar cada tupla em um de três grupos:

[0] Suburban VeryHigh  Liberal
[1] Rural    Medium    Conservative
[2] Suburban VeryHigh  Conservative
[3] Suburban Low       Liberal
[4] Suburban High      Liberal
[5] Suburban Low       Conservative
[6] Urban    Low       Liberal
[7] Rural    Low       Conservative

Primeiro, suponha que cada cluster recebe uma tupla única semente (de uma forma que será explicada mais tarde) para que a tupla 1 é atribuída ao cluster 0, tupla 6 é atribuída ao cluster 1 e tuple 0 é atribuído ao cluster 2. Existem várias maneiras de representar este cluster, mas o algoritmo INBIAC iria armazenar as informações como uma matriz:

[  2,  0, -1, -1, -1, -1,  1, -1 ]

Nessa matriz, os índices de matriz são tuplas, os valores da matriz são aglomerados e um valor de -1 indica que a tupla associada ainda não tiver sido atribuída a um cluster. Assim, conceitualmente, o agrupamento nesse ponto é:

c0 : Rural    Medium   Conservative  (tuple 1)
c1 : Urban    Low      Liberal       (tuple 6)
c2 : Suburban VeryHigh Liberal       (tuple 0)

Agora o objetivo é atribuir a primeira tupla não atribuída, tupla 2 (Suburban, VeryHigh, conservador), para um dos três conjuntos. Naive Bayes calcula as probabilidades que tupla 2 pertence a grupos 0, 1 e 2 e, em seguida, atribui a tupla ao cluster que tem a maior probabilidade. Expressa simbolicamente, se X = (Suburban, VeryHigh, conservador) c0 representa para cluster de 0, queremos:

P(c0 | X)
P(c1 | X)
P(c2 | X)

A primeira probabilidade pode ser lido como, "a probabilidade do cluster 0 dada os valores de X." Agora, pense por um momento. Para calcular essas probabilidades condicional, você tem que calcular termos eu chamo probabilidades parciais (PP). Após os parciais para cada uma das condicionais são computados, a probabilidade para cada cluster é igual a parcial para o cluster dividido pela soma de todos os parciais. Simbolicamente:

P(c0 | X) = PP(c0 | X) / [PP(c0 | X) + PP(c1 | X) + PP(c2 | X)]
P(c1 | X) = PP(c1 | X) / [PP(c0 | X) + PP(c1 | X) + PP(c2 | X)]
P(c2 | X) = PP(c2 | X) / [PP(c0 | X) + PP(c1 | X) + PP(c2 | X)]

A probabilidade parcial para P(c0 | X) é:

PP(c0 | X) = P(Suburban | c0) *
             P(VeryHigh | c0) *
             P(Conservative | c0) *
             P(c0)
           = count(Suburban     & co) / count c0 *
             count(VeryHigh     & co) / count c0 *
             count(Conservative & c0) / count c0 *
             P(c0)

Estas equações vêm da teoria de Bayes e não são óbvias a todos. O termo "ingênuo" em Naive Bayes significa que cada um nos termos de probabilidade as probabilidades parciais são considerados matematicamente independente, que leva a muito cálculos mais simples do que se os termos de probabilidade matematicamente dependentes.

O último termo, P(c0), é a "probabilidade de cluster 0." Este termo é às vezes chamado de um antes e pode ser calculado de duas maneiras. Uma maneira é assumir iguais Priores, caso em que o P(c0) = P(c1) = P(c2) = 1/3. A outra maneira é não assumir iguais Priores e usar a contagem atual de tuplas atribuídas, no qual caso P(c0) = count(c0) / (count(c0) + count(c1) + count(c2)). Para o algoritmo INBIAC, é preferível assumir iguais Priores.

Observe que a equação precisa que são chamados de conta conjunta. Por exemplo, count(Suburban & C0) é a contagem de tuplas atribuídas, onde o cluster é c0 e a localização de tupla é suburbano.

Se você olhar para trás o agrupamento atual, você verá que há um problema: Neste momento, com apenas as três primeiras sementes tuplas atribuídas aos clusters, o count(Suburban & C0) é 0, o que torna seu termo 0, que zeros check-out a toda probabilidade parcial. Para evitar isso, o conta conjunto é inicializado com um valor de 1. Isso é chamado de suavização de Laplacian. Suavização de laplacian também adiciona 3, o número de clusters, os denominadores das probabilidades condicional (mas não o termo probabilidade incondicional). Então a computação modificada para o parcial de c0 é:

PP(c0 | X) = P(Suburban     | c0) *
             P(VeryHigh     | c0) *
             P(Conservative | c0) *
             P(c0)
           = count(Suburban     & co) / (count c0 + 3) *
             count(VeryHigh     & co) / (count c0 + 3) *
             count(Conservative & c0) / (count c0 + 3) *
             1 / numClusters
           = (1 / 4) * (1 / 4) * (2 / 4) * (1 / 3)
           = 0.0104

Da mesma forma, as probabilidades parciais para c1 e c2 são:

PP(c1 | X) = count(Suburban     & c1) / (count c1 + 3) *
             count(VeryHigh     & c1) / (count c1 + 3) *
             count(Conservative & c1) / (count c1 + 3) *
             1 / numClusters
           = (1 / 4) * (1 / 4) * (1 / 4) * (1 / 3)
           = 0.0052
PP(c2 | X) = count(Suburban     & c2) / (count c2 + 3) *
             count(VeryHigh     & c2) / (count c2 + 3) *
             count(Conservative & c2) / (count c2 + 3) *
             1 / numClusters
           = (2 / 4) * (2 / 4) * (1 / 4) * (1 / 3)
           = 0.0208

Depois foram calculadas as parciais para cada cluster, é fácil de calcular as probabilidades para cada cluster que são necessários para atribuir a tupla 1 para um cluster. Aqui estão os cálculos:

P(c0 | X) = PP(X | c0) / [PP(X | c0) + PP(X | c1) + PP(X | c2)]
          = 0.0104 / (0.0104 + 0.0052 + 0.0208)
          = 0.2857
P(c1 | X) = PP(X | c1) / [PP(X | c0) + PP(X | c1) + PP(X | c2)]
          = 0.0052 / (0.0104 + 0.0052 + 0.0208)
          = 0.1429
P(c2 | X) = PP(X | c0) / [PP(X | c0) + PP(X | c1) + PP(X | c2)]
          = 0.0208 / (0.0104 + 0.0052 + 0.0208)
          = 0.5714

A tupla é atribuída ao cluster com a maior probabilidade, que neste caso é c2 de cluster.

Para resumir, para atribuir uma tupla para um cluster, as probabilidades parciais para cada cluster são calculadas usando a conta conjunta de tuplas que já tiverem sido atribuídas. As parciais são usados para calcular a probabilidade de que a tupla pertence a cada cluster. A tupla é atribuída ao cluster que tem a maior probabilidade.

Estruturas de dados-chave

Há várias maneiras para armazenar vários dados usados pelo algoritmo de clustering do INBIAC. Figura 3 mostra que a maioria das estruturas de dados usadas pelo programa demo. Matriz jointCounts é usado para calcular as probabilidades parciais que por sua vez, são usadas para calcular probabilidades de cluster que por sua vez, são usadas para atribuir uma tupla para um cluster. Há uma contagem comum para cada combinação de cluster e o valor do atributo. Assim, para a demonstração, porque há nove valores de atributo (urbano, suburbano,... Conservador) e três clusters, existem 9 * 3 = 27 comum conta. O primeiro índice de jointCounts indica o atributo, o segundo índice indica o valor do atributo e o terceiro índice indica o cluster. Por exemplo, jointCounts [1] [3] [2] mantém a contagem de tuplas atribuídas, onde a renda (1) é VeryHigh (3) e cluster é (2).

Key Data Structures
Figura 3 estruturas de dados-chave

Matriz de clustering codifica como tuplas são atribuídas aos clusters. O índice da matriz de cluster representa uma tupla, e o valor da célula representa um cluster. Por exemplo, se o cluster [0] = 2, então tupla 0 é atribuída ao cluster 2. Valores de célula-1 indicam que a tupla associada ainda não tiver sido atribuída a um cluster.

Implementando o método de cluster

Método de Cluster está listado em Figura 4. O método aceita como entradas a matriz tuplesAsInt (os dados para ser agrupado), numClusters (o número de clusters para usar), numTrials (que atribui tuplas iniciais para clusters), jointCounts (como explicado anteriormente), clusterCounts (o número de tuplas atribuídos a cada agrupamento, necessário se computação com Priores não-igual) e equalPriors (um valor booleano que indica como calcular as probabilidades de cada cluster ao calcular probabilidades parciais).

 Figura 4 método Cluster

static int[] Cluster(int[][] tuplesAsInt, int numClusters,
  int numTrials, int[][][] jointCounts, int[] clusterCounts,
  bool equalPriors)
{
  int numRows = tuplesAsInt.Length;
  int[] clustering = new int[numRows];
  for (int i = 0; i < clustering.Length; ++i)
    clustering[i] = -1;
  int[] goodIndexes = GetGoodIndexes(tuplesAsInt, numClusters, numTrials);
  for (int i = 0; i < goodIndexes.Length; ++i)
  {
    int idx = goodIndexes[i];
    clustering[idx] = i;
  }
  for (int i = 0; i < goodIndexes.Length; ++i)
  {
    int idx= goodIndexes[i];
    for (int j = 0; j < tuplesAsInt[idx].Length; ++j)
    {
      int v = tuplesAsInt[idx][j];
      ++jointCounts[j][v][i];     // Very tricky indexing
    }
  }
  for (int i = 0; i < clusterCounts.Length; ++i)
    ++clusterCounts[i];
  for (int i = 0; i < tuplesAsInt.Length; ++i)
  {
    if (clustering[i] != -1) continue; // Tuple already clustered
    double[] allProbabilities = AllProbabilities(tuplesAsInt[i],
      jointCounts, clusterCounts, equalPriors);
    int c = IndexOfLargestProbability(allProbabilities);
    clustering[i] = c;  // Assign tuple i to cluster c
    for (int j = 0; j < tuplesAsInt[i].Length; ++j)
    {
      int v = tuplesAsInt[i][j];
      ++jointCounts[j][v][c];
    }
    ++clusterCounts[c];
  } // Main loop
  return clustering;
}

Método de Cluster começa por alocar memória para a matriz de clustering e atribuir valores de -1 em cada célula, para não indicar nenhum cluster foi atribuído a tupla associada. Em seguida, auxiliar método GetGoodIndexes é chamado para obter os índices de tuplas màxima diferentes uns dos outros. Explicarei o método GetGoodIndexes em breve. Método de Cluster em seguida usa os bons índices para inicializar a matriz de clustering e atualiza as matrizes de jointCounts e clusterCounts.

O loop de processamento principal itera em cada tupla de dados na ordem e calcula as probabilidades que a tupla atual pertence a cada cluster usando o método AllProbabilities. Em seguida, o índice de maior probabilidade é determinado usando o auxiliar IndexOfLargestProbability. Porque clusters são baseado em zero, esse índice representa também o cluster melhor, e é usado para atribuir a tupla atual para um cluster (cluster array) e atualizar as matrizes de jointCounts e clusterCounts.

Porque o loop de processamento sempre começa na tupla [0], isto efetivamente dá mais peso à tuplas com índices de baixa numeração. Uma alternativa é andar com as tuplas em ordem aleatória. Observe que o algoritmo INBIAC atribui tuplas com base na maior probabilidade de adesão do cluster. Você também poderia calcular e retornar a média destas probabilidades maiores. Seria uma medida de confiança as atribuições de cluster. Em seguida, você poderia chamar o método Cluster várias vezes e retorno a aglomeração que foi produzido pela chamada que rendeu a maior confiança.

Outra opção que eu uso frequentemente é pós-processo clustering resultado produzido pelo método de Cluster para tentar gerar um melhor agrupamento. É a idéia em pseudocódigo:

loop n times
  select a random tuple index
  unassign the tuple from its curr cluster
  assign the tuple using non-equal priors computation
end loop

Lembre-se de que INBIAC acumula a atribuição de cluster uma tupla cada vez encontrando o cluster tupla atual pertence com maior probabilidade. As probabilidades são calculadas usando Priores iguais, ou seja, que as probabilidades de cada cluster são consideradas iguais. Mas depois de clustering, há agora mais informações disponíveis sobre a probabilidade de cada cluster é, e que informações podem ser usadas para possivelmente melhorar o resultado de clustering. Download do código implementa essa opção usando um método chamado refinar.

Recebendo tuplas de boa semente inicial

O algoritmo INBIAC de sementes de cada cluster com uma única tupla. É importante que estas tuplas de semente ser tão diferentes uns dos outros quanto possível. Existem muitas medidas de dissimilaridade utilizada pelos algoritmos de clustering. GetGoodIndexes método gera um conjunto de índices aleatórios do candidato e, em seguida, calcula o número total de atributos de tupla que são diferentes, uma métrica chamada a distância Hamming. Este processo é numTrials repetidas vezes, e os índices de tuplas que possuem a maior disparidade são retornados.

Por exemplo, considere os dados na Figura 1. Suponha que os índices do candidato são 0, 1, 2. As tuplas de dados correspondentes são:

[0] Suburban VeryHigh Liberal
[1] Rural    Medium   Conservative
[2] Suburban VeryHigh Conservative

Tuplas [0] e [1] diferem em três posições; tuplas [0] e [2] diferem-se em uma posição; e tuplas [1] e [2] diferem em duas posições, para um total delta de 3 + 1 + 2 = 6. Em pseudocódigo, o método GetGoodIndexes é:

init a result array
loop numTrials times
  generate numClusters distinct random tuple indexes
  compute their dissimilarity
  if curr dissimilarity > greatest dissimilarity
    greatest dissimilarity = curr dissimilarity
    store curr indexes into result array
  end if
end loop
return result array

Você pode querer considerar abordagens alternativas. Uma opção avançada é observar que o atributo renda — com valores Low, médio, alto e VeryHigh — é inerentemente numérica. Então você poderia modificar o método GetGoodIndexes para que a diferença entre Low e VeryHigh é maior que a diferença entre Low e média.

Gerar os índices de tupla de semente candidatos distintos é uma sub-problem pouco interessante. Isto é realizado pelo método auxiliar GetRandomIndexes. Em pseudocódigo, o método funciona da seguinte maneira:

init a dictionary to store result indexes
init a result array
set count = 0
while count < numClusters
  generate a random tuple index
  if index not in dictionary
    add index to result set
    add index to dictionary
    increment count
  end if
end while
return result

Esta técnica é uma abordagem de força bruta bastante, mas tem funcionado bem para mim na prática.

Resumo

Neste artigo, junto com o código para o programa de demonstração, deve dar-lhe uma base sólida para experimentar com Naive Bayesian clustering e adicionando funcionalidade de cluster para um sistema de software.Eu desenvolvi o INBIAC algoritmo de clustering enquanto trabalhava em um projeto que tinha um conjunto de dados extremamente grande que continha dados numéricos e categóricos.Achei que as ferramentas de clusters existentes eram demasiado lento, não funciona em todos ou deu maus resultados.O algoritmo apresentado aqui pode lidar com dados categóricos e numéricos (no caso de dados numéricos são guardados em categorias), pode manipular grandes conjuntos de dados e é muito rápido.

Como mencionado na introdução, a pesquisa sugere que não há nenhum melhor único algoritmo de clustering, mas sim que você deve experimentar com diferentes algoritmos para obter os melhores resultados.A capacidade de explorar os conjuntos de dados de cluster baseado no Naive Bayes inferência pode ser uma adição valiosa para seu conjunto de habilidades técnicas.

Dr. James McCaffrey* trabalha para a Volt Information Sciences Inc., onde gerencia o treinamento técnico para engenheiros de software trabalham no Microsoft Redmond, Wash., campus. Ele trabalhou em vários produtos da Microsoft, incluindo o Internet Explorer e o MSN Busca e Ele é autor de “.NET Test Automation Recipes” (Apress, 2006) e pode ser contatado pelo email jammc@microsoft.com.*

Agradecemos ao seguinte especialista técnico pela revisão deste artigo: Dan Liebling