exercice 1 code fonctionnel 35/40

This commit is contained in:
Francois Pelletier 2019-09-20 23:44:03 -04:00
commit f2a4afbbb0
4 changed files with 319 additions and 0 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
.idea/
data/
t1_results.txt

149
t1_conversion_questions.py Normal file
View file

@ -0,0 +1,149 @@
# -*- coding: utf-8 -*-
import re
questions_fn = "./data/questions-t1.txt"
results_filename = "./t1_results.txt"
# Mettre dans cette partie les expressions régulières
# que vous utilisez pour analyser les questions
# et en faire la conversion en affirmations
#
# Vos regex...
#
def run_task1(filename):
questions = load_questions(filename)
results = convert_all_questions(questions)
save_results(results)
def convert_all_questions(questions):
results = []
for question in questions:
sentence = convert(question)
results.append((question, sentence))
return results
def load_questions(filename):
with open(filename, 'r', encoding='utf-8') as f:
raw_questions = f.readlines()
questions = [x.strip() for x in raw_questions]
return questions
def convert(question):
# Insérer ici votre code pour le traitement des questions et leur conversion.
# Vous pouvez ajouter autant de fonctions que vous souhaitez.
# Voir fichier data/results-reference-t1.txt pour des exemples de conversion.
#
# IMPORTANT : Ne pas modifier les autres fonctions existantes de ce fichier
# afin de faciliter mon travail de correction.
# En cas de doute, me consulter.
# Votre code...
regex_qui = re.compile(r"(qui)\s"
r"(est|sont|était|étaient|sera|seront|a\s\w+|ont\s\w+)\s"
r"(.*)\?",
re.IGNORECASE)
modif1 = re.sub(regex_qui,
r"Luc Lamontagne \2 \3.",
question)
regex_questce = re.compile(r"(qu'est-ce\squ[ie'])\s?"
r"(.*)\?",
re.IGNORECASE)
modif2 = re.sub(regex_questce, r"\2 est X.", modif1)
regex_quesont = re.compile(r"(qu[e'])\s"
r"(est|sont|signifie|fait)-?(on)?"
r"(.*)\?",
re.IGNORECASE)
modif3 = re.sub(regex_quesont,
r"\4 \3 \2 X.",
modif2)
regex_ou = re.compile(r"((dans\squel(le)?\s(ville|région|pays))|où)\s"
r"(est|sont)\s"
r"(.*)\?",
re.IGNORECASE)
regex_capitale = re.compile(r"(quelle)(\sest\sla\scapitale)", re.IGNORECASE)
modif4 = re.sub(regex_ou,
r"\6 \5 à Québec.",
re.sub(regex_capitale,
r"\2", modif3))
regex_mesure = re.compile(r"([aà]\s)?quelle\s"
r"(est\s)?"
r"(l[a']\s?)?"
r"(hauteur|température|vitesse|distance|espérance\sde\svie)\s"
r"(.*)\?",
re.IGNORECASE)
modif5 = re.sub(regex_mesure,
r"\3 \4 \5 \2 1000.",
modif4)
regex_quelle_est = re.compile(r"quel[les]*\s(.*)(est|sont)\s(.*)\?",
re.IGNORECASE)
modif6 = re.sub(regex_quelle_est, r"\1\3 \2 X.", modif5)
regex_quand = re.compile(r"(quand|en\squelle\sannée)\s(.*)\?",
re.IGNORECASE)
modif7 = re.sub(regex_quand,
r"\2 en 2000.",
modif6)
regex_pourquoi = re.compile(r"pourquoi\s(.*)\?",
re.IGNORECASE)
modif8 = re.sub(regex_pourquoi,
r"\1 parce que X.",
modif7)
regex_combien1 = re.compile(r"combien\sde\s(\w+)(.*)\?",
re.IGNORECASE)
modif9 = re.sub(regex_combien1,
r"\2 1000 \1.",
modif8)
regex_combien2 = re.compile(r"combien\s(y\sa-t-il)?\s?de(.*)\?",
re.IGNORECASE)
modif10 = re.sub(r"\by\sa-t-il",
r"il y a",
re.sub(regex_combien2,
r"\1 1000 \2.",
modif9))
regex_quelle_fin = re.compile(r"(.*?)(qu\w+)\s(\w+)\?",
re.IGNORECASE)
modif11 = re.sub(regex_quelle_fin,
r"\1 \3 X.",
modif10)
# Modifications non liées aux mots
modif12 = re.sub(r"(\w+)(-t)?-(il|elle)", r"\1", modif11)
modif12 = re.sub(r"(\w+)(-t)?-(vous)", r"\3 \1", modif12)
modif12 = re.sub(r"\s{2,}", " ", modif12)
modif12 = re.sub(r"^\s", "", modif12)
modif12 = re.sub(r"\'\s", "'", modif12)
if question != modif11:
return modif12
else:
return "la terre est ronde."
def save_results(results):
with open(results_filename, 'w') as output_file:
for question, sentence in results:
output_file.write("Q: " + question + "\n")
output_file.write("A: " + sentence + "\n")
output_file.write("\n")
if __name__ == '__main__':
# Vous pouvez modifier cette section
print("Conversion des questions du fichier {} ".format(questions_fn))
run_task1(questions_fn)
print("Conversion complétée")

129
t2_classification_noms.py Normal file
View file

