Detection du "sujet" d'un article

ViPHP
ViPHP | 4039 Messages

18 sept. 2009, 14:48

C'est comme sékil l'explique, en fait on vectorise le texte, et ensuite on calcule une distance entre ces vecteurs (et c'est un peu plus compliqué que de transformer les mots en chiffres, méa culpa).

Bon, alors, tenez-vous. Plutôt que de faire dans le théorique, je vais tenter d'expliquer un cas pratique.

En fait, prenons le texte "Toto et deux de ses camarades".
Et "Toto et ses nombreux amis "

Il y à 8 mots différents, ce qui donne 8 dimensions possibles dans lesquelles le texte (= le vecteur) peut se déplacer (= se formuler):

[Toto, et, deux, de, ses, camarades, nombreux, amis].

Avec cette clef, on peut créer un vecteur d'après les occurrences des mots dans ses phrases:

Phrase 1 : [1, 1, 1, 1, 1, 1, 0, 0]
Phrase 2: [1, 1, 0, 0, 1, 0, 1, 1]

On nourris ça à la formule de pearson (une parmi d'autres, qui si je me souviens bien traite assez bien la comparaison de texte pour diverses raisons) qui va pondre un chiffre de -1 à 1. 1 signifie une correspondance exacte, 0 qu'il n'y à pas de comparaison, et -1 qu'ils sont diamétralement opposés. Ce qui donne une idée de leur "ressemblance".

En fait, on peut penser à notre espace tri-dimensionnel (x,y,z), dans lequel il est assez facile de calculer la distance entre deux points(genre (2,1,4) et (2,1,5) ). Sauf qu'ici, on utilise autant d'axes qu'il y à de mots, ce qui peut monter à plusieurs milliers quant on utilise un corpus un tant soit peu conséquent.

Maintenant, ça ne veut pas dire qu'ils sont proches, on peut presque tout interpréter. A un moment j'ai pensé analyser tout le contenu de phpfrance pour voir quels styles d'écritures étaient les plus proches (puisqu'on parle ici d'usage des mots). Mais ça donne une idée sur leur relative ressemblance, que ce soit parce qu'ils parlent du même sujet, sont écrit dans le même style,ou sont aussi creux l'un que l'autre :wink: .

En tout cas, je faisais ça sur des dizaines de milliers de texte, donc oui, ça pouvait prendre du temps :twisted:

Et sinon, on peut calculer la distance (on parle pas ici de distance géométrique ou euclidienne, mais d'une distance plus abstraite) entre deux mots avec la fonction levenshtein() de php, qui compte le nombre de permutations de lettres qu'il faut pour partir d'un mot pour arriver à un autre.
Mais qu'importe. (je suis ici - dernier petit projet)
Berze going social.

Mammouth du PHP | 985 Messages

18 sept. 2009, 15:09

Ok donc si j'ai bien compris le principe, au lieu de définir et de comparer séparément le nombres de mots similaires de deux textes...
On cumule les deux -> on en ressort une clef
Ensuite on compare cette clef avec les deux texte -> on en ressort deux autres clefs (0 -> Non, 1 -> Oui)
Le tout aidé d'une formule adaptée comme celle de Pearson (0 -> Non, 1 -> Oui, -1->opposé)
...
Face à la roche, le ruisseau l'emporte toujours, non pas par la force mais par la persévérance.

ViPHP
ViPHP | 4039 Messages

18 sept. 2009, 15:16

C'est un peu ça, avec des variations possibles.

Donc on commence avec un cadre de référence ( [Toto, et, deux, de, ses, camarades, nombreux, amis] pour l'exemple)

Dans lequel on exprime les différents textes. On peut choisir de se restreindre à la simple présence des mots (1=oui, 0=non) ou alors compter le nombre de fois qu'un mot se répète dans un texte, mais on risque alors de biaiser le résultat, puisque si deux textes sont assez semblables, un usage abusif d'un mot dans l'un peut atténuer le résultat. On peut aussi mélanger les approches, vérifier les résultats et décider des proportions et paramètres à utiliser (en gros, calibrer).
Mais qu'importe. (je suis ici - dernier petit projet)
Berze going social.

ViPHP
ViPHP | 4039 Messages

18 sept. 2009, 15:20

De même après vectorisé des textes , on peut s'amuser à les regrouper avec des méthodes telles que le k-means clustering, mais la on s'éloigne du sujet. :wink:
Mais qu'importe. (je suis ici - dernier petit projet)
Berze going social.

ViPHP
ViPHP | 5924 Messages

18 sept. 2009, 16:19

Et sinon, on peut calculer la distance (on parle pas ici de distance géométrique ou euclidienne, mais d'une distance plus abstraite) entre deux mots avec la fonction levenshtein() de php, qui compte le nombre de permutations de lettres qu'il faut pour partir d'un mot pour arriver à un autre.
Bah, sur ce point, à part pour repérer des fautes d'orthographes et proposer une correction (comme l'exemple de la fonction), je ne pense pas que c'ait une utilité réelle dans ce cas. On aura juste la différence orthographique entre deux mots, mais rien de très exploitable.

J'ai pensé aux vecteurs. J'ai hésité à en parler, je ne savais pas que la méthode de pearson se basait dessus.

Eléphanteau du PHP | 20 Messages

20 sept. 2009, 17:11

Très bien, merci Berzemus, cette fois-ci je comprend beaucoup mieux le côté théorique du calcul.

Si j'ai bien suivi, on commence par "vectoriser" les deux textes, puis on compare les deux vecteurs avec la formule de Pearson ( notamment grâce à la fonction déjà incluse dans php).

Seulement, il reste une zone d'ombre dans mon esprit:
Comment vectorise-t-on les deux textes?
Cela induit-il qu'il faut avoir stocké quelque part l'ensemble des mots du dictionnaire français, et ensuite tester leur présence ou non dans chacun des textes?
(Si c'est le cas, ca risque effectivement d'être long...)

ViPHP
ViPHP | 5924 Messages

20 sept. 2009, 19:06

Tu peux faire la liste des mots, ou des radicaux (mais pour cela il faut avoir un dico ou des traitements spéciaux) présents dans les deux textes, et ensuite tu attribues un nombre à chacun.

Eléphanteau du PHP | 20 Messages

20 sept. 2009, 19:14

Mais, Sékiltoyai, je ne comprend plus. Tu indiques qu'il faut attribuer un nombre à chaque mot present.

Or, Berzemus, indique qu'il faut uniquement creer deux tableaux, comme ceci :
Phrase 1 : [1, 1, 1, 1, 1, 1, 0, 0]
Phrase 2: [1, 1, 0, 0, 1, 0, 1, 1]
Or, selon la methode de Berzemus, ces deux tableaux n'attribuent non pas un nombre à chaque mot présent, mais simplement un booléen qui indique si le mot est présent ou non... je suis perdu.

ViPHP
ViPHP | 5924 Messages

20 sept. 2009, 19:20

Je disais cela en réponse à ta question :
Comment vectorise-t-on les deux textes?
La méthode que je te donne te permet d'avoir la liste des mots présents dans les deux textes. Tu peux te servir de cette liste (et de cette association mot <-> nombre) pour construire les deux vecteurs sans avoir besoin d'un dico.

Eléphanteau du PHP | 20 Messages

20 sept. 2009, 20:36

Ah d'accord! C'est vrai, c'est pas bête.

Je vais essayer de coder ça en PHP, voir un peu ce que ca donne en pratique. N'hésitez pas, si vous avez des conseils ou des suppléments d'information!

Eléphanteau du PHP | 20 Messages

21 sept. 2009, 16:45

J'étais gentiment en train de coder ca quand j'ai eu une petite idée.

Si je voulais étendre mon script à la comparaison globale de textes, c'est à dire non plus deux textes entre eux, mais un texte comparé à une multitude de textes, je pourrais stocker tous les mots du dictionnaire français dans une table, tester chacun d'eux dans le texte puis créer une très longue clé (du style [1,0,1,0,1,1,1,1,0,1,0, [...], 0, 0]) que je stockerai elle même avec l'article.

Ensuite, à chaque ajout d'article, il suffirait de tester la nouvelle clé avec toutes les autres clés déjà présentes dans la base afin de détecter les similitudes.

Qu'en pensez-vous? Ca vous semble réalisable?

ViPHP
ViPHP | 5924 Messages

21 sept. 2009, 17:14

Gourmand mais possible.
Après, là encore, ce n'est pas indispensable d'avoir un dico, mais ce serait plus simple (mais moins puissant) avec en effet.

ViPHP
ViPHP | 4039 Messages

21 sept. 2009, 17:18

Le plus simple est de constituer toi-même ton dictionnaire, au fur et à mesure des données (a chaque nouveau texte, il est d'abord analysé à la recherche de nouveaux mots à ajouter au dico, sans parler des mots conjugués).

Ensuite, le vecteur ne doit utiliser que les mots présents dans les deux textes à comparer, par simple souci d'économie de temps de calcul.

Et a chaque nouveau texte, il faudra le comparer à tous les autres déjà présents, ce qui implique un temps de calcul conséquent après quelques centaines.

Alors il y à deux approches, soit il faut générer un clef qui permet une comparaison rapide avec d'autres clefs existantes (d'une façon ou d'une autre), ou alors il faut précalculer les différences entre les textes, et les stocker.
Mais qu'importe. (je suis ici - dernier petit projet)
Berze going social.

Eléphanteau du PHP | 20 Messages

21 sept. 2009, 22:32

Bon, j'ai commencé déjà à tester mon code, et les résultats ne sont pas très concluants...

Pour 2 articles (de journal) qui parlent du même sujet, j'obtient un coefficient de Pearson de -0,75. Pour deux articles qui ne parlent pas de la même chose : -0,93.
J'ai ensuite effectué des tests plus simples avec les deux phrases : "je suis bob" et "je suis john et bob" et je suis remonté à -0,40. Mais je reste dans le négatif...

J'ai utilisé les fonctions que quelqu'un a posté en commentaire sur : http://be2.php.net/stats_stat_correlation.
La fonction stats_stat_correlation n'était pas reconnue par ma version de PHP apparement.

ViPHP
ViPHP | 4039 Messages

22 sept. 2009, 09:39

La fonction fait partie de PECL, une série de modules à installer séparément.

En ce qui concerne la fonction postée, j'ai pas trop vu de quelle inspiration elle était, ni de quel algo il s'agissait.

Quant à la signification des résultats, tout dépend de l'algo utilisé. Tu ne saura vraiment distinguer un résultat positif d'un négatif qu'après avoir fait quelques dizaines de comparaisons. C'est toute la science des statistiques que de produire une formule adaptée ^-^
Mais qu'importe. (je suis ici - dernier petit projet)
Berze going social.