optimisation script perl - Perl - Programmation
Marsh Posté le 22-05-2017 à 19:33:38
my $nbre_ligne = 4159480;
non!
my @tab_phrase_CORPUS = <$fh2>;
my $nbre_ligne = scalar(@tab_phrase_CORPUS);
Ensuite:
foreach my $mot (@tab_MOT_CORPUS) {
...
foreach my $ph (@tab_phrase_CORPUS) {
surtout pas! ca fait parcourir ton gros fichier scalar(@tab_MOT_CORPUS) fois.
Il ne faut parcourir @tab_phrase_CORPUS qu'une seule fois.
et passer par un hash pour accumuler les valeurs
Bref faire un truc dans ce gout la (pas testé):
use List::Util qw(uniqstr);
use Array::Utils qw(intersect);
my %tab_MOT_CORPUS;
{
open my $fh1, "<:utf8", CORPUS_MOT;
while (<$fh1> ) {
chop;
foreach (split) {
$tab_MOT_CORPUS{$_}=0;
}
}
}
# on a créé un hash de clés les mots du corpus et de valeurs 0
my @mots_corpus = keys %tab_MOT_CORPUS;
my $nbre_ligne = 0;
foreach (@tab_phrase_CORPUS) {
$nbre_ligne++;
chop;
my @mots = split;
@mots = uniqstr (@mots);
@mots = intersect(@mots_corpus, @mots);
# mots contient la liste des mots de la phrase qui sont dans le corpus, chacun étant distinct
foreach (@mots) {
$tab_MOT_CORPUS{$_}++;
# pour chacun, on incrémente le nb de lignes ou il figure
}
}
Note:
Je me demande si un truc plus basique serait pas plus efficace en fait:
my %lignes;
my $nbre_phrases = 0;
{
open my $fh, "<:utf8", CORPUS_MOT;
while (<$fh1> ) {
$nbre_phrases++;
chop;
my @mots = split;
foreach (uniqstr(@mots)) {
$lignes{$_}++;
}
}
close $fh;
}
et ensuite
sub idf($) {
my $mot= shift;
if ($nbre_phrase and $lignes{$mot}) {
return log($lignes{$mot}/$nb_phrase)/log(10);
}
else {
return 0;
}
}
Bref on construit un hash global pour tous les mots de ton corpus de texte, plutôt que de perdre du temps a chaque ligne a le filtrer vis a vis de ton corpus de mots. Ça ira plus vite, mais ça bouffera un peu plus de mémoire (mais pas plus que ton my @tab_phrase_CORPUS = <$fh2>; a priori).
A+,
Marsh Posté le 23-05-2017 à 00:12:02
bonsoir gilou, merci beaucoup pour la réponse
j'ai testé avec la première version, mais j'ai eu en sortie : "uniqstr" is not exported by the List::Util module
j'ai cherché sur google, mais j'ai pas réussi à trouver une solution ..
Marsh Posté le 23-05-2017 à 10:41:13
Probablement parce que votre module List::Util n'est pas à jour.
Si je regarde sur CPAN, c'est dedans:
http://search.cpan.org/~pevans/Sca [...] st/Util.pm
Code :
|
uniqstr fait partie des fonctions exportées.
A+,
Marsh Posté le 25-05-2017 à 14:04:21
Bon, j'ai eu le temps de regarder cela d'un peu plus près, vu que je bosse pas aujourd'hui.
Suite a vos mails en MP, je ferais ainsi:
Code :
|
Vu la taille de votre corpus, 1M de mots et 4M de lignes, c'est ce que je pense être le plus efficace.
Le seul endroit ou ca risque de ne pas satisfaire vos besoins, c'est le split /\b/.
En effet, si vos données sont en unicode, il n'est pas certain que cela ne splitte pas sur tout caractère accentué ou inhabituel.
Auquel cas, il faudra remplacer le /\b/ par une expression régulière plus adaptée (\b{wb}\ ?).
En tout cas, j'ai testé vite fait avec un mot comme Sørensen ou حاطه et il y avait pas de pb avec \b
Pour les perfs, on lit chaque ligne une seule fois, donc ça devrait rester acceptable.
Bon par contre si on a du bidirectionnel, faudra faire évoluer ce code, sinon on aura des choses style:
حاطه : -0.477121254719662
A+,
Marsh Posté le 22-05-2017 à 11:24:20
Bonjour à tous,
Le script suivant permet le calcul de l'IDF d'un mot (pour un mot w, idf(w) = log(nombre des phrases dans mon corpus / nombre des phrases contenant le mot w)
d'après les tests que je l'ai fait, ce script marche bien , cependant il est long , comment je peux l'optimiser.
voici le code