Kelime modeli Çanta: 2 PHP işlevleri, aynı sonuçlar: Neden?

2 Cevap php

Ben iki metin arasındaki ilişkiyi hesaplamak için iki PHP fonksiyonları var. Her ikisi de kelime modeli çanta kullanmak ama check2 () çok daha hızlıdır. Neyse, hem işlevleri aynı sonuçları verir. Neden? check1 () TÜM kelimeler içeren bir büyük sözlük dizi kullanır - kelimeler model çanta açıklandığı gibi. check2 () büyük bir dizi ama bir metnin sadece sözcükleri içeren bir dizi kullanmak değildir. Yani check2 () çalışmak gerekir ama o değil. Neden her iki işlevi aynı sonuçlar veriyorsunuz?

function check1($terms_in_article1, $terms_in_article2) {
    global $zeit_check1;
    $zeit_s = microtime(TRUE);
    $length1 = count($terms_in_article1); // number of words
    $length2 = count($terms_in_article2); // number of words
    $all_terms = array_merge($terms_in_article1, $terms_in_article2);
    $all_terms = array_unique($all_terms);
    foreach ($all_terms as $all_termsa) {
        $term_vector1[$all_termsa] = 0;
        $term_vector2[$all_termsa] = 0;
    }
    foreach ($terms_in_article1 as $terms_in_article1a) {
        $term_vector1[$terms_in_article1a]++;
    }
    foreach ($terms_in_article2 as $terms_in_article2a) {
        $term_vector2[$terms_in_article2a]++;
    }
    $score = 0;
    foreach ($all_terms as $all_termsa) {
        $score += $term_vector1[$all_termsa]*$term_vector2[$all_termsa];
    }
    $score = $score/($length1*$length2);
    $score *= 500; // for better readability
    $zeit_e = microtime(TRUE);
    $zeit_check1 += ($zeit_e-$zeit_s);
    return $score;
}
function check2($terms_in_article1, $terms_in_article2) {
    global $zeit_check2;
    $zeit_s = microtime(TRUE);
    $length1 = count($terms_in_article1); // number of words
    $length2 = count($terms_in_article2); // number of words
    $score_table = array();
    foreach($terms_in_article1 as $term){
        if(!isset($score_table[$term])) $score_table[$term] = 0;
        $score_table[$term] += 1;
    }
    $score_table2 = array();
    foreach($terms_in_article2 as $term){
        if(isset($score_table[$term])){
            if(!isset($score_table2[$term])) $score_table2[$term] = 0;
            $score_table2[$term] += 1;
        }
    }
    $score = 0;
    foreach($score_table2 as $key => $entry){
        $score += $score_table[$key] * $entry;
    }
    $score = $score/($length1*$length2);
    $score *= 500;
    $zeit_e = microtime(TRUE);
    $zeit_check2 += ($zeit_e-$zeit_s);
    return $score;
}

Bana yardımcı olur umarım. Şimdiden teşekkürler!

2 Cevap

Her iki fonksiyon hemen hemen aynı algoritmayı uygulamak, ancak ilki basit bir şekilde bunu yapar iken, ikincisi biraz daha zeki ve gereksiz iş bir kısmını atlar.

check1 şöyle:

// loop length(words1) times
for each word in words1:
    freq1[word]++

// loop length(words2) times
for each word in words2:
    freq2[word]++

// loop length(union(words1, words2)) times
for each word in union(words1, words2):
    score += freq1[word] * freq2[word]

Ama unutmayın: sıfır ile çarpın bir şey olduğunda, sıfır alırsınız.

Bu iki seti olmayan kelimelerin frekanslarını sayarak bir zaman kaybı olduğunu, gelir - biz sıfıra frekans çarpın ve bu skoru şey katacak.

check2 bunu dikkate alır:

// loop length(words1) times
for each word in words1:
    freq1[word]++

// loop length(words2) times
for each word in words2:
    if freq1[word] > 0:
        freq2[word]++

// loop length(intersection(words1, words2)) times
for each word in freq2:
    score += freq1[word] * freq2[word]

Eğer performansı hakkında endişe gibi görünüyor, çünkü burada algoritmasının iyileştirilmiş bir versiyonu geliştirilmiş hız için biraz daha yerleşik işlevleri kullanır check2 fonksiyonu bulunuyor.

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