# Import python modules import numpy as np import csv import matplotlib.pyplot as plt import nltk from nltk import * from nltk.stem.porter import * from math import log import string epsilon=0.00000000000001 def getZipf(points): #### calcul des paramètres de la loi de Zipf (similaire au TP sur l'estimation de plan dans une scène routière, mais en deux dimensions) M = np.zeros((2,2)) M[0,0] = np.sum(points[:,0]**2) M[0,1] = -np.sum(points[:,0]) M[1,0] = -M[0,1] M[1,1] = -points.shape[1] d = np.zeros(2) d[0] = -np.sum(points[:,0]*points[:,1]) d[1] = -np.sum(points[:,0]) d = -d x = np.dot(np.linalg.inv(M), d) # x = [a,b,c] return x #%% ############################### #chargement du fichier csv ############################## with open('movie_reviews.csv', encoding="utf-8") as csv_file: reader = csv.reader(csv_file, delimiter=',',quotechar='"') # on, initialise les données et les labels data =[] labels = [] # Pour chaque ligne du fichier for row in reader: # skip missing data if row[0] and row[1]: data.append(row[0]) # data.append(row[0].decode('utf-8')) y_label = -1 if row[1]=='negative' else 1 labels.append(y_label) #%% ######################################################### # Prétraitement pour toutes les critiques de film ######################################################### ############ liste de mots que l'on enlève stopwords = ['i', 'me', 'my', 'myself', 'we', 'our', 'ours', 'ourselves', 'you', 'your', 'yours', 'yourself', 'yourselves', 'he', 'him', 'his', 'himself', 'she', 'her', 'hers', 'herself', 'it', 'its', 'itself', 'they', 'them', 'their', 'theirs', 'themselves', 'what', 'which', 'who', 'whom', 'this', 'that', 'these', 'those', 'am', 'is', 'are', 'was', 'were', 'be', 'been', 'being', 'have', 'has', 'had', 'having', 'do', 'does', 'did', 'doing', 'a', 'an', 'the', 'and', 'but', 'if', 'or', 'because', 'as', 'until', 'while', 'of', 'at', 'by', 'for', 'with', 'about', 'against', 'between', 'into', 'through', 'during', 'before', 'after', 'above', 'below', 'to', 'from', 'up', 'down', 'in', 'out', 'on', 'off', 'over', 'under', 'again', 'further', 'then', 'once', 'here', 'there', 'when', 'where', 'why', 'how', 'all', 'any', 'both', 'each', 'few', 'more', 'most', 'other', 'some', 'such', 'no', 'nor', 'not', 'only', 'own', 'same', 'so', 'than', 'too', 'very', 's', 't', 'can', 'will', 'just', 'don', 'should', 'now'] texte="" ## on va mettre bout à bout tous les mots for doc_id, text in enumerate(data): # on enlève les ponctuations, les miniscules punctuation = set(string.punctuation) doc = ''.join([w for w in text.lower() if w not in punctuation]) # on enlève les mots trop fréquents doc = [w for w in doc.split() if w not in stopwords] # Stemming stemmer = PorterStemmer() doc = [stemmer.stem(w) for w in doc] # on convertit la liste des mots en une phrase doc = ' '.join(w for w in doc) data[doc_id] = doc texte = texte + ' ' texte = texte + doc #################################################### #%% Question 1: Vérification de la loi de Zipf #################################################### words = nltk.tokenize.word_tokenize(texte) ## on analyse mot par mot. fdist = nltk.FreqDist(words) ## calcul de la fréquence des mots lis = fdist.values() ## occurrences des mots my_lis=np.array([v for v in lis]) sorted_lis = np.sort(my_lis)[::-1] ## on a la liste des mots par ordre décroissant ## visualiser les fréquences de mots. m=20000 ## on analyse les 20000 mots les plus fréquents plt.plot(sorted_lis[:m]) #### calcul des paramètres de la loi de Zipf tab=np.zeros((m,2)) ### A compléter x=getZipf(tab) ################################################################################################################# #%% Question 2: Estimation des probabilités ################################################################################################################### ## Les critiques de 0 à 957 sont positives, celles de 958 à 1959 sont négatives ## apprentissage des fréquences sur les critiques positives: on garde les échantillons 0 à 850 texte_app1 = '' for i in range(850): texte_app1 = texte_app1 + data[i] words_app1 = nltk.tokenize.word_tokenize(texte_app1) fdist_app1=nltk.FreqDist(words_app1) ## apprentissage des fréquences sur les critiques négatives: on garde les échantillons 1000 à 1850 texte_app0 = '' for i in range(850): texte_app0 = texte_app0 + data[1000+i] words_app0 = nltk.tokenize.word_tokenize(texte_app0) fdist_app0=nltk.FreqDist(words_app0) ## test #%% ################################################################################################################# #%% Question 3: Reconnaissance de critiques de film, positives ou négatives, par maximum de vraisemblance par mots isolés ################################################################################################################### taux_erreur_singleton=0 nb=0 for i in range(100): ## on prend 100 exemples de critiques positives, non présentes dans l'apprentissage words_test = nltk.tokenize.word_tokenize(data[850+i]) nb+=1 ## A compléter for i in range(100):## on prend 100 exemples de critiques négatives, non présentes dans l'apprentissage words_test = nltk.tokenize.word_tokenize(data[1850+i]) nb+=1 ## A compléter taux_erreur_singleton=100*taux_erreur_singleton/nb print("taux d'erreur pour les mots isolés:") print(taux_erreur_singleton) #%% ## test ################################################################################################################# #%% Question 4: Reconnaissance de critiques de film, positives ou négatives, par maximum de vraisemblance avec des bigrammes ################################################################################################################### #%% on refait la même chose avec des bigrammes, en les considérant comme des mots élémentaires (même code que précédemment) words1=nltk.tokenize.word_tokenize(texte_app1) bgs_app1 = bigrams(words1) words0 = nltk.tokenize.word_tokenize(texte_app0) bgs_app0 = bigrams(words0) ## A compléter: utiliser fdist pour estimer les fréquences taux_erreur_bigramme=0 nb=0 for i in range(100): words_test = nltk.tokenize.word_tokenize(data[850+i]) bgs_test=bigrams(words_test) nb+=1 ## A compléter for i in range(100): words_test = nltk.tokenize.word_tokenize(data[1850+i]) bgs_test=bigrams(words_test) nb+=1 ## A compléter taux_erreur_bigramme=100*taux_erreur_bigramme/nb print("taux d'erreur pour les bigrammes:") print(taux_erreur_bigramme) #%% BONUS: on fait un générateur de reviews avec des bigrames, sans le stemming #accuracy = nltk.classify.util.accuracy(classifier, test_set)