Bonjour,
Oui, avec la méthode rstrip() appliquée à la chaine:
Tyrtamos
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 dico[mot[0]] = mot[1].rstrip('\n')
Bonjour,
Oui, avec la méthode rstrip() appliquée à la chaine:
Tyrtamos
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 dico[mot[0]] = mot[1].rstrip('\n')
merci tyrtamos
Maintenant que j'ai mon fichier de cooccurrence.
Il me reste plus qu'une chose après ça sera terminé!!!!! je vous laisserai tranquille!!!!
Je vous explique la suite.
j'ai une liste de mot séparé par des "\n" (on appelle le fichier d'évaluation fichierEvalution.log)
ex :
j'ai un fichier d'apprentissage (fichierApprentissage.log) sous ce format
Entre France et Top, il y a un "\t".
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 France Top Obama Hum
Le but est de charger les deux fichiers.
Le premier le stocker dans une liste
le second, le stocker dans un dico avec clé = Obama et valeur = Hum
L'objectif est d'affecter des traits sémantiques à la liste du fichier "fichierEvalution.log"
Pour cela,
je vous explique le principe et après je vous montre le bout de code.
Après avoir chargé les deux fichiers (l'une dans une liste et l'autre dans un dico)
je parcours la liste d'évaluation.
pour chaque mot MOTLISTE de la liste
je regarde s'il est dans la matrice de cooccurrence.
si oui
je récupère sa liste "LISTEA" de cooccurrent avec matrice[mot]
ensuite je parcours pour chaque mot MOTMATRICE de la matrice en récupérant pour chaque clé leur liste "LISTEB" et je fais une intersection de LISTE B & LISTE A pour récupérer le nombre de cooccurrent commun.
si le nombre de cooccurrent commun est supérieur à max (une valeur que je défini), je met dans la liste (LISTEEQUIVALENCE) de MOTLISTE, le mot MOTMATRICE.
ensuite je retourne la liste d'équivalence.
Ensuite je traite la liste d'équivalence récupérant le meilleur trait sémantique en m'aidant du dico d'apprentissage.
Je parcours LISTEQUIVALENCE
pour chaque mot, je regarde s'il se trouve dans le dico d'apprentissage
si oui, je récupère son trait sémantic (par ex pour Obama, le trait sémantique est Hum)
j'incrémente le trait Hum de 1
et à la fin je retourne le trait "TRAITAFFECTE" qui est apparu le plus de fois dans la liste d'équivalence
puis j'assigne à MOTLISTE le trait TRAITAFFECTE dans le fichier
la fonction qui pose problème :
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
37
38
39
40
41
42
43 def evaluation(matrice,fichier,random,unknown,nbCooccurrent): count = listeTrait() # je récupére la liste des traits sémantique stocké dans un dico, il y en 5 # les deux lignes suivantes récupère la liste des mots qui se trouve dans les deux fichiers expliqués ci dessus lexiqueApprentissage = treatLexiqueApprentissage() listeDeMot = treatEvaluationFile(fichier) fichierResultat = open("newLexique1.log","w") i=0 #pour chaque mot de la liste d'évaluation for mot in listeDeMot: i += 1 if i % 1000 == 0: print i if (random == False): #laisser tomber le random, ça marche très vite, le pb n'est pas là #on teste si le mot est dans le corpus à l'aide de matrice.has_key(mot) if motInCorpus(mot,matrice): #on recupere sa liste de meilleure cooccurrent de deuxieme ordre #le pb est dans la fonction treatsemantic listeOfBestCooccurrent = treatSemantic(matrice,mot,nbCooccurrent) #s'il possede une liste if(len(listeOfBestCooccurrent) > 0): #on recupere le meilleur de trait semantique de la liste p= listeEquivalence(listeOfBestCooccurrent,lexiqueApprentissage) #on incremente le trait recupere count[p[0][0]] += 1 fichierResultat.write (mot + "\t" + p[0][0] + "\n") else: #s'il n'a pas de liste, on recupere le mot le plus frequent fichierResultat.write (mot + "\t" + maxTrait(count) + "\n") else: #si le mot n'est pas dans le corpus, on a le choix de le stocker ou de l'ignorer if (unknown == False): #on ignore pas et on ecrit dans le fichier le mot avec comme le trait le plus frequent fichierResultat.write (mot + "\t" + maxTrait(count) + "\n") else: #on affecte les traits au mots aleatoirement trait = randomSemantic() if motInCorpus(mot,matrice): count[trait] += 1 fichierResultat.write(mot + "\t" + trait + "\n") else: if (unknown == False): fichierResultat.write(mot + "\t" + maxTrait(count)+"\n") fichierResultat.close()
en gros le pb c'est que ça met à peu près 7 min pour terminer.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 def treatSemantic(matrice,mot,max): listeequivalence = [] listeA = matrice[mot] for word,listeCooccurrent in matrice.items(): if (word <> mot): if len(set(listeCooccurrent)&set(listeA)) >= max: listeequivalence.append(word) return listeequivalence
je me demande si c normal.
car là, on est obligé de comparer la liste des mots avec tous les autres de la matrice.
et comme j'ai augmenté le nombre de mot qui était à 44000 à 88000.
je me demande si c normal ?
si ça l'est, c bon alors!!!!
Je suis en train de travailler sur une autre solution.
Celle de dividee est ébouriffante de maîtrise, elle m'a laissé baba, mais elle a quelques défauts à mon avis. Je reviens dans 2 heures environ.
moi aussi, je suis resté scotché!!!
maintenant j'essai d'optimiser l'autre problème que j'ai énoncé dans mon post précédent
L'utilisation du type ensemble (set) est une bonne idée; une optimisation simple serait de stocker dans la matrice directement l'ensemble (set) des cooccurents au lieu d'une liste de cooccurents; cela éviterait de devoir les convertir en set dans la boucle intérieure; qui deviendrait (en renommant les variables pour que ce soit cohérent):
Mais algorithmiquement on peut sans doute faire mieux, pour éviter d'avoir à parcourir toute la matrice. Une idée comme ça: Du fait de la symétrie de la relation de cooccurrence, tu devrais pouvoir ne considérer que les lignes de la matrice qui sont des cooccurrents des mots dans listeA. Cela donnerait (en incluant l'optimisation ci-dessus pour l'utilisation des ensemble):
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 if len(setCooccurrent & setA) >= max: listeequivalence.append(word)
Je n'ai pas testé alors il y a peut-être une erreur, mais l'idée est là.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 def treatSemantic(matrice,mot,max): listeequivalence = [] setA = matrice[mot] candidats = set(coocc for word in setA for coocc in matrice[word]) # ou bien: # candidats = reduce(operator.or_, (matrice[word] for word in setA)) candidats.discard(mot) for word in candidats: if len(matrix[word] & setA) >= max: listeequivalence.append(word) return listeequivalence
Je n'ai pas regardé le reste du code, mais en fonction de ce que tu en fais ensuite, listeequivalence pourrait peut-être aussi devenir setequivalence ?
On est obligé de parcourir tous les mots de la matrice.
je vais t'expliquer pourquoi :
imagine
dans la matrice :
on a
<institueur>école#enfants#collège</instituteur>
<professeur>université#école#mathématique</professeur>
<foot>ballon#argent</foot>
maintenant dans la liste des mots du fichier d'évaluation.
on doit affecter un trait sémantique à professeur.
pour cela, je regarde si professeur est dans la matrice.
elle y est.
donc je récupère sa liste université#école#mathématique
ensuite je parcours tous les mots de la matrice
donc il y a le mot institueur, on récupère sa liste école#enfants#collège
et on fait une intersection, et on obtient nombre de cooccurent = 1 (enfants)
1>max ==> donc on ajoute à la liste d'équivalence le mot instituteur
ensuite on a le mot foot, on récupère sa liste ballon#argent
on fait une intersection, nombre de cooccurent == 0
donc on fait rien
ton algo fait ça ?
j'ai lancé l'algo,
en 3s![]()
mais le résultat statistique que j'ai fait, j'obtiens pas totalement les memes résultats, mais ce n'est pas loin.
c'est pourquoi j'aimerai juste que tu m'explique ces lignes :
merci
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 candidats = set(coocc for word in setA for coocc in matrice[word]) # ou bien: # candidats = reduce(operator.or_, (matrice[word] for word in setA)) candidats.discard(mot)
Normalement oui; si la matrice est complète elle doit aussi contenir une entrée:
<école>professeur##instituteur##...</école>
Mon algo va rechercher cette entrée (ainsi que celles de "université" et "mathématique") et limite la recherche à ces mots-là.
Je craignais un peu en effet que le résultat ne soit pas parfaitement identique; c'est je pense à cause du filtrage qui est fait sur la relation de cooccurrence (et plus spécifiquement, sans doute le fait de se limiter aux 'm' meilleurs résultats), qui fait que la matrice n'est pas parfaitement symétrique. Si tu augmentes la valeur de 'm', tu devrais voir le résultat de cet algo se rapprocher du tien, si je ne me trompe pas.
Pour que ce soit parfaitement identique, il faudrait peut-être ne pas limiter le nombre de résultats, mais il faut voir si ça reste gérable au niveau mémoire et temps de calcul.
[edit:] En fait, si tu veux quand-même filtrer un peu, au lieu de limiter le nombre de résultat à un constante 'm', tu pourrais filtrer sur la valeur de dice, par exemple dice > 0,0001 (valeur optimale à déterminer). Comme la valeur de dice est symétrique, la matrice produite devrait toujours rester symétrique.
La première ligne va rechercher les cooccurrents des mots de setA, et construit l'union de ces ensembles (plutôt que de les stocker dans une liste, afin d'éliminer les doublons). Encore une autre façon de l'écrire serait:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 candidats = set(coocc for word in setA for coocc in matrice[word]) # ou bien: # candidats = reduce(operator.or_, (matrice[word] for word in setA)) candidats.discard(mot)
Le discard c'est pour éliminer 'mot', afin d'éviter le test (if word <> mot) dans la boucle qui suit.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 candidats = set() for word in setA: candidats |= matrice[word]
t un génie !!! y a rien à dire!!!
j'ai augmenté le m à 30.
j'ai testé les résultats, j'atteint 68% de bon résultats. (en plus l'algo tourne en moins de 30s)
je m'explique, j'ai un lexique d'évaluation avec les mots et leur traits déjà défini.
ce que je fais, c juste récupérer les mots et leur affecter un trait.
et après je compare mon nouveau lexique avec le lexique d'origine pour voir le taux de réussite.
et j'ai atteint 68%!!!, c super, la valeur max qui se trouve dans treatsemantic(), je l'ai mise à 7, qui est pas mal du tout.
pour info, le random que j'utilise, c'est juste un paramètre qui dit au pg, d'affecter d'aléatoirement un trait à tous les mots de la liste !!!
merci pour tout franchement !!!!!, là c'est vraiment géniale !!!!
là, je suis vraiment satisfait, maintenant, il me reste plus qu'à améliorer mon programme de stat en prenant en compte les mots simples et composés et là ça sera le top !!!!
dire que c'est à rendre pour demain soir!!!, la semaine dernière, j'ai bloqué pendant 1 semaine, et je me suis dit, va demander de l'aide au forum python
!!!! et j'ai bien fait
![]()
68% c'est bien ? Enfin, tu es le seul à pouvoir en juger...
Je suis content d'avoir pu aider, et c'est intéressant comme domaine d'application.
c pas mal du tout 68% !!!!!!
c'est vrai c'est un domaine intéressant: la linguistique
je t'envoie le lien du projet, actuellement le serveur est en panne, demain tu pourra le voir je pense
http://igm.univ-mlv.fr/ens/Master/M2...AL/project.php
merci pour tous !!
J'ai l'impression que le peloton est loin devant mais ça ne fait rien je me suis bien amusé à trouver ce qui suit.
-------------------------------------------
ekremyilmaz, tu as expliqué dans le message #44, en réponse à ma question sur la provenance du fichier mat1, qu'il y a la succession suivante:
Comme dividee a proposé une solution qui utilise dico1, j'ai d'abord pensé que c'était pour exploiter le fait que dico1, qui contient une information différente de dico2, existe obligatoirement comme passage obligé puiqu'il découle directement du traitement des 2 fichiers texte de départ, et qu'il était dommage de ne pas utiliser cette information, et que c'est ce qu'il avait fait avec le programme très malin qu'il a proposé.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 2 fichiers texte avec des délimiteurs {S} ---> dico1 = {1:{A,B,C,D,E};2{A,C,D,E};3{B,D,E}} ---> dico2 = {A:{1,2};B:{1,3};C:{1,2};D:{1,2,3};E:{1,2,3}} ---> fichier mat1 qui est: <A>1##2</A> <B>1##3</B> <C>1##2</C> <D>1##2##3</D> <E>1##2##3</E>
Avec les données dont on dispose, c'est à dire le fichier mat1, il a proposé le schéma de programme suivant, qui repose sur la création d'un troisième dico à partir des deux précédents exploités conjointement
Bien sûr, comme tu disposes des fichiers de départ, ekremyilmaz, dividee doit penser que tu utiliseras en réalité le schéma suivant
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 ---> fichier mat1 qui est: <A>1##2</A> <B>1##3</B> <C>1##2</C> <D>1##2##3</D> <E>1##2##3</E> ---> dico2 = {A:{1,2};B:{1,3};C:{1,2};D:{1,2,3};E:{1,2,3}} ---> dico1 = {1:{A,B,C,D,E};2{A,C,D,E};3{B,D,E}} ---> dico 3 = {A:{B:1,C:2,D:2,E:2} , B:{A:1,C:1,D:2,E:2} , C:{A:2,B:1,D:2,E:2} , D:{A:2,B:2,C:2,E:3} , E:{A:2,B:2,C:2,D:3} } ---> traitement pour trouver les co-occurents les plus fréquents
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 2 fichiers texte avec des délimiteurs {S} ---> dico1 = {1:{A,B,C,D,E};2{A,C,D,E};3{B,D,E}} ---> dico2 = {A:{1,2};B:{1,3};C:{1,2};D:{1,2,3};E:{1,2,3}} ---> dico 3 = {A:{B:1,C:2,D:2,E:2} , B:{A:1,C:1,D:2,E:2} , C:{A:2,B:1,etc} ,etc } ---> traitement pour trouver les co-occurents les plus fréquents
J'ai mis un sacré bout de temps avant de bien comprendre le code de dividee et j'en suis resté baba.
Mais j'ai fini par sentir que quelque chose n'allait pas.
D'abord il y a des calculs qui se répètent puisqu'on trouve le dice(3,7)==9 par exemple à la fois dans l'item mot3:{mot7:9,..} et dans l'item mot7:{mot3:9,....} de dico3.
Ensuite, au niveau algorithmique, je trouve peu satisfaisant de créer un dico2 à partir de dico 1, c'est à dire de réorganiser l'information, puis de devoir encore créer un dico3 et pour cela par dessus le marché en recourant à nouveau à dico1, c'est à dire en quelque sorte en remontant à l'information première.
Je me suis dit qu'il devait être possible de créer une variable dans laquelle il y aurait à la fois l'information de dico 1 et celle de dico 2 sans avoir à descendre jusqu'à dico2 en perdant l'organisation de l'information de dico1.
J'ai trouvé qu'à partir de dico1 il vaut mieux rassembler les numéros de phrases par couples de mots que par mot solitaire ---> d'où création d'un seul dictionnaire dicoBINX (pour BINôme:X) au lieu de dico2 et dico3:
Du point de vue mémoire, dicoBINX prend moins de place (10 variables)
Code : Sélectionner tout - Visualiser dans une fenêtre à part dicoBINX = { (A,B):1 , (A,C):1 , (A,D):2 , (A,E):2 , (B,C):1, (B,D):2 , (B,E):2 , (C,D):2 , (C,E):2 , (D,E):3 }
que dico3 (45 variables dans l'exemple)
puisque le dicoBINX évite les répétitions.
Code : Sélectionner tout - Visualiser dans une fenêtre à part dico3 = {A:{B:1,C:2,D:2,E:2} , B:{A:1,C:1,D:2,E:2} , C:{A:2,B:1,D:2,E:2} , D:{A:2,B:2,C:2,E:3} , E:{A:2,B:2,C:2,D:3} }
Ensuite on passe de dicoBINX à liBINX pour profiter de l'agilité des listes dans les calculs suivants. Nota bene: les binômes dans dicoBINX et les sous-listesl dans liBINX sont ordonnées.
---
Comme je ne dispose aussi que de mat1, je suis obligé de faire comme dividee pour tester mes programmes: recréer dico1 à partir de mat1.
Mais pour toi le véritable programme est celui ci dessous, qui n'a besoin que d'une chose, c'est qu'on lui fournisse dico1, soit sous forme de fichier, soit dans la foulée du traitement des 2 fichiers avec {S} de départ quand ce programme prend la main. Et il n'y a pas besoin de traiter mat1.
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 from collections import defaultdict from operator import itemgetter dico1 = open('dico1') f1 = open("matricecooccurrenceTest","w") m = 3 dicoBINX = defaultdict(int) N = defaultdict(int) for words in dico1.values(): for mot in words: N[mot]+=1 for autre_mot in words: if autre_mot>mot: dicoBINX[(mot,autre_mot)] += 1 liBINX = list(dicoBINX.iteritems()) # c'est une liste de doublets ( (A,B) , 6 ) for mot in N.keys(): coocs_dice = [ (binome[binome[0]==mot],2.0*float(x)/float(N[binome[0]]+N[binome[1]])) for binome,x in liBINX if mot in binome ] coocs_dice.sort(key=itemgetter(1),reverse=True) # coocs_dice est alors une liste de doublets (co-occurent de mot,valueDice) frequcoocs = [ cd[0] for cd in coocs_dice[0:m] ] if frequcoocs==[]: frequcoocs = ['---'] # frequcoocs est la liste des m co-occurents les plus frequents de 'mot' print '\n<',mot,'> ', for f in frequcoocs: print f,', ', f1.writelines('<' + mot + '>' + '##'.join(frequcoocs) + '</'+mot+'>\n') f1.close()
Est-ce que l'un de vous deux, dividee ou ekremyilmaz pourrait satisfaire ma curiosité en faisant tourner mes deux codes, svp ?
J'ai téléchargé le fichier mat1 de 64 Mo mais je ne peux pas l'exploiter parce qu'il est dans un format word non reconnu par les programmes Python et je ne sais pas changer son type.
Je suis curieux de savoir ce que donnent mes deux codes, celui du message #51 et celui du message précédent #73.
Ils tournent correctement, je les ai testés sur un mini fichier, mais ce sont les temps d'exécution qui m'intéressent.
Je pense que du fait qu'il ne calculent pas deux fois un même dice, ils tournent plus vite que celui de dividee. Le dernier, du message #73, doit normalement tourner encore plus vite. J'aimerais vérifier s'il en est bien ainsi.
Attention à m:
il est fixé à 20 dans le premier code(51) et à 3 dans le second73). Ce n'est pas ça qui va influerr beaucoup sur la vitesse , mais il faut fixer le même m pour les comparaisons.
je le teste cette après midi eyquem !!!!!, j'enverrai un post
merci!!!!!
j'ai pas compris le
'dico1' c'est un fichier ou un dico car après tu itéres sur dico1 ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part dico1 = open('dico1')
La ligne # dico1 = open('dico1') est une ligne-noeud au mouchoir.
J'ai mis cette instruction batarde avec un # devant pour rappeler qu'il faut fournir dico1 comme donnée de départ pour que la suite puisse être effectuée.
-- Explication:
Tu as expliqué dans le message #44 (j'ai simplement rajouté un 1 et un 2 pour nommer les dicos tels qu'on les appelle depuis le message #46 de dividee):
Donc première possibilité:Au départ, J'ai deux fichiers qui me sont fournis, ce sont des corpus de texte avec {S} qui est un délimiteur de phrase.
Je traite ces deux fichiers en mêmes temps. je récupère pour chaque phrase les mots simples (qui se trouve dans un fichier) et les mots composés (qui se trouve dans l'autre fichier)
à la fin j'obtiens un dico
qui ressemble à ça :
dico1 = {1:{A,B,C,D,E};2{A,C,D,E};3{B,D,E}} : ça signifie
que la phrase 1 contient la liste des mots A,B,C,D,E et ainsi de suite.
Ensuite je parcours ce dico pour stocker pour chaque mot la liste des phrases où il apparait.
donc j'obtiens le dico suivant :
dico2 = {A:{1,2};B:{1,3};C:{1,2};D:{1,2,3};E:{1,2,3}}
dico1 résulte du programme CREATION DE DICO1 qui te permet de faire ce que tu décris ci-dessus (programme que nous n'avons pas vu), et alors il suffit d'ajouter mon code à la suite du code de CREATION DE DICO1, sans avoir à écrire une instruction du genre open(dico1).
Deuxième possibilité:
tu travailles toujours sur les mêmes corpus de texte avec {S} et tu as stocké les données de dico1 dans un fichier; dans ce cas au lieu de refaire tourner CREATION DE DICO1, tu vas chercher les données de dico1 dans le fichier.
Par exemple, si on crée un fichier 'dico1' avec ce code:
alors il faut mettre le code suivant à la place de l'instruction # dico1 = open('dico1') :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 f = open('dico1','w') f.write('1'+'#'+'A'+'#'+'B'+'#'+'C'+'#'+'D'+'#'+'E'+'\n') f.write('2'+'#'+'A'+'#'+'C'+'#'+'D'+'#'+'E''\n') f.write('3'+'#'+'B'+'#'+'D'+'#'+'E''\n') f.close()
Les [:-1] sont pour enlever les '\n' en bout de ligne lue.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 dico1 = {} f = open('dico1','r') rd = f.readline()[:-1] while rd: li = rd.split('#') cle = int(li[0]) val = tuple(li[1:]) dico1[cle] = val rd = f.readline()[:-1] f.close() print 'dico1 =',dico1
============================
Remarque:
je me suis aperçu d'une petite erreur d'écriture dans mon message #73, qui ne porte pas à conséquence puisque elle n'est pas dans du code.
Dans
j'ai écrit les valeurs avec des symboles { } alors qu'elles ne sont pas des dictionnaires.dico2 = {A:{1,2};B:{1,3};C:{1,2};D:{1,2,3};E:{1,2,3}}
dico1 = {1:{A,B,C,D,E};2{A,C,D,E};3{B,D,E}}
C'est seulement les valeurs de
qui sont des dictionnaires.dico 3 = {A:{B:1,C:2,D:2,E:2} , B:{A:1,C:1,D:2,E:2} , C:{A:2,B:1,D:2,E:2} , D:{A:2,B:2,C:2,E:3} , E:{A:2,B:2,C:2,D:3} }
En réalité, quand je teste des codes, je ne fais ni la première possibilité (je n'ai pas les fichiers de départ avec {S} ), ni la deuxième (je n'ai pas enregistré dico1) pour obtenir dico1; en tête de mes programmes, je mets le début du code de dividee dans son message #47, à savoir
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 import re motif = re.compile(r"</|>|<|#+") f = file('mat1') dico2 = {} for line in f: l = motif.split(line) dico2[l[1]] = map(int,l[2:-2]) f.close() print 'dico2 =',dico2 dicoun = defaultdict(list) for mot, phrases in dico2.iteritems(): for phrase in phrases: dicoun[phrase].append(mot) # dicoun = { 1:[A,B,C,D,E] , 2:[A,C,D,E] , 3:[B,D,E] } print '\ndicoun =',dicoun dico1 = {} for k,v in dicoun.iteritems(): dico1[k] = tuple(v) # dicoun = { 1:(A,B,C,D,E) , 2:(A,C,D,E) , 3:(B,D,E) } print '\ndico1 =',dico1
J'ai simp[lement ajouté la fin
pour obtenir dico1 avec des clés qui sont des tuples parce que les tuples sont mieux quand le programme tournera pour un gros fichier comme le tien: les tuples prennent moins de place en mémoire.for k,v in dicoun.iteritems():
dico1[k] = tuple(v)
=======
Rappel:
mon code n'a besoin que de dico1 comme données de départ pour tourner.
Il crée un dictionnaire dicoBINX transformé en liste liBINX avant le traitement qui calcule les dices et les co-occurents de chaque mot.
Le programme de dividee implique la création d'un autre fichier dico2 à partir de dico1 (en fait il fait l'inverse puisqu'il n'a pas dico1 comme donnée de départ, il remonte de dico2 obtenu à partir de mat1) puis encore d'un fichier 3 qui doit être grosso modo d'une taille double de dicoBINX.
Voilà cette fois, je crois que c'est complet comme explications.
Pendant que j'y suis , j'explique rapidement mon code
======================
On part de:
On créedico1 = { 1 : (A,B,C,D,E) ; 2 : (A,C,D,E) ; 3 : (B,D,E) }
On peut remarque que dicoBINX n'est pas redondant en information et qu'il est moins lourd quedicoBINX = { (A,B):1 , (A,C):1 , (A,D):2 , (A,E):2 , (B,C):1, (B,D):2 , (B,E):2 , (C,D):2 , (C,E):2 , (D,E):3 }
et
N = { A:2 , B:2 , C:2 , D:3 , E:3 }
Les tuples (A,B) (A,C) (A,D) (A,E) (B,C) (B,D) (B,E) (C,D) (C,E) (D,E)dico 3 = {A:{B:1,C:2,D:2,E:2} , B:{A:1,,C:1,D:2,E:2} , C:{A:2,B:1,D:2,E:2} , D:{A:2,B:2,C:2,E:3} , E:{A:2,B:2,C:2,D:3} }
listent tous les couples possibles à partir de ABCDE sans tenir compte de l'ordre des deux mots, c'est à dire qu'il n'y a pas (B,A) (C,A) (C,B) etc.
Ça résulte directement de la symétrie des dices: dice(A,E) == dice(E,A) qui vient du fait que le nombre de co-occurences de E avec A est le même que le nombre de co-oocurences de A avec E. Il suffit donc de référencer une seule fois la valeur X commune à un couple (A,B) etc. Il résulte que les tuples sont apparemment ordonnés, mais cet ordonnancement ne sert à rien en lui même, il résulte simplement de l'instruction if autre_mot>mot: dans le code qui permet d'éviter le décompte dicoBINX[(mot,autre_mot)] += 1 de co-occurences déjà vues. On ne décompte la co-occurence (A,E) qu'une fois, celle de E avec A, et pas celle de A avec E en quelque sorte. C'est pour ça que les entiers en valeurs du dictionnaire dicoBINX sont des valeurs X telles que tu as défini X.
On change dicoBINX en
Ensuite, prenons le mot C par exemple, on calcule la liste coocs_dice pour C de la manière suivante:liBINX = { ((A,B),1) , ((A,C),1) , ((A,D),2) , ((A,E),2) , ((B,C),1), ((B,D),2) , ((B,E),2) , ((C,D),2) , ((C,E),2) , ((D,E),3) }
Les variables b et x prennent successivement les valeurs
Code : Sélectionner tout - Visualiser dans une fenêtre à part coocs_dice = [ [b[b[0]==mot],2.0*float(x)/float(N[b[0]]+N[b[1]])] for b,x in liBINX if C in b ]
parce que le mot C est présent dans toutes les valeurs de b. Mais il est soit en première position, soit en deuxième position à cause de l'ordre au sein de chaque tuple.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 b = (A,C) x=1 b = (B,C) x=1 b = (C,D) x=2 b = (C,E) x=2
Pour b = (A,C) on a b[0]==C qui vaut False c'est à dire 0 en langage Python. C n'est donc pas en position 0 et c'est donc la valeur à cette position qui doit être prélevée:
b[b[0]==mot] est b[0] c'est à dire A
On enregistre alors dans coocs la liste [A,0.5] car x==1 , N[A]==2 , N[C]==2
Puis ça passe à b = (B,C): idem ---> enregistre [B,0.5]
Ensuite b = (C,D) x=2
b[0]==C vaut True c'est à dire 1 , C est en première position, il faut donc prendre le mot à la deuxième position, qui est justement désignée par b[0]==C
D'où enregistrement de [D,0.4]
Puis b = (C,E) x=2 ---> enregistrement de [E,0.4]
Finalement coocs pour le mot C est
Ensuite
Code : Sélectionner tout - Visualiser dans une fenêtre à part coocs == [ [A,0.5] , [B,0.5] , [D,0.4] , [E,0.4] ]
conduisent à
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 coocs_dice.sort(key=itemgetter(1),reverse=True) frequcoocs = [ cd[0] for cd in coocs_dice[0:m] ]
'##'.join(frequcoocs) vaut 'A##B##D'frequcoocs = [ A, B, D ] si m=3
etenregistre
Code : Sélectionner tout - Visualiser dans une fenêtre à part f1.writelines('<' + mot + '>' + '##'.join(frequcoocs) + '</'+mot+'>\n')Ça itère ensuite sur les mots suivants D et E.'<C>'A##B##D</C>
Et hop !
PS
Je n'ai pas compris grand chose au problème supplémentaire décrit dans ton message #62.
Si ton rapport est à remettre ce soir, ce n'est sans doute pas la peine que je cherche à m'y mettre.
Pour accélérer l'exécution, il faudra faire appel à Psyco, quand tu auras le temps. Ça ne doit pas être essentiel pour le moment. J'ai commencé à regarder ce module mais de façon embryonnaire.
j'ai pas trop le temps de tester mon pg, j'essaierai en fin de soirée, je dois absolument finir et faire le rapport.
mais ton code m'a l'air vraiment clean.
je verrai ce soir, pour le moment j'ai repris le code de dividee.
merci encore eyquem !!!
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager