Question

Dans mes nouvelles projet de page, j'ai une table de base de données nouvelles avec la structure suivante:

 - id: [integer] unique number identifying the news entry, e.g.: *1983*
 - title: [string] title of the text, e.g.: *New Life in America No Longer Means a New Name*
 - topic: [string] category which should be chosen by the classificator, e.g: *Sports*

De plus, il y a une table Bayes avec des informations sur la fréquence des mots:

 - word: [string] a word which the frequencies are given for, e.g.: *real estate*
 - topic: [string] same content as "topic" field above, e.h. *Economics*
 - count: [integer] number of occurrences of "word" in "topic" (incremented when new documents go to "topic"), e.g: *100*

Maintenant, je veux que mon script PHP pour classer toutes les entrées de nouvelles et assign une de plusieurs catégories possibles (sujets) pour eux.

Est-ce la bonne mise en œuvre? Pouvez-vous améliorer?

<?php
include 'mysqlLogin.php';
$get1 = "SELECT id, title FROM ".$prefix."news WHERE topic = '' LIMIT 0, 150";
$get2 = mysql_abfrage($get1);
// pTOPICS BEGIN
$pTopics1 = "SELECT topic, SUM(count) AS count FROM ".$prefix."bayes WHERE topic != '' GROUP BY topic";
$pTopics2 = mysql_abfrage($pTopics1);
$pTopics = array();
while ($pTopics3 = mysql_fetch_assoc($pTopics2)) {
    $pTopics[$pTopics3['topic']] = $pTopics3['count'];
}
// pTOPICS END
// pWORDS BEGIN
$pWords1 = "SELECT word, topic, count FROM ".$prefix."bayes";
$pWords2 = mysql_abfrage($pWords1);
$pWords = array();
while ($pWords3 = mysql_fetch_assoc($pWords2)) {
    if (!isset($pWords[$pWords3['topic']])) {
        $pWords[$pWords3['topic']] = array();
    }
    $pWords[$pWords3['topic']][$pWords3['word']] = $pWords3['count'];
}
// pWORDS END
while ($get3 = mysql_fetch_assoc($get2)) {
    $pTextInTopics = array();
    $tokens = tokenizer($get3['title']);
    foreach ($pTopics as $topic=>$documentsInTopic) {
        if (!isset($pTextInTopics[$topic])) { $pTextInTopics[$topic] = 1; }
        foreach ($tokens as $token) {
            echo '....'.$token;
            if (isset($pWords[$topic][$token])) {
                $pTextInTopics[$topic] *= $pWords[$topic][$token]/array_sum($pWords[$topic]);
            }
        }
        $pTextInTopics[$topic] *= $pTopics[$topic]/array_sum($pTopics); // #documentsInTopic / #allDocuments
    }
    asort($pTextInTopics); // pick topic with lowest value
    if ($chosenTopic = each($pTextInTopics)) {
        echo '<p>The text belongs to topic '.$chosenTopic['key'].' with a likelihood of '.$chosenTopic['value'].'</p>';
    }
}
?>

La formation se fait manuellement, il ne figure pas dans ce code. Si le texte « Vous pouvez gagner de l'argent si vous vendez des biens immobiliers » est attribué à la catégorie / thème « économie », puis tous les mots (vous, peut, faire, ...) sont insérés dans la table Bayes avec "l'économie" comme sujet et 1 nombre standard. Si le mot est déjà là en combinaison avec le même sujet, le compte est incrémenté.

données d'apprentissage Exemple:

count

mot sujet

kaczynski Politique 1

Sony Technologie 1

Economie banque 1

téléphone Technologie 1

Sony Economie 3

ericsson Technologie 2

Exemple de sortie / résultats:

Titre du texte: test Téléphone Sony Ericsson Aspen - sensible Winberry

La politique

.... téléphone ....tester .... sony .... ericsson ....tremble ....sensible .... Winberry

Technologie

.... téléphone TROUVE ....tester .... sony TROUVE .... TROUVE ericsson ....tremble ....sensible .... Winberry

Economie

.... téléphone ....tester .... sony TROUVE .... ericsson ....tremble ....sensible .... Winberry

Résultat: Le texte appartient au sujet de la technologie avec un risque de ,013888888888889

Merci beaucoup à l'avance!

Était-ce utile?

La solution

Il semble que votre code est correct, mais il y a quelques moyens faciles à optimiser. Par exemple, calculer p (mot | sujet) à la volée pour chaque mot pendant que vous pouvez facilement calculer ces valeurs à l'avance. (Je suppose que vous voulez classer plusieurs documents ici, si vous faites un seul document que je suppose que cela est correct puisque vous ne calculez pas les mots ne sont pas dans le document)

De même, le calcul de p (le sujet) peut être déplacé en dehors de la boucle.

Enfin, vous n'avez pas besoin de trier le tableau entier pour trouver le maximum.

Tous les petits points! Mais c'est ce que vous avez demandé:)

J'ai écrit quelques montrant PHP-code non testé comment je mettre en œuvre ce ci-dessous:

<?php

// Get word counts from database
$nWordPerTopic = mystery_sql();

// Calculate p(word|topic) = nWord / sum(nWord for every word)
$nTopics = array();
$pWordPerTopic = array();
foreach($nWordPerTopic as $topic => $wordCounts)
{
    // Get total word count in topic
    $nTopic = array_sum($wordCounts);

    // Calculate p(word|topic)
    $pWordPerTopic[$topic] = array();
    foreach($wordCounts as $word => $count)
        $pWordPerTopic[$topic][$word] = $count / $nTopic;

    // Save $nTopic for next step
    $nTopics[$topic] = $nTopic;
}

// Calculate p(topic)
$nTotal = array_sum($nTopics);
$pTopics = array();
foreach($nTopics as $topic => $nTopic)
    $pTopics[$topic] = $nTopic / $nTotal;

// Classify
foreach($documents as $document)
{
    $title = $document['title'];
    $tokens = tokenizer($title);
    $pMax = -1;
    $selectedTopic = null;
    foreach($pTopics as $topic => $pTopic)
    {
        $p = $pTopic;
        foreach($tokens as $word)
        {
            if (!array_key_exists($word, $pWordPerTopic[$topic]))
                continue;
            $p *= $pWordPerTopic[$topic][$word];
        }

        if ($p > $pMax)
        {
            $selectedTopic = $topic;
            $pMax = $p;
        }
    }
} 
?>

En ce qui concerne les mathématiques ...

Vous essayez de maximiser p (sujet | mots), afin de trouver

arg max p(topic|words)

(IE le sujet d'argument pour lequel p (sujet | mots) est le plus élevé)

théorème de Bayes dit

                  p(topic)*p(words|topic)
p(topic|words) = -------------------------
                        p(words)

Vous cherchez

         p(topic)*p(words|topic)
arg max -------------------------
               p(words)

Comme p (mots) d'un document est le même pour tout sujet c'est le même que la recherche

arg max p(topic)*p(words|topic)

L'hypothèse de Bayes naïf (ce qui en fait un classifieur de Bayes naïf) est que

p(words|topic) = p(word1|topic) * p(word2|topic) * ...

Donc, en utilisant cela, vous devez trouver

arg max p(topic) * p(word1|topic) * p(word2|topic) * ...

p(topic) = number of words in topic / number of words in total

                   p(word, topic)                         1
p(word | topic) = ---------------- = p(word, topic) * ----------
                      p(topic)                         p(topic)

      number of times word occurs in topic     number of words in total
   = -------------------------------------- * --------------------------
            number of words in total           number of words in topic

      number of times word occurs in topic 
   = --------------------------------------
            number of words in topic
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top