chaine_unicode = u"Cette chaîne est en unicode" print type(chaine_unicode) chaine_ordinaire = "Cette chaîne est en UTF-8 (je crois)" print type(chaine_ordinaire) chaine_dechaine = chaine_ordinaire.decode("utf-8") print type(chaine_dechaine) unicode_enchaine = chaine_unicode.encode("utf-8", errors='ignore') print type(unicode_enchaine) phrase = "Longtemps, je me suis couché de bonne heure." phrase.split() print phrase.split(",") print phrase.split("couché") mots_de_phrase = phrase.split() print "_".join(mots_de_phrase) phrase.lower() print phrase.upper() print phrase.decode('utf-8').upper() print phrase.replace("o", "☺") print phrase.lower().replace(",","").replace(".","") import re print re.sub("[.,:;]","",phrase) import urllib f = urllib.urlopen("http://www.gutenberg.org/files/2650/2650-0.txt") texte = f.read() texte = texte.replace("\r","") # les fins de ligne de Gutenberg sont en CRLF. On enlève les CR. print texte[:1000] print texte[-20000:-18000] + "\n\n[...]\n\n" + texte[-2000:] texte = re.split("\*\*\* (?:START|END) OF THIS PROJECT GUTENBERG EBOOK [^*]*\*\*\*.*",texte)[1] texte = texte.strip() print texte[:100] print "[...]" print texte[-150:] texte = re.sub("^.*\n","",texte) texte = re.sub("\n.*$","", texte) texte = texte.strip() print texte[:100] print "[...]" print texte[-100:] def degutenberger(txt): t = txt.replace("\r","") t = re.split("\*\*\* (?:START|END) OF [^*]* PROJECT GUTENBERG [^*]*\*\*\*.*",t)[1] t = t.strip() t = re.sub("^.*\n\n","",t) t = re.sub("\n\n.*$","", t) return t.strip() import pattern.vector as vec doc_Swann = vec.Document(texte.replace("'"," ").decode('utf-8'), # Remplace les ' par des espaces, respectant le fait qu'en français, # les ' séparent des mots. Pour éviter des erreurs, je convertis aussi # le texte en unicode filter = lambda w: w.isalpha(), # Filtre les mots qui ne sont pas exclusivement composés de lettres punctuation = u'.,;:!?()[]{}\'`"@#$*+-|=~_«»', top = None, # Filtre les mots qui ne sont pas parmi les plus fréquents. threshold = 0, # Filtre les mots dont la fréquence est inférieure à un seuil. exclude = [], # Filtre les mots dans la liste noire. stemmer = None, # vec.STEMMER | vec.LEMMA | fonction | None stopwords = False, # Inclure les mots fonctionnels ? name = None, # Nom, type et description type = None, description = None, language = 'fr') # Langue du texte (fr | en | es | de | it | nl) print "couché".isalpha() print u"couché".isalpha() # "couché" est en format unicode, plutôt que chaîne UTF-8 print "couche".isalpha() textes_proust = [] i=0 for ln in liste_proust: f = urllib.urlopen("http://louis.philotech.org/confs/MtlPythonFr2014/corpus/" + ln) t = f.read() t = degutenberger(t) l = ln.split("_") if i == int(l[1]): textes_proust[-1] += t else: textes_proust.append(t) i=int(l[1]) documents_proust = [] for t in textes_proust: d = vec.Document(t.replace("'"," ").decode('utf-8'), # Remplace les ' par des espaces, respectant le fait qu'en français, les ' séparent des mots filter = lambda w: w.isalpha(), # Filtre les mots qui ne sont pas exclusivement composés de lettres punctuation = u'.,;:!?()[]{}\'`"@#$*+-|=~_«»', top = None, # Filtre les mots qui ne sont pas parmi les plus fréquents. threshold = 0, # Filtre les mots dont la fréquence est inférieure à un seuil. exclude = [], # Filtre les mots dans la liste noire. stemmer = None, # vec.STEMMER | vec.LEMMA | fonction | None stopwords = False, # Inclure les mots fonctionnels ? name = None, # Nom, type et description type = None, description = None, language = 'fr') # Langue du texte (fr | en | es | de | it | nl) documents_proust.append(d) corpus_proust = vec.Model(documents_proust, weight=vec.TFIDF) f = urllib.urlopen("http://www.gutenberg.org/cache/epub/13846/pg13846.txt") texte_detude = f.read() texte_detude = degutenberger(texte_detude) print texte_detude[:500] f = urllib.urlopen("http://louis.philotech.org/confs/MtlPythonFr2014/corpus/stoplist.fr.utf-8.txt") stoplist = f.read().decode('utf-8').split("\r\n") mots_etude = vec.words(texte_detude.lower().replace("'"," ").decode('utf-8'), filter = lambda w: w.isalpha() and len(w)>1 and w not in stoplist, # On filtre les mots d'un seul caractère et les mots fonctionnels punctuation = u'.,;:!?()[]{}\'`"@#$*+-|=~_«»') t = 50 segments_etude = [ " ".join(mots_etude[i:i+t]) for i in xrange(0, len(mots_etude), t) ] documents_etude = [] for t in segments_etude: d = vec.Document(t, language = 'fr') documents_etude.append(d) corpus_etude = vec.Model(documents_etude, weight=None) import numpy as np m = np.arange(12) # = np.array(range(12)) m = m.reshape((4,3)) # réarrange une matrice 1×12 en matrice 4×3 print m m[[1,2]] m[m.sum(1)<15] m.sum(0) m.T np.zeros((4,5)) matrice_etude = np.zeros((len(segments_etude),len(corpus_etude.features)), dtype=int) # Par défaut, numpy fait une matrice remplie de floats. J'utilise dtype pour spécifier que ce sont des entiers attributs_etude = corpus_etude.features # Liste des mots dans le corpus ln = 0 for doc in corpus_etude.documents: for mot in doc.words.keys(): matrice_etude[ln][attributs_etude.index(mot)]=doc.words[mot] # words() rend le nombre d'occurences du mot ln += 1 print matrice_etude.shape # Les dimensions de la matrice print matrice_etude.sum() # Somme de toutes les cellules = nombre total de mots dans l'œuvre (excluant les mots fonctionnels) ids = matrice_etude.sum(0)>1 print ids matrice_etude = matrice_etude.T[ids].T attributs_etude = np.array(attributs_etude) attributs_etude = attributs_etude[ids] print matrice_etude.shape for ln in doc_Swann.keywords(top=20): print "%0.08f\t%s" % ln doc_etude = vec.Document(" ".join(mots_etude), filter = None, stopwords = False, language = 'fr') for ln in doc_etude.keywords(top=20): print "%0.08f\t%s" % ln for ln in sorted(zip(matrice_etude.sum(0),attributs_etude), reverse=True)[:20]: print "%d\t%s" % ln classes = corpus_etude.cluster(k=10, iterations = 100) [len(i) for i in classes ] from scipy.cluster.vq import whiten, vq, kmeans center, dist = kmeans(matrice_etude, 10, iter=100) codes, distance = vq(matrice_etude, center) codes_uniq = np.unique(codes) # Ne garde qu'une instance de chaque item dans la liste print [ sum(codes==i) for i in codes_uniq ] rg_idx = np.arange(len(codes)) array_docs = np.array(corpus_etude.documents) classes_docs = [ array_docs[codes==i].tolist() for i in codes_uniq ] classes = [ rg_idx[codes==i].tolist() for i in codes_uniq ] freq_attributes_classe1 = matrice_etude[codes==codes_uniq[0]].sum(0) for ln in sorted(zip(freq_attributes_classe1, attributs_etude), reverse = True)[:10]: print "%g\t%s" % ln def mots_frequents(doclist): lsids = [ corpus_etude.documents.index(d) for d in doclist ] return sorted(zip(matrice_etude[lsids].sum(0), attributs_etude), reverse = True) from ipy_table import * # Pour faire un beau tableau! tableau = [] for c in classes_docs: ln = [] for freq, mot in mots_frequents(c)[:8]: ln.append(("%d %s" % (freq, mot)).encode('utf-8')) tableau.append(ln) # Renverser le tableau pour que 1 colonne = 1 classe tableau =np.array(tableau).T.tolist() make_table(tableau) def cle(dic, k): return dic[k] if k in dic else 0 def tfidf(mot, classe, corpus): tf = sum([ cle(d.words,mot) for d in classe]) / float(sum([ sum(d.words.values()) for d in classe])) doc_ayant_mot = len([d for d in corpus.documents if cle(d.words,mot) > 0 ]) idf = np.log( float(len(corpus)) / doc_ayant_mot ) if doc_ayant_mot != 0 else 0.0 return tf * idf def liste_tfidf(classe, corpus): return sorted(zip([ tfidf(m, classe, corpus) for m in attributs_etude ], attributs_etude), reverse=True) tableau = [] for c in classes_docs: ln = [] for freq, mot in liste_tfidf(c,corpus_etude)[:8]: ln.append(("%g %s" % (freq, mot)).encode('utf-8')) tableau.append(ln) # Renverser le tableau pour que 1 colonne = 1 classe tableau =np.array(tableau).T.tolist() make_table(tableau) from time import time def chi2(mot, classe, matrice): pasclasse = np.ones(len(matrice_etude), dtype=bool) pasclasse[classe]=False motidx = attributs_etude.tolist().index(mot) mat = matrice.clip(0,1) invmat = abs(mat-1) n11 = mat[classe].T[motidx].sum() n10 = invmat[classe].T[motidx].sum() n01 = mat[pasclasse].T[motidx].sum() n00 = invmat[pasclasse].T[motidx].sum() N = n11 + n10 + n01 + n00 r= N * ( n11 * n00 - n10 * n01)**2 / float( (n11+n00) * (n11+n10) * (n00+n01) * (n00+n10) ) return r def liste_chi2(classe, matrice): codes_classe = np.zeros(matrice.shape[0], dtype=int) codes_classe[classe] += 1 codes_pasclasse = np.ones(matrice.shape[0], dtype=int) codes_pasclasse[classe] -= 1 mat = matrice.clip(0,1) invmat = abs(mat-1) n11 = (codes_classe * mat.T).T.sum(0) n10 = (codes_classe * invmat.T).T.sum(0) n01 = (codes_pasclasse * mat.T).T.sum(0) n00 = (codes_pasclasse * invmat.T).T.sum(0) N = n11 + n10 + n01 + n00 r= N * ( n11 * n00 - n10 * n01)**2 / np.array( (n11+n00) * (n11+n10) * (n00+n01) * (n00+n10), dtype=float ) return sorted(zip(r, attributs_etude), reverse=True) tableau = [] for c in classes: ln = [] for freq, mot in liste_chi2(c,matrice_etude)[:8]: ln.append(("%g %s" % (freq, mot)).encode('utf-8')) tableau.append(ln) # Renverser le tableau pour que 1 colonne = 1 classe tableau =np.array(tableau).T.tolist() make_table(tableau)