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

Python Discussion :

optimisation fichier long


Sujet :

Python

  1. #21
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    358
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 358
    Points : 117
    Points
    117
    Par défaut
    @alexdevl

    l'algo que tu as fourni ne répond à mon pb
    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
    #!/usr/bin/env python
    # -*- coding: iso-8859-1 -*-
     
    '''
    <motA>1##2##3##4</motA>
    <motB>1##4##8</motB>
    <motC>5##8##10</motC>
    <motD>35##32##10</motD>
    <motE>1##2##3##4</motE
    '''
     
    fo=open("mat1.log","r")
    numPhrases={}
    motParPhrase={}
     
    # type de ligne <motA>1##2##3##4</motA>
    for ligne in fo:
        mot=ligne[1:].split(">",1)[0]
        numPhraseSplit=ligne.split(">",1)[1].split("<")[0].split("##")
        for numPhrase in numPhraseSplit:
            if numPhrase not in numPhrases.keys(): numPhrases[numPhrase]=[]
            numPhrases[numPhrase].append(mot) # Dico par num de phrases
        motParPhrase[mot]=numPhraseSplit # Dico par mot
    print numPhrases
    print motParPhrase
     
    # Création d'un dico du type :
    # numPhrases={'10': ['motC', 'motD'], '32': ['motD'], '35': ['motD'], '1': ['motA', 'motB', 'motE']...
    # motParPhrase={'motA': ['1', '2', '3', '4'], 'motB': ['1', '4', '8'],
    le souci, c'est que les deux dictionnaires que tu fourni, je l'avais déjà fait en fait.
    j'avais un dictionnaire motParPhrase, mais le souci,c'est lorsque tu veux comparer tous les mots entre eux, tu dois faire un double parcours (deux for imbriqués) et là, c'est aussi lent.

  2. #22
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut question
    Je ne comprends pas les regex employées

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	re.findall('<.*?>(.*?)</.*?>',i)
    	re.findall('<(.*?)>',i)
    Pourquoi un '?' aprés la '*' ?

    Pourquoi des regex d'ailleurs si chaque ligne commence par <mot> et se termine par </mot> avec exclusivement des digits et des # entre les balises ?

  3. #23
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    358
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 358
    Points : 117
    Points
    117
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    celle ci sert à récupérer la chaine qui se trouve entre les 
    balises <> et </>
    re.findall('<.*?>(.*?)</.*?>',i)
     
    celle ci sert à récuper le mot qui se trouve entre <>
    re.findall('<(.*?)>',i)
    c'est vrai que j'aurai pu utiliser la méthode "alexdevl" pour récupérer, mais je cherchais avec les regex.


    ex:
    <trêve des confiseurs>1872</trêve des confiseurs>
    <rêve américain>787##1872</rêve américain>
    <désunion>4917</désunion>

    après que l'algo se termine, je dois avoir dans un autre fichier un truc de ce genre
    <trêve des confiseurs>rêve américain</trêve des confiseurs>
    donc pour écrire "rêve américain", je dois bien le récupérer de la balise <rêve américain> d'où re.findall('<(.*?)>',i)

    si la ligne i est à égale <rêve américain>787##1872</rêve américain>
    la regex re.findall('<(.*?)>',i) me retourne rêve américain

    et re.findall('<.*?>(.*?)</.*?>',i) me retourne 787##1872

    sans ces deux regex, je ne vois pas trop comment peut t-on comparer les mots mots à mots.

  4. #24
    Membre averti Avatar de alexdevl
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    265
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2007
    Messages : 265
    Points : 344
    Points
    344
    Par défaut
    Je m'explique et j'ai continué le code,
    L'objet est d'analyser que les couples réels
    Cela limite par exemple les contrôles (num phrase/mot) de 115 à 10 dans cet exemple.

    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
     
    {'10': ['motC', 'motD'], '32': ['motD'], '35': ['motD'], '1': ['motA', 'motB', 'motE'], '3': ['motA', 'motE'], '2': ['motA', 'motE'], '5': ['motC'], '4': ['motA', 'motB', 'motE'], '8': ['motB', 'motC']}
    {'motA': ['1', '2', '3', '4'], 'motB': ['1', '4', '8'], 'motC': ['5', '8', '10'], 'motD': ['35', '32', '10'], 'motE': ['1', '2', '3', '4']}
    ('motC', 'motD') +1
    ('motA', 'motB') +1
    ('motA', 'motE') +1
    ('motB', 'motE') +1
    ('motA', 'motE') +1
    ('motA', 'motE') +1
    ('motA', 'motB') +1
    ('motA', 'motE') +1
    ('motB', 'motE') +1
    ('motB', 'motC') +1
     
    calcul des formules
    ('motA', 'motB') 0.571428571429
    ('motA', 'motE') 1.0
    ('motB', 'motE') 0.571428571429
    ('motC', 'motD') 0.333333333333
    ('motB', 'motC') 0.333333333333
    avec le code suivant

    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
    44
    45
    46
    47
    48
    49
     
    #!/usr/bin/env python
    # -*- coding: iso-8859-1 -*-
     
    '''
    <motA>1##2##3##4</motA>
    <motB>1##4##8</motB>
    <motC>5##8##10</motC>
    <motD>35##32##10</motD>
    <motE>1##2##3##4</motE
    '''
     
    fo=open("mat1.log","r")
    numPhrases={}
    motParPhrase={}
     
    # type de ligne <motA>1##2##3##4</motA>
    for ligne in fo:
        mot=ligne[1:].split(">",1)[0]
        numPhraseSplit=ligne.split(">",1)[1].split("<")[0].split("##")
        for numPhrase in numPhraseSplit:
            if numPhrase not in numPhrases.keys(): numPhrases[numPhrase]=[]
            numPhrases[numPhrase].append(mot) # Dico par num de phrases
        motParPhrase[mot]=numPhraseSplit # Dico par mot
    print numPhrases
    print motParPhrase
     
    # Création d'un dico du type :
    # numPhrases={'10': ['motC', 'motD'], '32': ['motD'], '35': ['motD'], '1': ['motA', 'motB', 'motE']...
    # motParPhrase={'motA': ['1', '2', '3', '4'], 'motB': ['1', '4', '8'],
    ''' 
    Je dois ensuite utiliser la formule de dice
    f = 2*X/(A+B)
    avec X = nombre de fois que les deux mots apparaissent ensemble dans le corpus
    A = nombre de fois qu'apparait le mot A dans tous le corpus
    B = nombre de fois qu'apparait le mot B dans tous le corpus
    '''
    X={}
    for num,mots in numPhrases.items():
      for mot1 in mots[:-1]:
        for mot2 in mots[1::]:
          if mot1<>mot2:
            if (mot1,mot2) not in X.keys(): X[(mot1,mot2)]=0
            print (mot1,mot2),"+1"
            X[(mot1,mot2)]+=1
    print
    print "calcul des formules"
    for couple,x in X.items():
      print couple,2.0*x/(len(motParPhrase[couple[0]])+len(motParPhrase[couple[1]]))

  5. #25
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    358
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 358
    Points : 117
    Points
    117
    Par défaut
    pour vraiment bien comprendre la structure du programme, je vais dérouler un jeu d'essai

    voici mon fichier mat1.log
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    <motA>1##2##3##4</motA>
    <motB>1##4##8</motB>
    <motC>5##8##10</motC>
    <motD>35##32##10</motD>
    je prend la première ligne :
    i = <motA>1##2##3##4</motA>
    je récupére "motA" avec re.findall('<(.*?)>',i)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
       elementA = re.findall('<(.*?)>',i)
    je récupère ensuite sa liste
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    liste1 = re.findall('<.*?>(.*?)</.*?>',i)
    ensuite je compare cette liste à toutes les autres du fichier (donc une boucle for)
    pour cela:
    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
     
    j = <motB>1##4##8</motB>
    je récupère "motB" avec re.findall('<(.*?)>',i)
       elementB = re.findall('<(.*?)>',j)
       listeB = re.findall('<.*?>(.*?)</.*?>',j)
     
    ensuite dans cette boucle for
    je transforme listeA et listeB en vrai liste en splitant par ##
    ensuite j'utilise la fonction DICE (expliqué dans post précédent)
    puis si 0<dice<1, 
    j'ajoute dans dicoTempo[elementB[0]] = dice
     
    puis je continue à comparer la première ligne avec la suite
    donc je teste la ligne i avec la ligne j = <motC>5##8##10</motC>
    puis avec j = <motD>35##32##10</motD>
     
    puis j'obtiens comme dico (je donne un dico au hasard)
    dico[motB] = 0.1
    dico[motC] = 0.5
     
    je trie le dico (en le transformant en liste) par valeur de dice décroissante et je récupère les m premièrs éléments (ici motC et motB)
    et j'écris dans le nouveau fichier :
    <motA>motC#motB</motA>
     
    ensuite je passe à la ligne suivante qui est 
    ligne i = <motB>1##4##8</motB>
    puis je compare cette ligne avec ligne  avec 
     
    <motA>1##2##3##4</motA>
    <motC>5##8##10</motC>
    <motD>35##32##10</motD>
     
    et ainsi de suite

  6. #26
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    358
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 358
    Points : 117
    Points
    117
    Par défaut
    @alexdevl

    je réfléchi à ton post

  7. #27
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    358
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 358
    Points : 117
    Points
    117
    Par défaut
    j'ai testé les deux méthodes
    dico et lecture séquentielle (avec seek et tell),
    rien ne change, c aussi long sur un petit corpus alors pour un gros, je laisse imaginer

    peut etre que la première idée, liste de liste, je vais essayer pour voir.

  8. #28
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    358
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 358
    Points : 117
    Points
    117
    Par défaut
    je reprend ça demain soir

  9. #29
    Membre chevronné
    Avatar de kedare
    Homme Profil pro
    Network Automation Engineer
    Inscrit en
    Juillet 2005
    Messages
    1 548
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Network Automation Engineer

    Informations forums :
    Inscription : Juillet 2005
    Messages : 1 548
    Points : 1 860
    Points
    1 860
    Par défaut
    Citation Envoyé par eyquem Voir le message
    Je pense que Psyco sera utile au final mais de mon point de vue ce n'est pas une bonne chose d'accélerer un mauvais programme, ça n'en fait pas un bon.
    Même si Psyco abaissait le temps d'exécution de 64 heures à 3 heures, ça resterait mauvais étant donné qu'à vue de nez je dirais que son programme doit pouvoir tourner en 10 minutes maxi si l'algorithme est bien pensé (quoique je m'avance beaucoup étant donné que je ne connais pas vraiment Psyco et que je n'ai encore pas compris ce qu'il veut faire avec son programme).
    rien ne t'empeche d'utiliser psyco et d'optimiser (par exemple remplacer les appels recursif par des yield a fait passé un script de 2.1s en 0.02s (fibo x30))

  10. #30
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 461
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 461
    Points : 9 248
    Points
    9 248
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Je ne sais pas si ça peut aider, mais on peut transformer la chaine (lue dans le fichier) en liste en une seule fois et en ne conservant que les infos utiles:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    ch = "<mirage>2375##3374##5106</mirage>"
    motif = re.compile(r"</|>|<|#+")
     
    L = motif.split(ch)[1:-2]
     
    print L
    ['mirage', '2375', '3374', '5106']
    On utilise pour ça le split() de "re" qui fabrique une liste à partir d'une chaine, avec un découpage selon un motif.

    En utilisant dans le motif le caractère "|" (c'est à dire "ou"), on découpe la chaine selon:

    - soit "</" (il faut commencer par ça pour trouver le dernier tag)
    - soit ">"
    - soit "<"
    - soit "#+" c'est à dire un mot composé d'une nombre quelconque de "#"

    Le "[1:-2]" permet d'éliminer tout de suite des parties inutiles de la liste obtenue (2 chaines vides et le dernier tag).

    Tyrtamos
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  11. #31
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 461
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 461
    Points : 9 248
    Points
    9 248
    Billets dans le blog
    6
    Par défaut
    Je continue mes idées.

    Prenons un fichier disque qui contient les chaines suivantes:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    ...
    ligne i => "<trêve des confiseurs>1872##787</trêve des confiseurs>"
    ...
    ligne j => "<rêve américain>787##3592</rêve américain>"
    ...
    Dans la mesure où on peut mettre tout le fichier en mémoire sous forme de liste de liste, voilà ce que ça donnerait avec mon expression régulière précédente.

    Lecture du fichier:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    motif = re.compile(r"</|>|<|#+")
     
    L = []
    f = open("mat1.log", "r")
    for ligne in f:
        L.append(motif.split(ligne)[1:-2])
    On obtient une liste de liste, dans laquelle on trouvera les 2 lignes précédentes:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    ...
    L[i] => ["trêve des confiseurs", "1872","787"]
    ...
    L[j] => ["rêve américain", "787", "3592"]
    ...
    Il faudra maintenant comparer la ligne i (i de 0 à len(L)-2 inclus) à toutes les lignes j suivantes (j de i+1 à len(L)-1 inclus), et calculer le dice:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    for i in range(0,len(L)-1):
        for j in range(i+1, len(L)):
            dice = 2*len([n1 for n1 in L[i][1:] for n2 in L[j][1:] if n1==n2])/(len(L[i])+len(L[j])-2)
    en effet, dans la formule du dice = 2*X/(A+B), on retrouve:
    A = len(L[i])-1
    B = len(L[j])-1
    X = len([n1 for n1 in L[i][1:] for n2 in L[j][1:] if n1==n2])

    la "list comprehension" de X fabrique la liste des doublons, dont on compte simplement la longueur.

    Après, je n'ai pas bien compris ce qu'on fait du résultat. Cependant, on peut au moins stocker les résultats sous la forme d'une nouvelle liste de liste:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    R = (
    ...
    (i, ((j1,d1), (j2,d2), ... (jk,dk), ... (jn,dn))),
    ...
    )
    Cette structure permettrait:
    - de ne stocker que les indices pour gagner de la place en mémoire,
    - de trier les listes (...(jk,dk)...) selon l'ordre décroissant des dice dk, afin de simplifier l'application des filtres,
    - de trier les listes (...(jk,dk)...) selon l'ordre alphabétique des tags jk, afin de faire des recherches rapides par dichotomie.
    - etc...


    Bon, il faut se rendre compte de l'énormité des calculs! Donnons quelques points de repères:

    - avec 44277 lignes, il faudra faire 980204226 (env. 980 millions) comparaisons!

    - le coût de la double boucle vide (avec pass) est finalement assez raisonnable: 1mn et 8s (qui a dit que Python était lent?).

    - le coût de 980204226 calculs de dice selon ma formule est de l'ordre de 1h et 10mn.

    Je pense qu'en soignant l'organisation des calculs, on peut effectivement beaucoup gagner sur le délai initial (début de topic), et une fois fait, utiliser psyco qui fait quelquefois des miracles!

    Tyrtamos
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  12. #32
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut Débroussaillage
    J'ai pris le code que tu donnes dans le message #1 et je l'ai modifié pour pouvoir le faire tourner sur un mini fichier mat1 que j'ai créé, afin de voir ce qui se passe.
    Mes modifications:

    - importation de re
    - importation de clock pour mesurer les temps d'exécution de chaque tour de la boucle for i in lp:
    - importation de itemgetter. Pas la peine d'importer le module operator en entier
    - je me suis créé la fonction dice()
    J'ai mis split dedans, pas la peine de faire une fonction spécialement pour ça. Bien mettre les float, sinon ça renvoit 0
    - openFile: ça sort d'où ce machin là ? Remplacé par open
    - j'ai pris m=3
    - rectifié l'indentation de else: chaine.append(lcountlist[alllist][0])
    - j'ai rendu muettes des lignes à la fin
    - comme chaine est une liste, malgre son nom, instructions à la fin pour connaître sa taille

    Voilà "mon" code1 = ton code modifié:

    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
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    import re
    from operator import itemgetter
     
    def dice(la,lb):
        la = la.split('##')
        lb = lb.split('##')
        return float(2*len([e for e in la if e in lb]))/float(len(la)+len(lb))
     
    f = open("mat1")
    lp = f.readlines()
    fg = open("mat1")
    d = fg.readlines()
    n=1
    chaine=[]
    countList={}
    for i in lp:
        listeA = re.findall('<.*?>(.*?)</.*?>',i)
        print '------------------------------------\n','n =',n
        print 'i =',i,
        print 'listA =',listeA
        element = re.findall('<(.*?)>',i)
        print 'element =',element
        chaine.append("<" + element[0] + ">")
        print 'chaine =',chaine,'\n'
        for j in d[n:]:
            listeB = re.findall('<.*?>(.*?)</.*?>',j) #recupère la liste entre les balises
            print 'listB =',listeB
            elementj = re.findall('<(.*?)>',j)#récupère l'élement de la balise
            diceValue = dice(listeA[0],listeB[0])
            #creerListe qui transforme la chaine 5##8##10 en une liste de 3 élements
            if diceValue>0 and diceValue<1: print diceValue,'   ',elementj
            if diceValue > 0.0 and diceValue < 1.0:
                countList[elementj[0]]=diceValue
        print '\n%%\n'
        lcountlist = countList.items()
        print 'lcountlist =',lcountlist
        lcountlist.sort(key=itemgetter(1),reverse=True)
        print 'lcountlist =',lcountlist
        lcountlist = lcountlist[:3]
        print 'lcountlist =',lcountlist
        print '\n%%\n'
        for alllist in range(len(lcountlist)):
            print '\nalllist =',alllist
            print '\nchhhaine1 =',chaine
            if alllist != len(lcountlist) - 1:
                chaine.append(lcountlist[alllist][0]+"##")
            else:
                chaine.append(lcountlist[alllist][0])
            print '\nchhhaine2 =',chaine 
            print "element[0] =  </", element[0] ,">\\n"
            chaine.append("</" + element[0] + ">\n")
            print '\nchhhaine3 =',chaine
            n+=1
            #cp+=1
        #f1 = open("matricecooccurrenceTest.log","w")
        #f1.writelines(chaine)
        #f1.writelines(chaineAutre)
    f.close()
    #f1.close()
    fg.close()
     
     
    print
    print "'chaine' finale est une liste de =",len(chaine),'éléments'
    print
    chaine_soudee = ''.join(chaine)
    print '                           et de ',len(chaine_soudee),'carctères.'
    Et voilà le mini fichier mat1:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <trêve des confiseurs>1872</trêve des confiseurs>
    <rêve américain>138##181##192##203##267##787##1872##5313##5316</rêve américain>
    <désunion>4917</désunion>
    <bouddhisme>787##3344##4805</bouddhisme>
    <unité politique>138##192##787##4727</unité politique>
    <mirage>2375##3374##5106</mirage>
    <sécurité>323##331##334##340##344##1872##345##543</sécurité>
    <faune>3815##3817</faune>
    <devenir>25##138##181##192##203##267##4519##5037##5313##5316##5346</devenir>
    <célébration>2988</célébration>

    Faire tourner --> ça ne donne pas ce qui est attendu.
    J'ai fait les modifications suivantes pour se rapprocher de ce que tu veux faire.

    1) L'erreur la plus grosse est que chaine n'est pas remise à zéro quand la ligne i change. Donc du début à la fin, chaine grossit grossit grossit.....
    Si on déplace chaine=[] juste après for i in lp: , les choses s'améliorent.

    2) Il faut sortir chaine.append("</" + element[0] + ">\n") de la boucle for alllist in range(len(lcountlist)):

    4) Il faut aussi réinitialiser à zéro le dictionnaire countList avant d'attaquer le traitement d'une nouvelle ligne i

    5) Il faut sortir n+=1 de la boucle for alllist in range(len(lcountlist)): sinon n augmente de 1 si lcountlist==1, de 2 si lcountlist==2, de 3 si lcountlist==3... avant qu'une nouvelle ligne soit appelée et donc la boucle for j in d[n:]: ne commencera pas immédiatement après la ligne i si la lcounlist précédente avait plus d'un élément.

    6) Attention à la place de f1 = open("matricecooccurrenceTest.log","w")
    L'ouverture en mode 'w' écrase tout fichier portant le nom "matricecooccurrenceTest.log" qui existerait déjà.


    Je suis donc parvenu au code2 suivant, beaucoup plus satisfaisant


    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
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    import re
    from time import clock
    from operator import itemgetter
     
    total = ''
     
    def dice(la,lb):
        la = la.split('##')
        lb = lb.split('##')
        return float(2*len([e for e in la if e in lb]))/float(len(la)+len(lb))
     
    f = open("mat1")
    lp = f.readlines()
    fg = open("mat1")
    d = fg.readlines()
    f1 = open("matricecooccurrenceTest.log","w")
    n=0
    countList={}
    for i in lp:
        t0 = clock()
        n+=1
        chaine=[]
        countList = {}
        listeA = re.findall('<.*?>(.*?)</.*?>',i)
        print '------------------------------------\n','n =',n
        print 'i =',i,
        print 'listA =',listeA
        element = re.findall('<(.*?)>',i)
        print 'element =',element
        chaine.append("<" + element[0] + ">")
        for j in d[n:]:
            listeB = re.findall('<.*?>(.*?)</.*?>',j) #recupère la liste entre les balises
            elementj = re.findall('<(.*?)>',j)#récupère l'élement de la balise
            diceValue = dice(listeA[0],listeB[0])
            if diceValue > 0.0 and diceValue < 1.0:
                print diceValue,j[:-1]
                countList[elementj[0]]=diceValue
        lcountlist = countList.items()
        lcountlist.sort(key=itemgetter(1),reverse=True)
        lcountlist = lcountlist[:3]
        for alllist in range(len(lcountlist)):
            if alllist != len(lcountlist) - 1:
                chaine.append(lcountlist[alllist][0]+"##")
            else:
                chaine.append(lcountlist[alllist][0])
            #cp+=1
        chaine.append("</" + element[0] + ">\n")
        print 'chaine =',chaine,'\n'
        total = total + ''.join(chaine)
        f1.writelines(chaine)
        #f1.writelines(chaineAutre)
        print clock() - t0,'secondes\n'
    f.close()
    fg.close()
    f1.close()
     
    print 'total =\n',total
    print 'len de total =',len(total)
    La variable 'total' donne tout à la fin le contenu de ce qui a été écrit dans le fichier récepteur des résultats.
    Avec code 1 c'était 916 caractères qui étaient écrits , avec code2 ce ne sont plus que 350 soit 2,6 fois moins.
    Cette différence s'observe sur un fichier de 10 lignes. On peut imaginer ce que donne le gonflement de la variable 'chaine' sur 44277 lignes !!

    Il y a d'autres choses à dire mais pour le moment, je vais étudier les messages de tyrtamos et alexdevl

    Essaye de faire tourner code 2, ça devrait aller beaucoup mieux.

    PS c'est quoi cp ?

  13. #33
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut tyrtamos
    Est-ce que l'expression
    [ n1 for n1 in L[i][1:] for n2 in L[j][1:] if n1==n2 ]
    n'est pas avantageusement remplacée par
    [ n for n in L[i][1:] if n in L[j][1:] ] ?


    C'est quoi la double boucle vide ?

  14. #34
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    358
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 358
    Points : 117
    Points
    117
    Par défaut
    ok merci
    je vais tester ça.
    je vous tiens au courant

  15. #35
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 461
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 461
    Points : 9 248
    Points
    9 248
    Billets dans le blog
    6
    Par défaut
    Citation Envoyé par eyquem Voir le message
    Est-ce que l'expression
    [ n1 for n1 in L[i][1:] for n2 in L[j][1:] if n1==n2 ]
    n'est pas avantageusement remplacée par
    [ n for n in L[i][1:] if n in L[j][1:] ] ?
    Si!

    Citation Envoyé par eyquem Voir le message
    C'est quoi la double boucle vide ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    for i in range(0,44276):
        for j in range(i+1, 44277):
            pass
    Tyrtamos
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  16. #36
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut ekremyilmaz, question
    Dans ton message #25, tu écris:

    « ensuite je passe à la ligne suivante qui est
    ligne i = <motB>1##4##8</motB>
    puis je compare cette ligne avec ligne avec

    <motA>1##2##3##4</motA>
    <motC>5##8##10</motC>
    <motD>35##32##10</motD> »

    C'est en contradiction avec ce que tu as écrit dans les messages précédents et avec l'algorithme de ton code du message #1 (j in d[n:] avec n qui augmente de 1 à chaque tour).

    Qu'en est-il finalement ?

    C'est une question primordiale parce qu'elle détermine l'algorithme à concevoir.

    Si chaque ligne n'est à comparer qu'à celles qui la suivent, alors, comme tyrtamos l'a écrit, il y a 44277 x 44276 / 2 = 980204226 valeurs dice à calculer et elles sont a priori toutes différentes.

    Tandis que si chaqe ligne doit être comparée à toutes celles qui la précèdent et qui la suivent, cela fait 44277 x 44276 = 1 960 408 452 valeurs dice à calculer. Mais dans cette masse de valeurs, il y a une symétrie: dice(k,m) = dice(m,k), ce qui permet d'envisager des astuces malgré l'enormité de ce nombre de valeurs dice qu'ont ne peut envisager de toutes mettre dans un dictionnaire au fur et à mesure de leur calcul.

    Pour ma part, il me semble que si on s'intéresse aux co-occurents de 'mot3567', il n'y a pas de raison de négliger ceux qui sont référencés dans des lignes précédant la ligne de 'mot3567'. Dans ce cas, ton code ne va pas.
    Sinon, il restera à améliorer ton code avec ton algorithme parce que grosso modo il est OK et je ne vois pas comment on pourrait procéder autrement.

  17. #37
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut euh...
    et elle sert à quoi la double boucle vide stp ?

  18. #38
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    358
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 358
    Points : 117
    Points
    117
    Par défaut
    cp c'est une variable que j'ai ajouté pour voir le nombre de ligne qui a réussi à traiter.
    j'ai rajouté ça juste avant ta première instruction avant le clock
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
        if (cp>100):
            print cp
            cp  =0
        t0 = clock()
    ensuite j'incrémente cp à la fin de la boucle.
    j'ai testé sur mon gros corpus
    tjs la meme chose, c la meme vitesse
    pour traiter 100 lignes, il met à peu près 4 min.
    sachant qu'il y a 44000 environ

    je t'envoi le gros corpus

    http://ekremyilmaz.free.fr/mat1.log (le fichier fait 64Mo environ

    teste le pour voir ce que ça donne, ajoute l'instruction juste avant le clock().
    et incrémente cp à la fin du for.

    et dis moi, si ça met autant de tant.

    merci

  19. #39
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 461
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 461
    Points : 9 248
    Points
    9 248
    Billets dans le blog
    6
    Par défaut
    Citation Envoyé par eyquem Voir le message
    et elle sert à quoi la double boucle vide stp ?
    Je n'ai parlé d'une double boucle vide que pour évaluer ce qu'elle coûtait en temps:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    import time
    t = time.clock()
    for i in range(0,44276):
        for j in range(i+1, 44277):
            pass
    print time.clock()-t
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  20. #40
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    358
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 358
    Points : 117
    Points
    117
    Par défaut
    exactement eyquem

    y a deux solutions
    soit on la compare à tous les précédentes

    soit on la compare uniquement aux suivantes.

    perso, j'avais choisi la première, mais je me suis dit, c trop long

    ensuite j'ai fait la seconde, dans cette hypothèse

    j'ai fait ça:

    après qu'on calcule chaque dice pour le motA avec tous les autres mots.

    j'ai mon dico après dice
    liste pour le mot A = ["B:3","C:3"]
    ensuite j'écrit dans le fichier
    <A>B##C</A>
    mais aussi
    <B>A</B>
    <C>A</C>
    ce qui permet de gérer la symétrie.
    A la fin de l'algo, je peux me retrouver avec un fichier :
    <A>B##C</A>
    <B>A</B>
    <C>A</C>
    <B>M,Z</B>
    <C>P,Y</C>

    j'ai crée une fonction qui permet de réunifier la liste de tous les mots identiques.
    par ex:
    <A>B##C</A>
    Pour B
    <B>A,M,Z</B>
    Pour C
    <C>A,P,Y</C>

    donc voilà voilà

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. importer fichier long
    Par mizou00 dans le forum Macros et VBA Excel
    Réponses: 15
    Dernier message: 13/08/2010, 09h15
  2. Impossible de transferer des fichiers long
    Par feldene dans le forum Langage
    Réponses: 4
    Dernier message: 24/03/2010, 18h38
  3. Copier les fichiers long Win98/ME
    Par compdev dans le forum Windows 2000/Me/98/95
    Réponses: 1
    Dernier message: 11/09/2009, 22h50
  4. nom de fichier long
    Par karim_usthb dans le forum Scripts/Batch
    Réponses: 0
    Dernier message: 02/06/2008, 12h50
  5. [Win XP] Optimisation (fichier de "swap" et RAM)
    Par BiM dans le forum Windows XP
    Réponses: 11
    Dernier message: 05/04/2006, 13h13

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