IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Perl Discussion :

calcul tf à l'aide de hachage


Sujet :

Langage Perl

  1. #1
    Membre du Club
    Inscrit en
    Avril 2009
    Messages
    128
    Détails du profil
    Informations forums :
    Inscription : Avril 2009
    Messages : 128
    Points : 43
    Points
    43
    Par défaut calcul tf à l'aide de hachage
    Bonjour à tous,

    en fait mon objectif est de calculer la fréquence d'apparition de chaque mot de mon corpus, pour ce faire j'ai une liste des mots, pour chaque mot je veux calculer son tf qui est egal au nombre d'occurrence de ce mot dans le corpus divisé par le nombre total des mots de corpus,
    je veux utilisé le hachage pour éviter le problème de "out of memory" et pour optimiser mon code:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    #tf mot = nombre d'occurrence des mots dans le corpus / nombre total des mots dans le corpus 
        use strict;
        use warnings;
        use autodie;
     
    open my $fh_resultat, ">:utf8", 'TF_exple.txt';
    use constant CORPUS_MOT => 'exple_mots.txt';
    use constant CORPUS_Phrases => 'exple_phrases.txt';
    open my $fh2, "<:utf8", CORPUS_Phrases;
     
    open my $fh1, "<:utf8", CORPUS_MOT;
     
     
    my %words;   # hachage de compteurs
     
    while (my $word = <$fh1> ) {
        chomp $word;
    next if $word =~ /^\s*$/; 
        $words{$word} = 0;
    }
    close $fh1;
    comment je peux utiliser le hachage pour calculer le nombre total de mot dans le CORPUS_Phrases et le nombre d'occurrence de chaque mot de CORPUS_MOT dans le CORPUS_Phrases pour avoir à la fin: mot:tf
    Merci beaucoup d'avance.

  2. #2
    Membre actif Avatar de olivier1969
    Homme Profil pro
    Assistant aux utilisateurs
    Inscrit en
    Novembre 2013
    Messages
    151
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Assistant aux utilisateurs
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Novembre 2013
    Messages : 151
    Points : 208
    Points
    208
    Par défaut
    Bonjour,

    Tu remplaces par

  3. #3
    Membre habitué
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Mars 2015
    Messages
    138
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : Service public

    Informations forums :
    Inscription : Mars 2015
    Messages : 138
    Points : 138
    Points
    138
    Par défaut
    Ci-après, un exemple de code répondant à la demande.
    Chaque enregistrement lu est splitté sur la base de 0 ou plus occurrence d'une virgule, d'un point ou d'un point-virgule, suivi d'un ou plusieurs caractères d'espacement.
    Les résultats sont stockés dans une table de hachage dont la clé est le mot et la valeur une référence vers un tableau contenant le nombre d’occurrences du mot et son tf
    Le code peut être bien sûr plus concis mais tel quel répond mieux à des besoins didactiques.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    #!/usr/bin/env perl
    use strict;
    use warnings;
    use Data::Dumper;
    use feature 'say';
     
    my %words;
    my $nb_mots;
     
    while ( my $record = <DATA> ) {
        chomp $record;
        my @words = split /[,.;]?\s+/, $record ;
     
        foreach my $word ( @words ) {
            $words{$word}->[0]++;
            $nb_mots++;
        }
    }
     
    # calcul tf
    foreach my $word ( keys %words ) {
            $words{$word}->[1] = $words{$word}->[0] / $nb_mots;
    }
    say Dumper \%words
     
    __DATA__
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent nec nisi ut felis commodo venenatis nec et quam. Vestibulum eu diam tortor. Morbi a facilisis arcu. Vestibulum et pharetra urna, scelerisque lacinia mauris. Phasellus semper felis facilisis magna accumsan hendrerit. Quisque finibus velit id neque mattis, id pharetra neque ultricies. Aliquam erat volutpat. Cras facilisis pellentesque ultricies. Integer vel tincidunt quam. Nunc a maximus sem, et congue turpis.
     
    Aenean in dui vulputate, elementum lacus non, commodo felis. Etiam semper ut est quis mattis. Quisque dictum nibh et ullamcorper suscipit. In venenatis justo consectetur magna vehicula, vitae bibendum ex sagittis. Curabitur condimentum urna sed sagittis laoreet. In ultrices sodales venenatis. Nam consequat, massa ut porttitor condimentum, ex ligula lobortis est, dapibus tristique massa elit eget dui. Ut dictum in diam quis sodales. Duis rhoncus eget tortor a tincidunt. Nunc placerat mauris id ultricies iaculis. Vivamus tristique id metus ullamcorper bibendum. Aliquam quis dolor hendrerit, elementum massa iaculis, placerat lorem. Cras a aliquet augue.
     
    Morbi felis turpis, scelerisque vitae nisl sed, bibendum laoreet dui. Pellentesque tempus convallis ornare. Vestibulum semper nisl augue, eu molestie urna porttitor eu. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Morbi blandit odio a felis posuere pharetra. Nunc fermentum sem a mauris lobortis, et elementum risus dapibus. Maecenas ante orci, molestie nec ante eget, viverra malesuada elit. Aenean at purus iaculis mi auctor euismod. In hac habitasse platea dictumst. In hendrerit auctor urna. Nam ac enim pharetra purus ultrices rutrum. Maecenas at ex ac dui mollis vulputate. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
     
    In hac habitasse platea dictumst. Quisque eget molestie metus, nec congue lectus. Pellentesque consequat tortor sit amet varius dapibus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sodales in enim eget luctus. Maecenas in nisi et dui ullamcorper maximus. Phasellus semper a diam sed porta. Sed vel luctus elit. Etiam nulla turpis, aliquet vel dolor id, pharetra convallis risus.
     
    Aliquam lectus quam, tincidunt eget eros nec, laoreet scelerisque felis. Proin ornare, orci in convallis efficitur, sapien ipsum consequat risus, a lobortis felis libero in ex. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed eu lorem a justo dapibus ultricies et a leo. Maecenas feugiat nulla vitae nunc lobortis elementum. Integer luctus egestas sem, id bibendum magna dictum eget. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Mauris eu sapien blandit, maximus nisi nec, consequat ipsum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque placerat euismod felis quis consequat. Etiam sed pharetra felis. Fusce volutpat feugiat aliquet.
    Sortie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    $VAR1 = {
    $VAR1 = {
              'bibendum' => [
                              4,
                              '0.00909090909090909'
                            ],
              'ultrices' => [
                              3,
                              '0.00681818181818182'
                            ],
              'sodales' => [
                             3,
                             '0.00681818181818182'
                           ],
              'lectus' => [
                            2,
                            '0.00454545454545455'
                          ],
              'dui' => [
                         5,
                         '0.0113636363636364'
                       ],
    ...
            };

  4. #4
    Membre du Club
    Inscrit en
    Avril 2009
    Messages
    128
    Détails du profil
    Informations forums :
    Inscription : Avril 2009
    Messages : 128
    Points : 43
    Points
    43
    Par défaut
    bonjour à tous ,
    en fait mon obectif est de calculer la fréquence d'apparition des mots se trouvant dans un fichier keywords.txt

    et la recherche est dans le texte search.txt
    voici mon code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
     
        #!usr/bin/perl
        use strict;
        use warnings;
        open my $keywords,    '<:utf8', 'keywords.txt' or die "Can't open keywords: $!";
        open my $search_file, '<:utf8', 'search.txt'   or die "Can't open search file: $!";
        open my($file), '<', 'search.txt';
        my %words;   # hachage de compteurs
        while (my $word = <$keywords> ) {
            chomp $word;
        next if $word =~ /^\s*$/;  
            $words{$word} = 1;
        }  
        close $keywords;
        my %freq;
        while( my $word = <$file> ) {
        $freq{$word}++ if $words{$word};  
         }
        foreach my $word ( keys %words) {
        print "$word $freq{$word}\n";
        }
    mais le résultat est faux
    search.txt:
    red yellow blue red
    red red yellow

    keywords.txt:
    blue
    red
    green
    yellow

  5. #5
    Membre éprouvé Avatar de Gardyen
    Homme Profil pro
    Bio informaticien
    Inscrit en
    Août 2005
    Messages
    637
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bio informaticien

    Informations forums :
    Inscription : Août 2005
    Messages : 637
    Points : 1 050
    Points
    1 050
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    while( my $word = <$file> ) {
        $freq{$word}++ if $words{$word};  
    }
    ici tu lis et compare ta ligne entière, tu ne découpes pas selon tes mots ? tu peux aussi chercher chaque keyword avec une expression régulière
    Nous les geeks, c'est pas qu'on a une case en moins, c'est juste qu'on compte à partir de zéro.
    Plus les choses changent, plus elles restent les mêmes

  6. #6
    Expert éminent sénior Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 243
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 243
    Points : 13 459
    Points
    13 459
    Par défaut
    Bonjour

    2 choses:
    • Tu compares des lignes et des mots.
    • Tu utilises $freq{$word} avant même de savoir si c'est défini.
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  7. #7
    Membre confirmé
    Avatar de cmcmc
    Homme Profil pro
    Inscrit en
    Juillet 2013
    Messages
    316
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2013
    Messages : 316
    Points : 641
    Points
    641
    Par défaut
    Je ne suis pas sûr de ce que tu veux dire par "fréquence d'apparition". Le programme ci-dessous énumère pour chaque mot clé son nombre d'occurrences dans le(s) fichier(s) passés en paramètre, et sa fréquence d'apparition (définie comme le quotient de ce nombre d'occurrences par le nombre total de mots) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $ perl -E '{ local @ARGV = shift @ARGV; while (<>) { ++$k{$_} for split /\s+/}} while (<>) { ++$cnt,++$o{$_} for split /\s+/} say join("\t", $_, $o{$_}//0, $o{$_}/$cnt) for sort keys %k' keywords.txt search.txt
    blue	1	0.142857142857143
    green	0	0
    red	4	0.571428571428571
    yellow	2	0.285714285714286
    $
    Le fait de passer les noms de fichier en paramètre est plus flexible que ton approche de les coder en dur dans le programme. En particulier l'approche ci-dessus permet de passer plusieurs fichiers de recherche, par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    $ echo "red red red red red red yellow" > more.txt
    $ perl -E '...' keywords.txt search.txt more.txt
    blue	1	0.0714285714285714
    green	0	0
    red	10	0.714285714285714
    yellow	3	0.214285714285714
    $
    Dans les exemples ci-dessus la somme des fréquences est 1 (à un arrondi près) parce que tous les mots des fichiers de recherche sont présents dans keywords.txt. Ce n'est évidemment pas le cas général :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    $ echo "orange white cyan cyan black black black teal" > extra.txt
    $ perl -E '...' keywords.txt search.txt more.txt extra.txt
    blue	1	0.0454545454545455
    green	0	0
    red	10	0.454545454545455
    yellow	3	0.136363636363636
    $
    Tu peux évidemment rediriger la sortie vers un fichier :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ perl -E '...' keywords.txt search.txt more.txt extra.txt > resultats.txt
    $
    Note également que l'utilisation de @ARGV permet d'utiliser le programme dans un pipeline :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ ...process de production du corpus... | perl -E '...' keywords.txt | ...process d'analyse des résultats...
    $
    Sauf indication contraire tous les codes que je présente sont utilisables et testés (mais sans garantie d'aucune sorte)
    J'apporte beaucoup de soin à la rédaction de mes posts et apprécie les retours donc merci de s'il vous paraissent pertinents ou utiles
    Lazyness, Impatience and Hubris are good for you

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo