Compartir a través de


Este artículo proviene de un motor de traducción automática.

Agrupamiento de datos

Agrupamiento de datos mediante inferencia de Bayes Ingenuo

James McCaffrey

Descargar el ejemplo de código

Organización es una técnica de aprendizaje máquina que tiene muchas importantes aplicaciones prácticas, como agrupar datos de ventas para revelar el comportamiento de consumidor compra o agrupar datos de la red para dar ideas sobre patrones de comunicación.Organización también es útil para identificar puntos de datos anómalos.En este artículo presento un completo programa de C# que puede utilizar como base para agregar características de agrupamiento a un sistema de software o para crear una utilidad de agrupación independiente potente.

Hay muchos diferentes algoritmos de clustering, en parte porque la eficacia de un algoritmo de agrupamiento depende en cierta medida las características de los datos se agrupan.El algoritmo más común se llama k-means clustering.Desafortunadamente, este algoritmo es aplicable solamente para los artículos de datos numéricos.En contraste, el algoritmo de agrupamiento que presento en este artículo se basa en una técnica llamada inferencia Naive Bayes, que trabaja con datos categóricos o numéricos.Aunque todas las ideas que se utiliza en el algoritmo de agrupamiento presentado aquí son bien sabidas, el algoritmo general y la implementación específica se no, a lo mejor de mi conocimiento, han publicado antes.Llamo a este algoritmo y su implementación iterativa ingenuo Bayesiano inferencia aglomerativo Clustering (INBIAC) para distinguirla de otras técnicas de clustering.Inferencia de Bayes Ingenuo es una técnica muy común para realizar la clasificación de datos, pero generalmente no se conoce que Naive Bayes puede utilizarse también para el agrupamiento de datos.

La mejor forma de entender donde me estoy dirigí en este artículo es echar un vistazo a figura 1.El programa de demostración comienza por generar ocho tuplas de datos aleatorios que describen la ubicación (urbana, suburbana o rural), ingresos (baja, media, alta o muy alta) y política (liberal o conservador) ocho personas hipotético.Entonces, el programa carga los datos de la materia prima de la cadena en la memoria y convierte los datos en valores int para habilitar el procesamiento eficiente.Por ejemplo, se almacena la última tupla de ("Rural", "Low" "conservador") (2, 0, 1).

Data Clustering Using Naive Bayes Inference
Figura 1 datos clúster mediante inferencia de Bayes Ingenuo

Muchos algoritmos de clustering, incluyendo INBIAC, requieren el número de racimos que se especificará.Aquí, la variable numClusters se establece en 3.El programa de demostración de clústeres de los datos y luego muestra el agrupamiento final de [2, 0, 2, 1, 1, 2, 1, 0].Detrás de las escenas, el algoritmo semillas 0, 1 y 2 con tuplas 1, 6 y 0, respectivamente.Luego cada uno de los restantes cinco tuplas se asigna, uno a la vez, a un grupo.Este tipo de algoritmo se llama aglomerativo.

Porque ninguna intervención de datos o usuario de formación es necesaria, el agrupamiento a veces se denomina "aprendizaje sin supervisión". Cada índice de la matriz de agrupamiento representa una tupla y el valor de la matriz es un identificador de grupo.Para tupla 2 ("Suburbano", "Muy elevado," "conservador") se asigna a 0, tupla 1 ("Rural", "Medium," "Conservador") se asigna al grupo 2 y así sucesivamente.

El programa de demostración termina mostrando los datos en bruto originales en forma agrupada.Como puede ver, el agrupamiento final parece razonable.Y si nos fijamos en los datos originales, creo que estará de acuerdo que tratar de agrupar datos manualmente, incluso para conjuntos de datos muy pequeñas, sería extremadamente difícil.

Este artículo asume que ha avanzado habilidades de programación con un lenguaje de serie C, pero no asume que tenga experiencia Naive Bayes inferencia o algoritmos de clustering.El programa de demostración se muestra en la figura 1 es una simple aplicación de consola de C#.Lo codifiqué sin utilizar técnicas de programación orientada a objetos, así que usted puede refactorizar más fácilmente a los lenguajes que no admiten totalmente OOP.

