KMeans не дает правильных результатов - PullRequest
0 голосов
/ 16 октября 2018

Я пытаюсь реализовать кластеризацию kmeans в Java, и она не возвращает правильные результаты.

У меня есть 3 папки, каждая из которых содержит 8 связанных документов (всего 24 документа), и я пытаюсь использовать KMeans для их кластеризации.Я предварительно обрабатываю данные, а затем строю матрицу частот слова и использую ее для построения матрицы tf-idf.Я чувствую себя довольно хорошо с моей матрицей, потому что, когда я прошу ее выложить самые распространенные слова (т.е. ключевые слова для папки), я получаю хорошие результаты.

Однако, когда я добавляю матрицу в мои KMeans с k = 3, я никогда не получаю правильный результат (а иногда получаю 2 кластера).

Моя основная функция:

    public void kmeans() {

        // randomly fill centroids
        randomlyFillCentroids();
        double threshhold = 0.001;
        int iteration = 0;

        double[][] iterCentroids = centroids;

        do {

            // set centroids to previous results
            centroids = iterCentroids;

            // assignLabels each point to the closest centroid
            assignLabels();

            // updateCentroids
            iterCentroids = updateCentroids();

            iteration++;

        } while (!stopCondition(iteration, threshhold, iterCentroids));
    }

Затем я назначаю метки в:

private void assignLabels() {

    for (int i = 0; i < numDocuments; i++) {

        double minDistance = Double.POSITIVE_INFINITY;
        int minJ = 0;

        for (int j = 0; j < k; j++) {
            double distance = distance(data[i], centroids[j]);
            if (distance < minDistance) {
                minDistance = distance;
                minJ = j;
            }
        }
        label[i] = minJ;
    }

}

Где расстояние - расстояние косинуса.

ИЯ обновляю центроиды в:

private double[][] updateCentroids() {

    double[][] tempCentroids = new double[k][numWords]; // 3 x 64
    int[] tally = new int[k];

    // initialize to zero
    for (int i = 0; i < k; i++) {
        tally[i] = 0;
        for (int j = 0; j < numWords; j++) {
            tempCentroids[i][j] = 0.0;
        }
    }

    // do the sums
    for (int i = 0; i < numDocuments; i++) {

        int value = label[i]; // get the document's label (0, 1, 2)

        for (int j = 0; j < numWords; j++) {
            tempCentroids[value][j] += data[i][j];
        }

        tally[value]++;
    }

    // get the average
    for (int i = 0; i < k; i++) {
        for (int j = 0; j < numWords; j++) {
            tempCentroids[i][j] /= tally[i];
        }
    }


    return tempCentroids;
}

Что мне не хватает?

Любая помощь будет принята с благодарностью.

...