@ -0,0 +1,129 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import glob
import os
import string
import unicodedata
import json
datafiles = "./data/names/*.txt" # les fichiers pour construire vos modèles
test_filename = './data/test-names-t2.txt' # le fichier contenant les données de test pour évaluer vos modèles
names_by_origin = {} # un dictionnaire qui contient une liste de noms pour chaque langue d'origine
all_origins = [] # la liste des 18 langues d'origines de noms
BOS = "~" # character used to pad the beginning of a name
EOS = "!" # character used to pad the end of a name
def find_files(path):
"""Retourne le nom des fichiers contenus dans un répertoire.
glob fait le matching du nom de fichier avec un pattern - par ex. *.txt"""
return glob.glob(path)
def get_origin_from_filename(filename):
"""Passe-passe qui retourne la langue d'origine d'un nom de fichier.
Par ex. cette fonction retourne Arabic pour "./data/names/Arabic.txt". """
return os.path.splitext(os.path.basename(filename))[0]
def unicode_to_ascii(s):
"""Convertion des caractères spéciaux en ascii. Par exemple, Hélène devient Helene.
Tiré d'un exemple de Pytorch. """
all_letters = string.ascii_letters + " .,;'"
return ''.join(
c for c in unicodedata.normalize('NFD', s)
if unicodedata.category(c) != 'Mn'
and c in all_letters
)
def read_names(filename):
"""Retourne une liste de tous les noms contenus dans un fichier."""
with open(filename, encoding='utf-8') as f:
names = f.read().strip().split('\n')
return [unicode_to_ascii(name) for name in names]
def load_names():
"""Lecture des noms et langues d'origine d'un fichier. Par la suite,
sauvegarde des noms pour chaque origine dans le dictionnaire names_by_origin."""
for filename in find_files(datafiles):
origin = get_origin_from_filename(filename)
all_origins.append(origin)
names = read_names(filename)
names_by_origin[origin] = names
def train_models():
load_names()
# Vous ajoutez à partir d'ici tout le code dont vous avez besoin
# pour construire vos modèles N-grammes pour chacune des langues d'origines.
#
# Vous pouvez ajouter au fichier toutes les fonctions que vous jugerez nécessaire.
# Merci de ne pas modifier les fonctions présentes dans ce fichier.
#
# À compléter - Fonction pour la construction des modèles unigrammes, bigrammes et trigrammes.
#
# Votre code à partir d'ici...
def most_probable_origin(name, n=3):
# Retourne la langue d'origine la plus probable du nom.
# n désigne la longueur des N-grammes. Par ex n=3 --> trigramme
# À compléter...
return "French" # À modifier
def logprob(name, origin, n=3):
# Retourne la valeur du logprob d'un nom étant donné une origine
# Utilisez une fonction logarithme en base 2.
# À compléter...
return -35.6 # À modifier
def perplexity(name, origin, n=3):
# Retourne la valeur de perplexité d'un nom étant donné une origine
# À compléter...
return 7.8 # À modifier
def load_test_names(filename):
"""Retourne un dictionnaire contenant les données à utiliser pour évaluer vos modèles.
Le dictionnaire contient une liste de noms (valeurs) et leur origine (clé)."""
with open(filename, 'r') as fp:
test_data = json.load(fp)
return test_data
def evaluate_models(filename, n=3):
"""Fonction utilitaire pour évaluer vos modèles. Aucune contrainte particulière.
Je n'utiliserai pas cette fonction pour l'évaluation de votre travail. """
test_data = load_test_names(filename)
# À compléter - Fonction pour l'évaluation des modèles N-grammes.
# ...
if __name__ == '__main__':
# Vous pouvez modifier cette section comme bon vous semble
load_names()
print("Les {} langues d'origine sont:".format(len(all_origins)))
print(all_origins)
print("Les noms chinois sont:")
print(names_by_origin["Chinese"])
train_models()
some_name = "Lamontagne"
some_origin = most_probable_origin(some_name)
logprob = logprob(some_name, some_origin)
perplexity = perplexity(some_name, some_origin)
print("\nLangue d'origine de {}: ".format(some_name), some_origin)
print("logprob({}, {}):".format(some_name, some_origin), logprob)
print("perplexity({}, {}):".format(some_name, some_origin), perplexity)
test_names = load_test_names(test_filename)
print("\nLes données pour tester vos modèles sont:")
for org, name_list in test_names.items():
print("\t", org, name_list)
evaluate_models(test_filename, 3)

View file

@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
training_questions_fn = "./data/questions-t3.txt"
test_questions_fn = "./data/test-questions-t3.txt"
def run_question_classification(training_fn, test_fn):
accuracy_train, accuracy_test = train_and_test_classifier(training_fn, test_fn)
print("Accuracy on training set: {0:.4f}".format(accuracy_train))
print("Accuracy on test set: {0:.4f}".format(accuracy_test))
def train_and_test_classifier(training_fn, test_fn):
questions, labels = load_dataset(training_fn)
print("Nb questions d'entraînement:", len(questions))
test_questions, test_labels = load_dataset(test_fn)
print("Nb questions de test:", len(test_questions))
# Insérer ici votre code pour la classification des questions.
# Votre code...
accuracy_train = 0.8 # A modifier
accuracy_test = 0.8 # A modifier
return accuracy_train, accuracy_test
def load_dataset(filename):
with open(filename) as f:
lines = f.read().splitlines()
labels, questions = zip(*[tuple(s.split(' ', 1)) for s in lines])
return questions, labels
if __name__ == '__main__':
run_question_classification(training_questions_fn, test_questions_fn)