Quité todos error checking para mantener las ideas tan claramente como sea posible.El código para el programa de demostración es demasiado largo para presentar en su totalidad en este artículo, por lo que centraremos en explicar las partes claves del algoritmo.El código fuente completo para el programa de demostración está disponible en archive.msdn.microsoft.com/mag201303INBIAC.

Estructura del programa

La estructura general del programa, con algunos comentarios y declaraciones WriteLine quitadas, cotiza en figura 2.

Figura 2 agrupamiento programa estructura

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

Usé Visual Studio 2010 para crear una aplicación de consola de C# llamada ClusteringBayesian. En la ventana Explorador de soluciones me cambió nombre archivo Program.cs a la más descriptiva ClusteringBayesian­Program.cs, cuyo nombre automáticamente la clase sola. Quité innecesarios generados por plantilla referencias a los espacios de nombres. net; Observe el programa tiene algunas dependencias y necesita sólo el espacio de nombres Systems.Collections.Generic.

Declaro un objeto de ámbito de la clase Random denominado al azar. Este objeto se utiliza para generar los datos sin procesar sonidos y para determinar qué tuplas para cada cluster de la semilla. En el método Main, instanciar al azar utilizando un valor de 6, sólo porque esto genera una demo de aspecto agradable.

Las siguientes líneas del programa demo usan métodos auxiliares MakeData y ShowData para generar y desplegar ocho líneas de datos ficticios. MakeData llama a los métodos de sub-helper MakeParty, MakeLocation, MakeIncome y MakePolitics. Si desea experimentar con las tuplas de datos codificado específico, puede reemplazar este código con, por ejemplo:

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

A continuación, el hardcodes del programa de demostración el atributo nombres de ubicación, la renta y la política. En algunas situaciones, por ejemplo si tus datos en un archivo de texto con un encabezado o en una tabla SQL con nombres de columna, quizás desee explorar sus datos y determinar mediante programación los nombres de atributo.

La demo del programa también hardcodes los valores de atributo urbana, suburbana y Rural para ubicación; Low, medio, alto y muy elevado de ingresos; y Liberal y conservador para la política. Una vez más, en algunos escenarios puede analizar sus datos crudos para determinar mediante programación a los valores de atributo.

El programa de demostración llama método auxiliar LoadData para cargar los datos de la materia prima de la cadena en una matriz de matrices en memoria. Para conjuntos de datos muy grandes, esto no sería posible. En estos casos usted necesitará cargar bloques de datos en un momento o iterar a través de los datos brutos externamente almacenados una línea o fila a la vez.

Aunque es posible trabajar con datos de cadena crudo directamente, es mucho más eficiente para trabajar con los datos codificados como tipo int. Por lo tanto, a continuación, método auxiliar TuplesToInts acepta la matriz de matrices de cadenas, explora esa matriz, cada cadena convierte en un índice de base cero y almacena todos los datos en una matriz de matrices de tipo int. Otra vez, para conjuntos de datos muy grandes puede que necesite leer datos sin procesar una línea en un momento y convertir valores de atributo ints sobre la marcha.

El programa de demostración prepara la rutina de agrupamiento por dos valores de parámetro de ajuste. Parámetro numClusters es el número de racimos para generar. En general, la organización es un proceso exploratorio y debe experimentar con diferentes valores de numClusters (aunque hay algunas técnicas fascinantes para determinar mediante programación un número óptimo de clusters). Parámetro numTrials es utilizado por la rutina de agrupamiento al generar el agrupamiento inicial, como lo explicaré brevemente.

El método de agrupamiento requiere dos matrices para mantener las cuentas de tuplas asignados en cualquier momento dado en el algoritmo INBIAC. Matriz jointCounts contiene el número de tuplas agrupados que tienen un valor de atributo particular y un grupo particular. La matriz de jointCounts es un poco complicada, y voy a explicar más detalladamente poco. Pero cada valor en jointCounts se inicializa en 1 como parte de un paso importante en la técnica bayesiana llamada suavizado laplaciano. La segunda matriz, clusterCounts, contiene el número de tuplas asignados a cada grupo en cada momento. El índice de clusterCounts representa un racimo, y el valor es el número asociado.

