Подобие косинуса по сравнению с [закрытым] Расстоянием Хемминга

Тот же эффект может быть достигнут в веб-консоли GCP, нажав кнопку «Изменить» на кластере и установив размер каждого узла пула равным 0.

Ссылка: https://cloud.google.com/kubernetes-engine/docs/how-to/resizing-a-cluster

18
задан caw 3 June 2009 в 16:29
поделиться

4 ответа

Расстояние Хэмминга должно быть установлено между двумя строками одинаковой длины и с учетом порядка.

Поскольку ваши документы, безусловно, имеют разную длину и если места слов не учитываются, косинусное сходство лучше (обратите внимание, что в зависимости от ваших потребностей существуют лучшие решения). :)

Вот функция косинусного сходства двух массивов слов:

function cosineSimilarity($tokensA, $tokensB)
{
    $a = $b = $c = 0;
    $uniqueTokensA = $uniqueTokensB = array();

    $uniqueMergedTokens = array_unique(array_merge($tokensA, $tokensB));

    foreach ($tokensA as $token) $uniqueTokensA[$token] = 0;
    foreach ($tokensB as $token) $uniqueTokensB[$token] = 0;

    foreach ($uniqueMergedTokens as $token) {
        $x = isset($uniqueTokensA[$token]) ? 1 : 0;
        $y = isset($uniqueTokensB[$token]) ? 1 : 0;
        $a += $x * $y;
        $b += $x;
        $c += $y;
    }
    return $b * $c != 0 ? $a / sqrt($b * $c) : 0;
}

Это быстро ( isset () вместо in_array () убивает большие массивы ).

Как видите, в результатах не учитывается "величина" каждого слова.

Я использую его для обнаружения разосланных сообщений с "почти" скопированными текстами. Это работает хорошо. :)

Лучшая ссылка о метриках сходства строк : http://www.dcs.shef.ac.uk/~sam/stringmetrics.html

Для получения дополнительных интересных материалов:

http://www.miislita.com/information-retrieval-tutorial/ косинус-подобие-tutorial.html http://bioinformatics.oxfordjournals.org/cgi/content/full/22/18/2298

17
ответ дан 30 November 2019 в 07:44
поделиться

Прошу прощения за игнорируя тот факт, что вы сказали, что не хотите использовать какие-либо другие алгоритмы, но серьезно, расстояние Левенштейна и расстояние Дамерау-Левенштейна гораздо более полезны, чем расстояние Хэмминга. Вот реализация расстояния DL в PHP , и если вам не нравится собственная функция PHP levenshtein () , которую, я думаю, вы не сделаете, потому что она имеет ограничение по длине, вот Версия без ограничения длины:

function levenshtein_distance($text1, $text2) {
    $len1 = strlen($text1);
    $len2 = strlen($text2);
    for($i = 0; $i <= $len1; $i++)
        $distance[$i][0] = $i;
    for($j = 0; $j <= $len2; $j++)
        $distance[0][$j] = $j;
    for($i = 1; $i <= $len1; $i++)
        for($j = 1; $j <= $len2; $j++)
            $distance[$i][$j] = min($distance[$i - 1][$j] + 1, $distance[$i][$j - 1] + 1, $distance[$i - 1][$j - 1] + ($text1[$i - 1] != $text2[$j - 1]));
    return $distance[$len1][$len2];
}
5
ответ дан 30 November 2019 в 07:44
поделиться

Если я не ошибаюсь, я думаю, что у вас есть алгоритм на полпути между двумя алгоритмами . Для расстояния Хэмминга используйте:

function check ($terms1, $terms2) {
    $counts1 = array_count_values($terms1);
    $totalScore = 0;
    foreach ($terms2 as $term) {
        if (isset($counts1[$term])) $totalScore += 1;
    }
    return $totalScore * 500 / (count($terms1) * count($terms2));
}

(обратите внимание, что вы добавляете только 1 для каждого согласованного элемента в векторах лексем.)

А для косинусного сходства используйте:

function check ($terms1, $terms2) {
    $counts1 = array_count_values($terms1);
    $counts2 = array_count_values($terms2);
    $totalScore = 0;
    foreach ($terms2 as $term) {
        if (isset($counts1[$term])) $totalScore += $counts1[$term] * $counts2[$term];
    }
    return $totalScore / (count($terms1) * count($terms2));
}

(обратите внимание, что вы добавляете произведение количества токенов между двумя документами. )

Основное различие между ними состоит в том, что косинусное сходство даст более сильный индикатор, когда два документа содержат одно и то же слово несколько раз в документах , в то время как расстояние Хэмминга не заботит, как часто появляются отдельные токены .

Редактировать : только что заметил ваш запрос об удалении служебных слов и т. д. Я советую это, если вы собираетесь использовать косинусное сходство - поскольку служебные слова довольно часто встречаются (на английском языке по крайней мере), вы можете исказить результат, не отфильтровав их. Если вы используете расстояние Хэмминга, эффект будет не таким большим, но в некоторых случаях он все же может быть заметен. Кроме того, если у вас есть доступ к лемматизатору , он сократит количество промахов, например, когда один документ содержит «галактики», а другой - «галактики».

9
ответ дан 30 November 2019 в 07:44
поделиться

Вот мой исправленный код для функции косинусного расстояния, опубликованный Тото

function cosineSimilarity($tokensA, $tokensB)
{
    $a = $b = $c = 0;
    $uniqueTokensA = $uniqueTokensB = array();

    $uniqueMergedTokens = array_unique(array_merge($tokensA, $tokensB));

    foreach ($tokensA as $token) $uniqueTokensA[$token] = 0;
    foreach ($tokensB as $token) $uniqueTokensB[$token] = 0;

    foreach ($uniqueMergedTokens as $token) {
        $x = isset($uniqueTokensA[$token]) ? 1 : 0;
        $y = isset($uniqueTokensB[$token]) ? 1 : 0;
        $a += $x * $y;
        $b += pow($x,2);
        $c += pow($y,2);
    }
    return $b * $c != 0 ? $a / sqrt($b * $c) : 0;
}
2
ответ дан 30 November 2019 в 07:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: