проблема сходства косинусов - PullRequest
3 голосов
/ 23 февраля 2010

Я разработал некоторую Java-программу для расчета косинусного сходства на основе TF * IDF. Это сработало очень хорошо. Но есть одна проблема ....: (

например: Если у меня есть две следующие матрицы и я хочу вычислить косинусное сходство, оно не работает, так как строки не одинаковы по длине

doc 1
1 2 3
4 5 6

doc 2
1 2 3 4 5 6
7 8 5 2 4 9

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

Любые советы ???

Ответы [ 2 ]

3 голосов
/ 21 апреля 2011

Простое сходство по Java-косинусу

 static double cosine_similarity(Map<String, Double> v1, Map<String, Double> v2) {
            Set<String> both = Sets.newHashSet(v1.keySet());
            both.removeAll(v2.keySet());
            double sclar = 0, norm1 = 0, norm2 = 0;
            for (String k : both) sclar += v1.get(k) * v2.get(k);
            for (String k : v1.keySet()) norm1 += v1.get(k) * v1.get(k);
            for (String k : v2.keySet()) norm2 += v2.get(k) * v2.get(k);
            return sclar / Math.sqrt(norm1 * norm2);
    }
3 голосов
/ 23 февраля 2010

Я не уверен в вашей реализации, но косинусное расстояние двух векторов равно нормализованному точечному произведению этих векторов.

Точечное произведение двух матриц может быть выражено как. b = a T b. В результате, если матрица имеет разную длину, вы не можете взять скалярное произведение для определения косинуса.

Теперь в стандартном подходе TF * IDF термины в вашей матрице должны быть проиндексированы на term, document, в результате любые термины, не встречающиеся в документе, должны отображаться как нули в вашей матрице.

Теперь то, как вы его настроили, похоже, предполагает наличие двух разных матриц для ваших двух документов. Я не уверен, что это ваше намерение, но это кажется неправильным.

С другой стороны, если одна из ваших матриц должна быть вашим запросом, то это должен быть вектор, а не матрица, чтобы транспонирование давало правильный результат.

Ниже приводится полное объяснение TF * IDF:

Хорошо, в классической TF * IDF вы строите матрицу терм-документа a. Каждое значение в матрице a характеризуется как i, j , где i - это термин, а j - это документ. Это значение является комбинацией локальных, глобальных и нормализованных весов (хотя, если вы нормализуете свои документы, нормализованный вес должен быть 1). Таким образом, a i, j = f i, j * D / d i , где f i, j - частота слова i в документе j, D - размер документа, а d i - количество документов с термином i в них.

Ваш запрос представляет собой вектор терминов, обозначенных b. Для каждого термина b i, q в вашем запросе относится к термину i для запроса q. b i, q = f i, q , где f i, q - частота слагаемого i в запросе q. В этом случае каждый запрос является вектором, а несколько запросов образуют матрицу.

Затем мы можем вычислить единичные векторы для каждого, так что, когда мы возьмем скалярное произведение, он получит правильный косинус. Чтобы получить единичный вектор, мы делим матрицу a и запрос b на их норму Фробениуса .

Наконец, мы можем выполнить косинусное расстояние, взяв транспонирование вектора b для данного запроса. Таким образом, один запрос (или вектор) для расчета. Это обозначается как b T a. Конечным результатом является вектор с оценкой для каждого термина, где более высокий балл обозначает более высокий ранг документа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...