La agrupación se realiza por el método Cluster. Cluster de método devuelve una matriz que codifica que clúster se asigna a cada tupla. El programa de demostración concluye mostrando la matriz clustering y mostrando los datos agrupados por clúster utilizando el método auxiliar DisplayClustered.

Inferencia de Bayes Ingenuo

La clave para entender el algoritmo INBIAC para que usted será capaz de modificar el código de demostración para satisfacer sus propias necesidades es entender la inferencia Naive Bayes. Naive Bayes se explica por ejemplo. Supongamos que tienes los ocho tuplas se muestra en la figura 1 y desea colocar cada tupla en uno de tres 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

En primer lugar, asumir que cada grupo recibe una tupla de semilla (de manera que se explicará más adelante) para que se asigna la tupla 1 a 0, tupla 6 se asigna a 1, y tupla 0 se asigna al grupo 2. Hay varias maneras para representar a esta agrupación, pero el algoritmo INBIAC almacenará la información como una matriz:

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

En esta matriz, los índices de la matriz son tuplas, los valores de la matriz son los racimos y el valor -1 indica que la tupla asociada todavía no ha sido asignada a un grupo. Por lo tanto, conceptualmente, el agrupamiento en este momento es:

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

Ahora el objetivo es asignar la primera tupla sin asignar, tupla 2 (Suburban, muy elevado, conservador), a uno de los tres grupos. Naive Bayes calcula las probabilidades tupla 2 pertenece a grupos 0, 1 y 2 y luego asigna la tupla al grupo que tiene la mayor probabilidad. Expresado simbólicamente, si X = (Suburban, muy elevado, conservador) y c0 está parado para grupo 0, queremos:

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

La primera probabilidad puede leerse como, "la probabilidad de clúster 0 dada los valores de X." Ahora, paciencia conmigo por un momento. Para calcular estas probabilidades condicionales, tienes que calcular términos llamo probabilidades parciales (PP). Después de que se computan los parciales para cada una de las condicionantes, la probabilidad para cada cluster es igual al parcial para el cluster dividido por la suma de todos los parciales. Simbólicamente:

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)]

La probabilidad parcial para P(c0 | X) es:

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 ecuaciones provienen de la teoría de Bayes y no son en absoluto obvias. El término "ingenua" en Naive Bayes significa que cada uno de los términos de la probabilidad en las probabilidades parciales se asumen para ser matemáticamente independientes, que conduce a mucho más simples cálculos que si los términos de la probabilidad eran matemáticamente dependientes.

El último término, P(c0), es la "probabilidad de cluster 0". Este término a veces se llama a un previo y puede calcularse de dos maneras. Una forma es asumir iguales Priores, en cuyo caso el P(c0) = P(c1) = P(c2) = 1/3. La otra forma es no asumir iguales Priores y utilizar las cuentas actuales de tuplas asignados, en cual caso P(c0) = count(c0) / (count(c0) + count(c1) + count(c2)). El algoritmo de INBIAC, es preferible asumir iguales priores.

Observe que la ecuación tiene lo que se denomina cuentas conjuntas. Por ejemplo, count(Suburban & C0) es el número de tuplas asignados, donde el grupo es c0 y la ubicación de la tupla es suburbano.

Si miras hacia atrás en la actual agrupación, verás que hay un problema: en este momento, con sólo las tres primeras tuplas asignados a los racimos, la count(Suburban & de la semilla C0) es 0, lo que hace su término 0, que los ceros a la toda probabilidad parcial. Para evitar esto, las cuentas conjuntas se inicializan con un valor de 1. Esto se denomina suavizado laplaciano. Suavizado laplaciano también añade 3, el número de grupos, a los denominadores de las probabilidades condicionales (pero no el término de la probabilidad incondicional). Por lo tanto el cómputo modificado para el parcial de c0 es:

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

