Introduction
La fouille de texte est une méthode essentielle pour extraire des informations précieuses à partir de vastes corpus de texte. Un aspect fondamental de cette analyse est l’étude des cooccurrences à partir d’un mot clé, qui peut révéler des relations sémantiques importantes et des tendances dans le texte. Cet article, propose un script Python conçu pour analyser les cooccurrences de mots clés dans un corpus de texte.
Nous aborderons également ce qu’est une cooccurrence et l’importance de définir des segments de texte pour cette analyse.
Une des applications possible de ce script (dans une perspective de fouille de texte) vide à comparer et analyser des discours politiques. En saisissant un mot clé pertinent pour chaque discours, vous pouvez examiner comment différents orateurs abordent un même sujet et comprendre les réseaux sémantiques sous-jacents. Par exemple, comparer les cooccurrences du mot « économie » dans deux discours permet de voir les thèmes associés et de révéler des différences d’approche entre les orateurs.
Les points forts du script résident dans le fait qu’il a été testé sur un corpus de 700 articles provenant du site Europresse (que j’avais sous le coude), ce qui le rend fiable pour l’analyse de gros volumes de données. Le point faible, cependant, est que j’aurais dû tester le script avec un corpus plus restreint, comme des discours politiques, qui sont la tendance du mois de juin. Dans ce cadre, le script permet de comparer deux discours distincts et d’analyser les cooccurrences autour d’un même mot-clé. Certes, le choix du mot-clé est arbitraire, mais cela peut constituer une bonne introduction à la fouille de texte.
Pour exécuter le script dans cette configuration, il suffit d’analyser deux corpus distincts (deux fichiers texte distincts) contenant des discours politiques. La seule particularité est que la première ligne de chaque discours doit être constituée par le séparateur ****.
Définition de la cooccurrence
En linguistique, une cooccurrence se réfère à la fréquence avec laquelle deux mots apparaissent ensemble dans un segment de texte donné. Par exemple, si nous considérons le mot clé « intelligence », une cooccurrence pourrait être « intelligence artificielle » si ces deux termes apparaissent fréquemment ensemble dans le texte. La cooccurrence révèle les relations contextuelles et sémantiques entre les termes, offrant un aperçu des thèmes dominants et des sujets abordés dans le corpus.
Pour tout vous dire, ce script a été développé autour d’un corpus de 700 articles provenant du site Europresse. À l’origine, j’avais horodaté les articles pour essayer de réaliser une analyse longitudinale.
Pour cela, j’ai utilisé le script d’encodage des articles Europresse pour IRAMUTEQ, en ne gardant que les dates comme variable étoilée, notamment pour essayer de visualiser l’évolution des cooccurrences à travers le temps. Bon, je me suis un peu compliqué la tâche dès le départ et je n’arrivais pas à obtenir des résultats cohérents.
J’ai donc réduit mes ambitions. Même si l’analyse de la distribution des cooccurrences semble plutôt simpliste, la cooccurrence constitue néanmoins la plus petite unité linguistique.
Présence simultanée de deux ou plusieurs éléments ou classes d’éléments dans le même énoncé.
Importance des segments de texte
Définir des segments de texte est crucial pour l’analyse des cooccurrences. La ponctuation et d’autres marqueurs syntaxiques servent souvent à délimiter ces segments. Par exemple, dans une analyse de discours politique, chaque phrase ou paragraphe peut être considéré comme un segment. Cela permet de contextualiser les cooccurrences et d’obtenir une vision plus précise des relations entre les mots.
Dans le cas de ce script, le segment de texte est en fait le paragraphe complet de l’article de presse.
Le script utilise donc le segment de texte analysé est le paragraphe complet de chaque article, délimité par la ligne commençant par ****.
Ce séparateur **** est utilisé pour indiquer le début d’un nouvel article, donc tout le texte entre deux séparateurs **** est considéré comme un article entier et traité comme tel. La ponctuation n’est pas utilisée pour segmenter le texte dans ce script.
Le script python pour l’analyse des cooccurrences
Ce script utilise des bibliothèques Python populaires comme NLTK
pour le traitement du langage naturel et wordcloud
pour la visualisation. L’utilisateur peut saisir un mot clé et le script analyse les cooccurrences de ce mot dans le corpus, génère un nuage de mots et produit un fichier CSV avec les fréquences des cooccurrences.
Fonctionnalités du script :
- Sélection du fichier et répertoire de sortie : L’utilisateur peut sélectionner un fichier texte et un répertoire pour sauvegarder les résultats.
- Saisie du mot clé : L’utilisateur saisit le mot clé à analyser.
Exclusion des verbes(oui/non) de l’analyse : Je n’ai pas réussi à intégrer cette option à l’interface.- Exclusion des mots qui n’auraient pas été filtrée par les stopwords.
- Choix du nombre de cooccurrences à afficher dans le nuage de mots.
- Calcul des cooccurrences : Le script calcule la fréquence des mots apparaissant à proximité du mot clé.
- Génération du CSV et du nuage de mots : Les résultats sont sauvegardés dans un fichier CSV (fréquence des cooccurrences trouvées) et visualisés sous forme de nuage de mots.
Un point important à souligner est que, comme vous l’avez remarqué dans l’exemple (cf. image) du corpus, je suis parti d’un fichier qui aurait nécessité un nettoyage manuel.
Mais comme je suis un peu fainéant, j’ai intégré dans l’interface la possibilité d’écarter des « aberrations » linguistiques sans devoir repasser par un nettoyage manuel du corpus (fichier texte).
Vous pouvez ainsi tester rapidement l’analyse des cooccurrences en y excluant des mots ou des lettres indésirables.
import tkinter as tk from tkinter import filedialog, messagebox, StringVar from tkinter.ttk import Notebook, Frame import pandas as pd import matplotlib.pyplot as plt from collections import Counter import nltk from nltk.corpus import stopwords as nltk_stopwords from nltk.tokenize import word_tokenize from wordcloud import WordCloud # Charger les ressources NLTK nltk.download('punkt') nltk.download('stopwords') # Variables globales file_path = "" output_directory = "" keyword = "" custom_stopwords = [] top_n_cooccurrences = 10 total_words_processed = 0 total_articles = 0 most_frequent_cooccurrence = "" # Initialiser la liste des stopwords avec les mots supplémentaires => vous pouvez ajouter à cette liste vos stopwords french_stopwords = set(nltk_stopwords.words('french')) french_stopwords.update(["encore", "plus", "cela", "entre", "si", "très", "comme"]) # vous pouvez ajouter à cette liste vos stopwords def log_message(message): text_area.insert(tk.END, message + "\n") text_area.see(tk.END) def open_file(): global file_path file_path = filedialog.askopenfilename(title="Ouvrir un fichier texte", filetypes=(("Text files", "*.txt"),)) if file_path: log_message(f"Fichier sélectionné: {file_path}") def select_output_directory(): global output_directory output_directory = filedialog.askdirectory(title="Sélectionner le Répertoire de Sortie") if output_directory: log_message(f"Répertoire de sortie sélectionné: {output_directory}") def set_keyword(): global keyword keyword = keyword_entry.get() if keyword: log_message(f"Mot-clé sélectionné: {keyword}") def set_custom_stopwords(): global custom_stopwords, french_stopwords stopwords_str = stopwords_entry.get() if stopwords_str: custom_stopwords = [word.strip().lower() for word in stopwords_str.split(',')] french_stopwords.update(custom_stopwords) log_message(f"Mots à exclure ajoutés: {', '.join(custom_stopwords)}") def set_top_n_cooccurrences(): global top_n_cooccurrences try: top_n_cooccurrences = int(top_n_entry.get()) log_message(f"Nombre de co-occurrences à afficher: {top_n_cooccurrences}") except ValueError: top_n_cooccurrences = 10 log_message(f"Valeur incorrecte pour le nombre de co-occurrences. Utilisation de la valeur par défaut: 10") def preprocess_text(doc): global total_words_processed tokens = word_tokenize(doc) filtered_tokens = [token.lower() for token in tokens if token.lower().isalnum() and token.lower() not in french_stopwords] total_words_processed += len(filtered_tokens) return filtered_tokens def read_and_preprocess_file(file_path): global total_articles articles = [] current_article = [] with open(file_path, 'r', encoding='utf-8') as file: for line in file: if line.startswith('****'): if current_article: articles.append(' '.join(current_article).strip()) current_article = [] else: current_article.append(line) if current_article: articles.append(' '.join(current_article).strip()) total_articles = len(articles) return articles def calculate_cooccurrences(articles, keyword, window_size=10): cooccurrence_counter = Counter() for article in articles: tokens = preprocess_text(article) keyword_indices = [i for i, token in enumerate(tokens) if token == keyword] for index in keyword_indices: window_start = max(0, index - window_size) window_end = min(len(tokens), index + window_size + 1) context_tokens = tokens[window_start:index] + tokens[index + 1:window_end] for token in context_tokens: if token != keyword: cooccurrence_counter[token] += 1 global most_frequent_cooccurrence if cooccurrence_counter: most_frequent_cooccurrence = cooccurrence_counter.most_common(1)[0][0] else: most_frequent_cooccurrence = "Aucune co-occurrence trouvée" return cooccurrence_counter def generate_csv(cooccurrences, output_directory, keyword): df = pd.DataFrame(cooccurrences.items(), columns=['Cooccurrence', 'Frequency']) csv_path = f"{output_directory}/cooccurrences_{keyword}.csv" df.to_csv(csv_path, index=False) log_message(f"Fichier CSV généré: {csv_path}") return csv_path def generate_wordcloud(cooccurrences, output_directory, keyword, top_n): top_cooccurrences = dict(cooccurrences.most_common(top_n)) wordcloud = WordCloud(width=800, height=400, background_color='white').generate_from_frequencies(top_cooccurrences) plt.figure(figsize=(10, 5)) plt.imshow(wordcloud, interpolation='bilinear') plt.axis('off') plt.title(f"Top {top_n} Cooccurrences for '{keyword}'") plt_path = f"{output_directory}/wordcloud_{keyword}.png" plt.savefig(plt_path, bbox_inches='tight') plt.show() log_message(f"Nuage de mots généré: {plt_path}") return plt_path def process_file(): global file_path, output_directory, keyword, top_n_cooccurrences, total_words_processed, total_articles, most_frequent_cooccurrence total_words_processed = 0 total_articles = 0 most_frequent_cooccurrence = "" set_keyword() set_custom_stopwords() set_top_n_cooccurrences() if not file_path: messagebox.showerror("Erreur", "Veuillez sélectionner un fichier texte.") return if not output_directory: messagebox.showerror("Erreur", "Veuillez sélectionner un répertoire de sortie.") return if not keyword: messagebox.showerror("Erreur", "Veuillez saisir un mot-clé.") return log_message("Début du traitement du fichier...") articles = read_and_preprocess_file(file_path) log_message("Fichier lu et prétraité") cooccurrences = calculate_cooccurrences(articles, keyword) log_message("Calcul des co-occurrences terminé") csv_path = generate_csv(cooccurrences, output_directory, keyword) wordcloud_path = generate_wordcloud(cooccurrences, output_directory, keyword, top_n_cooccurrences) info_text.set(f"Nombre de mots traités: {total_words_processed}\nNombre d'articles dans le corpus: {total_articles}\nCo-occurrence la plus fréquente: {most_frequent_cooccurrence}") messagebox.showinfo("Succès", f"Analyse terminée.\nFichier CSV: {csv_path}\nNuage de mots: {wordcloud_path}") log_message("Analyse terminée") # Interface utilisateur root = tk.Tk() root.title("Analyse des Co-occurrences") root.geometry("1000x800") notebook = Notebook(root) notebook.pack(expand=True, fill='both') tab1 = Frame(notebook) notebook.add(tab1, text="Analyse des Co-occurrences") text_area = tk.Text(tab1, height=10, width=120) text_area.pack(pady=5) info_text = StringVar() info_label = tk.Label(tab1, textvariable=info_text, justify='left') info_label.pack(pady=5) file_btn = tk.Button(tab1, text="Ouvrir un Fichier", command=open_file) file_btn.pack(pady=5) directory_btn = tk.Button(tab1, text="Sélectionner le Répertoire de Sortie", command=select_output_directory) directory_btn.pack(pady=5) keyword_label = tk.Label(tab1, text="Entrez le mot-clé pour l'analyse:") keyword_label.pack(pady=5) keyword_entry = tk.Entry(tab1) keyword_entry.pack(pady=5) stopwords_label = tk.Label(tab1, text="Entrez les mots à exclure supplémentaires (séparés par une virgule):") stopwords_label.pack(pady=5) stopwords_entry = tk.Entry(tab1) stopwords_entry.pack(pady=5) top_n_label = tk.Label(tab1, text="Nombre de co-occurrences à afficher:") top_n_label.pack(pady=5) top_n_entry = tk.Entry(tab1) top_n_entry.pack(pady=5) process_btn = tk.Button(tab1, text="Traiter le Fichier et Générer les Résultats", command=process_file) process_btn.pack(pady=5) link_label = tk.Label(tab1, text="www.codeandcortex.fr", fg="white", cursor="hand2") link_label.pack(pady=5) link_label.bind("<Button-1>", lambda e: open_url("https://www.codeandcortex.fr")) def open_url(url): import webbrowser webbrowser.open_new(url) root.mainloop()
Conclusion et perspectives
Il n’est pas absolument nécessaire d’utiliser NLTK pour calculer les cooccurrences.
Bien que NLTK soit une bibliothèque puissante et polyvalente pour le traitement du langage naturel, il existe d’autres outils et bibliothèques qui peuvent également être utilisés pour cette tâche, tels que:
- Pandas : Pour manipuler et analyser des données structurées (amplement suffisant).
- spaCy : Pour un traitement du langage naturel.
- gensim : Spécialement conçu pour le traitement de grands corpus de texte.
- Bert (CamenBERT, la version fr développée par l’INRIA)
Ainsi, dans la continuité du script faisant l’analyse des cooccurrences, je vais travailler sur l’analyse de similarité lexicale basée sur les cooccurrences et une analyse de similarité sémantique sur des segments de texte.
Cette approche, utilisera un test de similarité cosinus (Le test de similarité cosinus est une mesure de similarité entre deux vecteurs dans un espace vectoriel, qui quantifie la différence angulaire entre eux), reposant sur un modèle de traitement de langage naturel comme Spacy ou BERT, avec des outils comme la tokenisation, le POS tagging (annotation des mots avec leur catégorie grammaticale : nom, verbe, adjectif, etc.), le stemming, la lemmatisation,…