exercice 1 code fonctionnel 35/40
This commit is contained in:
commit
f2a4afbbb0
4 changed files with 319 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
.idea/
|
||||
data/
|
||||
t1_results.txt
|
149
t1_conversion_questions.py
Normal file
149
t1_conversion_questions.py
Normal 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"où\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
129
t2_classification_noms.py
Normal 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)
|
38
t3_classification_questions.py
Normal file
38
t3_classification_questions.py
Normal 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)
|
Loading…
Add table
Reference in a new issue