Del mismo modo, las probabilidades parciales para c1 y c2 son:

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

Después de que se han calculado los parciales para cada grupo, es fácil calcular las probabilidades para cada cluster que se necesitan para asignar tupla 1 a un clúster. Aquí están los 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

La tupla se asigna al grupo con la mayor probabilidad, que en este caso es el grupo c2.

Para resumir, para asignar una tupla a un clúster, se calculan las probabilidades parciales para cada cluster utilizando las cuentas conjuntas de tuplas que ya han sido asignados. Los parciales se utilizan para calcular la probabilidad que la tupla pertenece a cada grupo. La tupla se asigna al grupo que tiene la mayor probabilidad.

Estructuras de datos clave

Existen varias formas para almacenar los datos usados por el algoritmo de agrupamiento de INBIAC. Figura 3 muestra la mayoría de las estructuras de datos utilizadas por el programa de demostración. JointCounts de la matriz se utiliza para calcular las probabilidades parciales que a su vez se utilizan para calcular probabilidades de clúster que a su vez se utilizan para asignar una tupla a un cluster. Hay una cuenta conjunta para cada combinación de valor de atributo y cluster. Así, para la demostración, porque hay nueve valores de atributo (urbano, suburbano,... Conservador) y tres grupos, hay 9 * 3 = 27 conjunta cuenta. El primer índice en jointCounts indica el atributo, el segundo índice indica el valor del atributo y el tercer índice indica el racimo. Por ejemplo, jointCounts [1] [3] [2] es el número de tuplas asignados donde los ingresos (1) sean muy elevado (3) y racimo es (2).

Key Data Structures
Estructuras de datos clave de la figura 3

Matriz de clustering codifica como tuplas se asignan a grupos. El índice de matriz clustering representa una tupla, y el valor de la celda representa un clúster. Por ejemplo, si la agrupación [0] = 2, entonces tupla 0 se asigna al grupo 2. Valores de las celdas-1 indican que la tupla asociada todavía no ha sido asignada a un grupo.

Implementar el método de agrupamiento

Método Cluster cotiza en figura 4. El método acepta como entradas la tuplesAsInt matriz (los datos a agruparse), numClusters (el número de racimos a utilizar), numTrials (que asigna tuplas iniciales a racimos), jointCounts (como se explicó antes), clusterCounts (el número de tuplas asignados a cada grupo, es necesario si la computación con igual no reincidentes) y equalPriors (un valor booleano que indica cómo calcular las probabilidades de cada clúster cuando probabilidades parciales).

 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 Cluster comienza por asignar memoria para la matriz de agrupamiento y asignar valores de -1 en cada celda, para no indicar que ningún grupo se ha asignado a la tupla asociada. A continuación, método auxiliar GetGoodIndexes se llama para obtener los índices de las tuplas que máximo difieren unos de otros. Voy a explicar el método GetGoodIndexes poco. Método Cluster a continuación utiliza los índices buenos para inicializar el array de agrupamiento y luego actualiza las matrices jointCounts y clusterCounts.

El bucle principal de procesamiento recorre cada tupla de datos en orden y calcula las probabilidades de que la tupla actual pertenece a cada grupo utilizando el método AllProbabilities. Entonces el índice de la mayor probabilidad se determina usando ayudante IndexOfLargestProbability. Porque los racimos son de base cero, ese índice también representa la mejor concentración, y se utiliza para asignar la tupla actual a un cluster (en la matriz clustering) y actualizar las matrices jointCounts y clusterCounts.

Porque el lazo de procesamiento siempre empieza en la tupla [0], esto efectivamente da más peso a tuplas con menor número de índices. Una alternativa es caminar a través de las tuplas en orden aleatorio. Tenga en cuenta que el algoritmo INBIAC asigna tuplas basadas en la mayor probabilidad de pertenencia a grupo. Usted también podría computar y vuelve el promedio de estas mayores probabilidades. Esto sería una medida de confianza en las asignaciones de clúster. Entonces se podría llamar el método Cluster varias veces y regreso de la agrupación fue producido por la llamada que rindió la mayor confianza.

