Распределение слов по теме p(w|t) в Mallet

Мне нужно получить распределение слов для каждой темы, найденной Mallet в Java (не в CLI как задано в как получить распределение вероятностей для тема в молотке?). Пример того, что я имею в виду: Введение в латентный Распределение Дирихле:

Topic A: 30% broccoli, 15% bananas, 10% breakfast, 10% munching, … (at which point, you could interpret topic A to be about food)
Topic B: 20% chinchillas, 20% kittens, 20% cute, 15% hamster, … (at which point, you could interpret topic B to be about cute animals)

Mallet предоставляет токены «веса» для каждой темы и в http://comments.gmane.org/gmane.comp.ai.mallet.devel/2064 кто-то попытался написать метод для получения распределения слов по темам для Mallet.

Я модифицировал метод, чтобы все веса делились на их сумму, как обсуждалось в списке рассылки выше.

Правильно ли вычисляет следующий метод (при добавлении в ParallelTopicModel.java) распределение слов по теме p(w|t) в Mallet?

/**
 * Get the normalized topic word weights (weights sum up to 1.0)
 * @param topic the topic
 * @return the normalized topic word weights (weights sum up to 1.0)
 */
public ArrayList<double[]> getNormalizedTopicWordWeights(int topic) {
    ArrayList<double[]> tokenWeights = new ArrayList<double[]>();
    for (int type = 0; type < numTypes; type++) {
        int[] topicCounts = typeTopicCounts[type];
        double weight = beta;
        int index = 0;
        while (index < topicCounts.length && topicCounts[index] > 0) {
            int currentTopic = topicCounts[index] & topicMask;
            if (currentTopic == topic) {
                weight += topicCounts[index] >> topicBits;
                break;
            }
            index++;
        }
        double[] tokenAndWeight = { (double) type, weight };
        tokenWeights.add(tokenAndWeight);
    }
    // normalize
    double sum = 0;
    // get the sum
    for (double[] tokenAndWeight : tokenWeights) {
        sum += tokenAndWeight[1];
    }
    // divide each element by the sum
    ArrayList<double[]> normalizedTokenWeights = new ArrayList<double[]>();
    for (double[] tokenAndWeight : tokenWeights) {
        tokenAndWeight[1] = tokenAndWeight[1]/sum;
        normalizedTokenWeights.add(tokenAndWeight);
    }
    return normalizedTokenWeights;
}

person tkja    schedule 27.05.2016    source источник


Ответы (1)


Похоже, это сработает, но у меня есть несколько замечаний по стилю.

Я не в восторге от использования массива double для представления пар тема/вес. Если вы перебираете все типы, почему бы не использовать плотный массив double[] с типом в качестве индекса? Если вам нужно отсортировать записи в другом методе, отличном от этого, ArrayList может иметь смысл, но ненормализованный промежуточный ArrayList кажется расточительным.

Второй цикл суммирования кажется ненужным. Вы можете сначала инициализировать sum до numTypes * beta, а затем добавить weight - beta только тогда, когда вы нажмете ненулевой тип счетчика.

Часто бывает заметна разница, если вы определяете normalizer = 1.0/sum, а затем умножаете, а не делите в цикле нормализации.

person David Mimno    schedule 10.06.2016