-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.py
executable file
·162 lines (144 loc) · 8.06 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#! /usr/bin/env python
# coding:utf-8
# Prérequis :
# pip install Cython word2vec
# auteurs
# Marine Courtin (Université Paris Sorbonne Nouvelle)
# Luigi Liu (Université Paris Nanterre, MoDyCo)
# todos :
# 2. élaborer un test des hyperparamètres F, CIBLE_INCLUSES pour avoir un premier bilan -> utiliser la méthode grid search ?
# L -> c'est-à-dire ? itérer sur une double boucle avec (F,CIBLE_INCLUSES) dans toutes les valeurs pertinentes ?
# M -> il me semble qu'il y a une fonction qui existe pour ça : from sklearn.grid_search import ParameterGrid +
# on a aussi l'air de pouvoir trouver automatiquement la combinaison de cesparamètres qui maximise le score,
# je ne sais pas si tu as déjà utilisé ça : http://scikit-learn.sourceforge.net/stable/modules/generated/sklearn.grid_search.GridSearchCV.html#sklearn.grid_search.GridSearchCV
# L -> ça peut être utile : deux limites, tout de même.
# 1. dépendence de la bibliothéque sklearn
# 2. on veux aussi observer la courbe score(F,CIBLE_INCLUSE) pour mieux comprendre la tâche
# le code a été refactorisé pour que tu puisses appliquer plus facilement gridsearch -> donc, allez y !
#
# 3. pondérer les vecteurs par les poids obtenus par la TF-IDF sur un corpus de français
# 4. introduire 2-ème solution sur FREDIST : (Henestroza Anguiano & Denis, 2011) : les plus proches voisins sont déjà
# calculés, téléchargeable ici : https://gforge.inria.fr/projects/fredist/
# 7. rapport écrit suivant la consigne :
# Vous ferez un petit rapport réexpliquant la tâche, la méthode, et commentant vos résultats.
# Votre programme doit contenir une aide en ligne (l’option –h doit indiquer comment utiliser le
# programme).
# 8. Toute idée d’amélioration est la bienvenue
# 9. (implémentation facultative) repas au Crous
# références :
# [1] Melamud, O., Levy, O., Dagan, I., & Ramat-Gan, I. (2015, June). A Simple Word Embedding Model for Lexical Substitution. In VS@ HLT-NAACL (pp. 1-7).
# [2] Desalle, Y., Navarro, E., Chudy, Y., Magistry, P., & Gaume, B. (2014). BACANAL: Balades Aléatoires Courtes pour ANAlyses Lexicales Application à la substitution lexicale. In TALN-20 2014: Atelier SEMDIS.
#
# proposition
# la somme des vecteurs de mot dans le contexte plein semble faire perdre
# plus d'informations qu'elle permet d'agréer. nous proposons de ne pas sommer
# les vecteurs, mais conisdérer les vecteurs du contexte plein comme un ensemble
# de coordonnées qui permettent de localiser le bon mot cible
#
# note : si nous voulons traiter les vecteurs de mots dans le contexte plein comme
# des coordonnées -> Algorithme de Gram-Schmidt est utile pour trouver
# les coordonnées de bonne formation (Algèbre linéaire)
#
# soit les vecteurs du mots pleins dans le contexte v_x1, v_x2, ..., v_xn,
# vx_i : i-ème vecteur du contexte plein, i in [1,n], x pour noter conte'x'te
# vc : vecteur du mot cible
# nous définissions un pi comme le produit scalaire entre v_xi et vc
# pi := produit_scalair(v_xi, vc)
# P = [p1,p2,...,pN] est une liste d'inicateur de longueur N
# qi := produit_scalaire(v_xi, vy)
# Q = [q1,q2,...,qN]
# vy est un vecteur de mot dans le vocabualaire
#
# la nouvelle mesure de sililarité comme
# A. produit_scalaire(P,Q) version non-normalisée
# B. produit_scalaire(P,Q) version normalisée
#
# reférence : idée est proche du "match filter" dans le domaine du traitement du signal
import argparse, word2vec, sys, numpy, codecs
import semdis_eval
from lexsub import *
# VARIABLES GLOBALES
n_candidats = 10
F_max = 10
OVER_SAMPLING = 2
if __name__ == '__main__' :
parser = argparse.ArgumentParser(description='Analyse sémantique TP-1 : substitution lexicale')
parser.add_argument('infile', type=str, help='fichier de données de test : mots cibles et leurs contextes')
parser.add_argument('resfile', type=str, help='fichier des vecteurs de mot pré-générés via word2vec')
parser.add_argument('goldfile', type=str, help='fichier de réponse gold')
parser.add_argument('-o','--outfile', type=str, help='fichier de réponse en sortie',default = 'tmp')
parser.add_argument('-v','--verbose', help='voir des détails en temps réel', action="store_true")
parser.add_argument('-r','--restype', type=int, help="le type de ressource lexciale employée : 0 pour FRWAC (par défault), 1 pour FRDIC, 2 pour HYBRIDE", default = 0) #ajout d'un 3eme mode d'utilisation des ressources
args = parser.parse_args()
if args.verbose :
print (args)
# chargement des ressources lexicales
model = word2vec.load(args.resfile)
with codecs.open(args.infile, encoding = 'utf-8') as f :
for CIBLE_INCLUSE in [False, True] :
for F in range(0, F_max) :
if not F and not CIBLE_INCLUSE : continue
with codecs.open(args.outfile, 'w', encoding = 'utf-8') as fout :
for line in f :
# lecture des colonnes de fichier
id, c, c_pos, c_position, sentence = line.split(u'\t')
tokens = [t.split(u'/') for t in sentence.split()]
# géneration des substituts potentiels
if args.restype == 1:
candidats = generateSubstitutes(c, c_pos, n_candidats)
elif args.restype == 2:
# on prend les 100 premiers résultats dans FREDIST comme substituts potentiels
# nb de substituts choisi arbitraire
candidats = generateSubstitutes(c, c_pos, 100)
try:
candidats = [candidat+"_"+c_pos for candidat in candidats]
except TypeError: #cible pas dans FREDIST, on retombe sur r = 0
candidats, scores = \
generateSubstitutes_w2v(model, c, c_pos, OVER_SAMPLING * n_candidats)
# préparation et nettoyage du contexte plein
c_position_new, tokens_full = rm_stopword_from_tokens(tokens, cat_full, c_position)
overwindowing,CTX = windowing (tokens_full, c_position_new, F, CIBLE_INCLUSE)
CTX = clean_ctx(CTX)
Z = continous_bag_words(model, CTX)
# ordonnancement de la liste des substituts proposés par le contexte
candidats, scores = sort_response(model, candidats, Z)
candidats = candidats[0:n_candidats]
else:
# print(candidats)
candidats, scores = \
generateSubstitutes_hybrid(model, c, c_pos, candidats, OVER_SAMPLING * n_candidats)
# TO ADD
# utilisation des candidats pour chercher la similarite cosinus entre la cible et
# les candidats en utilisant les vecteurs obtenus avec word2vec et pre-entraines par J.P Fauconnier
# préparation et nettoyage du contexte plein
c_position_new, tokens_full = rm_stopword_from_tokens(tokens, cat_full, c_position)
overwindowing,CTX = windowing (tokens_full, c_position_new, F, CIBLE_INCLUSE)
CTX = clean_ctx(CTX)
Z = continous_bag_words(model, CTX)
# ordonnancement de la liste des substituts proposés par le contexte
candidats, scores = sort_response(model, candidats, Z)
candidats = candidats[0:n_candidats]
else :
candidats, scores = \
generateSubstitutes_w2v(model, c, c_pos, OVER_SAMPLING * n_candidats)
# préparation et nettoyage du contexte plein
c_position_new, tokens_full = rm_stopword_from_tokens(tokens, cat_full, c_position)
overwindowing,CTX = windowing (tokens_full, c_position_new, F, CIBLE_INCLUSE)
CTX = clean_ctx(CTX)
Z = continous_bag_words(model, CTX)
# ordonnancement de la liste des substituts proposés par le contexte
candidats, scores = sort_response(model, candidats, Z)
candidats = candidats[0:n_candidats]
# sorties
if args.verbose and not args.restype :
show_infobox (id, c, c_pos, c_position, sentence, F, CIBLE_INCLUSE, CTX)
if candidats :
export_substituants (id, c, c_pos, candidats, fout)
f.seek(0)
# évaluation
print (u'(F, CIBLE_INCLUSE) = ({}, {})'.format(F, CIBLE_INCLUSE))
s = semdis_eval.SemdisEvaluation(args.goldfile)
s.evaluate(args.outfile, metric = 'all', normalize = True)
# pour le moment la solution basée sur FRDIC n'emploie pas le contexte
# pas intéressant de boucler avec (F, CIBLE_INCLUSE) différents
if args.restype : exit()