Otra opción que utilizo a menudo es postprocesar el agrupamiento resultado producido por método Cluster para tratar de generar un mejor agrupamiento. La idea en pseudocódigo es:

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

Hay que recordar que INBIAC acumula una tupla de clúster asignación a la vez encontrando el cluster de la tupla actual pertenece a con mayor probabilidad. Las probabilidades se calculan utilizando a Priores iguales, lo que significa que las probabilidades de cada grupo se supone que son iguales. Pero después de clustering, hay ahora más información disponible sobre probabilidades cada cluster es, y que la información puede utilizarse para posiblemente mejorar el resultado de la agrupación. La descarga de código implementa esta opción, utilizando un método denominado refinar.

Conseguir buena semilla inicial tuplas

El algoritmo INBIAC semillas cada cluster con una sola tupla. Es importante que estas tuplas de semilla tan diferentes entre sí como sea posible. Hay muchas medidas de la desemejanza utilizada algoritmos de clustering. Método GetGoodIndexes genera un conjunto de índices de candidato al azar y luego calcula el número total de atributos de tupla que son diferentes, una métrica llamada la distancia de Hamming. Este proceso es numTrials repetidas veces, y se muestran los índices de las tuplas que tienen la mayor desemejanza.

Por ejemplo, consideremos los datos en figura 1.  Supongamos que los índices del candidato son 0, 1, 2. Las tuplas de datos correspondientes son:

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

Tuplas [0] y [1] se diferencian en tres posiciones; tuplas [0] y [2] difieren en una posición; y tuplas [1] y [2] difieren en dos posiciones, para un incremento total 3 + 1 + 2 = 6. En pseudocódigo, método GetGoodIndexes es:

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

Usted tal vez desee considerar enfoques alternativos. Es una opción avanzada para observar ese atributo ingreso — con valores Low, medio, alto y muy elevado, es inherentemente numérica. Por lo que se podría modificar el método GetGoodIndexes por lo que la diferencia entre Low y muy elevado es mayor que la diferencia entre Low y media.

La generación de los índices de tupla de semilla candidato distinto es un sub-problema poco interesante. Esto se realiza por el método auxiliar GetRandomIndexes. En pseudocódigo, el método funciona así:

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 es un enfoque bastante fuerza bruta, pero ha funcionado bien para mí en la práctica.

Terminando

Este artículo, junto con el código para el programa de demostración, debe darle una base sólida para experimentar con Bayesiano ingenuo clustering y agregar funcionalidad agrupamiento a un sistema de software. He desarrollado el INBIAC algoritmo de agrupamiento mientras trabajaba en un proyecto que tuvo un gran conjunto de datos que contenía datos numéricos tanto categóricos. Encontré que las herramientas existentes de agrupamiento eran demasiado lento, no funcionó en absoluto o dio malos resultados. El algoritmo presentado aquí puede tratar datos tanto categóricos y numéricos (si los datos numéricos se clasifica en categorías), puede manejar grandes conjuntos de datos y es muy rápido.

Como mencioné en la introducción, la investigación sugiere que no hay solo mejor algoritmo de agrupamiento, sino que debe experimentar con diferentes algoritmos para obtener los mejores resultados. La capacidad de explorar conjuntos de datos con clustering basado en Naive Bayes inferencia puede ser una valiosa adición a su conjunto de habilidades técnicas.

Dr.James McCaffrey trabaja para Volt Information Sciences Inc., donde dirige el entrenamiento técnico para ingenieros de software trabajando en el Microsoft Redmond, Washington, campus. Ha trabajado en varios productos de Microsoft Internet Explorer y MSN Search. Él es el autor de ".NET Test Automation recetas" (Apress, 2006) y puede ser contactado en jammc@microsoft.com.

Gracias a los siguientes expertos técnicos por su ayuda en la revisión de este artículo: Dan Liebling