• Keine Ergebnisse gefunden

Exemple 3: Concordance avec un mot provenant d'un fichier texte

3.16. Text Clustering : regroupement des termes d’un texte par des algorithmes de clustering par des algorithmes de clustering

3.16.2. Text clustering par des algorithmes basés sur la matrice TF- TF-IDF TF-IDF

3.16.2.1. Construction de la matrice TF-IDF

Avant de mettre en œuvre le clustering, il faut d’abord calculer la matrice TF-IDF associée à la problématique étudiée. Pour mieux comprendre le concept de matrice TF-IDF, partons de l’exemple développé par Brandon Rose (http://brandonrose.org/clustering) concernant l’analyse des 100 films les plus populaires de l’histoire du Cinéma. Chaque film est décrit par un titre (title) et un synoptique, présentation permettant de saisir d'un seul coup d'œil un ensemble d'informations liées au film (synopses). Voir http://www.imdb.com/list/ls055592025/.

Ces deux informations ont été déjà extraites et stockées dans des fichiers nommés respectivement title_list.txt et synopses_list_wiki.txt enregistrés dans le répertoire courant. En somme, on dispose de 100 titres auquels correspondent 100 synoptiques.

Le but visé ici est d’exploiter les synopses à travers du text clustering afin de tirer l’essentiel des informations qui sous-tendent l’ensemble de ces films et au final regrouper les films selon les grandes catégories. En gros, il s’agit de faire du text clustering sur l’ensemble des 100 films afin de dégager des grandes catégories de films plus homogènes.

Dans la perspective de la construction de la matrice TF-IDF, il faut avoir à l’esprit que chaque synopsis constitue un document; chaque document document étant constitué d’un ensemble de termes (mots).

Avant d’aborder le calcul de la matrice TF-IDF, importons d’abord les textes et effectuons les traitements nécessaires.

Importation des textes

########### Lecture de la liste des synopses

with open("synopses_list_wiki.txt", 'r', encoding="utf-8") as x: # synopses=x.read().strip() # lecture du fichier de synopses (lire tout le fichier en un seul bloc)

186 synopses =synopses.split("BREAKS HERE") #découper le texte dont le séparateur est le mot "BREAKS HERE"

print(len(synopses))

for i in range(len(synopses)):

synopses[i]=synopses[i].strip() # Suppression des lignes vides représentées par \n

#print(synopses[i])

del synopses[len(synopses)-1] # Suppression du dernier élément qui contient uniquement l'espace vide " "

################### Lecture de la liste des titres

with open("title_list.txt", 'r', encoding="utf-8") as x: #

titles=x.read().strip() # lecture du fichier des titres(lire tout le fichier en un seul bloc)

titles =titles.split("\n") #découper le texte dont le séparateur est le mot "\n" nouvelle ligne

#print(len(titles))

for i in range(len(titles)):

titles[i]=titles[i].strip() # Suppression de potentielles lignes vides

#print(titles[i])

## Examen des deux fichiers

print (titles[:10]) # les 10 premiers titres

print (synopses[0][:200]) # les 200 premiers caractères du premier film (premier élément de synopses)

La liste synopses contients les 100 documents et la liste titles contient les 100 titres correspondants.

Opérations de pré-traitement sur les texte: Stopwords, stemming, et tokenizing

- Les stop words (mots vides) sont des mots communs dans un texte à tel qu'il est inutile de les indexer ou de les utiliser dans une recherche. En français, des mots vides évidents sont entre autres « le », « la », « de », « du », « ce », etc…

- Le stemming des termes dans un texte consiste à raciniser chaque mot dans le texte. Il s’agit en générale de supprimer les préfixes et les suffixes afin de ramener le texte à sa stricte racine.

Ex : stem(frontal)=front ; stem(fishing)=fish. Le stemming permet la détermination des mots clés (généralement utilisés dans les référencements).

-le tokenizing consiste en un découpage du texte en un ensemble de mots, tout en éliminant les ponctuations. On peut découper un texte en phrases (sentence) ou découper en mots(

words). Cette dernière est celle qui sera utilisée dans la procédure de text clustering.

Le module NLT fournit des fonctions qui permettent de réaliser ces trois opérations. En cas de nécessité, installer d’abord toutes les fonctions utiles de NLTK.

187

# nltk.download() # Choisir all

# détermination des Stop Words

stopwords = nltk.corpus.stopwords.words('english') # à adapter dans le cas du français : french

# Stemming

from nltk.stem.snowball import SnowballStemmer

stemmer = SnowballStemmer("english") # à adapter dans le cas du français : french

Pour la tokenization, on va définir deux fonctions. Une première qui tokenize le texte et fait du stemming des tokens (des mots). Une seconde fonction qui fait simplement du tokenize sur le texte. Ces deux fonctions sont définies comme suit :

def tokenize_and_stem(text):

tokens = [word for sent in nltk.sent_tokenize(text) for word in nltk.word_tokenize(sent)] # tokenize d’abord par phrase, puis par mot pour s'assurer que les ponctuations sont traitées

filtered_tokens = []

for token in tokens: # Elimination des tokens ne contenant pas de lettres (p. Ex., tokens uniquement numériques, ponctuation brute)

if re.search('[a-zA-Z]', token):

filtered_tokens.append(token)

stems = [stemmer.stem(t) for t in filtered_tokens]

return stems

def tokenize_only(text):

tokens = [word.lower() for sent in nltk.sent_tokenize(text) for word in nltk.word_tokenize(sent)] # tokenize d’abord par phrase, puis par mot pour s'assurer que les ponctuations sont traitées

filtered_tokens = []

for token in tokens: # Elimination des tokens ne contenant pas de lettres (p. Ex., tokens uniquement numériques, ponctuation brute)

if re.search('[a-zA-Z]', token):

filtered_tokens.append(token) return filtered_tokens

On va appliquer ces deux fonctions sur la liste synopses afin de constituer le vocabulaire des documents. On a deux vocabulaires : vocabulaire avec et sans stemming. Ces deux listes se construisent comme suit :

totalvocab_stemmed = []

totalvocab_tokenized = []

for i in synopses:

188 allwords_stemmed = tokenize_and_stem(i) #for each item in 'synopses', tokenize/stem

totalvocab_stemmed.extend(allwords_stemmed) #extend the 'totalvocab_stemmed' list (généralisation de append())

allwords_tokenized = tokenize_only(i)

totalvocab_tokenized.extend(allwords_tokenized) On utilise ces deux listes pour former un data frame comme suit :

vocab_frame = pd.DataFrame({'words': totalvocab_tokenized}, index = totalvocab_stemmed)

print ('Il y a ' + str(vocab_frame.shape[0]) + ' items dans vocab_frame')

print (vocab_frame.head(n=10)) # affichage des 10 première observations (termes)

On note ici qu’il y a des répétition des à la fois dans les stems mais aussi dans les termes compltes. Pour examiner plus en détail ce texte, on peut appliquer les analyses suivantes :

#vocab_frame['words'].value_counts() #nombre de répétitions pour chaque valeur

#vocab_frame['words'].nunique() # nombre de valeurs qui sont dupliquées dans la table

#vocab_frame['duplic']=vocab_frame.duplicated() # recherche la duplication sur l’ensemble des variables de la table (renvoie True ou False).

#On peut alors supprimer les valeurs dupliquées si les fréquences ne sont pas utiles pour l'analyse. Dans ce cas, on fait :

#vocab_frame.drop_duplicates() # supprime les duplication sur toute la table

Mais ici, on va garder les valeurs comme telles.

Construction de la matrice TF-IDF

Le principe de construction de la matrie TF-IDF se base sur le tableau de ce genre:

Structure de la matrice des fréquences

terme 1 terme 2 terme 3 … termec J

Doc 1 n11 n12 n13 … N1j

Doc 2 n21 n22 n23 … n2j

Document vector

189

Doc 3 n31 n32 n33 … n3j

… … … …

Doc i ni1 ni2 ni3 … nij

Word vector

La matrice fournit la fréquence (nij) de chaque terme dans chaque document (ici chaque synopsis).

NB : Il faut juste noter que comme il s’agit ici des clustering des documents. Les document se présenteront alors en lignes alors que les termes seront en colonne.

La matrice TF-IDF est construite à partir de cette première matrice. Pour la construction de la matrice TF-IDF, on va utiliser la fonction TfidfVectorizer() de sklearn. Les paramètres de cette fonction seront fixés comme suit :

-max_df: représente la proportion maximale de documents un terme ne doit pas atteindre pourqu’il soit pris en compte dans le calcul de la matrice tfi-idf. Par exemple, un terme qui apparait dans 90% des documents est probablement un terme qui n’apporte pas beaucoup d’informations au moment du clustering. Ici, on fixe max_df=0,8 (soit 80%).

-min_idf: représente le pourcentage minimal de documents dans lequel apparait un terme pour qu’il soit pris en compte dans le calcul de la matrice tf-idf. Ici, on choisit min_idf=0,2 (20%).

-ngram_range: On fixe le paramètre ngram_range entre 1 et 3. Ce qui signifie juste qu’on s’interesse uniquement aux unigrams, bigrams et trigrams.

En spécifiant ces paramètres, la matrice tf-idf se calcule comme suit :

from sklearn.feature_extraction.text import TfidfVectorizer

tfidf_vectorizer = TfidfVectorizer(max_df=0.8, max_features=200000, min_df=0.2, stop_words='english', use_idf=True,

tokenizer=tokenize_and_stem, ngram_range=(1,3)) # definition du vectorizer des parameters. ici on utilise la fonction tokenize_and_stem définit plus comme le tokenizer

NB: Pour lse stops word en Français, il faut créer en amont une liste de mots avec nltk et assigner cette liste à l'option stop_words=. Pour cela, on peut juste utiliser la variable stopwords créer plus haut en mettant juste la valeur french.

tfidf_matrix = tfidf_vectorizer.fit_transform(synopses) # calcul de la tfidf_matrix sur synopses

print(tfidf_matrix.shape) Construction du vocabulaire nettoyé

190 terms = tfidf_vectorizer.get_feature_names() # On récupère juste le termes issus de la construction de la matrie tf-idf.

Construction de la matrice de distance

La matrice de distance permet de mesurer la dissimilarité entre chaque paire de document. La distance entre deux documents (deux vecteurs documents) est égale à 1 moins la cosine simularity entre ces deux documents. La fonction ci-dessous permet d’obtenir la matrice de distance.

from sklearn.metrics.pairwise import cosine_similarity dist = 1 - cosine_similarity(tfidf_matrix)

print(dist)

La matrice tf-idf et la matrice de distance étant maintenant calculées, on peut appliquer différents algorithmes de clustering. Voir ci-après.