ajustements #2 et début documentation
This commit is contained in:
parent
71adb32e5a
commit
c8569e54d3
2 changed files with 64 additions and 22 deletions
40
rapport.md
40
rapport.md
|
@ -1,6 +1,6 @@
|
|||
# Travail pratique 1
|
||||
|
||||
IFT7022 - Traitement automatique de la langue naturelle
|
||||
IFT7022 —Traitement automatique de la langue naturelle
|
||||
|
||||
Remis par François Pelletier
|
||||
|
||||
|
@ -8,19 +8,19 @@ Remis par François Pelletier
|
|||
|
||||
## Conversion de questions
|
||||
|
||||
L'objectif de ce problème est de convertir un ensemble de questions en affirmations à l'aide d'expressions régulières et règles de subsitution.
|
||||
L'objectif de ce problème est de convertir un ensemble de questions en affirmations à l'aide d'expressions régulières et règles de substitution.
|
||||
|
||||
Comme il est important de garder une forme la plus générale possible pour ces expressions, il est attendu à ce qu'un certain nombre de questions ne soient pas converties adéquatement. Sinon, il aurait été facile d'y aller avec une solution triviale qui associe une expression différente pour chaque question.
|
||||
|
||||
### Approche utilisée
|
||||
|
||||
L'approche utilisée a été d'identifier d'abord les mots questions, ensuite d'identifier la structure générale de la phrase, dont le verbe principal et les noms à remplacer, le cas échéant. Puis, j'ai dentifié les différents types de réponses requises, et lorsqu'un même motif de question nécessitait deux types de réponses différentes, j'ai séparé en deux expressions consécutives. Ensuite, j'ai construit quelques règles qui appliquent des corrections mineures au niveau des signes et de la ponctuation.
|
||||
L'approche utilisée a été d'identifier d'abord les mots questions, ensuite d'identifier la structure générale de la phrase, dont le verbe principal et les noms à remplacer, le cas échéant. Puis, j'ai identifié les différents types de réponses requises, et lorsqu'un même motif de question nécessitait deux types de réponses différentes, j'ai séparé en deux expressions consécutives. Ensuite, j'ai construit quelques règles qui appliquent des corrections mineures au niveau des signes et de la ponctuation.
|
||||
|
||||
Toutes ces règles sont enchaînées les unes à la suite des autres. Comme la conversion élimine le point d'interrogation à la fin de la phrase, les motifs subséquents au premier qui a donné une correspondance sont ainsi ignorés. Il n'y a donc aucun traitement conditionnel en dehors de ceux inclus dans les expressions régulières.
|
||||
Toutes ces règles sont enchainées les unes à la suite des autres. Comme la conversion élimine le point d'interrogation à la fin de la phrase, les motifs subséquents au premier qui a donné une correspondance sont ainsi ignorés. Il n'y a donc aucun traitement conditionnel en dehors de ceux inclus dans les expressions régulières.
|
||||
|
||||
### Description des motifs utilisés
|
||||
|
||||
Les motifs suivent cet ordre. Sauf indication contraire, le groupe affirmatif à convertir est située après le motif recherché:
|
||||
Les motifs suivent cet ordre. Sauf indication contraire, le groupe affirmatif à convertir est situé après le motif recherché :
|
||||
|
||||
1. Mot-question **qui**, suivi d'un verbe auxiliaire, sous forme d'énumération partielle
|
||||
1. Mot-question **qu'est-ce qu'**
|
||||
|
@ -34,11 +34,11 @@ Les motifs suivent cet ordre. Sauf indication contraire, le groupe affirmatif à
|
|||
1. Mot question **combien** suivi de **y a-t-il**. La différence ici est que la réponse conserve l'ordre de la question et qu'il faut transformer **y a-t-il** en **il y a**.
|
||||
1. Mot-question **quel** à la fin de la question. Ce motif sert à attraper une forme moins fréquente de questions où la question est posée après le groupe affirmatif.
|
||||
|
||||
Quelques modifications au niveau de la phrase viennent ensuite *nettoyer* la résultante:
|
||||
Quelques modifications au niveau de la phrase viennent ensuite *nettoyer* la résultante :
|
||||
|
||||
1. Suppression des inversions *-il*, *-elle*, *-t-il*, *-t-elle*
|
||||
1. Inversion du pronom *vous*
|
||||
1. Retrait des double espaces
|
||||
1. Retrait des doubles espaces
|
||||
1. Retrait des espaces au début de la phrase
|
||||
1. Retrait des espaces après les apostrophes
|
||||
|
||||
|
@ -46,14 +46,28 @@ Quelques modifications au niveau de la phrase viennent ensuite *nettoyer* la ré
|
|||
|
||||
#### Fichier d'entrainement
|
||||
|
||||
Sur l'ensemble des questions à convertir, quatre réponses ne correspondent pas à celles dans le fichier d'entrainement:
|
||||
Sur l'ensemble des questions à convertir, quatre réponses ne correspondent pas à celles dans le fichier d'entrainement :
|
||||
|
||||
1. *Q: Qui était Galileo?* Comme cette question correspond au motif *qui*, la réponse que le module produit est **Luc Lamontagne était Galileo.**, alors qu'elle aurait du tomber dans la catégorie *autre*. Pour ce faire, cela aurait nécessité une analyse syntaxique.
|
||||
1. *Q: A quelle distance se trouve la ligne de service du net au tennis?* Il me reste le mot distance au début de l'affirmation, que je n'arrive pas à enlever sans devoir faire une expression trop spécifique.
|
||||
1. *Q: Combien de litres dans un gallon?* C'est la seule question de cette forme où la réponse donnée est au début et non à la fin. Ma réponse est équivalente.
|
||||
1. *Q: Que fait-on avec des drapeaux usés ou périmés?* Encore une fois, c'est la seule version où la réponse est au début et non à la fin. Ma réponse est équivalente.
|
||||
1. `Q : Qui était Galileo?`
|
||||
- Comme cette question correspond au motif 1, la réponse que le module produit est **Luc Lamontagne était Galileo.**, alors qu'elle aurait du tomber dans la catégorie *autre*. Pour ce faire, cela aurait nécessité une analyse syntaxique.
|
||||
1. `Q : A quelle distance se trouve la ligne de service du net au tennis?`
|
||||
- Il me reste le mot distance au début de l'affirmation, que je n'arrive pas à enlever sans devoir faire une expression trop spécifique.
|
||||
1. `Q : Combien de litres dans un gallon?`
|
||||
- C'est la seule question de cette forme où la réponse donnée est au début et non à la fin. Ma réponse est équivalente.
|
||||
1. `Q : Que fait-on avec des drapeaux usés ou périmés?`
|
||||
- Encore une fois, c'est la seule version où la réponse est au début et non à la fin. Ma réponse est équivalente.
|
||||
|
||||
#### Fichier de test
|
||||
|
||||
## Langue d'origine du nom
|
||||
## Origine du nom de famille
|
||||
|
||||
Dans cette section, nous allons créer des modèles pour les noms de famille provenant de plusieurs origines. Nous disposons de jeux d'entrainement et de test étiquetés, ce qui nous permettra d'analyser la performance de nos différents modèles d'origine.
|
||||
|
||||
Pour chaque origine, nous allons normaliser les noms de famille en les mettant en minuscules et les convertissant en encodage ASCII. Nous allons ensuite construire des unigrammes pour chacun des noms de familles. Ceci nous permettra tout d'abord de disposer de listes de lettres au lieu de mots, ce qui facilitera la création des bigrammes et trigrammes. Celà nous permet aussi de mesurer la taille `V` du vocabulaire, soit le nombre de caractères différents, incluant un caractère virtuel pour représenter la fin de mot.
|
||||
|
||||
### Unigrammes
|
||||
|
||||
### Bigrammes
|
||||
|
||||
### Trigrammes
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@ EOS = "!" # character used to pad the end of a name
|
|||
|
||||
kgram_models = {}
|
||||
|
||||
V = 26
|
||||
|
||||
|
||||
def find_files(path):
|
||||
"""Retourne le nom des fichiers contenus dans un répertoire.
|
||||
|
@ -106,14 +108,14 @@ def train_models():
|
|||
for word in names_by_origin[origin]:
|
||||
word = normalize_word(word)
|
||||
unigrams.append(make_unigram(word))
|
||||
for k in range(1, 4):
|
||||
for k in range(1, 5):
|
||||
kgrams_origin = []
|
||||
for unigram_word in unigrams:
|
||||
kgrams_origin.append(make_kgram(unigram_word, k))
|
||||
kgram_models[(origin, k)] = make_count_dict(kgrams_origin)
|
||||
|
||||
|
||||
def most_probable_origin(name, n=3):
|
||||
def most_probable_origin(name, n=3, use_logprob=True):
|
||||
# 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...
|
||||
|
@ -129,7 +131,10 @@ def most_probable_origin(name, n=3):
|
|||
most_probable_origin_prob = max(log_prob_origin.items(), key=lambda k: k[1])[0]
|
||||
most_probable_origin_perp = min(perplexity_origin.items(), key=lambda k: k[1])[0]
|
||||
|
||||
return most_probable_origin_perp
|
||||
if use_logprob:
|
||||
return most_probable_origin_prob
|
||||
else:
|
||||
return most_probable_origin_perp
|
||||
|
||||
|
||||
def logprob(name, origin, n=3):
|
||||
|
@ -140,7 +145,6 @@ def logprob(name, origin, n=3):
|
|||
unigram_name = make_unigram(name)
|
||||
kgram_name = make_kgram(unigram_name, n)
|
||||
k_counts = kgram_models[(origin, n)]
|
||||
V = 26
|
||||
logprob_name = 0
|
||||
if n == 1:
|
||||
N = sum(k_counts.values())
|
||||
|
@ -199,7 +203,7 @@ def load_test_names(filename):
|
|||
return test_data
|
||||
|
||||
|
||||
def evaluate_models(filename, n=3):
|
||||
def evaluate_models(filename, n=3, use_logprob=True):
|
||||
"""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)
|
||||
|
@ -207,11 +211,29 @@ def evaluate_models(filename, n=3):
|
|||
# ...
|
||||
|
||||
results = {}
|
||||
compteur_succes = {}
|
||||
for org, name_list in test_data.items():
|
||||
compteur_succes[org] = {}
|
||||
results[org] = {}
|
||||
for name in name_list:
|
||||
results[org][most_probable_origin(name)] = results[org].get(most_probable_origin(name), 0) + 1
|
||||
return results
|
||||
mp_origin = most_probable_origin(name, n, use_logprob)
|
||||
results[org][mp_origin] = results[org].get(mp_origin, 0) + 1
|
||||
if org == mp_origin:
|
||||
compteur_succes[org]["succes"] = compteur_succes[org].get("succes", 0) + 1
|
||||
else:
|
||||
compteur_succes[org]["echec"] = compteur_succes[org].get("echec", 0) + 1
|
||||
return results, compteur_succes
|
||||
|
||||
|
||||
def compute_v():
|
||||
global V
|
||||
vocab = {}
|
||||
for origin in all_origins:
|
||||
modele_courant = kgram_models[(origin, 1)]
|
||||
for k in modele_courant.keys():
|
||||
vocab[k] = vocab.get(k, 0) + modele_courant.get(k, 0)
|
||||
V = len(vocab.keys()) + 1
|
||||
print("la valeur de V est "+str(V))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -223,6 +245,7 @@ if __name__ == '__main__':
|
|||
print(names_by_origin["Chinese"])
|
||||
|
||||
train_models()
|
||||
compute_v()
|
||||
some_name = "Lamontagne"
|
||||
some_origin = most_probable_origin(some_name)
|
||||
some_logprob = logprob(some_name, some_origin)
|
||||
|
@ -235,5 +258,10 @@ if __name__ == '__main__':
|
|||
# print("\nLes données pour tester vos modèles sont:")
|
||||
# for org, name_list in test_names.items():
|
||||
# print("\t", org, name_list)
|
||||
res = evaluate_models(test_filename, 3)
|
||||
pprint.pprint(res)
|
||||
n = 1
|
||||
res_logprob, succ_logprob = evaluate_models(test_filename, n, True)
|
||||
res_perp, succ_perp = evaluate_models(test_filename, n, False)
|
||||
print("Avec logprob:\n")
|
||||
pprint.pprint(succ_logprob)
|
||||
print("Avec perplexité:\n")
|
||||
pprint.pprint(succ_perp)
|
||||
|
|
Loading…
Add table
Reference in a new issue