Demosthene-OR
commited on
Commit
•
babcb18
1
Parent(s):
95043cb
Add
Browse files- app.py +35 -13
- tabs/data_viz_tab.py +42 -37
- tabs/exploration_tab.py +98 -100
- tabs/game_tab.py +43 -22
- tabs/id_lang_tab.py +102 -72
- tabs/intro.py +48 -20
- tabs/modelisation_dict_tab.py +182 -168
- tabs/modelisation_seq2seq_tab.py +94 -96
- translate_app.py +18 -0
app.py
CHANGED
@@ -5,8 +5,8 @@ from streamlit_option_menu import option_menu
|
|
5 |
# Define TITLE, TEAM_MEMBERS and PROMOTION values, in config.py.
|
6 |
import config
|
7 |
from tabs.custom_vectorizer import custom_tokenizer, custom_preprocessor
|
8 |
-
|
9 |
-
|
10 |
|
11 |
# Initialize a session state variable that tracks the sidebar state (either 'expanded' or 'collapsed').
|
12 |
if 'sidebar_state' not in st.session_state:
|
@@ -20,10 +20,23 @@ st.set_page_config (
|
|
20 |
initial_sidebar_state=st.session_state.sidebar_state
|
21 |
)
|
22 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
# Define the root folders depending on local/cloud run
|
24 |
thisfile = os.path.abspath(__file__)
|
|
|
25 |
if ('/' in thisfile):
|
26 |
os.chdir(os.path.dirname(thisfile))
|
|
|
27 |
|
28 |
# Nécessaire pour la version windows 11
|
29 |
os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'python'
|
@@ -43,20 +56,27 @@ st.markdown(f"<style>{style}</style>", unsafe_allow_html=True)
|
|
43 |
# as value as follow :
|
44 |
TABS = OrderedDict(
|
45 |
[
|
46 |
-
(intro.sidebar_name, intro),
|
47 |
-
(exploration_tab.sidebar_name, exploration_tab),
|
48 |
-
(data_viz_tab.sidebar_name, data_viz_tab),
|
49 |
-
(id_lang_tab.sidebar_name, id_lang_tab),
|
50 |
-
(modelisation_dict_tab.sidebar_name, modelisation_dict_tab),
|
51 |
-
(modelisation_seq2seq_tab.sidebar_name, modelisation_seq2seq_tab),
|
52 |
-
(game_tab.sidebar_name, game_tab ),
|
53 |
]
|
54 |
)
|
55 |
|
56 |
|
57 |
-
|
|
|
|
|
|
|
|
|
58 |
global lang_tgt, label_lang
|
59 |
-
|
|
|
|
|
|
|
60 |
st.sidebar.image(
|
61 |
"assets/demosthene_logo.png",
|
62 |
width=270,
|
@@ -64,7 +84,7 @@ def run():
|
|
64 |
with st.sidebar:
|
65 |
tab_name = option_menu(None, list(TABS.keys()),
|
66 |
# icons=['house', 'bi-binoculars', 'bi bi-graph-up', 'bi-chat-right-text','bi-book', 'bi-body-text'], menu_icon="cast", default_index=0,
|
67 |
-
icons=['house', 'binoculars', 'graph-up', 'search','book', 'chat-right-text',
|
68 |
styles={"container": {"padding": "0!important","background-color": "#10b8dd", "border-radius": "0!important"},
|
69 |
"nav-link": {"font-size": "1rem", "text-align": "left", "margin":"0em", "padding": "0em",
|
70 |
"padding-left": "0.2em", "--hover-color": "#eee", "font-weight": "400",
|
@@ -78,9 +98,11 @@ def run():
|
|
78 |
for member in config.TEAM_MEMBERS:
|
79 |
st.sidebar.markdown(member.sidebar_markdown(), unsafe_allow_html=True)
|
80 |
|
|
|
|
|
|
|
81 |
tab = TABS[tab_name]
|
82 |
tab.run()
|
83 |
|
84 |
-
|
85 |
if __name__ == "__main__":
|
86 |
run()
|
|
|
5 |
# Define TITLE, TEAM_MEMBERS and PROMOTION values, in config.py.
|
6 |
import config
|
7 |
from tabs.custom_vectorizer import custom_tokenizer, custom_preprocessor
|
8 |
+
import os
|
9 |
+
from translate_app import tr
|
10 |
|
11 |
# Initialize a session state variable that tracks the sidebar state (either 'expanded' or 'collapsed').
|
12 |
if 'sidebar_state' not in st.session_state:
|
|
|
20 |
initial_sidebar_state=st.session_state.sidebar_state
|
21 |
)
|
22 |
|
23 |
+
# Si l'application tourne localement, session_state.Cloud == 0
|
24 |
+
# Si elle tourne sur le Cloud de Hugging Face, ==1
|
25 |
+
st.session_state.Cloud = 1
|
26 |
+
# En fonction de la valeur de varible précédente, le data path est différent
|
27 |
+
if st.session_state.Cloud == 0:
|
28 |
+
st.session_state.DataPath = "../data"
|
29 |
+
st.session_state.reCalcule = False
|
30 |
+
else:
|
31 |
+
st.session_state.DataPath = "data"
|
32 |
+
st.session_state.reCalcule = False
|
33 |
+
|
34 |
# Define the root folders depending on local/cloud run
|
35 |
thisfile = os.path.abspath(__file__)
|
36 |
+
print("Path before:",os.path.abspath(__file__))
|
37 |
if ('/' in thisfile):
|
38 |
os.chdir(os.path.dirname(thisfile))
|
39 |
+
print("Path after:",os.path.abspath(__file__))
|
40 |
|
41 |
# Nécessaire pour la version windows 11
|
42 |
os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'python'
|
|
|
56 |
# as value as follow :
|
57 |
TABS = OrderedDict(
|
58 |
[
|
59 |
+
(tr(intro.sidebar_name), intro),
|
60 |
+
(tr(exploration_tab.sidebar_name), exploration_tab),
|
61 |
+
(tr(data_viz_tab.sidebar_name), data_viz_tab),
|
62 |
+
(tr(id_lang_tab.sidebar_name), id_lang_tab),
|
63 |
+
(tr(modelisation_dict_tab.sidebar_name), modelisation_dict_tab),
|
64 |
+
(tr(modelisation_seq2seq_tab.sidebar_name), modelisation_seq2seq_tab),
|
65 |
+
(tr(game_tab.sidebar_name), game_tab ),
|
66 |
]
|
67 |
)
|
68 |
|
69 |
|
70 |
+
lang_tgt = ['fr','en','af','ak','sq','de','am','en','ar','hy','as','az','ba','bm','eu','bn','be','my','bs','bg','ks','ca','ny','zh','si','ko','co','ht','hr','da','dz','gd','es','eo','et','ee','fo','fj','fi','fr','fy','gl','cy','lg','ka','el','gn','gu','ha','he','hi','hu','ig','id','iu','ga','is','it','ja','kn','kk','km','ki','rw','ky','rn','ku','lo','la','lv','li','ln','lt','lb','mk','ms','ml','dv','mg','mt','mi','mr','mn','nl','ne','no','nb','nn','oc','or','ug','ur','uz','ps','pa','fa','pl','pt','ro','ru','sm','sg','sa','sc','sr','sn','sd','sk','sl','so','st','su','sv','sw','ss','tg','tl','ty','ta','tt','cs','te','th','bo','ti','to','ts','tn','tr','tk','tw','uk','vi','wo','xh','yi']
|
71 |
+
label_lang = ['Français', 'Anglais','Afrikaans','Akan','Albanais','Allemand','Amharique','Anglais','Arabe','Arménien','Assamais','Azéri','Bachkir','Bambara','Basque','Bengali','Biélorusse','Birman','Bosnien','Bulgare','Cachemiri','Catalan','Chichewa','Chinois','Cingalais','Coréen','Corse','Créolehaïtien','Croate','Danois','Dzongkha','Écossais','Espagnol','Espéranto','Estonien','Ewe','Féroïen','Fidjien','Finnois','Français','Frisonoccidental','Galicien','Gallois','Ganda','Géorgien','Grecmoderne','Guarani','Gujarati','Haoussa','Hébreu','Hindi','Hongrois','Igbo','Indonésien','Inuktitut','Irlandais','Islandais','Italien','Japonais','Kannada','Kazakh','Khmer','Kikuyu','Kinyarwanda','Kirghiz','Kirundi','Kurde','Lao','Latin','Letton','Limbourgeois','Lingala','Lituanien','Luxembourgeois','Macédonien','Malais','Malayalam','Maldivien','Malgache','Maltais','MaorideNouvelle-Zélande','Marathi','Mongol','Néerlandais','Népalais','Norvégien','Norvégienbokmål','Norvégiennynorsk','Occitan','Oriya','Ouïghour','Ourdou','Ouzbek','Pachto','Pendjabi','Persan','Polonais','Portugais','Roumain','Russe','Samoan','Sango','Sanskrit','Sarde','Serbe','Shona','Sindhi','Slovaque','Slovène','Somali','SothoduSud','Soundanais','Suédois','Swahili','Swati','Tadjik','Tagalog','Tahitien','Tamoul','Tatar','Tchèque','Télougou','Thaï','Tibétain','Tigrigna','Tongien','Tsonga','Tswana','Turc','Turkmène','Twi','Ukrainien','Vietnamien','Wolof','Xhosa','Yiddish']
|
72 |
+
|
73 |
+
@st.cache_data
|
74 |
+
def find_lang_label(lang_sel):
|
75 |
global lang_tgt, label_lang
|
76 |
+
return label_lang[lang_tgt.index(lang_sel)]
|
77 |
+
|
78 |
+
def run():
|
79 |
+
|
80 |
st.sidebar.image(
|
81 |
"assets/demosthene_logo.png",
|
82 |
width=270,
|
|
|
84 |
with st.sidebar:
|
85 |
tab_name = option_menu(None, list(TABS.keys()),
|
86 |
# icons=['house', 'bi-binoculars', 'bi bi-graph-up', 'bi-chat-right-text','bi-book', 'bi-body-text'], menu_icon="cast", default_index=0,
|
87 |
+
icons=['house', 'binoculars', 'graph-up', 'search','book', 'chat-right-text','controller'], menu_icon="cast", default_index=0,
|
88 |
styles={"container": {"padding": "0!important","background-color": "#10b8dd", "border-radius": "0!important"},
|
89 |
"nav-link": {"font-size": "1rem", "text-align": "left", "margin":"0em", "padding": "0em",
|
90 |
"padding-left": "0.2em", "--hover-color": "#eee", "font-weight": "400",
|
|
|
98 |
for member in config.TEAM_MEMBERS:
|
99 |
st.sidebar.markdown(member.sidebar_markdown(), unsafe_allow_html=True)
|
100 |
|
101 |
+
with st.sidebar:
|
102 |
+
st.selectbox("langue:",lang_tgt, format_func = find_lang_label, key="Language", label_visibility="hidden")
|
103 |
+
|
104 |
tab = TABS[tab_name]
|
105 |
tab.run()
|
106 |
|
|
|
107 |
if __name__ == "__main__":
|
108 |
run()
|
tabs/data_viz_tab.py
CHANGED
@@ -17,10 +17,11 @@ from gensim import corpora
|
|
17 |
import networkx as nx
|
18 |
from sklearn.manifold import TSNE
|
19 |
from gensim.models import KeyedVectors
|
20 |
-
|
21 |
|
22 |
title = "Data Vizualization"
|
23 |
sidebar_name = "Data Vizualization"
|
|
|
24 |
|
25 |
with contextlib.redirect_stdout(open(os.devnull, "w")):
|
26 |
nltk.download('stopwords')
|
@@ -34,7 +35,7 @@ if ((first_line+max_lines)>137860):
|
|
34 |
# Nombre maximum de ligne à afficher pour les DataFrame
|
35 |
max_lines_to_display = 50
|
36 |
|
37 |
-
@st.cache_data
|
38 |
def load_data(path):
|
39 |
|
40 |
input_file = os.path.join(path)
|
@@ -47,7 +48,7 @@ def load_data(path):
|
|
47 |
data = data.split('\n')
|
48 |
return data[first_line:min(len(data),first_line+max_lines)]
|
49 |
|
50 |
-
@st.cache_data
|
51 |
def load_preprocessed_data(path,data_type):
|
52 |
|
53 |
input_file = os.path.join(path)
|
@@ -68,14 +69,14 @@ def load_preprocessed_data(path,data_type):
|
|
68 |
data=data2
|
69 |
return data
|
70 |
|
71 |
-
@st.cache_data
|
72 |
def load_all_preprocessed_data(lang):
|
73 |
-
txt =load_preprocessed_data('
|
74 |
-
corpus =load_preprocessed_data('
|
75 |
-
txt_split = load_preprocessed_data('
|
76 |
-
df_count_word = pd.concat([load_preprocessed_data('
|
77 |
-
sent_len =load_preprocessed_data('
|
78 |
-
vec_model= KeyedVectors.load_word2vec_format('
|
79 |
return txt, corpus, txt_split, df_count_word,sent_len, vec_model
|
80 |
|
81 |
#Chargement des textes complet dans les 2 langues
|
@@ -92,7 +93,7 @@ def plot_word_cloud(text, title, masque, stop_words, background_color = "white")
|
|
92 |
max_font_size=50, random_state=42)
|
93 |
# Générer et afficher le nuage de mots
|
94 |
fig=plt.figure(figsize= (20,10))
|
95 |
-
plt.title(title, fontsize=25, color="green")
|
96 |
wc.generate(text)
|
97 |
|
98 |
# getting current axes
|
@@ -130,7 +131,7 @@ def dist_frequence_mots(df_count_word):
|
|
130 |
|
131 |
sns.set()
|
132 |
fig = plt.figure() #figsize=(4,4)
|
133 |
-
plt.title("Nombre d'apparitions des mots", fontsize=16)
|
134 |
|
135 |
chart = sns.barplot(x='mots',y='occurences',data=nb_occurences.iloc[:40]);
|
136 |
chart.set_xticklabels(chart.get_xticklabels(), rotation=45, horizontalalignment='right', size=8)
|
@@ -174,7 +175,7 @@ def dist_longueur_phrase(sent_len,sent_len2, lang1, lang2 ):
|
|
174 |
chart = sns.histplot(df, color=['r','b'], label=[lang1,lang2], binwidth=1, binrange=[2,22], element="step",
|
175 |
common_norm=False, multiple="layer", discrete=True, stat='proportion')
|
176 |
plt.xticks([2,4,6,8,10,12,14,16,18,20,22])
|
177 |
-
chart.set(title='Distribution du nombre de mots sur '+str(len(sent_len))+' phrase(s)');
|
178 |
st.pyplot(fig)
|
179 |
|
180 |
'''
|
@@ -245,8 +246,8 @@ def proximite():
|
|
245 |
labels = []
|
246 |
tokens = []
|
247 |
|
248 |
-
nb_words = st.slider('Nombre de mots à afficher :',10,50, value=20)
|
249 |
-
df = pd.read_csv('data/dict_we_en_fr',header=0,index_col=0, encoding ="utf-8", keep_default_na=False)
|
250 |
words_en = df.index.to_list()[:nb_words]
|
251 |
words_fr = df['Francais'].to_list()[:nb_words]
|
252 |
|
@@ -280,7 +281,7 @@ def proximite():
|
|
280 |
va='bottom',
|
281 |
color= color,
|
282 |
size=20)
|
283 |
-
plt.title("Proximité des mots anglais avec leur traduction", fontsize=30, color="green")
|
284 |
plt.legend(loc='best');
|
285 |
st.pyplot(fig)
|
286 |
|
@@ -292,13 +293,13 @@ def run():
|
|
292 |
global full_txt_fr, full_corpus_fr, full_txt_split_fr, full_df_count_word_fr,full_sent_len_fr, vec_model_fr
|
293 |
|
294 |
st.write("")
|
295 |
-
st.title(title)
|
296 |
|
297 |
#
|
298 |
-
st.write("## **Paramètres :**\n")
|
299 |
-
Langue = st.radio('Langue:',('Anglais','Français'), horizontal=True)
|
300 |
-
first_line = st.slider('No de la premiere ligne à analyser :',0,137859)
|
301 |
-
max_lines = st.select_slider('Nombre de lignes à analyser :',
|
302 |
options=[1,5,10,15,100, 500, 1000,'Max'])
|
303 |
if max_lines=='Max':
|
304 |
max_lines=137860
|
@@ -328,74 +329,78 @@ def run():
|
|
328 |
st.dataframe(pd.DataFrame(data=full_txt_fr,columns=['Texte']).loc[first_line:last_line-1].head(max_lines_to_display), width=800)
|
329 |
st.write("")
|
330 |
|
331 |
-
tab1, tab2, tab3, tab4, tab5 = st.tabs(["World Cloud", "Frequence","Distribution longueur", "Co-occurence", "Proximité"])
|
332 |
|
333 |
with tab1:
|
334 |
-
st.subheader("World Cloud")
|
335 |
-
st.markdown(
|
336 |
"""
|
337 |
On remarque, en changeant de langue, que certains mot de taille importante dans une langue,
|
338 |
apparaissent avec une taille identique dans l'autre langue.
|
339 |
La traduction mot à mot sera donc peut-être bonne.
|
340 |
-
"""
|
341 |
)
|
342 |
if (Langue == 'Anglais'):
|
343 |
text = ""
|
344 |
# Initialiser la variable des mots vides
|
345 |
stop_words = set(stopwords.words('english'))
|
346 |
for e in txt_en : text += e
|
347 |
-
plot_word_cloud(text, "English words corpus", "images/coeur.png", stop_words)
|
348 |
else:
|
349 |
text = ""
|
350 |
# Initialiser la variable des mots vides
|
351 |
stop_words = set(stopwords.words('french'))
|
352 |
for e in txt_fr : text += e
|
353 |
-
plot_word_cloud(text,"Mots français du corpus", "images/coeur.png", stop_words)
|
354 |
|
355 |
with tab2:
|
356 |
-
st.subheader("Frequence d'apparition des mots")
|
357 |
-
st.markdown(
|
358 |
"""
|
359 |
On remarque, en changeant de langue, que certains mot fréquents dans une langue,
|
360 |
apparaissent aussi fréquemment dans l'autre langue.
|
361 |
Cela peut nous laisser penser que la traduction mot à mot sera peut-être bonne.
|
362 |
-
"""
|
363 |
)
|
364 |
if (Langue == 'Anglais'):
|
365 |
dist_frequence_mots(df_count_word_en)
|
366 |
else:
|
367 |
dist_frequence_mots(df_count_word_fr)
|
368 |
with tab3:
|
369 |
-
st.subheader("Distribution des longueurs de phrases")
|
370 |
-
st.markdown(
|
371 |
"""
|
372 |
Malgré quelques différences entre les 2 langues (les phrases anglaises sont généralement un peu plus courtes),
|
373 |
on constate une certaine similitude dans les ditributions de longueur de phrases.
|
374 |
Cela peut nous laisser penser que la traduction mot à mot ne sera pas si mauvaise.
|
375 |
-
"""
|
376 |
)
|
377 |
if (Langue == 'Anglais'):
|
378 |
dist_longueur_phrase(sent_len_en, sent_len_fr, 'Anglais','Français')
|
379 |
else:
|
380 |
dist_longueur_phrase(sent_len_fr, sent_len_en, 'Français', 'Anglais')
|
381 |
with tab4:
|
382 |
-
st.subheader("Co-occurence des mots dans une phrase")
|
383 |
if (Langue == 'Anglais'):
|
384 |
graphe_co_occurence(txt_split_en[:1000],corpus_en)
|
385 |
else:
|
386 |
graphe_co_occurence(txt_split_fr[:1000],corpus_fr)
|
387 |
with tab5:
|
388 |
-
st.subheader("Proximité sémantique des mots (Word Embedding)")
|
389 |
-
st.markdown(
|
390 |
"""
|
391 |
MUSE est une bibliothèque Python pour l'intégration de mots multilingues, qui fournit
|
392 |
notamment des "Word Embedding" multilingues
|
393 |
Facebook fournit des dictionnaires de référence. Ces embeddings sont des embeddings fastText Wikipedia pour 30 langues qui ont été alignés dans un espace espace vectoriel unique.
|
394 |
Dans notre cas, nous avons utilisé 2 mini-dictionnaires d'environ 3000 mots (Français et Anglais).
|
395 |
|
|
|
|
|
|
|
|
|
396 |
En novembre 2015, l'équipe de recherche de Facebook a créé fastText qui est une extension de la bibliothèque word2vec.
|
397 |
Elle s'appuie sur Word2Vec en apprenant des représentations vectorielles pour chaque mot et les n-grammes trouvés dans chaque mot.
|
398 |
-
"""
|
399 |
)
|
400 |
st.write("")
|
401 |
proximite()
|
|
|
17 |
import networkx as nx
|
18 |
from sklearn.manifold import TSNE
|
19 |
from gensim.models import KeyedVectors
|
20 |
+
from translate_app import tr
|
21 |
|
22 |
title = "Data Vizualization"
|
23 |
sidebar_name = "Data Vizualization"
|
24 |
+
dataPath = st.session_state.DataPath
|
25 |
|
26 |
with contextlib.redirect_stdout(open(os.devnull, "w")):
|
27 |
nltk.download('stopwords')
|
|
|
35 |
# Nombre maximum de ligne à afficher pour les DataFrame
|
36 |
max_lines_to_display = 50
|
37 |
|
38 |
+
@st.cache_data
|
39 |
def load_data(path):
|
40 |
|
41 |
input_file = os.path.join(path)
|
|
|
48 |
data = data.split('\n')
|
49 |
return data[first_line:min(len(data),first_line+max_lines)]
|
50 |
|
51 |
+
@st.cache_data
|
52 |
def load_preprocessed_data(path,data_type):
|
53 |
|
54 |
input_file = os.path.join(path)
|
|
|
69 |
data=data2
|
70 |
return data
|
71 |
|
72 |
+
@st.cache_data
|
73 |
def load_all_preprocessed_data(lang):
|
74 |
+
txt =load_preprocessed_data(dataPath+'/preprocess_txt_'+lang,0)
|
75 |
+
corpus =load_preprocessed_data(dataPath+'/preprocess_corpus_'+lang,0)
|
76 |
+
txt_split = load_preprocessed_data(dataPath+'/preprocess_txt_split_'+lang,3)
|
77 |
+
df_count_word = pd.concat([load_preprocessed_data(dataPath+'/preprocess_df_count_word1_'+lang,1), load_preprocessed_data(dataPath+'/preprocess_df_count_word2_'+lang,1)])
|
78 |
+
sent_len =load_preprocessed_data(dataPath+'/preprocess_sent_len_'+lang,2)
|
79 |
+
vec_model= KeyedVectors.load_word2vec_format(dataPath+'/mini.wiki.'+lang+'.align.vec')
|
80 |
return txt, corpus, txt_split, df_count_word,sent_len, vec_model
|
81 |
|
82 |
#Chargement des textes complet dans les 2 langues
|
|
|
93 |
max_font_size=50, random_state=42)
|
94 |
# Générer et afficher le nuage de mots
|
95 |
fig=plt.figure(figsize= (20,10))
|
96 |
+
plt.title(tr(title), fontsize=25, color="green")
|
97 |
wc.generate(text)
|
98 |
|
99 |
# getting current axes
|
|
|
131 |
|
132 |
sns.set()
|
133 |
fig = plt.figure() #figsize=(4,4)
|
134 |
+
plt.title(tr("Nombre d'apparitions des mots"), fontsize=16)
|
135 |
|
136 |
chart = sns.barplot(x='mots',y='occurences',data=nb_occurences.iloc[:40]);
|
137 |
chart.set_xticklabels(chart.get_xticklabels(), rotation=45, horizontalalignment='right', size=8)
|
|
|
175 |
chart = sns.histplot(df, color=['r','b'], label=[lang1,lang2], binwidth=1, binrange=[2,22], element="step",
|
176 |
common_norm=False, multiple="layer", discrete=True, stat='proportion')
|
177 |
plt.xticks([2,4,6,8,10,12,14,16,18,20,22])
|
178 |
+
chart.set(title=tr('Distribution du nombre de mots sur '+str(len(sent_len))+' phrase(s)'));
|
179 |
st.pyplot(fig)
|
180 |
|
181 |
'''
|
|
|
246 |
labels = []
|
247 |
tokens = []
|
248 |
|
249 |
+
nb_words = st.slider(tr('Nombre de mots à afficher')+' :',10,50, value=20)
|
250 |
+
df = pd.read_csv('../data/dict_we_en_fr',header=0,index_col=0, encoding ="utf-8", keep_default_na=False)
|
251 |
words_en = df.index.to_list()[:nb_words]
|
252 |
words_fr = df['Francais'].to_list()[:nb_words]
|
253 |
|
|
|
281 |
va='bottom',
|
282 |
color= color,
|
283 |
size=20)
|
284 |
+
plt.title(tr("Proximité des mots anglais avec leur traduction"), fontsize=30, color="green")
|
285 |
plt.legend(loc='best');
|
286 |
st.pyplot(fig)
|
287 |
|
|
|
293 |
global full_txt_fr, full_corpus_fr, full_txt_split_fr, full_df_count_word_fr,full_sent_len_fr, vec_model_fr
|
294 |
|
295 |
st.write("")
|
296 |
+
st.title(tr(title))
|
297 |
|
298 |
#
|
299 |
+
st.write("## **"+tr("Paramètres")+" :**\n")
|
300 |
+
Langue = st.radio(tr('Langue:'),('Anglais','Français'), horizontal=True)
|
301 |
+
first_line = st.slider(tr('No de la premiere ligne à analyser')+' :',0,137859)
|
302 |
+
max_lines = st.select_slider(tr('Nombre de lignes à analyser')+' :',
|
303 |
options=[1,5,10,15,100, 500, 1000,'Max'])
|
304 |
if max_lines=='Max':
|
305 |
max_lines=137860
|
|
|
329 |
st.dataframe(pd.DataFrame(data=full_txt_fr,columns=['Texte']).loc[first_line:last_line-1].head(max_lines_to_display), width=800)
|
330 |
st.write("")
|
331 |
|
332 |
+
tab1, tab2, tab3, tab4, tab5 = st.tabs([tr("World Cloud"), tr("Frequence"),tr("Distribution longueur"), tr("Co-occurence"), tr("Proximité")])
|
333 |
|
334 |
with tab1:
|
335 |
+
st.subheader(tr("World Cloud"))
|
336 |
+
st.markdown(tr(
|
337 |
"""
|
338 |
On remarque, en changeant de langue, que certains mot de taille importante dans une langue,
|
339 |
apparaissent avec une taille identique dans l'autre langue.
|
340 |
La traduction mot à mot sera donc peut-être bonne.
|
341 |
+
""")
|
342 |
)
|
343 |
if (Langue == 'Anglais'):
|
344 |
text = ""
|
345 |
# Initialiser la variable des mots vides
|
346 |
stop_words = set(stopwords.words('english'))
|
347 |
for e in txt_en : text += e
|
348 |
+
plot_word_cloud(text, "English words corpus", "../images/coeur.png", stop_words)
|
349 |
else:
|
350 |
text = ""
|
351 |
# Initialiser la variable des mots vides
|
352 |
stop_words = set(stopwords.words('french'))
|
353 |
for e in txt_fr : text += e
|
354 |
+
plot_word_cloud(text,"Mots français du corpus", "../images/coeur.png", stop_words)
|
355 |
|
356 |
with tab2:
|
357 |
+
st.subheader(tr("Frequence d'apparition des mots"))
|
358 |
+
st.markdown(tr(
|
359 |
"""
|
360 |
On remarque, en changeant de langue, que certains mot fréquents dans une langue,
|
361 |
apparaissent aussi fréquemment dans l'autre langue.
|
362 |
Cela peut nous laisser penser que la traduction mot à mot sera peut-être bonne.
|
363 |
+
""")
|
364 |
)
|
365 |
if (Langue == 'Anglais'):
|
366 |
dist_frequence_mots(df_count_word_en)
|
367 |
else:
|
368 |
dist_frequence_mots(df_count_word_fr)
|
369 |
with tab3:
|
370 |
+
st.subheader(tr("Distribution des longueurs de phrases"))
|
371 |
+
st.markdown(tr(
|
372 |
"""
|
373 |
Malgré quelques différences entre les 2 langues (les phrases anglaises sont généralement un peu plus courtes),
|
374 |
on constate une certaine similitude dans les ditributions de longueur de phrases.
|
375 |
Cela peut nous laisser penser que la traduction mot à mot ne sera pas si mauvaise.
|
376 |
+
""")
|
377 |
)
|
378 |
if (Langue == 'Anglais'):
|
379 |
dist_longueur_phrase(sent_len_en, sent_len_fr, 'Anglais','Français')
|
380 |
else:
|
381 |
dist_longueur_phrase(sent_len_fr, sent_len_en, 'Français', 'Anglais')
|
382 |
with tab4:
|
383 |
+
st.subheader(tr("Co-occurence des mots dans une phrase"))
|
384 |
if (Langue == 'Anglais'):
|
385 |
graphe_co_occurence(txt_split_en[:1000],corpus_en)
|
386 |
else:
|
387 |
graphe_co_occurence(txt_split_fr[:1000],corpus_fr)
|
388 |
with tab5:
|
389 |
+
st.subheader(tr("Proximité sémantique des mots (Word Embedding)") )
|
390 |
+
st.markdown(tr(
|
391 |
"""
|
392 |
MUSE est une bibliothèque Python pour l'intégration de mots multilingues, qui fournit
|
393 |
notamment des "Word Embedding" multilingues
|
394 |
Facebook fournit des dictionnaires de référence. Ces embeddings sont des embeddings fastText Wikipedia pour 30 langues qui ont été alignés dans un espace espace vectoriel unique.
|
395 |
Dans notre cas, nous avons utilisé 2 mini-dictionnaires d'environ 3000 mots (Français et Anglais).
|
396 |
|
397 |
+
""")
|
398 |
+
)
|
399 |
+
st.markdown(tr(
|
400 |
+
"""
|
401 |
En novembre 2015, l'équipe de recherche de Facebook a créé fastText qui est une extension de la bibliothèque word2vec.
|
402 |
Elle s'appuie sur Word2Vec en apprenant des représentations vectorielles pour chaque mot et les n-grammes trouvés dans chaque mot.
|
403 |
+
""")
|
404 |
)
|
405 |
st.write("")
|
406 |
proximite()
|
tabs/exploration_tab.py
CHANGED
@@ -6,13 +6,21 @@ import collections
|
|
6 |
from nltk.tokenize import word_tokenize
|
7 |
from nltk import download
|
8 |
from ast import literal_eval
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
|
14 |
title = "Exploration et Preprocessing"
|
15 |
sidebar_name = "Exploration et Preprocessing"
|
|
|
16 |
|
17 |
# Indiquer si l'on veut enlever les stop words. C'est un processus long
|
18 |
stopwords_to_do = True
|
@@ -29,10 +37,12 @@ if ((first_line+max_lines)>137860):
|
|
29 |
# Nombre maximum de ligne à afficher pour les DataFrame
|
30 |
max_lines_to_display = 50
|
31 |
|
32 |
-
|
33 |
download('punkt')
|
34 |
-
|
35 |
-
|
|
|
|
|
|
|
36 |
|
37 |
@st.cache_data
|
38 |
def load_data(path):
|
@@ -67,23 +77,25 @@ def load_preprocessed_data(path,data_type):
|
|
67 |
data=data2
|
68 |
return data
|
69 |
|
70 |
-
|
71 |
def load_all_preprocessed_data(lang):
|
72 |
-
txt =load_preprocessed_data('
|
73 |
-
txt_split = load_preprocessed_data('
|
74 |
-
txt_lem = load_preprocessed_data('
|
75 |
-
txt_wo_stopword = load_preprocessed_data('
|
76 |
-
df_count_word = pd.concat([load_preprocessed_data('
|
77 |
return txt, txt_split, txt_lem, txt_wo_stopword, df_count_word
|
78 |
|
79 |
#Chargement des textes complet dans les 2 langues
|
80 |
-
full_txt_en = load_data('
|
81 |
-
full_txt_fr = load_data('
|
|
|
|
|
|
|
|
|
|
|
|
|
82 |
|
83 |
-
# Chargement du résultat du préprocessing
|
84 |
-
_ , full_txt_split_en, full_txt_lem_en, full_txt_wo_stopword_en, full_df_count_word_en = load_all_preprocessed_data('en')
|
85 |
-
_ , full_txt_split_fr, full_txt_lem_fr, full_txt_wo_stopword_fr, full_df_count_word_fr = load_all_preprocessed_data('fr')
|
86 |
-
"""
|
87 |
def remove_stopwords(text, lang):
|
88 |
stop_words = set(stopwords.words(lang))
|
89 |
# stop_words will contain set all english stopwords
|
@@ -245,7 +257,7 @@ def preprocess_txt (data, lang):
|
|
245 |
txt_n_unique_val= pd.DataFrame(columns=corpus,index=range(nb_phrases), data=countvectors.todense()).astype(float)
|
246 |
|
247 |
return data, corpus, data_split, data_lemmatized, data_wosw, txt_n_unique_val, sentence_length, data_length_wo_stopwords, data_lem_length
|
248 |
-
|
249 |
|
250 |
def count_world(data):
|
251 |
word_count = collections.Counter()
|
@@ -269,47 +281,45 @@ def display_preprocess_results(lang, data, data_split, data_lem, data_wosw, txt_
|
|
269 |
txt_n_unique_val = txt_n_unique_val.drop(columns=columns_with_only_zeros)
|
270 |
|
271 |
# Affichage du nombre de mot en fonction du pré-processing réalisé
|
272 |
-
tab1, tab2, tab3, tab4 = st.tabs(["Résumé", "Tokenisation","Lemmatisation", "Sans Stopword"])
|
273 |
with tab1:
|
274 |
-
st.subheader("Résumé du pré-processing")
|
275 |
-
st.write("**Nombre de phrases : "+str(nb_phrases)+"**")
|
276 |
-
st.write("**Nombre de mots : "+str(nb_mots)+"**")
|
277 |
-
st.write("**Nombre de mots uniques : "+str(nb_mots_uniques)+"**")
|
278 |
st.write("")
|
279 |
-
st.write("\n**Nombre d'apparitions de chaque mot dans chaque phrase (:red[Bag Of Words])
|
280 |
st.dataframe(txt_n_unique_val.head(max_lines_to_display), width=800)
|
281 |
with tab2:
|
282 |
-
st.subheader("Tokenisation")
|
283 |
-
st.write('Texte "splited":')
|
284 |
st.dataframe(pd.DataFrame(data=data_split, index=range(first_line,last_line)).head(max_lines_to_display).fillna(''), width=800)
|
285 |
-
st.write("**Nombre de mots uniques : "+str(nb_mots_uniques)+"**")
|
286 |
st.write("")
|
287 |
-
st.write("\n**Mots uniques:**")
|
288 |
st.markdown(corpus[:500])
|
289 |
-
st.write("\n**Nombre d'apparitions de chaque mot dans chaque phrase (:red[Bag Of Words])
|
290 |
st.dataframe(txt_n_unique_val.head(max_lines_to_display), width=800)
|
291 |
with tab3:
|
292 |
-
st.subheader("Lemmatisation")
|
293 |
if lemmatize_to_do:
|
294 |
-
st.dataframe(pd.DataFrame(data=data_lem,columns=['Texte lemmatisé'],index=range(first_line,last_line)).head(max_lines_to_display), width=800)
|
295 |
# Si langue anglaise, affichage du taggage des mots
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
"""
|
302 |
-
st.write("**Nombre de mots uniques lemmatisés : "+str(nb_mots_lem)+"**")
|
303 |
st.write("")
|
304 |
-
st.write("\n**Mots uniques lemmatisés
|
305 |
st.markdown(mots_lem[:500])
|
306 |
with tab4:
|
307 |
-
st.subheader("Sans Stopword")
|
308 |
if stopwords_to_do:
|
309 |
st.dataframe(pd.DataFrame(data=data_wosw,columns=['Texte sans stopwords'],index=range(first_line,last_line)).head(max_lines_to_display), width=800)
|
310 |
-
st.write("**Nombre de mots uniques sans stop words: "+str(nb_mots_wo_stopword)+"**")
|
311 |
st.write("")
|
312 |
-
st.write("\n**Mots uniques sans stop words:**")
|
313 |
st.markdown(mots_wo_sw[:500])
|
314 |
|
315 |
|
@@ -319,40 +329,40 @@ def run():
|
|
319 |
global full_txt_fr, full_txt_split_fr, full_txt_lem_fr, full_txt_wo_stopword_fr, full_df_count_word_fr
|
320 |
|
321 |
st.write("")
|
322 |
-
st.title(title)
|
323 |
|
324 |
-
st.write("## **Explications :**\n")
|
325 |
-
|
326 |
-
st.markdown(
|
327 |
"""
|
328 |
Le traitement du langage naturel permet à l'ordinateur de comprendre et de traiter les langues humaines.
|
329 |
Lors de notre projet, nous avons étudié le dataset small_vocab, proposés par Suzan Li, Chief Data Scientist chez Campaign Research à Toronto.
|
330 |
Celui-ci représente un corpus de phrases simples en anglais, et sa traduction (approximative) en français.
|
331 |
:red[**Small_vocab**] contient 137 860 phrases en anglais et français.
|
|
|
|
|
|
|
|
|
332 |
Afin de découvrir ce corpus et de préparer la traduction, nous allons effectuer un certain nombre de tâches de pré-traitement (preprocessing).
|
333 |
Ces taches sont, par exemple:
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
*
|
338 |
-
|
339 |
-
|
340 |
-
"""
|
341 |
-
|
|
|
342 |
#
|
343 |
-
st.write("## **Paramètres :**\n")
|
344 |
-
Langue = st.radio('Langue:',('Anglais','Français'), horizontal=True)
|
345 |
-
first_line = st.slider('No de la premiere ligne à analyser:',0,137859)
|
346 |
-
max_lines = st.select_slider('Nombre de lignes à analyser:',
|
347 |
options=[1,5,10,15,100, 500, 1000,'Max'])
|
348 |
if max_lines=='Max':
|
349 |
max_lines=137860
|
350 |
if ((first_line+max_lines)>137860):
|
351 |
max_lines = max(137860-first_line,0)
|
352 |
-
# if ((max_lines-first_line)>1000):
|
353 |
-
# lemmatize_to_do = True
|
354 |
-
# else:
|
355 |
-
# lemmatize_to_do = False
|
356 |
|
357 |
last_line = first_line+max_lines
|
358 |
if (Langue=='Anglais'):
|
@@ -361,62 +371,50 @@ def run():
|
|
361 |
st.dataframe(pd.DataFrame(data=full_txt_fr,columns=['Texte']).loc[first_line:last_line-1].head(max_lines_to_display), width=800)
|
362 |
st.write("")
|
363 |
|
364 |
-
# Chargement
|
365 |
txt_en = full_txt_en[first_line:last_line]
|
366 |
-
txt_split_en = full_txt_split_en[first_line:last_line]
|
367 |
-
txt_lem_en = full_txt_lem_en[first_line:last_line]
|
368 |
-
txt_wo_stopword_en = full_txt_wo_stopword_en[first_line:last_line]
|
369 |
-
df_count_word_en = full_df_count_word_en.loc[first_line:last_line-1]
|
370 |
txt_fr = full_txt_fr[first_line:last_line]
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
375 |
|
376 |
# Lancement du préprocessing du texte qui va spliter nettoyer les phrases et les spliter en mots
|
377 |
# et calculer nombre d'occurences des mots dans chaque phrase
|
378 |
if (Langue == 'Anglais'):
|
379 |
-
st.write("## **Préprocessing de small_vocab_en :**\n")
|
380 |
if max_lines>10000:
|
381 |
with st.status(":sunglasses:", expanded=True):
|
382 |
-
|
|
|
383 |
display_preprocess_results('en',txt_en, txt_split_en, txt_lem_en, txt_wo_stopword_en, df_count_word_en)
|
384 |
else:
|
385 |
-
|
|
|
386 |
display_preprocess_results('en',txt_en, txt_split_en, txt_lem_en, txt_wo_stopword_en, df_count_word_en)
|
387 |
else:
|
388 |
-
st.write("## **Préprocessing de small_vocab_fr :**\n")
|
389 |
if max_lines>10000:
|
390 |
with st.status(":sunglasses:", expanded=True):
|
391 |
-
|
|
|
392 |
display_preprocess_results('fr', txt_fr, txt_split_fr, txt_lem_fr, txt_wo_stopword_fr, df_count_word_fr)
|
393 |
else:
|
394 |
-
|
|
|
395 |
display_preprocess_results('fr', txt_fr, txt_split_fr, txt_lem_fr, txt_wo_stopword_fr, df_count_word_fr)
|
396 |
|
397 |
|
398 |
|
399 |
-
# Might be used later....
|
400 |
-
# DEFAULT_TEXT = """Google was founded in September 1998 by Larry Page and Sergey Brin while they were Ph.D. students at Stanford University in California. Together they own about 14 percent of its shares and control 56 percent of the stockholder voting power through supervoting stock. They incorporated Google as a California privately held company on September 4, 1998, in California. Google was then reincorporated in Delaware on October 22, 2002."""
|
401 |
-
"""
|
402 |
-
spacy_model = "en_core_web_sm"
|
403 |
-
|
404 |
-
text = st.text_area("Text to analyze", DEFAULT_TEXT, height=200)
|
405 |
-
doc = spacy_streamlit.process_text(spacy_model, text)
|
406 |
-
|
407 |
-
spacy_streamlit.visualize_ner(
|
408 |
-
doc,
|
409 |
-
labels=["PERSON", "DATE", "GPE"],
|
410 |
-
show_table=False,
|
411 |
-
title="Persons, dates and locations",
|
412 |
-
)
|
413 |
-
st.text(f"Analyzed using spaCy model {spacy_model}")
|
414 |
-
"""
|
415 |
-
|
416 |
-
# models = ["en_core_web_sm"]
|
417 |
-
# default_text = "Google was founded in September 1998 by Larry Page and Sergey Brin while they were Ph.D. students at Stanford University in California. Together they own about 14 percent of its shares and control 56 percent of the stockholder voting power through supervoting stock. They incorporated Google as a California privately held company on September 4, 1998, in California. Google was then reincorporated in Delaware on October 22, 2002."
|
418 |
-
# spacy_streamlit.visualize(models, default_text)
|
419 |
-
|
420 |
|
421 |
|
422 |
|
|
|
6 |
from nltk.tokenize import word_tokenize
|
7 |
from nltk import download
|
8 |
from ast import literal_eval
|
9 |
+
from translate_app import tr
|
10 |
+
if st.session_state.Cloud == 0:
|
11 |
+
import nltk
|
12 |
+
import contextlib
|
13 |
+
import re
|
14 |
+
from nltk.corpus import stopwords
|
15 |
+
import warnings
|
16 |
+
warnings.filterwarnings('ignore')
|
17 |
+
# from PIL import Image
|
18 |
+
# import time
|
19 |
+
# import random
|
20 |
|
21 |
title = "Exploration et Preprocessing"
|
22 |
sidebar_name = "Exploration et Preprocessing"
|
23 |
+
dataPath = st.session_state.DataPath
|
24 |
|
25 |
# Indiquer si l'on veut enlever les stop words. C'est un processus long
|
26 |
stopwords_to_do = True
|
|
|
37 |
# Nombre maximum de ligne à afficher pour les DataFrame
|
38 |
max_lines_to_display = 50
|
39 |
|
|
|
40 |
download('punkt')
|
41 |
+
|
42 |
+
if st.session_state.Cloud == 0:
|
43 |
+
download('averaged_perceptron_tagger')
|
44 |
+
with contextlib.redirect_stdout(open(os.devnull, "w")):
|
45 |
+
download('stopwords')
|
46 |
|
47 |
@st.cache_data
|
48 |
def load_data(path):
|
|
|
77 |
data=data2
|
78 |
return data
|
79 |
|
80 |
+
@st.cache_data
|
81 |
def load_all_preprocessed_data(lang):
|
82 |
+
txt =load_preprocessed_data(dataPath+'/preprocess_txt_'+lang,0)
|
83 |
+
txt_split = load_preprocessed_data(dataPath+'/preprocess_txt_split_'+lang,3)
|
84 |
+
txt_lem = load_preprocessed_data(dataPath+'/preprocess_txt_lem_'+lang,0)
|
85 |
+
txt_wo_stopword = load_preprocessed_data(dataPath+'/preprocess_txt_wo_stopword_'+lang,0)
|
86 |
+
df_count_word = pd.concat([load_preprocessed_data(dataPath+'/preprocess_df_count_word1_'+lang,1), load_preprocessed_data(dataPath+'/preprocess_df_count_word2_'+lang,1)])
|
87 |
return txt, txt_split, txt_lem, txt_wo_stopword, df_count_word
|
88 |
|
89 |
#Chargement des textes complet dans les 2 langues
|
90 |
+
full_txt_en = load_data(dataPath+'/small_vocab_en')
|
91 |
+
full_txt_fr = load_data(dataPath+'/small_vocab_fr')
|
92 |
+
|
93 |
+
# Chargement du résultat du préprocessing, si st.session_state.reCalcule == False
|
94 |
+
if not st.session_state.reCalcule:
|
95 |
+
full_txt_en, full_txt_split_en, full_txt_lem_en, full_txt_wo_stopword_en, full_df_count_word_en = load_all_preprocessed_data('en')
|
96 |
+
full_txt_fr, full_txt_split_fr, full_txt_lem_fr, full_txt_wo_stopword_fr, full_df_count_word_fr = load_all_preprocessed_data('fr')
|
97 |
+
|
98 |
|
|
|
|
|
|
|
|
|
99 |
def remove_stopwords(text, lang):
|
100 |
stop_words = set(stopwords.words(lang))
|
101 |
# stop_words will contain set all english stopwords
|
|
|
257 |
txt_n_unique_val= pd.DataFrame(columns=corpus,index=range(nb_phrases), data=countvectors.todense()).astype(float)
|
258 |
|
259 |
return data, corpus, data_split, data_lemmatized, data_wosw, txt_n_unique_val, sentence_length, data_length_wo_stopwords, data_lem_length
|
260 |
+
|
261 |
|
262 |
def count_world(data):
|
263 |
word_count = collections.Counter()
|
|
|
281 |
txt_n_unique_val = txt_n_unique_val.drop(columns=columns_with_only_zeros)
|
282 |
|
283 |
# Affichage du nombre de mot en fonction du pré-processing réalisé
|
284 |
+
tab1, tab2, tab3, tab4 = st.tabs([tr("Résumé"), tr("Tokenisation"),tr("Lemmatisation"), tr("Sans Stopword")])
|
285 |
with tab1:
|
286 |
+
st.subheader(tr("Résumé du pré-processing"))
|
287 |
+
st.write("**"+tr("Nombre de phrases")+" : "+str(nb_phrases)+"**")
|
288 |
+
st.write("**"+tr("Nombre de mots")+" : "+str(nb_mots)+"**")
|
289 |
+
st.write("**"+tr("Nombre de mots uniques")+" : "+str(nb_mots_uniques)+"**")
|
290 |
st.write("")
|
291 |
+
st.write("\n**"+tr("Nombre d'apparitions de chaque mot dans chaque phrase (:red[Bag Of Words]):")+"**")
|
292 |
st.dataframe(txt_n_unique_val.head(max_lines_to_display), width=800)
|
293 |
with tab2:
|
294 |
+
st.subheader(tr("Tokenisation"))
|
295 |
+
st.write(tr('Texte "splited":'))
|
296 |
st.dataframe(pd.DataFrame(data=data_split, index=range(first_line,last_line)).head(max_lines_to_display).fillna(''), width=800)
|
297 |
+
st.write("**"+tr("Nombre de mots uniques")+" : "+str(nb_mots_uniques)+"**")
|
298 |
st.write("")
|
299 |
+
st.write("\n**"+tr("Mots uniques")+":**")
|
300 |
st.markdown(corpus[:500])
|
301 |
+
st.write("\n**"+tr("Nombre d'apparitions de chaque mot dans chaque phrase (:red[Bag Of Words]):")+"**")
|
302 |
st.dataframe(txt_n_unique_val.head(max_lines_to_display), width=800)
|
303 |
with tab3:
|
304 |
+
st.subheader(tr("Lemmatisation"))
|
305 |
if lemmatize_to_do:
|
306 |
+
st.dataframe(pd.DataFrame(data=data_lem,columns=[tr('Texte lemmatisé')],index=range(first_line,last_line)).head(max_lines_to_display), width=800)
|
307 |
# Si langue anglaise, affichage du taggage des mots
|
308 |
+
# if lang == 'en':
|
309 |
+
# for i in range(min(5,len(data))):
|
310 |
+
# s = str(nltk.pos_tag(data_split[i]))
|
311 |
+
# st.markdown("**Texte avec Tags "+str(i)+"** : "+s)
|
312 |
+
st.write("**"+tr("Nombre de mots uniques lemmatisés")+" : "+str(nb_mots_lem)+"**")
|
|
|
|
|
313 |
st.write("")
|
314 |
+
st.write("\n**"+tr("Mots uniques lemmatisés:")+"**")
|
315 |
st.markdown(mots_lem[:500])
|
316 |
with tab4:
|
317 |
+
st.subheader(tr("Sans Stopword"))
|
318 |
if stopwords_to_do:
|
319 |
st.dataframe(pd.DataFrame(data=data_wosw,columns=['Texte sans stopwords'],index=range(first_line,last_line)).head(max_lines_to_display), width=800)
|
320 |
+
st.write("**"+tr("Nombre de mots uniques sans stop words")+": "+str(nb_mots_wo_stopword)+"**")
|
321 |
st.write("")
|
322 |
+
st.write("\n**"+tr("Mots uniques sans stop words")+":**")
|
323 |
st.markdown(mots_wo_sw[:500])
|
324 |
|
325 |
|
|
|
329 |
global full_txt_fr, full_txt_split_fr, full_txt_lem_fr, full_txt_wo_stopword_fr, full_df_count_word_fr
|
330 |
|
331 |
st.write("")
|
332 |
+
st.title(tr(title))
|
333 |
|
334 |
+
st.write("## **"+tr("Explications")+" :**\n")
|
335 |
+
st.markdown(tr(
|
|
|
336 |
"""
|
337 |
Le traitement du langage naturel permet à l'ordinateur de comprendre et de traiter les langues humaines.
|
338 |
Lors de notre projet, nous avons étudié le dataset small_vocab, proposés par Suzan Li, Chief Data Scientist chez Campaign Research à Toronto.
|
339 |
Celui-ci représente un corpus de phrases simples en anglais, et sa traduction (approximative) en français.
|
340 |
:red[**Small_vocab**] contient 137 860 phrases en anglais et français.
|
341 |
+
""")
|
342 |
+
, unsafe_allow_html=True)
|
343 |
+
st.markdown(tr(
|
344 |
+
"""
|
345 |
Afin de découvrir ce corpus et de préparer la traduction, nous allons effectuer un certain nombre de tâches de pré-traitement (preprocessing).
|
346 |
Ces taches sont, par exemple:
|
347 |
+
""")
|
348 |
+
, unsafe_allow_html=True)
|
349 |
+
st.markdown(
|
350 |
+
"* "+tr("le :red[**nettoyage**] du texte (enlever les majuscules et la ponctuation)")+"\n"+ \
|
351 |
+
"* "+tr("la :red[**tokenisation**] (découpage du texte en mots)")+"\n"+ \
|
352 |
+
"* "+tr("la :red[**lemmatisation**] (traitement lexical qui permet de donner une forme unique à toutes les \"variations\" d'un même mot)")+"\n"+ \
|
353 |
+
"* "+tr("l'élimination des :red[**mots \"transparents\"**] (sans utilité pour la compréhension, tels que les articles).")+" \n"+ \
|
354 |
+
tr("Ce prétraintement se conclut avec la contruction d'un :red[**Bag Of Worlds**], c'est à dire une matrice qui compte le nombre d'apparition de chaque mots (colonne) dans chaque phrase (ligne)")
|
355 |
+
, unsafe_allow_html=True)
|
356 |
#
|
357 |
+
st.write("## **"+tr("Paramètres")+" :**\n")
|
358 |
+
Langue = st.radio(tr('Langue:'),('Anglais','Français'), horizontal=True)
|
359 |
+
first_line = st.slider(tr('No de la premiere ligne à analyser:'),0,137859)
|
360 |
+
max_lines = st.select_slider(tr('Nombre de lignes à analyser:'),
|
361 |
options=[1,5,10,15,100, 500, 1000,'Max'])
|
362 |
if max_lines=='Max':
|
363 |
max_lines=137860
|
364 |
if ((first_line+max_lines)>137860):
|
365 |
max_lines = max(137860-first_line,0)
|
|
|
|
|
|
|
|
|
366 |
|
367 |
last_line = first_line+max_lines
|
368 |
if (Langue=='Anglais'):
|
|
|
371 |
st.dataframe(pd.DataFrame(data=full_txt_fr,columns=['Texte']).loc[first_line:last_line-1].head(max_lines_to_display), width=800)
|
372 |
st.write("")
|
373 |
|
374 |
+
# Chargement des textes sélectionnés dans les 2 langues (max lignes = max_lines)
|
375 |
txt_en = full_txt_en[first_line:last_line]
|
|
|
|
|
|
|
|
|
376 |
txt_fr = full_txt_fr[first_line:last_line]
|
377 |
+
|
378 |
+
# Elimination des phrases non traduites
|
379 |
+
# txt_en, txt_fr = clean_untranslated_sentence(txt_en, txt_fr)
|
380 |
+
|
381 |
+
if not st.session_state.reCalcule:
|
382 |
+
txt_split_en = full_txt_split_en[first_line:last_line]
|
383 |
+
txt_lem_en = full_txt_lem_en[first_line:last_line]
|
384 |
+
txt_wo_stopword_en = full_txt_wo_stopword_en[first_line:last_line]
|
385 |
+
df_count_word_en = full_df_count_word_en.loc[first_line:last_line-1]
|
386 |
+
txt_split_fr = full_txt_split_fr[first_line:last_line]
|
387 |
+
txt_lem_fr = full_txt_lem_fr[first_line:last_line]
|
388 |
+
txt_wo_stopword_fr = full_txt_wo_stopword_fr[first_line:last_line]
|
389 |
+
df_count_word_fr = full_df_count_word_fr.loc[first_line:last_line-1]
|
390 |
|
391 |
# Lancement du préprocessing du texte qui va spliter nettoyer les phrases et les spliter en mots
|
392 |
# et calculer nombre d'occurences des mots dans chaque phrase
|
393 |
if (Langue == 'Anglais'):
|
394 |
+
st.write("## **"+tr("Préprocessing de small_vocab_en")+" :**\n")
|
395 |
if max_lines>10000:
|
396 |
with st.status(":sunglasses:", expanded=True):
|
397 |
+
if st.session_state.reCalcule:
|
398 |
+
txt_en, corpus_en, txt_split_en, txt_lem_en, txt_wo_stopword_en, df_count_word_en,sent_len_en, sent_wo_sw_len_en, sent_lem_len_en = preprocess_txt (txt_en,'en')
|
399 |
display_preprocess_results('en',txt_en, txt_split_en, txt_lem_en, txt_wo_stopword_en, df_count_word_en)
|
400 |
else:
|
401 |
+
if st.session_state.reCalcule:
|
402 |
+
txt_en, corpus_en, txt_split_en, txt_lem_en, txt_wo_stopword_en, df_count_word_en,sent_len_en, sent_wo_sw_len_en, sent_lem_len_en = preprocess_txt (txt_en,'en')
|
403 |
display_preprocess_results('en',txt_en, txt_split_en, txt_lem_en, txt_wo_stopword_en, df_count_word_en)
|
404 |
else:
|
405 |
+
st.write("## **"+tr("Préprocessing de small_vocab_fr")+" :**\n")
|
406 |
if max_lines>10000:
|
407 |
with st.status(":sunglasses:", expanded=True):
|
408 |
+
if st.session_state.reCalcule:
|
409 |
+
txt_fr, corpus_fr, txt_split_fr, txt_lem_fr, txt_wo_stopword_fr, df_count_word_fr,sent_len_fr, sent_wo_sw_len_fr, sent_lem_len_fr = preprocess_txt (txt_fr,'fr')
|
410 |
display_preprocess_results('fr', txt_fr, txt_split_fr, txt_lem_fr, txt_wo_stopword_fr, df_count_word_fr)
|
411 |
else:
|
412 |
+
if st.session_state.reCalcule:
|
413 |
+
txt_fr, corpus_fr, txt_split_fr, txt_lem_fr, txt_wo_stopword_fr, df_count_word_fr,sent_len_fr, sent_wo_sw_len_fr, sent_lem_len_fr = preprocess_txt (txt_fr,'fr')
|
414 |
display_preprocess_results('fr', txt_fr, txt_split_fr, txt_lem_fr, txt_wo_stopword_fr, df_count_word_fr)
|
415 |
|
416 |
|
417 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
418 |
|
419 |
|
420 |
|
tabs/game_tab.py
CHANGED
@@ -10,17 +10,20 @@ import csv
|
|
10 |
from extra_streamlit_components import tab_bar, TabBarItemData
|
11 |
import matplotlib.pyplot as plt
|
12 |
from datetime import datetime
|
|
|
|
|
13 |
|
14 |
title = "Jouez avec nous !"
|
15 |
sidebar_name = "Jeu"
|
|
|
16 |
|
17 |
@st.cache_data
|
18 |
def init_game():
|
19 |
new = int(time.time())
|
20 |
-
sentence_test = pd.read_csv('
|
21 |
sentence_test = sentence_test[4750:]
|
22 |
# Lisez le contenu du fichier JSON
|
23 |
-
with open('
|
24 |
lan_to_language = json.load(fichier)
|
25 |
t_now = time.time()
|
26 |
return sentence_test, lan_to_language, new, t_now
|
@@ -65,16 +68,16 @@ def calc_score(n_rep,duration):
|
|
65 |
return s
|
66 |
|
67 |
def read_leaderboard():
|
68 |
-
return pd.read_csv('
|
69 |
|
70 |
def write_leaderboard(lb):
|
71 |
lb['Nom'] = lb['Nom'].astype(str)
|
72 |
lb['Rang'] = lb['Rang'].astype(int)
|
73 |
-
lb.to_csv(path_or_buf='
|
74 |
|
75 |
def display_leaderboard():
|
76 |
lb = read_leaderboard()
|
77 |
-
st.write("**Leaderboard :**")
|
78 |
list_champ = """
|
79 |
| Rang | Nom | Score |
|
80 |
|------|------------|-------|"""
|
@@ -86,38 +89,56 @@ def display_leaderboard():
|
|
86 |
return lb
|
87 |
|
88 |
def write_log(TS,Nom,Score,BR,Duree):
|
89 |
-
log = pd.read_csv('
|
90 |
date_heure = datetime.fromtimestamp(TS)
|
91 |
Date = date_heure.strftime('%Y-%m-%d %H:%M:%S')
|
92 |
log = pd.concat([log, pd.DataFrame(data={'Date':[Date], 'Nom':[Nom],'Score':[Score],'BR':[BR],'Duree':[Duree]})], ignore_index=True)
|
93 |
-
log.to_csv(path_or_buf='
|
94 |
|
95 |
def display_files():
|
96 |
-
log = pd.read_csv('
|
97 |
-
lb = pd.read_csv('
|
98 |
st.dataframe(lb)
|
99 |
st.dataframe(log)
|
100 |
|
|
|
101 |
def run():
|
102 |
global sentence_test, lan_to_language
|
103 |
|
104 |
sentence_test, lan_to_language, new, t_debut = init_game()
|
105 |
|
106 |
st.write("")
|
107 |
-
st.title(title)
|
108 |
-
st.write("#### **Etes vous un expert es Langues
|
109 |
-
st.markdown(
|
110 |
"""
|
111 |
Essayer de trouvez, sans aide, la langue des 5 phrases suivantes.
|
112 |
Attention : Vous devez être le plus rapide possible !
|
113 |
-
""", unsafe_allow_html=True
|
114 |
)
|
115 |
st.write("")
|
116 |
-
player_name = st.text_input("Quel est votre nom ?")
|
117 |
-
|
118 |
if player_name == 'display_files':
|
119 |
display_files()
|
120 |
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
121 |
|
122 |
score = 0
|
123 |
col1, col2 = st.columns([0.7,0.3])
|
@@ -133,7 +154,7 @@ def run():
|
|
133 |
t_previous_debut = t_debut
|
134 |
t_debut = time.time()
|
135 |
|
136 |
-
if st.button(label="Valider", type="primary"):
|
137 |
st.cache_data.clear()
|
138 |
|
139 |
nb_bonnes_reponses = 0
|
@@ -147,21 +168,21 @@ def run():
|
|
147 |
score = calc_score(nb_bonnes_reponses,duration)
|
148 |
write_log(time.time(),player_name,score,nb_bonnes_reponses,duration)
|
149 |
if nb_bonnes_reponses >=4:
|
150 |
-
st.write(":red[**Félicitations, vous avez "+str(nb_bonnes_reponses)+" bonnes réponses
|
151 |
-
st.write(":red[Votre score est de "+str(score)+" points]")
|
152 |
else:
|
153 |
if nb_bonnes_reponses >1 : s="s"
|
154 |
else: s=""
|
155 |
-
st.write("**:red[Vous avez "+str(nb_bonnes_reponses)+" bonne"+s+" réponse"+s+".]**")
|
156 |
if nb_bonnes_reponses >0 : s="s"
|
157 |
else: s=""
|
158 |
-
st.write(":red[Votre score est de "+str(score)+" point"+s+"]")
|
159 |
|
160 |
-
st.write("Bonne réponses:")
|
161 |
for i in range(5):
|
162 |
st.write("- "+sentence_test['sentence'].iloc[sent_sel[i]]+" -> :blue[**"+lan_to_language[sentence_test['lan_code'].iloc[sent_sel[i]]]+"**]")
|
163 |
new = int(time.time())
|
164 |
-
st.button(label="Play again ?", type="primary")
|
165 |
|
166 |
with col2:
|
167 |
now = time.time()
|
|
|
10 |
from extra_streamlit_components import tab_bar, TabBarItemData
|
11 |
import matplotlib.pyplot as plt
|
12 |
from datetime import datetime
|
13 |
+
import tracemalloc
|
14 |
+
from translate_app import tr
|
15 |
|
16 |
title = "Jouez avec nous !"
|
17 |
sidebar_name = "Jeu"
|
18 |
+
dataPath = st.session_state.DataPath
|
19 |
|
20 |
@st.cache_data
|
21 |
def init_game():
|
22 |
new = int(time.time())
|
23 |
+
sentence_test = pd.read_csv(dataPath+'/multilingue/sentence_test_extract.csv')
|
24 |
sentence_test = sentence_test[4750:]
|
25 |
# Lisez le contenu du fichier JSON
|
26 |
+
with open(dataPath+'/multilingue/lan_to_language.json', 'r') as fichier:
|
27 |
lan_to_language = json.load(fichier)
|
28 |
t_now = time.time()
|
29 |
return sentence_test, lan_to_language, new, t_now
|
|
|
68 |
return s
|
69 |
|
70 |
def read_leaderboard():
|
71 |
+
return pd.read_csv(dataPath+'/game_leaderboard.csv', index_col=False,encoding='utf8')
|
72 |
|
73 |
def write_leaderboard(lb):
|
74 |
lb['Nom'] = lb['Nom'].astype(str)
|
75 |
lb['Rang'] = lb['Rang'].astype(int)
|
76 |
+
lb.to_csv(path_or_buf=dataPath+'/game_leaderboard.csv',columns=['Rang','Nom','Score','Timestamp','BR','Duree'],index=False, header=True,encoding='utf8')
|
77 |
|
78 |
def display_leaderboard():
|
79 |
lb = read_leaderboard()
|
80 |
+
st.write("**"+tr("Leaderboard")+" :**")
|
81 |
list_champ = """
|
82 |
| Rang | Nom | Score |
|
83 |
|------|------------|-------|"""
|
|
|
89 |
return lb
|
90 |
|
91 |
def write_log(TS,Nom,Score,BR,Duree):
|
92 |
+
log = pd.read_csv(dataPath+'/game_log.csv', index_col=False,encoding='utf8')
|
93 |
date_heure = datetime.fromtimestamp(TS)
|
94 |
Date = date_heure.strftime('%Y-%m-%d %H:%M:%S')
|
95 |
log = pd.concat([log, pd.DataFrame(data={'Date':[Date], 'Nom':[Nom],'Score':[Score],'BR':[BR],'Duree':[Duree]})], ignore_index=True)
|
96 |
+
log.to_csv(path_or_buf=dataPath+'/game_log.csv',columns=['Date','Nom','Score','BR','Duree'],index=False, header=True,encoding='utf8')
|
97 |
|
98 |
def display_files():
|
99 |
+
log = pd.read_csv(dataPath+'/game_log.csv', index_col=False,encoding='utf8')
|
100 |
+
lb = pd.read_csv(dataPath+'/game_leaderboard.csv', index_col=False,encoding='utf8')
|
101 |
st.dataframe(lb)
|
102 |
st.dataframe(log)
|
103 |
|
104 |
+
|
105 |
def run():
|
106 |
global sentence_test, lan_to_language
|
107 |
|
108 |
sentence_test, lan_to_language, new, t_debut = init_game()
|
109 |
|
110 |
st.write("")
|
111 |
+
st.title(tr(title))
|
112 |
+
st.write("#### **"+tr("Etes vous un expert es Langues ?")+"**\n")
|
113 |
+
st.markdown(tr(
|
114 |
"""
|
115 |
Essayer de trouvez, sans aide, la langue des 5 phrases suivantes.
|
116 |
Attention : Vous devez être le plus rapide possible !
|
117 |
+
"""), unsafe_allow_html=True
|
118 |
)
|
119 |
st.write("")
|
120 |
+
player_name = st.text_input(tr("Quel est votre nom ?"))
|
121 |
+
|
122 |
if player_name == 'display_files':
|
123 |
display_files()
|
124 |
return
|
125 |
+
elif player_name == 'malloc_start':
|
126 |
+
tracemalloc.start(30)
|
127 |
+
return
|
128 |
+
elif player_name == 'malloc_stop':
|
129 |
+
snapshot = tracemalloc.take_snapshot()
|
130 |
+
top_stats = snapshot.statistics('traceback')
|
131 |
+
# pick the biggest memory block
|
132 |
+
for k in range(3):
|
133 |
+
stat = top_stats[k]
|
134 |
+
print("%s memory blocks: %.1f KiB" % (stat.count, stat.size / 1024))
|
135 |
+
for line in stat.traceback.format():
|
136 |
+
print(line)
|
137 |
+
total_mem = sum(stat.size for stat in top_stats)
|
138 |
+
print("Total allocated size: %.1f KiB" % (total_mem / 1024))
|
139 |
+
return
|
140 |
+
|
141 |
+
|
142 |
|
143 |
score = 0
|
144 |
col1, col2 = st.columns([0.7,0.3])
|
|
|
154 |
t_previous_debut = t_debut
|
155 |
t_debut = time.time()
|
156 |
|
157 |
+
if st.button(label=tr("Valider"), type="primary"):
|
158 |
st.cache_data.clear()
|
159 |
|
160 |
nb_bonnes_reponses = 0
|
|
|
168 |
score = calc_score(nb_bonnes_reponses,duration)
|
169 |
write_log(time.time(),player_name,score,nb_bonnes_reponses,duration)
|
170 |
if nb_bonnes_reponses >=4:
|
171 |
+
st.write(":red[**"+tr("Félicitations, vous avez "+str(nb_bonnes_reponses)+" bonnes réponses !")+"**]")
|
172 |
+
st.write(":red["+tr("Votre score est de "+str(score)+" points")+"]")
|
173 |
else:
|
174 |
if nb_bonnes_reponses >1 : s="s"
|
175 |
else: s=""
|
176 |
+
st.write("**:red["+tr("Vous avez "+str(nb_bonnes_reponses)+" bonne"+s+" réponse"+s+".")+"]**")
|
177 |
if nb_bonnes_reponses >0 : s="s"
|
178 |
else: s=""
|
179 |
+
st.write(":red["+tr("Votre score est de "+str(score)+" point"+s)+"]")
|
180 |
|
181 |
+
st.write(tr("Bonne réponses")+":")
|
182 |
for i in range(5):
|
183 |
st.write("- "+sentence_test['sentence'].iloc[sent_sel[i]]+" -> :blue[**"+lan_to_language[sentence_test['lan_code'].iloc[sent_sel[i]]]+"**]")
|
184 |
new = int(time.time())
|
185 |
+
st.button(label=tr("Play again ?"), type="primary")
|
186 |
|
187 |
with col2:
|
188 |
now = time.time()
|
tabs/id_lang_tab.py
CHANGED
@@ -20,9 +20,11 @@ from sklearn.decomposition import PCA
|
|
20 |
import matplotlib.pyplot as plt
|
21 |
import seaborn as sns
|
22 |
from sklearn import naive_bayes
|
|
|
23 |
|
24 |
title = "Identification de langue"
|
25 |
sidebar_name = "Identification de langue"
|
|
|
26 |
|
27 |
# CountVectorizer a une liste de phrase en entrée.
|
28 |
# Cette fonction met les données d'entrée dans le bon format
|
@@ -47,7 +49,7 @@ def create_BOW(data):
|
|
47 |
def load_vectorizer(tokenizer):
|
48 |
global dict_token, dict_ids, nb_token
|
49 |
|
50 |
-
path = '
|
51 |
vectorizer = joblib.load(path)
|
52 |
dict_token = {tokenizer.decode([cle]): cle for cle, valeur in vectorizer.vocabulary_.items()}
|
53 |
dict_ids = {cle: tokenizer.decode([cle]) for cle, valeur in vectorizer.vocabulary_.items()} #dict_ids.items()}
|
@@ -67,11 +69,11 @@ def init_nb_identifier():
|
|
67 |
tokenizer = tiktoken.get_encoding("cl100k_base")
|
68 |
|
69 |
# Chargement du classificateur sauvegardé
|
70 |
-
clf_nb = joblib.load("
|
71 |
vectorizer = load_vectorizer(tokenizer)
|
72 |
|
73 |
# Lisez le contenu du fichier JSON
|
74 |
-
with open('
|
75 |
lan_to_language = json.load(fichier)
|
76 |
return tokenizer, dict_token, dict_ids, nb_token, lan_to_language, clf_nb, vectorizer
|
77 |
|
@@ -84,7 +86,7 @@ def encode_text(textes):
|
|
84 |
|
85 |
def read_list_lan():
|
86 |
|
87 |
-
with open('
|
88 |
reader = csv.reader(fichier_csv)
|
89 |
lan_code = next(reader)
|
90 |
return lan_code
|
@@ -96,8 +98,8 @@ def init_dl_identifier():
|
|
96 |
list_lan = read_list_lan()
|
97 |
lan_identified = [lan_to_language[l] for l in list_lan]
|
98 |
label_encoder.fit(list_lan)
|
99 |
-
merge = Merge("
|
100 |
-
dl_model = keras.models.load_model("
|
101 |
return dl_model, label_encoder, list_lan, lan_identified
|
102 |
|
103 |
def lang_id_dl(sentences):
|
@@ -117,7 +119,7 @@ def init_lang_id_external():
|
|
117 |
lang_id_model_ext = pipeline('text-classification',model="papluca/xlm-roberta-base-language-detection")
|
118 |
dict_xlmr = {"ar":"ara", "bg":"bul", "de":"deu", "el": "ell", "en":"eng", "es":"spa", "fr":"fra", "hi": "hin","it":"ita","ja":"jpn", \
|
119 |
"nl":"nld", "pl":"pol", "pt":"por", "ru":"rus", "sw":"swh", "th":"tha", "tr":"tur", "ur": "urd", "vi":"vie", "zh":"cmn"}
|
120 |
-
sentence_test = pd.read_csv('
|
121 |
sentence_test = sentence_test[:4750]
|
122 |
# Instanciation d'un exemple
|
123 |
exemples = ["Er weiß überhaupt nichts über dieses Buch", # Phrase 0
|
@@ -135,8 +137,8 @@ def init_lang_id_external():
|
|
135 |
return lang_id_model_ext, dict_xlmr, sentence_test, lang_exemples, exemples
|
136 |
|
137 |
@st.cache_data
|
138 |
-
def display_acp():
|
139 |
-
data = np.load('
|
140 |
X_train_scaled = data['X_train_scaled']
|
141 |
y_train_pred = data['y_train_pred']
|
142 |
label_arrow = ['.', ',', '?', ' a', ' de', ' la', ' que', 'Tom', ' un', ' the', ' in', \
|
@@ -167,7 +169,7 @@ def display_acp():
|
|
167 |
plt.rc("xtick", labelsize=14) # Taille des étiquettes de l'axe des x
|
168 |
plt.rc("ytick", labelsize=14) # Taille des étiquettes de l'axe des y
|
169 |
|
170 |
-
st.write(
|
171 |
st.write("")
|
172 |
fig = plt.figure(figsize=(20, 15))
|
173 |
sns.scatterplot(x='PC1', y='PC2', hue='Langue', data=finalDF, alpha=0.5)
|
@@ -175,7 +177,7 @@ def display_acp():
|
|
175 |
plt.arrow(0, 0, coeff[i, 0]*1.5, coeff[i, 1]*0.8,color='k', alpha=0.08, head_width=0.01, )
|
176 |
plt.text(coeff[i, 0]*1.5, coeff[i, 1] * 0.8, label_arrow[i], color='k', weight='bold')
|
177 |
|
178 |
-
plt.title(
|
179 |
plt.xlim(-0.4, 0.45)
|
180 |
plt.ylim(-0.15, 0.28);
|
181 |
st.pyplot(fig)
|
@@ -183,7 +185,7 @@ def display_acp():
|
|
183 |
|
184 |
@st.cache_data
|
185 |
def read_BOW_examples():
|
186 |
-
return pd.read_csv('
|
187 |
|
188 |
def analyse_nb(sel_phrase):
|
189 |
global lang_exemples,exemples
|
@@ -199,9 +201,9 @@ def analyse_nb(sel_phrase):
|
|
199 |
if sb[i] > 0: nb_unique_token +=1
|
200 |
return sb, nb_unique_token
|
201 |
|
202 |
-
st.write("#### **Probabilité d'appartenance de la phrase à une langue :**")
|
203 |
st.image("./assets/formule_proba_naive_bayes.png")
|
204 |
-
st.write("où **C** est la classe (lan_code), **Fi** est la caractéristique i du BOW, **Z** est l'\"evidence\" servant à regulariser la
|
205 |
st.write("")
|
206 |
nb_lang = 5
|
207 |
lan_code = ['deu','eng','fra','spa','ita']
|
@@ -214,14 +216,14 @@ def analyse_nb(sel_phrase):
|
|
214 |
nb_phrases_lang =[]
|
215 |
for l in lan_code:
|
216 |
nb_phrases_lang.append(sum(df_BOW['lan_code']==l))
|
217 |
-
st.write("Phrase à analyser :",'**:'+lan_color[lang_exemples[sel_phrase]]+'['+lang_exemples[sel_phrase],']** - **"'+exemples[sel_phrase]+'"**')
|
218 |
|
219 |
# Tokenisation et encodage de la phrase
|
220 |
encodage = tokenizer.encode(exemples[sel_phrase])
|
221 |
|
222 |
# Création du vecteur BOW de la phrase
|
223 |
bow_exemple, nb_unique_token = create_small_BOW(exemples[sel_phrase])
|
224 |
-
st.write("Nombre de tokens retenus dans le BOW: "+ str(nb_unique_token))
|
225 |
masque_tokens_retenus = [(1 if token in list(dict_ids.keys()) else 0) for token in encodage]
|
226 |
str_token = " "
|
227 |
for i in range(len(encodage)):
|
@@ -232,7 +234,7 @@ def analyse_nb(sel_phrase):
|
|
232 |
str_token += "**:violet["+tokenizer.decode([encodage[i]])+"]** "
|
233 |
else: str_token += ":green["+tokenizer.decode([encodage[i]])+"] "
|
234 |
|
235 |
-
st.write("Tokens se trouvant dans le modèle (en :red[rouge] ou :violet[violet]) :"+str_token+" ")
|
236 |
|
237 |
st.write("")
|
238 |
# Afin de continuer l'analyse on ne garde que les token de la phrase disponibles dans le BOW
|
@@ -251,7 +253,7 @@ def analyse_nb(sel_phrase):
|
|
251 |
col_name = [str(i+1)+'-'+tokenizer.decode([int(token_used[i])]) for i in range(len(token_used))]
|
252 |
df_count = pd.DataFrame(data=votes,columns=token_used, index=lan_code)
|
253 |
df_count.columns = col_name
|
254 |
-
st.write("\n**Nombre d'apparitions des tokens, dans chaque langue**")
|
255 |
|
256 |
# Lissage de Laplace n°1 (Laplace smoothing )
|
257 |
# df_count = df_count+1
|
@@ -284,7 +286,7 @@ def analyse_nb(sel_phrase):
|
|
284 |
df_proba['Proba'] = df_proba['Proba'].round(3)
|
285 |
|
286 |
# Affichage de la matrice des probabilités
|
287 |
-
st.write("**Probabilités conditionnelles d'apparition des tokens retenus, dans chaque langue:**")
|
288 |
st.dataframe(df_proba)
|
289 |
str_token = "Lang proba max: "# "*20
|
290 |
for i,token in enumerate(df_proba.columns[:-1]):
|
@@ -292,17 +294,17 @@ def analyse_nb(sel_phrase):
|
|
292 |
st.write(str_token)
|
293 |
st.write("")
|
294 |
|
295 |
-
st.write("Langue réelle de la phrase"+" "*35+": **:"+lan_color[lang_exemples[sel_phrase]]+'['+lang_exemples[sel_phrase]+']**')
|
296 |
-
st.write("Langue dont la probabilité est la plus forte "+": **:"+lan_color[df_proba['Proba'].idxmax()]+'['+df_proba['Proba'].idxmax(),"]** (proba={:.2f}".format(max(df_proba['Proba']))+")")
|
297 |
prediction = clf_nb2.predict([bow_exemple])
|
298 |
-
st.write("Langue prédite par Naiva Bayes"+" "*23+": **:"+lan_color[prediction[0]]+'['+prediction[0]+"]** (proba={:.2f}".format(max(clf_nb2.predict_proba([bow_exemple])[0]))+")")
|
299 |
st.write("")
|
300 |
|
301 |
fig, axs = plt.subplots(1, 2, figsize=(10, 6))
|
302 |
df_proba_sorted =df_proba.sort_index(ascending=True)
|
303 |
-
axs[0].set_title("Probabilités calculée manuellement", fontsize=12)
|
304 |
axs[0].barh(df_proba_sorted.index, df_proba_sorted['Proba'])
|
305 |
-
axs[1].set_title("Probabilités du classifieur Naive Bayes", fontsize=12)
|
306 |
axs[1].barh(df_proba_sorted.index, clf_nb2.predict_proba([bow_exemple])[0]);
|
307 |
st.pyplot(fig)
|
308 |
return
|
@@ -313,9 +315,9 @@ def find_exemple(lang_sel):
|
|
313 |
return exemples[lang_sel]
|
314 |
|
315 |
def display_shapley(lang_sel):
|
316 |
-
st.write("**Analyse de l'importance de chaque token dans l'identification de la langue**")
|
317 |
st.image('assets/fig_schapley'+str(lang_sel)+'.png')
|
318 |
-
st.write("**Recapitulatif de l'influence des tokens sur la selection de la langue**")
|
319 |
st.image('assets/fig_schapley_recap'+str(lang_sel)+'.png')
|
320 |
return
|
321 |
|
@@ -330,54 +332,58 @@ def run():
|
|
330 |
lang_id_model_ext, dict_xlmr, sentence_test, lang_exemples, exemples= init_lang_id_external()
|
331 |
|
332 |
st.write("")
|
333 |
-
st.title(title)
|
334 |
-
st.write("## **Explications :**\n")
|
335 |
-
st.markdown(
|
336 |
"""
|
337 |
-
Afin de mettre en oeuvre cette fonctionnalité nous avons utilisé un jeu d'entrainement multilinge de
|
338 |
-
Les 95 langues identifiées sont:
|
|
|
|
|
|
|
|
|
339 |
"""
|
340 |
-
)
|
341 |
-
st.selectbox(label="",options=sorted(lan_identified))
|
342 |
-
st.markdown("""
|
343 |
Nous avons utilisé 2 méthodes pour identifier la langue d'un texte:
|
344 |
1. un classificateur **Naïve Bayes**
|
345 |
2. un modèle de **Deep Learning**
|
346 |
-
|
|
|
|
|
|
|
347 |
Les 2 modèles ont un accuracy similaire sur le jeu de test: **:red[96% pour NB et 97,5% pour DL]**
|
348 |
<br>
|
349 |
-
"""
|
350 |
, unsafe_allow_html=True)
|
351 |
|
352 |
chosen_id = tab_bar(data=[
|
353 |
-
TabBarItemData(id="tab1", title="Id. Naïve Bayes", description="avec le Bag Of Words"),
|
354 |
-
TabBarItemData(id="tab2", title="Id. Deep Learning", description=" avec Keras"),
|
355 |
-
TabBarItemData(id="tab3", title="Interpretabilité", description="du modèle Naïve Bayes ")],
|
356 |
default="tab1")
|
357 |
|
358 |
if (chosen_id == "tab1") or (chosen_id == "tab2"):
|
359 |
-
st.write("## **Paramètres :**\n")
|
360 |
|
361 |
-
toggle_val = st.toggle('Phrase à saisir/Phrase test', value=True, help="Off = phrase à saisir, On = selection d'une phrase test parmi 9500
|
362 |
if toggle_val:
|
363 |
-
custom_sentence= st.selectbox("Selectionnez une phrases test à identifier:", sentence_test['sentence'] )
|
364 |
else:
|
365 |
-
custom_sentence = st.text_area(label="Saisir le texte dont vous souhaitez identifier la langue:")
|
366 |
-
st.button(label="Valider", type="primary")
|
367 |
|
368 |
if custom_sentence!='':
|
369 |
-
st.write("## **Résultats :**\n")
|
370 |
md = """
|
371 |
-
|Identifieur |Langue
|
372 |
|-------------------------------------|---------------|"""
|
373 |
md1 = ""
|
374 |
if toggle_val:
|
375 |
lan_reelle = sentence_test['lan_code'].loc[sentence_test['sentence']==custom_sentence].tolist()[0]
|
376 |
md1 = """
|
377 |
-
|Langue réelle |**:blue["""+lan_to_language[lan_reelle]+"""]**|"""
|
378 |
md2 = """
|
379 |
-
|Classificateur Naïve Bayes |**:red["""+lang_id_nb(custom_sentence)+"""]**|
|
380 |
-
|Modèle de Deep Learning |**:red["""+lang_id_dl(custom_sentence)+"""]**|"""
|
381 |
md3 = """
|
382 |
|XLM-RoBERTa (Hugging Face) |**:red["""+lan_to_language[dict_xlmr[lang_id_model_ext(custom_sentence)[0]['label']]]+"""]**|"""
|
383 |
if toggle_val:
|
@@ -386,64 +392,88 @@ def run():
|
|
386 |
|
387 |
st.markdown(md+md1+md2+md3, unsafe_allow_html=True)
|
388 |
|
389 |
-
st.write("## **Details sur la méthode :**\n")
|
390 |
if (chosen_id == "tab1"):
|
391 |
-
st.markdown(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
392 |
"""
|
393 |
-
Afin d'utiliser le classificateur Naïve Bayes, il nous a fallu:
|
394 |
-
- Créer un Bag of Words de token..
|
395 |
-
- ..Tokeniser le texte d'entrainement avec CountVectorizer et un tokenizer 'custom', **Tiktoken** d'OpenAI.
|
396 |
-
- Utiliser des matrices creuses (Sparse Matrix), car notre BOW contenait 10 M de lignes x 59122 tokens.
|
397 |
-
- Sauvegarder le vectorizer (non serialisable) et le classificateur entrainé.
|
398 |
-
|
399 |
L'execution de toutes ces étapes est assez rapide: une dizaine de minutes
|
400 |
<br>
|
401 |
Le résultat est très bon: L'Accuracy sur le jeu de test est =
|
402 |
**:red[96%]** sur les 95 langues, et **:red[99,1%]** sur les 5 langues d'Europe de l'Ouest (en,fr,de,it,sp)
|
403 |
<br>
|
|
|
|
|
|
|
|
|
404 |
**Note 1:** Les 2 modèles ont un accuracy similaire sur le jeu de test: **:red[96% pour NB et 97,5% pour DL]**
|
405 |
**Note 2:** Le modèle *XLM-RoBERTa* de Hugging Face (qui identifie 20 langues seulement) a une accuracy, sur notre jeu de test = **97,8%**,
|
406 |
versus **99,3% pour NB** et **99,2% pour DL** sur ces 20 langues.
|
407 |
-
"""
|
408 |
, unsafe_allow_html=True)
|
409 |
else:
|
410 |
-
st.markdown(
|
411 |
"""
|
412 |
-
Nous avons mis en oeuvre un modèle Keras avec une couche d'embedding et 4 couches denses *
|
413 |
-
Nous avons utilisé le tokeniser
|
414 |
La couche d'embedding accepte 250 tokens, ce qui signifie que la détection de langue s'effectue sur approximativement les 200 premiers mots.
|
415 |
<br>
|
|
|
|
|
|
|
|
|
416 |
L'entrainement a duré plus de 10 heures..
|
417 |
Finalement, le résultat est très bon: L'Accuracy sur le jeu de test est =
|
418 |
**:red[97,5%]** sur les 95 langues, et **:red[99,1%]** sur les 5 langues d'Europe de l'Ouest (en,fr,de,it,sp).
|
419 |
Néanmoins, la durée pour une prédiction est relativement longue: approximativement 5/100 de seconde
|
420 |
<br>
|
421 |
-
|
422 |
-
|
|
|
|
|
|
|
|
|
|
|
423 |
versus **99,3% pour NB** et **99,2% pour DL** sur ces 20 langues.
|
424 |
<br>
|
425 |
-
"""
|
426 |
, unsafe_allow_html=True)
|
427 |
-
st.write("<center><h5>Architecture du modèle
|
428 |
plot_model(dl_model, show_shapes=True, show_layer_names=True, show_layer_activations=True,rankdir='TB',to_file='./assets/model_plot.png')
|
429 |
col1, col2, col3 = st.columns([0.15,0.7,0.15])
|
430 |
with col2:
|
431 |
st.image('./assets/model_plot.png',use_column_width="auto")
|
432 |
elif (chosen_id == "tab3"):
|
433 |
-
st.write("### **Interpretabilité du classifieur Naïve Bayes sur 5 langues**")
|
434 |
-
st.write("##### ..et un Training set réduit (15000 phrases et 94 tokens)")
|
435 |
st.write("")
|
436 |
|
437 |
chosen_id2 = tab_bar(data=[
|
438 |
-
TabBarItemData(id="tab1", title="Analyse en Compos. Princ.", description=""),
|
439 |
-
TabBarItemData(id="tab2", title="Simul. calcul NB", description=""),
|
440 |
-
TabBarItemData(id="tab3", title="Shapley", description="")],
|
441 |
default="tab1")
|
442 |
if (chosen_id2 == "tab1"):
|
443 |
-
display_acp()
|
444 |
if (chosen_id2 == "tab2") or (chosen_id2 == "tab3"):
|
445 |
-
sel_phrase = st.selectbox('Selectionnez une phrase à "interpréter":', range(9), format_func=find_exemple)
|
446 |
if (chosen_id2 == "tab2"):
|
447 |
analyse_nb(sel_phrase)
|
448 |
if (chosen_id2 == "tab3"):
|
449 |
display_shapley(sel_phrase)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
import matplotlib.pyplot as plt
|
21 |
import seaborn as sns
|
22 |
from sklearn import naive_bayes
|
23 |
+
from translate_app import tr
|
24 |
|
25 |
title = "Identification de langue"
|
26 |
sidebar_name = "Identification de langue"
|
27 |
+
dataPath = st.session_state.DataPath
|
28 |
|
29 |
# CountVectorizer a une liste de phrase en entrée.
|
30 |
# Cette fonction met les données d'entrée dans le bon format
|
|
|
49 |
def load_vectorizer(tokenizer):
|
50 |
global dict_token, dict_ids, nb_token
|
51 |
|
52 |
+
path = dataPath+'/vectorizer_tiktoken_big.pkl'
|
53 |
vectorizer = joblib.load(path)
|
54 |
dict_token = {tokenizer.decode([cle]): cle for cle, valeur in vectorizer.vocabulary_.items()}
|
55 |
dict_ids = {cle: tokenizer.decode([cle]) for cle, valeur in vectorizer.vocabulary_.items()} #dict_ids.items()}
|
|
|
69 |
tokenizer = tiktoken.get_encoding("cl100k_base")
|
70 |
|
71 |
# Chargement du classificateur sauvegardé
|
72 |
+
clf_nb = joblib.load(dataPath+"/id_lang_tiktoken_nb_sparse_big.pkl")
|
73 |
vectorizer = load_vectorizer(tokenizer)
|
74 |
|
75 |
# Lisez le contenu du fichier JSON
|
76 |
+
with open(dataPath+'/multilingue/lan_to_language.json', 'r') as fichier:
|
77 |
lan_to_language = json.load(fichier)
|
78 |
return tokenizer, dict_token, dict_ids, nb_token, lan_to_language, clf_nb, vectorizer
|
79 |
|
|
|
86 |
|
87 |
def read_list_lan():
|
88 |
|
89 |
+
with open(dataPath+'/multilingue/lan_code.csv', 'r') as fichier_csv:
|
90 |
reader = csv.reader(fichier_csv)
|
91 |
lan_code = next(reader)
|
92 |
return lan_code
|
|
|
98 |
list_lan = read_list_lan()
|
99 |
lan_identified = [lan_to_language[l] for l in list_lan]
|
100 |
label_encoder.fit(list_lan)
|
101 |
+
merge = Merge(dataPath+"/dl_id_lang_split", "../data", "dl_tiktoken_id_language_model.h5").merge(cleanup=False)
|
102 |
+
dl_model = keras.models.load_model(dataPath+"/dl_tiktoken_id_language_model.h5")
|
103 |
return dl_model, label_encoder, list_lan, lan_identified
|
104 |
|
105 |
def lang_id_dl(sentences):
|
|
|
119 |
lang_id_model_ext = pipeline('text-classification',model="papluca/xlm-roberta-base-language-detection")
|
120 |
dict_xlmr = {"ar":"ara", "bg":"bul", "de":"deu", "el": "ell", "en":"eng", "es":"spa", "fr":"fra", "hi": "hin","it":"ita","ja":"jpn", \
|
121 |
"nl":"nld", "pl":"pol", "pt":"por", "ru":"rus", "sw":"swh", "th":"tha", "tr":"tur", "ur": "urd", "vi":"vie", "zh":"cmn"}
|
122 |
+
sentence_test = pd.read_csv(dataPath+'//multilingue/sentence_test_extract.csv')
|
123 |
sentence_test = sentence_test[:4750]
|
124 |
# Instanciation d'un exemple
|
125 |
exemples = ["Er weiß überhaupt nichts über dieses Buch", # Phrase 0
|
|
|
137 |
return lang_id_model_ext, dict_xlmr, sentence_test, lang_exemples, exemples
|
138 |
|
139 |
@st.cache_data
|
140 |
+
def display_acp(title, comment):
|
141 |
+
data = np.load(dataPath+'/data_lang_id_acp.npz')
|
142 |
X_train_scaled = data['X_train_scaled']
|
143 |
y_train_pred = data['y_train_pred']
|
144 |
label_arrow = ['.', ',', '?', ' a', ' de', ' la', ' que', 'Tom', ' un', ' the', ' in', \
|
|
|
169 |
plt.rc("xtick", labelsize=14) # Taille des étiquettes de l'axe des x
|
170 |
plt.rc("ytick", labelsize=14) # Taille des étiquettes de l'axe des y
|
171 |
|
172 |
+
st.write(comment)
|
173 |
st.write("")
|
174 |
fig = plt.figure(figsize=(20, 15))
|
175 |
sns.scatterplot(x='PC1', y='PC2', hue='Langue', data=finalDF, alpha=0.5)
|
|
|
177 |
plt.arrow(0, 0, coeff[i, 0]*1.5, coeff[i, 1]*0.8,color='k', alpha=0.08, head_width=0.01, )
|
178 |
plt.text(coeff[i, 0]*1.5, coeff[i, 1] * 0.8, label_arrow[i], color='k', weight='bold')
|
179 |
|
180 |
+
plt.title(title)
|
181 |
plt.xlim(-0.4, 0.45)
|
182 |
plt.ylim(-0.15, 0.28);
|
183 |
st.pyplot(fig)
|
|
|
185 |
|
186 |
@st.cache_data
|
187 |
def read_BOW_examples():
|
188 |
+
return pd.read_csv(dataPath+'/lang_id_small_BOW.csv')
|
189 |
|
190 |
def analyse_nb(sel_phrase):
|
191 |
global lang_exemples,exemples
|
|
|
201 |
if sb[i] > 0: nb_unique_token +=1
|
202 |
return sb, nb_unique_token
|
203 |
|
204 |
+
st.write("#### **"+tr("Probabilité d'appartenance de la phrase à une langue")+" :**")
|
205 |
st.image("./assets/formule_proba_naive_bayes.png")
|
206 |
+
st.write(tr("où **C** est la classe (lan_code), **Fi** est la caractéristique i du BOW, **Z** est l'\"evidence\" servant à regulariser la probabilité"))
|
207 |
st.write("")
|
208 |
nb_lang = 5
|
209 |
lan_code = ['deu','eng','fra','spa','ita']
|
|
|
216 |
nb_phrases_lang =[]
|
217 |
for l in lan_code:
|
218 |
nb_phrases_lang.append(sum(df_BOW['lan_code']==l))
|
219 |
+
st.write(tr("Phrase à analyser")+" :",'**:'+lan_color[lang_exemples[sel_phrase]]+'['+lang_exemples[sel_phrase],']** - **"'+exemples[sel_phrase]+'"**')
|
220 |
|
221 |
# Tokenisation et encodage de la phrase
|
222 |
encodage = tokenizer.encode(exemples[sel_phrase])
|
223 |
|
224 |
# Création du vecteur BOW de la phrase
|
225 |
bow_exemple, nb_unique_token = create_small_BOW(exemples[sel_phrase])
|
226 |
+
st.write(tr("Nombre de tokens retenus dans le BOW")+": "+ str(nb_unique_token))
|
227 |
masque_tokens_retenus = [(1 if token in list(dict_ids.keys()) else 0) for token in encodage]
|
228 |
str_token = " "
|
229 |
for i in range(len(encodage)):
|
|
|
234 |
str_token += "**:violet["+tokenizer.decode([encodage[i]])+"]** "
|
235 |
else: str_token += ":green["+tokenizer.decode([encodage[i]])+"] "
|
236 |
|
237 |
+
st.write(tr("Tokens se trouvant dans le modèle (en")+" :red["+tr("rouge")+"] "+tr("ou")+" :violet["+tr("violet")+"]) :"+str_token+" ")
|
238 |
|
239 |
st.write("")
|
240 |
# Afin de continuer l'analyse on ne garde que les token de la phrase disponibles dans le BOW
|
|
|
253 |
col_name = [str(i+1)+'-'+tokenizer.decode([int(token_used[i])]) for i in range(len(token_used))]
|
254 |
df_count = pd.DataFrame(data=votes,columns=token_used, index=lan_code)
|
255 |
df_count.columns = col_name
|
256 |
+
st.write("\n**"+tr("Nombre d'apparitions des tokens, dans chaque langue")+"**")
|
257 |
|
258 |
# Lissage de Laplace n°1 (Laplace smoothing )
|
259 |
# df_count = df_count+1
|
|
|
286 |
df_proba['Proba'] = df_proba['Proba'].round(3)
|
287 |
|
288 |
# Affichage de la matrice des probabilités
|
289 |
+
st.write("**"+tr("Probabilités conditionnelles d'apparition des tokens retenus, dans chaque langue")+":**")
|
290 |
st.dataframe(df_proba)
|
291 |
str_token = "Lang proba max: "# "*20
|
292 |
for i,token in enumerate(df_proba.columns[:-1]):
|
|
|
294 |
st.write(str_token)
|
295 |
st.write("")
|
296 |
|
297 |
+
st.write(tr("Langue réelle de la phrase")+" "*35+": **:"+lan_color[lang_exemples[sel_phrase]]+'['+lang_exemples[sel_phrase]+']**')
|
298 |
+
st.write(tr("Langue dont la probabilité est la plus forte ")+": **:"+lan_color[df_proba['Proba'].idxmax()]+'['+df_proba['Proba'].idxmax(),"]** (proba={:.2f}".format(max(df_proba['Proba']))+")")
|
299 |
prediction = clf_nb2.predict([bow_exemple])
|
300 |
+
st.write(tr("Langue prédite par Naiva Bayes")+" "*23+": **:"+lan_color[prediction[0]]+'['+prediction[0]+"]** (proba={:.2f}".format(max(clf_nb2.predict_proba([bow_exemple])[0]))+")")
|
301 |
st.write("")
|
302 |
|
303 |
fig, axs = plt.subplots(1, 2, figsize=(10, 6))
|
304 |
df_proba_sorted =df_proba.sort_index(ascending=True)
|
305 |
+
axs[0].set_title(tr("Probabilités calculée manuellement"), fontsize=12)
|
306 |
axs[0].barh(df_proba_sorted.index, df_proba_sorted['Proba'])
|
307 |
+
axs[1].set_title(tr("Probabilités du classifieur Naive Bayes"), fontsize=12)
|
308 |
axs[1].barh(df_proba_sorted.index, clf_nb2.predict_proba([bow_exemple])[0]);
|
309 |
st.pyplot(fig)
|
310 |
return
|
|
|
315 |
return exemples[lang_sel]
|
316 |
|
317 |
def display_shapley(lang_sel):
|
318 |
+
st.write("**"+tr("Analyse de l'importance de chaque token dans l'identification de la langue")+"**")
|
319 |
st.image('assets/fig_schapley'+str(lang_sel)+'.png')
|
320 |
+
st.write("**"+tr("Recapitulatif de l'influence des tokens sur la selection de la langue")+"**")
|
321 |
st.image('assets/fig_schapley_recap'+str(lang_sel)+'.png')
|
322 |
return
|
323 |
|
|
|
332 |
lang_id_model_ext, dict_xlmr, sentence_test, lang_exemples, exemples= init_lang_id_external()
|
333 |
|
334 |
st.write("")
|
335 |
+
st.title(tr(title))
|
336 |
+
st.write("## **"+tr("Explications")+" :**\n")
|
337 |
+
st.markdown(tr(
|
338 |
"""
|
339 |
+
Afin de mettre en oeuvre cette fonctionnalité nous avons utilisé un jeu d'entrainement multilinge de <b> 9.757.778 phrases dans 95 langues</b>.
|
340 |
+
Les 95 langues identifiées sont:
|
341 |
+
""")
|
342 |
+
, unsafe_allow_html=True)
|
343 |
+
st.selectbox(label="Lang",options=sorted(lan_identified),label_visibility="hidden")
|
344 |
+
st.markdown(tr(
|
345 |
"""
|
|
|
|
|
|
|
346 |
Nous avons utilisé 2 méthodes pour identifier la langue d'un texte:
|
347 |
1. un classificateur **Naïve Bayes**
|
348 |
2. un modèle de **Deep Learning**
|
349 |
+
""")
|
350 |
+
, unsafe_allow_html=True)
|
351 |
+
st.markdown(tr(
|
352 |
+
"""
|
353 |
Les 2 modèles ont un accuracy similaire sur le jeu de test: **:red[96% pour NB et 97,5% pour DL]**
|
354 |
<br>
|
355 |
+
""")
|
356 |
, unsafe_allow_html=True)
|
357 |
|
358 |
chosen_id = tab_bar(data=[
|
359 |
+
TabBarItemData(id="tab1", title=tr("Id. Naïve Bayes"), description=tr("avec le Bag Of Words")),
|
360 |
+
TabBarItemData(id="tab2", title=tr("Id. Deep Learning"), description=tr(" avec Keras")),
|
361 |
+
TabBarItemData(id="tab3", title=tr("Interpretabilité"), description=tr("du modèle Naïve Bayes "))],
|
362 |
default="tab1")
|
363 |
|
364 |
if (chosen_id == "tab1") or (chosen_id == "tab2"):
|
365 |
+
st.write("## **"+tr("Paramètres")+" :**\n")
|
366 |
|
367 |
+
toggle_val = st.toggle(tr('Phrase à saisir/Phrase test'), value=True, help=tr("Off = phrase à saisir, On = selection d'une phrase test parmi 9500 phrases"))
|
368 |
if toggle_val:
|
369 |
+
custom_sentence= st.selectbox(tr("Selectionnez une phrases test à identifier")+":", sentence_test['sentence'] )
|
370 |
else:
|
371 |
+
custom_sentence = st.text_area(label=tr("Saisir le texte dont vous souhaitez identifier la langue:"))
|
372 |
+
st.button(label=tr("Valider"), type="primary")
|
373 |
|
374 |
if custom_sentence!='':
|
375 |
+
st.write("## **"+tr("Résultats")+" :**\n")
|
376 |
md = """
|
377 |
+
|"""+tr("Identifieur")+""" |"""+tr("Langue identifiée")+"""|
|
378 |
|-------------------------------------|---------------|"""
|
379 |
md1 = ""
|
380 |
if toggle_val:
|
381 |
lan_reelle = sentence_test['lan_code'].loc[sentence_test['sentence']==custom_sentence].tolist()[0]
|
382 |
md1 = """
|
383 |
+
|"""+tr("Langue réelle")+""" |**:blue["""+lan_to_language[lan_reelle]+"""]**|"""
|
384 |
md2 = """
|
385 |
+
|"""+tr("Classificateur Naïve Bayes")+""" |**:red["""+lang_id_nb(custom_sentence)+"""]**|
|
386 |
+
|"""+tr("Modèle de Deep Learning")+""" |**:red["""+lang_id_dl(custom_sentence)+"""]**|"""
|
387 |
md3 = """
|
388 |
|XLM-RoBERTa (Hugging Face) |**:red["""+lan_to_language[dict_xlmr[lang_id_model_ext(custom_sentence)[0]['label']]]+"""]**|"""
|
389 |
if toggle_val:
|
|
|
392 |
|
393 |
st.markdown(md+md1+md2+md3, unsafe_allow_html=True)
|
394 |
|
395 |
+
st.write("## **"+tr("Details sur la méthode")+" :**\n")
|
396 |
if (chosen_id == "tab1"):
|
397 |
+
st.markdown(tr(
|
398 |
+
"""
|
399 |
+
Afin d'utiliser le classificateur Naïve Bayes, il nous a fallu:""")+"\n"+
|
400 |
+
"* "+tr("Créer un Bag of Words de token..")+"\n"+
|
401 |
+
"* "+tr("..Tokeniser le texte d'entrainement avec CountVectorizer et un tokenizer 'custom', **Tiktoken** d'OpenAI. ")+"\n"+
|
402 |
+
"* "+tr("Utiliser des matrices creuses (Sparse Matrix), car notre BOW contenait 10 Millions de lignes x 59122 tokens. ")+"\n"+
|
403 |
+
"* "+tr("Sauvegarder le vectorizer (non serialisable) et le classificateur entrainé. ")
|
404 |
+
, unsafe_allow_html=True)
|
405 |
+
st.markdown(tr(
|
406 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
407 |
L'execution de toutes ces étapes est assez rapide: une dizaine de minutes
|
408 |
<br>
|
409 |
Le résultat est très bon: L'Accuracy sur le jeu de test est =
|
410 |
**:red[96%]** sur les 95 langues, et **:red[99,1%]** sur les 5 langues d'Europe de l'Ouest (en,fr,de,it,sp)
|
411 |
<br>
|
412 |
+
""")
|
413 |
+
, unsafe_allow_html=True)
|
414 |
+
st.markdown(tr(
|
415 |
+
"""
|
416 |
**Note 1:** Les 2 modèles ont un accuracy similaire sur le jeu de test: **:red[96% pour NB et 97,5% pour DL]**
|
417 |
**Note 2:** Le modèle *XLM-RoBERTa* de Hugging Face (qui identifie 20 langues seulement) a une accuracy, sur notre jeu de test = **97,8%**,
|
418 |
versus **99,3% pour NB** et **99,2% pour DL** sur ces 20 langues.
|
419 |
+
""")
|
420 |
, unsafe_allow_html=True)
|
421 |
else:
|
422 |
+
st.markdown(tr(
|
423 |
"""
|
424 |
+
Nous avons mis en oeuvre un modèle Keras avec une couche d'embedding et 4 couches denses (*Voir architecture ci-dessous*).
|
425 |
+
Nous avons utilisé le tokeniser <b>Tiktoken</b> d'OpenAI.
|
426 |
La couche d'embedding accepte 250 tokens, ce qui signifie que la détection de langue s'effectue sur approximativement les 200 premiers mots.
|
427 |
<br>
|
428 |
+
""")
|
429 |
+
, unsafe_allow_html=True)
|
430 |
+
st.markdown(tr(
|
431 |
+
"""
|
432 |
L'entrainement a duré plus de 10 heures..
|
433 |
Finalement, le résultat est très bon: L'Accuracy sur le jeu de test est =
|
434 |
**:red[97,5%]** sur les 95 langues, et **:red[99,1%]** sur les 5 langues d'Europe de l'Ouest (en,fr,de,it,sp).
|
435 |
Néanmoins, la durée pour une prédiction est relativement longue: approximativement 5/100 de seconde
|
436 |
<br>
|
437 |
+
""")
|
438 |
+
, unsafe_allow_html=True)
|
439 |
+
st.markdown(tr(
|
440 |
+
"""
|
441 |
+
**Note 1:** Les 2 modèles ont un accuracy similaire sur le jeu de test: **:red[96% pour NB et 97,5% pour DL]**""")+"<br>"+
|
442 |
+
tr("""
|
443 |
+
**Note 2:** Le modèle *XLM-RoBERTa* de Hugging Face (qui identifie 20 langues seulement) a une accuracy, sur notre jeu de test = <b>97,8%</b>,
|
444 |
versus **99,3% pour NB** et **99,2% pour DL** sur ces 20 langues.
|
445 |
<br>
|
446 |
+
""")
|
447 |
, unsafe_allow_html=True)
|
448 |
+
st.write("<center><h5>"+tr("Architecture du modèle utilisé")+":</h5></center>", unsafe_allow_html=True)
|
449 |
plot_model(dl_model, show_shapes=True, show_layer_names=True, show_layer_activations=True,rankdir='TB',to_file='./assets/model_plot.png')
|
450 |
col1, col2, col3 = st.columns([0.15,0.7,0.15])
|
451 |
with col2:
|
452 |
st.image('./assets/model_plot.png',use_column_width="auto")
|
453 |
elif (chosen_id == "tab3"):
|
454 |
+
st.write("### **"+tr("Interpretabilité du classifieur Naïve Bayes sur 5 langues")+"**")
|
455 |
+
st.write("##### "+tr("..et un Training set réduit (15000 phrases et 94 tokens)"))
|
456 |
st.write("")
|
457 |
|
458 |
chosen_id2 = tab_bar(data=[
|
459 |
+
TabBarItemData(id="tab1", title=tr("Analyse en Compos. Princ."), description=""),
|
460 |
+
TabBarItemData(id="tab2", title=tr("Simul. calcul NB"), description=""),
|
461 |
+
TabBarItemData(id="tab3", title=tr("Shapley"), description="")],
|
462 |
default="tab1")
|
463 |
if (chosen_id2 == "tab1"):
|
464 |
+
display_acp(tr("Importance des principaux tokens dans \n l'identification de langue par l'algorithme Naive Bayes"),tr("Affichage de 10 000 phrases (points) et des 50 tokens les + utilisés (flèches)"))
|
465 |
if (chosen_id2 == "tab2") or (chosen_id2 == "tab3"):
|
466 |
+
sel_phrase = st.selectbox(tr('Selectionnez une phrase à "interpréter"')+':', range(9), format_func=find_exemple)
|
467 |
if (chosen_id2 == "tab2"):
|
468 |
analyse_nb(sel_phrase)
|
469 |
if (chosen_id2 == "tab3"):
|
470 |
display_shapley(sel_phrase)
|
471 |
+
|
472 |
+
|
473 |
+
|
474 |
+
|
475 |
+
|
476 |
+
|
477 |
+
|
478 |
+
|
479 |
+
|
tabs/intro.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1 |
import streamlit as st
|
2 |
-
|
3 |
-
|
4 |
|
5 |
title = "Démosthène"
|
6 |
sidebar_name = "Introduction"
|
@@ -15,51 +14,80 @@ def run():
|
|
15 |
# st.image("assets/tough-communication.gif",use_column_width=True)
|
16 |
|
17 |
st.write("")
|
18 |
-
st.
|
19 |
-
|
|
|
|
|
|
|
|
|
20 |
st.markdown('''
|
21 |
-
## **Système de traduction adapté aux lunettes connectées**
|
22 |
---
|
23 |
''')
|
24 |
-
st.header("**A propos**")
|
25 |
-
st.markdown(
|
26 |
"""
|
27 |
Ce projet a été réalisé dans le cadre d’une formation de Data Scientist, entre juin et novembre 2023.
|
28 |
<br>
|
29 |
:red[**Démosthène**] est l'un des plus grands orateurs de l'Antiquité. Il savait s’exprimer, et se faire comprendre.
|
30 |
Se faire comprendre est l’un des principaux objectifs de la traduction.
|
|
|
|
|
|
|
|
|
31 |
Démosthène avait de gros problèmes d’élocution.
|
32 |
Il les a surmontés en s’entraînant à parler avec des cailloux dans la bouche.
|
33 |
À l’image de l’Intelligence Artificielle, où des entraînements sont nécessaires pour obtenir de bons résultats.
|
34 |
Il nous a semblé pertinent de donner le nom de cet homme à un projet qu’il a fort bien illustré, il y a 2300 ans.
|
35 |
-
"""
|
36 |
, unsafe_allow_html=True)
|
37 |
-
st.header("**Contexte**")
|
38 |
|
39 |
-
st.
|
|
|
40 |
"""
|
41 |
Les personnes malentendantes communiquent difficilement avec autrui. Par ailleurs, toute personne se trouvant dans un pays étranger
|
42 |
dont il ne connaît pas la langue se retrouve dans la situation d’une personne malentendante.
|
|
|
|
|
|
|
|
|
43 |
L’usage de lunettes connectées, dotées de la technologie de reconnaissance vocale et d’algorithmes IA de deep learning, permettrait
|
44 |
de détecter la voix d’un interlocuteur, puis d’afficher la transcription textuelle, sur les verres en temps réel.
|
45 |
À partir de cette transcription, il est possible d’:red[**afficher la traduction dans la langue du porteur de ces lunettes**].
|
|
|
|
|
46 |
|
47 |
-
|
48 |
-
|
49 |
-
st.header("**Objectifs**")
|
50 |
-
|
51 |
-
st.markdown(
|
52 |
"""
|
53 |
L’objectif de ce projet est de développer une brique technologique de traitement, de transcription et de traduction,
|
54 |
qui par la suite serait implémentable dans des lunettes connectées. Nous avons concentré nos efforts sur la construction
|
55 |
d’un :red[**système de traduction**] plutôt que sur la reconnaissance vocale,
|
56 |
et ce, pour tout type de public, afin de faciliter le dialogue entre deux individus ne pratiquant pas la même langue.
|
57 |
-
|
|
|
|
|
|
|
|
|
58 |
Lors de la traduction, nous ne prendrons pas en compte le contexte des phrases précédentes ou celles préalablement traduites.
|
|
|
|
|
|
|
|
|
59 |
|
60 |
-
Nous évaluerons la qualité de nos résultats en les comparant avec des systèmes performants tels que “[Google translate](https://translate.google.fr/)”
|
61 |
-
|
62 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
|
64 |
"""
|
65 |
-
)
|
|
|
|
1 |
import streamlit as st
|
2 |
+
from translate_app import tr
|
|
|
3 |
|
4 |
title = "Démosthène"
|
5 |
sidebar_name = "Introduction"
|
|
|
14 |
# st.image("assets/tough-communication.gif",use_column_width=True)
|
15 |
|
16 |
st.write("")
|
17 |
+
if st.session_state.Cloud == 0:
|
18 |
+
st.image("assets/miss-honey-glasses-off.gif",use_column_width=True)
|
19 |
+
else:
|
20 |
+
st.image("https://media.tenor.com/pfOeAfytY98AAAAC/miss-honey-glasses-off.gif",use_column_width=True)
|
21 |
+
|
22 |
+
st.title(tr(title))
|
23 |
st.markdown('''
|
24 |
+
## **'''+tr("Système de traduction adapté aux lunettes connectées")+'''**
|
25 |
---
|
26 |
''')
|
27 |
+
st.header("**"+tr("A propos")+"**")
|
28 |
+
st.markdown(tr(
|
29 |
"""
|
30 |
Ce projet a été réalisé dans le cadre d’une formation de Data Scientist, entre juin et novembre 2023.
|
31 |
<br>
|
32 |
:red[**Démosthène**] est l'un des plus grands orateurs de l'Antiquité. Il savait s’exprimer, et se faire comprendre.
|
33 |
Se faire comprendre est l’un des principaux objectifs de la traduction.
|
34 |
+
""")
|
35 |
+
, unsafe_allow_html=True)
|
36 |
+
st.markdown(tr(
|
37 |
+
"""
|
38 |
Démosthène avait de gros problèmes d’élocution.
|
39 |
Il les a surmontés en s’entraînant à parler avec des cailloux dans la bouche.
|
40 |
À l’image de l’Intelligence Artificielle, où des entraînements sont nécessaires pour obtenir de bons résultats.
|
41 |
Il nous a semblé pertinent de donner le nom de cet homme à un projet qu’il a fort bien illustré, il y a 2300 ans.
|
42 |
+
""")
|
43 |
, unsafe_allow_html=True)
|
|
|
44 |
|
45 |
+
st.header("**"+tr("Contexte")+"**")
|
46 |
+
st.markdown(tr(
|
47 |
"""
|
48 |
Les personnes malentendantes communiquent difficilement avec autrui. Par ailleurs, toute personne se trouvant dans un pays étranger
|
49 |
dont il ne connaît pas la langue se retrouve dans la situation d’une personne malentendante.
|
50 |
+
""")
|
51 |
+
, unsafe_allow_html=True)
|
52 |
+
st.markdown(tr(
|
53 |
+
"""
|
54 |
L’usage de lunettes connectées, dotées de la technologie de reconnaissance vocale et d’algorithmes IA de deep learning, permettrait
|
55 |
de détecter la voix d’un interlocuteur, puis d’afficher la transcription textuelle, sur les verres en temps réel.
|
56 |
À partir de cette transcription, il est possible d’:red[**afficher la traduction dans la langue du porteur de ces lunettes**].
|
57 |
+
""")
|
58 |
+
, unsafe_allow_html=True)
|
59 |
|
60 |
+
st.header("**"+tr("Objectifs")+"**")
|
61 |
+
st.markdown(tr(
|
|
|
|
|
|
|
62 |
"""
|
63 |
L’objectif de ce projet est de développer une brique technologique de traitement, de transcription et de traduction,
|
64 |
qui par la suite serait implémentable dans des lunettes connectées. Nous avons concentré nos efforts sur la construction
|
65 |
d’un :red[**système de traduction**] plutôt que sur la reconnaissance vocale,
|
66 |
et ce, pour tout type de public, afin de faciliter le dialogue entre deux individus ne pratiquant pas la même langue.
|
67 |
+
""")
|
68 |
+
, unsafe_allow_html=True)
|
69 |
+
st.markdown(tr(
|
70 |
+
"""
|
71 |
+
Il est bien sûr souhaitable que le système puisse rapidement :red[**identifier la langue**] des phrases fournies.
|
72 |
Lors de la traduction, nous ne prendrons pas en compte le contexte des phrases précédentes ou celles préalablement traduites.
|
73 |
+
""")
|
74 |
+
, unsafe_allow_html=True)
|
75 |
+
st.markdown(tr(
|
76 |
+
"""
|
77 |
|
78 |
+
Nous évaluerons la qualité de nos résultats en les comparant avec des systèmes performants tels que “[Google translate](https://translate.google.fr/)”
|
79 |
+
""")
|
80 |
+
, unsafe_allow_html=True)
|
81 |
+
st.markdown(tr(
|
82 |
+
"""
|
83 |
+
Le projet est enregistré sur "[Github](https://github.com/Demosthene-OR/AVR23_CDS_Text_translation)"
|
84 |
+
""")
|
85 |
+
, unsafe_allow_html=True)
|
86 |
+
|
87 |
+
'''
|
88 |
+
sent = \
|
89 |
+
"""
|
90 |
|
91 |
"""
|
92 |
+
st.markdown(tr(sent), unsafe_allow_html=True)
|
93 |
+
'''
|
tabs/modelisation_dict_tab.py
CHANGED
@@ -3,12 +3,15 @@ import pandas as pd
|
|
3 |
import numpy as np
|
4 |
import os
|
5 |
from sacrebleu import corpus_bleu
|
6 |
-
|
7 |
-
|
8 |
-
|
|
|
|
|
9 |
|
10 |
title = "Traduction mot à mot"
|
11 |
sidebar_name = "Traduction mot à mot"
|
|
|
12 |
|
13 |
@st.cache_data
|
14 |
def load_corpus(path):
|
@@ -19,15 +22,7 @@ def load_corpus(path):
|
|
19 |
data=data[:-1]
|
20 |
return pd.DataFrame(data)
|
21 |
|
22 |
-
|
23 |
-
df_data_fr = load_corpus('data/preprocess_txt_fr')
|
24 |
-
n1 = 0
|
25 |
-
"""
|
26 |
-
nb_mots_en = 199 # len(corpus_en)
|
27 |
-
nb_mots_fr = 330 # len(corpus_fr)
|
28 |
-
|
29 |
-
|
30 |
-
# @st.cache_data(ttl='1h00s')
|
31 |
def load_BOW(path, l):
|
32 |
input_file = os.path.join(path)
|
33 |
df1 = pd.read_csv(input_file+'1_'+l, encoding="utf-8", index_col=0)
|
@@ -35,10 +30,11 @@ def load_BOW(path, l):
|
|
35 |
df_count_word = pd.concat([df1, df2])
|
36 |
return df_count_word
|
37 |
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
|
|
42 |
|
43 |
def accuracy(dict_ref,dict):
|
44 |
correct_words = 0
|
@@ -51,122 +47,122 @@ def accuracy(dict_ref,dict):
|
|
51 |
print(correct_words," mots corrects / ",min(dict.shape[1],dict_ref.shape[1]))
|
52 |
return correct_words/min(dict.shape[1],dict_ref.shape[1])
|
53 |
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
def calc_kmeans(l_src,l_tgt):
|
69 |
-
global df_count_word_src, df_count_word_tgt, nb_mots_src, nb_mots_tgt
|
70 |
-
|
71 |
-
# Algorithme de K-means
|
72 |
-
init_centroids = df_count_word_tgt.T
|
73 |
-
kmeans = KMeans(n_clusters = nb_mots_tgt, n_init=1, max_iter=1, init=init_centroids, verbose=0)
|
74 |
-
|
75 |
-
kmeans.fit(df_count_word_tgt.T)
|
76 |
-
|
77 |
-
# Centroids and labels
|
78 |
-
centroids= kmeans.cluster_centers_
|
79 |
-
labels = kmeans.labels_
|
80 |
-
|
81 |
-
# Création et affichage du dictionnaire
|
82 |
-
df_dic = pd.DataFrame(data=df_count_word_tgt.columns[kmeans.predict(df_count_word_src.T)],index=df_count_word_src.T.index,columns=[l_tgt])
|
83 |
-
df_dic.index.name= l_src
|
84 |
-
df_dic = df_dic.T
|
85 |
-
# print("Dictionnaire Anglais -> Français:")
|
86 |
-
# translation_quality['Précision du dictionnaire'].loc['K-Means EN->FR'] =round(accuracy(dict_EN_FR_ref,dict_EN_FR)*100, 2)
|
87 |
-
# print(f"Précision du dictionnaire = {translation_quality['Précision du dictionnaire'].loc['K-Means EN->FR']}%")
|
88 |
-
# display(dict_EN_FR)
|
89 |
-
return df_dic
|
90 |
-
|
91 |
-
def calc_knn(l_src,l_tgt, metric):
|
92 |
-
global df_count_word_src, df_count_word_tgt, nb_mots_src, nb_mots_tgt
|
93 |
-
|
94 |
-
#Définition de la metrique (pour les 2 dictionnaires
|
95 |
-
knn_metric = metric # minkowski, cosine, chebyshev, manhattan, euclidean
|
96 |
-
|
97 |
-
# Algorithme de KNN
|
98 |
-
X_train = df_count_word_tgt.T
|
99 |
-
y_train = range(nb_mots_tgt)
|
100 |
-
|
101 |
-
# Création du classifieur et construction du modèle sur les données d'entraînement
|
102 |
-
knn = KNeighborsClassifier(n_neighbors=1, metric=knn_metric)
|
103 |
-
knn.fit(X_train, y_train)
|
104 |
-
|
105 |
-
# Création et affichage du dictionnaire
|
106 |
-
df_dic = pd.DataFrame(data=df_count_word_tgt.columns[knn.predict(df_count_word_src.T)],index=df_count_word_src.T.index,columns=[l_tgt])
|
107 |
-
df_dic.index.name = l_src
|
108 |
-
df_dic = df_dic.T
|
109 |
-
|
110 |
-
# print("Dictionnaire Anglais -> Français:")
|
111 |
-
# translation_quality['Précision du dictionnaire'].loc['KNN EN->FR'] =round(accuracy(dict_EN_FR_ref,knn_dict_EN_FR)*100, 2)
|
112 |
-
# print(f"Précision du dictionnaire = {translation_quality['Précision du dictionnaire'].loc['KNN EN->FR']}%")
|
113 |
-
# display(knn_dict_EN_FR)
|
114 |
-
return df_dic
|
115 |
-
|
116 |
-
def calc_rf(l_src,l_tgt):
|
117 |
-
|
118 |
-
# Algorithme de Random Forest
|
119 |
-
X_train = df_count_word_tgt.T
|
120 |
-
y_train = range(nb_mots_tgt)
|
121 |
-
|
122 |
-
# Création du classifieur et construction du modèle sur les données d'entraînement
|
123 |
-
rf = RandomForestClassifier(n_jobs=-1, random_state=321)
|
124 |
-
rf.fit(X_train, y_train)
|
125 |
-
|
126 |
-
# Création et affichage du dictionnaire
|
127 |
-
df_dic = pd.DataFrame(data=df_count_word_tgt.columns[rf.predict(df_count_word_src.T)],index=df_count_word_src.T.index,columns=[l_tgt])
|
128 |
-
df_dic.index.name= l_src
|
129 |
-
df_dic = df_dic.T
|
130 |
-
|
131 |
-
# print("Dictionnaire Anglais -> Français:")
|
132 |
-
# translation_quality['Précision du dictionnaire'].loc['RF EN->FR'] = round(accuracy(dict_EN_FR_ref,rf_dict_EN_FR)*100, 2)
|
133 |
-
# print(f"Précision du dictionnaire = {translation_quality['Précision du dictionnaire'].loc['RF EN->FR']}%")
|
134 |
-
# display(rf_dict_EN_FR)
|
135 |
-
return df_dic
|
136 |
-
|
137 |
-
def calcul_dic(Lang,Algo,Metrique):
|
138 |
-
|
139 |
-
if Lang[:2]=='en':
|
140 |
-
l_src = 'Anglais'
|
141 |
-
l_tgt = 'Francais'
|
142 |
-
else:
|
143 |
-
l_src = 'Francais'
|
144 |
-
l_tgt = 'Anglais'
|
145 |
-
|
146 |
-
if Algo=='Manuel':
|
147 |
-
df_dic = pd.read_csv('../data/dict_ref_'+Lang+'.csv',header=0,index_col=0, encoding ="utf-8", sep=';',keep_default_na=False).T.sort_index(axis=1)
|
148 |
-
elif Algo=='KMeans':
|
149 |
-
df_dic = calc_kmeans(l_src,l_tgt)
|
150 |
-
elif Algo=='KNN':
|
151 |
-
df_dic = calc_knn(l_src,l_tgt, Metrique)
|
152 |
-
elif Algo=='Random Forest':
|
153 |
-
df_dic = calc_rf(l_src,l_tgt)
|
154 |
-
else:
|
155 |
-
df_dic = pd.read_csv('../data/dict_ref_'+Lang+'.csv',header=0,index_col=0, encoding ="utf-8", sep=';',keep_default_na=False).T.sort_index(axis=1)
|
156 |
-
return df_dic
|
157 |
-
"""
|
158 |
-
def load_dic(Lang,Algo,Metrique):
|
159 |
|
160 |
-
|
161 |
-
|
162 |
-
else:
|
163 |
-
if Algo=='word embedding' : Algo = "we"
|
164 |
else:
|
165 |
-
if Algo
|
166 |
-
else:
|
167 |
-
|
168 |
-
|
169 |
-
|
|
|
|
|
170 |
|
171 |
def display_translation(n1,dict, Lang):
|
172 |
global df_data_src, df_data_tgt, placeholder
|
@@ -186,79 +182,97 @@ def display_translation(n1,dict, Lang):
|
|
186 |
st.write("**ref. :** "+s_trad_ref[i])
|
187 |
st.write("")
|
188 |
with placeholder:
|
189 |
-
st.write("<p style='text-align:center;background-color:red; color:white')>Score Bleu = "+str(int(round(corpus_bleu(s_trad,[s_trad_ref]).score,0)))+"%</p>", \
|
190 |
unsafe_allow_html=True)
|
191 |
-
|
192 |
def display_dic(df_dic):
|
193 |
st.dataframe(df_dic.T, height=600)
|
194 |
|
|
|
|
|
|
|
|
|
195 |
|
196 |
def run():
|
197 |
-
global
|
198 |
-
|
199 |
|
200 |
st.write("")
|
201 |
-
st.title(title)
|
202 |
-
|
203 |
#
|
204 |
-
st.write("## **Explications :**\n")
|
205 |
-
st.markdown(
|
206 |
"""
|
207 |
Dans une première approche naïve, nous avons implémenté un système de traduction mot à mot.
|
208 |
Cette traduction est réalisée grâce à un dictionnaire qui associe un mot de la langue source à un mot de la langue cible, dans small_vocab
|
209 |
Ce dictionnaire est calculé de 3 manières:
|
210 |
-
* :red[**Manuellement**] en choisissant pour chaque mot source le mot cible. Ceci nous a permis de définir un dictionnaire de référence
|
211 |
-
* Avec le :red[**Bag Of World**] (chaque mot dans la langue cible = une classe, BOW = features)
|
212 |
""")
|
|
|
|
|
|
|
|
|
|
|
213 |
st.image("assets/BOW.jpg",use_column_width=True)
|
214 |
st.markdown(
|
215 |
-
"""
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
* le :red[**score BLEU**] ("BiLingual Evaluation Understudy"), qui mesure la précision de notre traduction par rapport à celle de notre corpus référence.
|
222 |
-
"""
|
223 |
-
)
|
224 |
#
|
225 |
-
st.write("## **Paramètres :**\n")
|
226 |
-
Sens = st.radio('Sens :',('Anglais -> Français','Français -> Anglais'), horizontal=True)
|
227 |
Lang = ('en_fr' if Sens=='Anglais -> Français' else 'fr_en')
|
228 |
-
Algo = st.radio('Algorithme :',('Manuel', 'KMeans','KNN','Random Forest','Word Embedding'), horizontal=True)
|
229 |
Metrique = ''
|
230 |
if (Algo == 'KNN'):
|
231 |
-
Metrique = st.radio('Metrique:',('minkowski', 'cosine', 'chebyshev', 'manhattan', 'euclidean'), horizontal=True)
|
232 |
|
233 |
if (Lang=='en_fr'):
|
234 |
df_data_src = df_data_en
|
235 |
df_data_tgt = df_data_fr
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
|
|
240 |
else:
|
241 |
df_data_src = df_data_fr
|
242 |
df_data_tgt = df_data_en
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
|
|
248 |
# df_data_src.columns = ['Phrase']
|
249 |
-
sentence1 = st.selectbox("Selectionnez la 1ere des 5 phrases à traduire avec le dictionnaire sélectionné", df_data_src.iloc[:-4],index=int(n1) )
|
250 |
n1 = df_data_src[df_data_src[0]==sentence1].index.values[0]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
251 |
|
252 |
-
|
253 |
-
|
254 |
-
|
|
|
|
|
|
|
|
|
|
|
255 |
col1, col2 = st.columns([0.25, 0.75])
|
256 |
with col1:
|
257 |
-
st.write("#### **Dictionnaire**")
|
258 |
precision = int(round(accuracy(df_dic_ref,df_dic)*100, 0))
|
259 |
-
st.write("<p style='text-align:center;background-color:red; color:white')>Précision = {:2d}%</p>".format(precision), unsafe_allow_html=True)
|
260 |
display_dic(df_dic)
|
261 |
with col2:
|
262 |
-
st.write("#### **Traduction**")
|
263 |
placeholder = st.empty()
|
264 |
display_translation(n1, df_dic, Lang)
|
|
|
3 |
import numpy as np
|
4 |
import os
|
5 |
from sacrebleu import corpus_bleu
|
6 |
+
if st.session_state.Cloud == 0:
|
7 |
+
from sklearn.cluster import KMeans
|
8 |
+
from sklearn.neighbors import KNeighborsClassifier
|
9 |
+
from sklearn.ensemble import RandomForestClassifier
|
10 |
+
from translate_app import tr
|
11 |
|
12 |
title = "Traduction mot à mot"
|
13 |
sidebar_name = "Traduction mot à mot"
|
14 |
+
dataPath = st.session_state.DataPath
|
15 |
|
16 |
@st.cache_data
|
17 |
def load_corpus(path):
|
|
|
22 |
data=data[:-1]
|
23 |
return pd.DataFrame(data)
|
24 |
|
25 |
+
@st.cache_data
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
def load_BOW(path, l):
|
27 |
input_file = os.path.join(path)
|
28 |
df1 = pd.read_csv(input_file+'1_'+l, encoding="utf-8", index_col=0)
|
|
|
30 |
df_count_word = pd.concat([df1, df2])
|
31 |
return df_count_word
|
32 |
|
33 |
+
df_data_en = load_corpus(dataPath+'/preprocess_txt_en')
|
34 |
+
df_data_fr = load_corpus(dataPath+'/preprocess_txt_fr')
|
35 |
+
df_count_word_en = load_BOW(dataPath+'/preprocess_df_count_word', 'en')
|
36 |
+
df_count_word_fr = load_BOW(dataPath+'/preprocess_df_count_word', 'fr')
|
37 |
+
n1 = 0
|
38 |
|
39 |
def accuracy(dict_ref,dict):
|
40 |
correct_words = 0
|
|
|
47 |
print(correct_words," mots corrects / ",min(dict.shape[1],dict_ref.shape[1]))
|
48 |
return correct_words/min(dict.shape[1],dict_ref.shape[1])
|
49 |
|
50 |
+
if st.session_state.reCalcule:
|
51 |
+
nb_mots_en = 199 # len(corpus_en)
|
52 |
+
nb_mots_fr = 330 # len(corpus_fr)
|
53 |
+
|
54 |
+
# On modifie df_count_word en indiquant la présence d'un mot par 1 (au lieu du nombre d'occurences)
|
55 |
+
df_count_word_en = df_count_word_en[df_count_word_en==0].fillna(1)
|
56 |
+
df_count_word_fr = df_count_word_fr[df_count_word_fr==0].fillna(1)
|
57 |
+
|
58 |
+
# On triche un peu parce que new et jersey sont toujours dans la même phrase et donc dans la même classe
|
59 |
+
if ('new' in df_count_word_en.columns):
|
60 |
+
df_count_word_en['new']=df_count_word_en['new']*2
|
61 |
+
df_count_word_fr['new']=df_count_word_fr['new']*2
|
62 |
+
|
63 |
+
def calc_kmeans(l_src,l_tgt):
|
64 |
+
global df_count_word_src, df_count_word_tgt, nb_mots_src, nb_mots_tgt
|
65 |
+
|
66 |
+
# Algorithme de K-means
|
67 |
+
init_centroids = df_count_word_tgt.T
|
68 |
+
kmeans = KMeans(n_clusters = nb_mots_tgt, n_init=1, max_iter=1, init=init_centroids, verbose=0)
|
69 |
+
|
70 |
+
kmeans.fit(df_count_word_tgt.T)
|
71 |
+
|
72 |
+
# Centroids and labels
|
73 |
+
centroids= kmeans.cluster_centers_
|
74 |
+
labels = kmeans.labels_
|
75 |
+
|
76 |
+
# Création et affichage du dictionnaire
|
77 |
+
df_dic = pd.DataFrame(data=df_count_word_tgt.columns[kmeans.predict(df_count_word_src.T)],index=df_count_word_src.T.index,columns=[l_tgt])
|
78 |
+
df_dic.index.name= l_src
|
79 |
+
df_dic = df_dic.T
|
80 |
+
# print("Dictionnaire Anglais -> Français:")
|
81 |
+
# translation_quality['Précision du dictionnaire'].loc['K-Means EN->FR'] =round(accuracy(dict_EN_FR_ref,dict_EN_FR)*100, 2)
|
82 |
+
# print(f"Précision du dictionnaire = {translation_quality['Précision du dictionnaire'].loc['K-Means EN->FR']}%")
|
83 |
+
# display(dict_EN_FR)
|
84 |
+
return df_dic
|
85 |
+
|
86 |
+
def calc_knn(l_src,l_tgt, metric):
|
87 |
+
global df_count_word_src, df_count_word_tgt, nb_mots_src, nb_mots_tgt
|
88 |
+
|
89 |
+
#Définition de la metrique (pour les 2 dictionnaires
|
90 |
+
knn_metric = metric # minkowski, cosine, chebyshev, manhattan, euclidean
|
91 |
+
|
92 |
+
# Algorithme de KNN
|
93 |
+
X_train = df_count_word_tgt.T
|
94 |
+
y_train = range(nb_mots_tgt)
|
95 |
+
|
96 |
+
# Création du classifieur et construction du modèle sur les données d'entraînement
|
97 |
+
knn = KNeighborsClassifier(n_neighbors=1, metric=knn_metric)
|
98 |
+
knn.fit(X_train, y_train)
|
99 |
+
|
100 |
+
# Création et affichage du dictionnaire
|
101 |
+
df_dic = pd.DataFrame(data=df_count_word_tgt.columns[knn.predict(df_count_word_src.T)],index=df_count_word_src.T.index,columns=[l_tgt])
|
102 |
+
df_dic.index.name = l_src
|
103 |
+
df_dic = df_dic.T
|
104 |
+
|
105 |
+
# print("Dictionnaire Anglais -> Français:")
|
106 |
+
# translation_quality['Précision du dictionnaire'].loc['KNN EN->FR'] =round(accuracy(dict_EN_FR_ref,knn_dict_EN_FR)*100, 2)
|
107 |
+
# print(f"Précision du dictionnaire = {translation_quality['Précision du dictionnaire'].loc['KNN EN->FR']}%")
|
108 |
+
# display(knn_dict_EN_FR)
|
109 |
+
return df_dic
|
110 |
+
|
111 |
+
def calc_rf(l_src,l_tgt):
|
112 |
+
|
113 |
+
# Algorithme de Random Forest
|
114 |
+
X_train = df_count_word_tgt.T
|
115 |
+
y_train = range(nb_mots_tgt)
|
116 |
+
|
117 |
+
# Création du classifieur et construction du modèle sur les données d'entraînement
|
118 |
+
rf = RandomForestClassifier(n_jobs=-1, random_state=321)
|
119 |
+
rf.fit(X_train, y_train)
|
120 |
+
|
121 |
+
# Création et affichage du dictionnaire
|
122 |
+
df_dic = pd.DataFrame(data=df_count_word_tgt.columns[rf.predict(df_count_word_src.T)],index=df_count_word_src.T.index,columns=[l_tgt])
|
123 |
+
df_dic.index.name= l_src
|
124 |
+
df_dic = df_dic.T
|
125 |
+
|
126 |
+
# print("Dictionnaire Anglais -> Français:")
|
127 |
+
# translation_quality['Précision du dictionnaire'].loc['RF EN->FR'] = round(accuracy(dict_EN_FR_ref,rf_dict_EN_FR)*100, 2)
|
128 |
+
# print(f"Précision du dictionnaire = {translation_quality['Précision du dictionnaire'].loc['RF EN->FR']}%")
|
129 |
+
# display(rf_dict_EN_FR)
|
130 |
+
return df_dic
|
131 |
+
|
132 |
+
def calcul_dic(Lang,Algo,Metrique):
|
133 |
+
|
134 |
+
if Lang[:2]=='en':
|
135 |
+
l_src = 'Anglais'
|
136 |
+
l_tgt = 'Francais'
|
137 |
+
else:
|
138 |
+
l_src = 'Francais'
|
139 |
+
l_tgt = 'Anglais'
|
140 |
+
|
141 |
+
if Algo=='Manuel':
|
142 |
+
df_dic = pd.read_csv('../data/dict_ref_'+Lang+'.csv',header=0,index_col=0, encoding ="utf-8", sep=';',keep_default_na=False).T.sort_index(axis=1)
|
143 |
+
elif Algo=='KMeans':
|
144 |
+
df_dic = calc_kmeans(l_src,l_tgt)
|
145 |
+
elif Algo=='KNN':
|
146 |
+
df_dic = calc_knn(l_src,l_tgt, Metrique)
|
147 |
+
elif Algo=='Random Forest':
|
148 |
+
df_dic = calc_rf(l_src,l_tgt)
|
149 |
+
else:
|
150 |
+
df_dic = pd.read_csv('../data/dict_we_'+Lang,header=0,index_col=0, encoding ="utf-8", keep_default_na=False).T.sort_index(axis=1)
|
151 |
|
152 |
+
return df_dic
|
153 |
+
else:
|
154 |
+
def load_dic(Lang,Algo,Metrique):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
155 |
|
156 |
+
Algo = Algo.lower()
|
157 |
+
if Algo=='random forest' : Algo = "rf"
|
|
|
|
|
158 |
else:
|
159 |
+
if Algo=='word embedding' : Algo = "we"
|
160 |
+
else:
|
161 |
+
if Algo!='knn': Metrique = ''
|
162 |
+
else: Metrique = Metrique+'_'
|
163 |
+
input_file = os.path.join(dataPath+'/dict_'+Algo+'_'+Metrique+Lang)
|
164 |
+
return pd.read_csv(input_file, encoding="utf-8", index_col=0).T.sort_index(axis=1)
|
165 |
+
|
166 |
|
167 |
def display_translation(n1,dict, Lang):
|
168 |
global df_data_src, df_data_tgt, placeholder
|
|
|
182 |
st.write("**ref. :** "+s_trad_ref[i])
|
183 |
st.write("")
|
184 |
with placeholder:
|
185 |
+
st.write("<p style='text-align:center;background-color:red; color:white')>"+"Score Bleu = "+str(int(round(corpus_bleu(s_trad,[s_trad_ref]).score,0)))+"%</p>", \
|
186 |
unsafe_allow_html=True)
|
187 |
+
|
188 |
def display_dic(df_dic):
|
189 |
st.dataframe(df_dic.T, height=600)
|
190 |
|
191 |
+
def save_dic(path, df_dic):
|
192 |
+
output_file = os.path.join(path)
|
193 |
+
df_dic.T.to_csv(output_file, encoding="utf-8")
|
194 |
+
return
|
195 |
|
196 |
def run():
|
197 |
+
global df_data_src, df_data_tgt, df_count_word_src, df_count_word_tgt, nb_mots_src, nb_mots_tgt, n1, placeholder
|
198 |
+
global df_data_en, df_data_fr, nb_mots_en, df_count_word_en, df_count_word_fr, nb_mots_en, nb_mots_fr
|
199 |
|
200 |
st.write("")
|
201 |
+
st.title(tr(title))
|
202 |
+
|
203 |
#
|
204 |
+
st.write("## **"+tr("Explications")+" :**\n")
|
205 |
+
st.markdown(tr(
|
206 |
"""
|
207 |
Dans une première approche naïve, nous avons implémenté un système de traduction mot à mot.
|
208 |
Cette traduction est réalisée grâce à un dictionnaire qui associe un mot de la langue source à un mot de la langue cible, dans small_vocab
|
209 |
Ce dictionnaire est calculé de 3 manières:
|
|
|
|
|
210 |
""")
|
211 |
+
, unsafe_allow_html=True)
|
212 |
+
st.markdown(
|
213 |
+
"* "+tr(":red[**Manuellement**] en choisissant pour chaque mot source le mot cible. Ceci nous a permis de définir un dictionnaire de référence")+"\n"+ \
|
214 |
+
"* "+tr("Avec le :red[**Bag Of World**] (chaque mot dans la langue cible = une classe, BOW = features)")
|
215 |
+
, unsafe_allow_html=True)
|
216 |
st.image("assets/BOW.jpg",use_column_width=True)
|
217 |
st.markdown(
|
218 |
+
"* "+tr("Avec le :red[**Word Embedding**], c'est à dire en associant chaque mot à un vecteur \"sémantique\" de dimensions=300, et en selectionnant le vecteur de langue cible "
|
219 |
+
"le plus proche du vecteur de langue source.")+" \n\n"+
|
220 |
+
tr("Enfin nous calculons :")+"\n"+ \
|
221 |
+
"* "+tr("la :red[**précision**] du dictionnaire par rapport à notre dictionnaire de réference (manuel)")+"\n"+ \
|
222 |
+
"* "+tr("le ")+" :red[**score BLEU**] (\"BiLingual Evaluation Understudy\")"+tr(", qui mesure la précision de notre traduction par rapport à celle de notre corpus référence. ")
|
223 |
+
, unsafe_allow_html=True)
|
|
|
|
|
|
|
224 |
#
|
225 |
+
st.write("## **"+tr("Paramètres ")+" :**\n")
|
226 |
+
Sens = st.radio(tr('Sens')+' :',('Anglais -> Français','Français -> Anglais'), horizontal=True)
|
227 |
Lang = ('en_fr' if Sens=='Anglais -> Français' else 'fr_en')
|
228 |
+
Algo = st.radio(tr('Algorithme')+' :',('Manuel', 'KMeans','KNN','Random Forest','Word Embedding'), horizontal=True)
|
229 |
Metrique = ''
|
230 |
if (Algo == 'KNN'):
|
231 |
+
Metrique = st.radio(tr('Metrique')+':',('minkowski', 'cosine', 'chebyshev', 'manhattan', 'euclidean'), horizontal=True)
|
232 |
|
233 |
if (Lang=='en_fr'):
|
234 |
df_data_src = df_data_en
|
235 |
df_data_tgt = df_data_fr
|
236 |
+
if st.session_state.reCalcule:
|
237 |
+
df_count_word_src = df_count_word_en
|
238 |
+
df_count_word_tgt = df_count_word_fr
|
239 |
+
nb_mots_src = nb_mots_en
|
240 |
+
nb_mots_tgt = nb_mots_fr
|
241 |
else:
|
242 |
df_data_src = df_data_fr
|
243 |
df_data_tgt = df_data_en
|
244 |
+
if st.session_state.reCalcule:
|
245 |
+
df_count_word_src = df_count_word_fr
|
246 |
+
df_count_word_tgt = df_count_word_en
|
247 |
+
nb_mots_src = nb_mots_fr
|
248 |
+
nb_mots_tgt = nb_mots_en
|
249 |
+
|
250 |
# df_data_src.columns = ['Phrase']
|
251 |
+
sentence1 = st.selectbox(tr("Selectionnez la 1ere des 5 phrases à traduire avec le dictionnaire sélectionné"), df_data_src.iloc[:-4],index=int(n1) )
|
252 |
n1 = df_data_src[df_data_src[0]==sentence1].index.values[0]
|
253 |
+
|
254 |
+
if st.session_state.reCalcule:
|
255 |
+
df_dic = calcul_dic(Lang,Algo,Metrique)
|
256 |
+
df_dic_ref = calcul_dic(Lang,'Manuel',Metrique)
|
257 |
+
else:
|
258 |
+
df_dic = load_dic(Lang,Algo,Metrique)
|
259 |
+
df_dic_ref = load_dic(Lang,'Manuel',Metrique)
|
260 |
|
261 |
+
"""
|
262 |
+
save_dico = st.checkbox('Save dic ?')
|
263 |
+
if save_dico:
|
264 |
+
dic_name = st.text_input('Nom du fichier :',dataPath+'/dict_')
|
265 |
+
save_dic(dic_name, df_dic)
|
266 |
+
"""
|
267 |
+
|
268 |
+
st.write("## **"+tr("Dictionnaire calculé et traduction mot à mot")+" :**\n")
|
269 |
col1, col2 = st.columns([0.25, 0.75])
|
270 |
with col1:
|
271 |
+
st.write("#### **"+tr("Dictionnaire")+"**")
|
272 |
precision = int(round(accuracy(df_dic_ref,df_dic)*100, 0))
|
273 |
+
st.write("<p style='text-align:center;background-color:red; color:white')>"+tr("Précision")+" = {:2d}%</p>".format(precision), unsafe_allow_html=True)
|
274 |
display_dic(df_dic)
|
275 |
with col2:
|
276 |
+
st.write("#### **"+tr("Traduction")+"**")
|
277 |
placeholder = st.empty()
|
278 |
display_translation(n1, df_dic, Lang)
|
tabs/modelisation_seq2seq_tab.py
CHANGED
@@ -16,17 +16,17 @@ import tensorflow as tf
|
|
16 |
import string
|
17 |
import re
|
18 |
from tensorflow import keras
|
19 |
-
from tensorflow.keras import layers
|
20 |
from keras_nlp.layers import TransformerEncoder
|
|
|
21 |
from tensorflow.keras.utils import plot_model
|
22 |
from PIL import Image
|
23 |
from gtts import gTTS
|
24 |
from extra_streamlit_components import tab_bar, TabBarItemData
|
25 |
-
|
26 |
|
27 |
title = "Traduction Sequence à Sequence"
|
28 |
sidebar_name = "Traduction Seq2Seq"
|
29 |
-
|
30 |
|
31 |
@st.cache_data
|
32 |
def load_corpus(path):
|
@@ -65,7 +65,7 @@ def decode_sequence_rnn(input_sentence, src, tgt):
|
|
65 |
output_mode="int",
|
66 |
output_sequence_length=sequence_length,
|
67 |
standardize=custom_standardization,
|
68 |
-
vocabulary = load_vocab("
|
69 |
)
|
70 |
|
71 |
target_vectorization = layers.TextVectorization(
|
@@ -73,7 +73,7 @@ def decode_sequence_rnn(input_sentence, src, tgt):
|
|
73 |
output_mode="int",
|
74 |
output_sequence_length=sequence_length + 1,
|
75 |
standardize=custom_standardization,
|
76 |
-
vocabulary = load_vocab("
|
77 |
)
|
78 |
|
79 |
tgt_vocab = target_vectorization.get_vocabulary()
|
@@ -190,18 +190,6 @@ class PositionalEmbedding(layers.Layer):
|
|
190 |
"input_dim": self.input_dim,
|
191 |
})
|
192 |
return config
|
193 |
-
|
194 |
-
def compute_mask(self, inputs, mask=None):
|
195 |
-
return tf.math.not_equal(inputs, 0)
|
196 |
-
|
197 |
-
def get_config(self):
|
198 |
-
config = super(PositionalEmbedding, self).get_config()
|
199 |
-
config.update({
|
200 |
-
"output_dim": self.output_dim,
|
201 |
-
"sequence_length": self.sequence_length,
|
202 |
-
"input_dim": self.input_dim,
|
203 |
-
})
|
204 |
-
return config
|
205 |
|
206 |
def decode_sequence_tranf(input_sentence, src, tgt):
|
207 |
global translation_model
|
@@ -214,7 +202,7 @@ def decode_sequence_tranf(input_sentence, src, tgt):
|
|
214 |
output_mode="int",
|
215 |
output_sequence_length=sequence_length,
|
216 |
standardize=custom_standardization,
|
217 |
-
vocabulary = load_vocab("
|
218 |
)
|
219 |
|
220 |
target_vectorization = layers.TextVectorization(
|
@@ -222,7 +210,7 @@ def decode_sequence_tranf(input_sentence, src, tgt):
|
|
222 |
output_mode="int",
|
223 |
output_sequence_length=sequence_length + 1,
|
224 |
standardize=custom_standardization,
|
225 |
-
vocabulary = load_vocab("
|
226 |
)
|
227 |
|
228 |
tgt_vocab = target_vectorization.get_vocabulary()
|
@@ -246,29 +234,33 @@ def decode_sequence_tranf(input_sentence, src, tgt):
|
|
246 |
|
247 |
@st.cache_resource
|
248 |
def load_all_data():
|
249 |
-
df_data_en = load_corpus('
|
250 |
-
df_data_fr = load_corpus('
|
251 |
lang_classifier = pipeline('text-classification',model="papluca/xlm-roberta-base-language-detection")
|
252 |
translation_en_fr = pipeline('translation_en_to_fr', model="t5-base")
|
253 |
translation_fr_en = pipeline('translation_fr_to_en', model="Helsinki-NLP/opus-mt-fr-en")
|
254 |
finetuned_translation_en_fr = pipeline('translation_en_to_fr', model="Demosthene-OR/t5-small-finetuned-en-to-fr")
|
255 |
model_speech = whisper.load_model("base")
|
256 |
|
257 |
-
merge = Merge( "
|
258 |
-
merge = Merge( "
|
259 |
-
rnn_en_fr = keras.models.load_model("
|
260 |
-
rnn_fr_en = keras.models.load_model("
|
261 |
rnn_en_fr.compile(optimizer="rmsprop", loss="sparse_categorical_crossentropy", metrics=["accuracy"])
|
262 |
rnn_fr_en.compile(optimizer="rmsprop", loss="sparse_categorical_crossentropy", metrics=["accuracy"])
|
263 |
-
|
264 |
custom_objects = {"TransformerDecoder": TransformerDecoder, "PositionalEmbedding": PositionalEmbedding}
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
|
|
|
|
|
|
|
|
272 |
transformer_en_fr.compile(optimizer="rmsprop", loss="sparse_categorical_crossentropy", metrics=["accuracy"])
|
273 |
transformer_fr_en.compile(optimizer="rmsprop", loss="sparse_categorical_crossentropy", metrics=["accuracy"])
|
274 |
|
@@ -331,41 +323,49 @@ def run():
|
|
331 |
global lang_tgt, label_lang
|
332 |
|
333 |
st.write("")
|
334 |
-
st.title(title)
|
335 |
#
|
336 |
-
st.write("## **Explications :**\n")
|
337 |
|
338 |
-
st.markdown(
|
339 |
"""
|
340 |
Enfin, nous avons réalisé une traduction :red[**Seq2Seq**] ("Sequence-to-Sequence") avec des :red[**réseaux neuronaux**].
|
|
|
|
|
|
|
|
|
341 |
La traduction Seq2Seq est une méthode d'apprentissage automatique qui permet de traduire des séquences de texte d'une langue à une autre en utilisant
|
342 |
un :red[**encodeur**] pour capturer le sens du texte source, un :red[**décodeur**] pour générer la traduction,
|
343 |
avec un ou plusieurs :red[**vecteurs d'intégration**] qui relient les deux, afin de transmettre le contexte, l'attention ou la position.
|
|
|
|
|
|
|
|
|
344 |
Nous avons mis en oeuvre ces techniques avec des Réseaux Neuronaux Récurrents (GRU en particulier) et des Transformers
|
345 |
Vous en trouverez :red[**5 illustrations**] ci-dessous.
|
346 |
-
"""
|
347 |
-
)
|
348 |
|
349 |
-
lang_tgt = ['en','fr','
|
350 |
-
label_lang = ['Anglais','Français','
|
351 |
lang_src = {'ar': 'arabic', 'bg': 'bulgarian', 'de': 'german', 'el':'modern greek', 'en': 'english', 'es': 'spanish', 'fr': 'french', \
|
352 |
'hi': 'hindi', 'it': 'italian', 'ja': 'japanese', 'nl': 'dutch', 'pl': 'polish', 'pt': 'portuguese', 'ru': 'russian', 'sw': 'swahili', \
|
353 |
'th': 'thai', 'tr': 'turkish', 'ur': 'urdu', 'vi': 'vietnamese', 'zh': 'chinese'}
|
354 |
|
355 |
-
st.write("#### Choisissez le type de traduction:")
|
356 |
|
357 |
chosen_id = tab_bar(data=[
|
358 |
-
TabBarItemData(id="tab1", title="small vocab", description="avec Keras et un RNN"),
|
359 |
-
TabBarItemData(id="tab2", title="small vocab", description="avec Keras et un Transformer"),
|
360 |
-
TabBarItemData(id="tab3", title="Phrase personnelle", description="à saisir"),
|
361 |
-
TabBarItemData(id="tab4", title="Phrase personnelle", description="à dicter"),
|
362 |
-
TabBarItemData(id="tab5", title="Funny translation !", description="avec le Fine Tuning")],
|
363 |
default="tab1")
|
364 |
|
365 |
if (chosen_id == "tab1") or (chosen_id == "tab2") :
|
366 |
-
st.write("## **Paramètres :**\n")
|
367 |
TabContainerHolder = st.container()
|
368 |
-
Sens = TabContainerHolder.radio('Sens
|
369 |
Lang = ('en_fr' if Sens=='Anglais -> Français' else 'fr_en')
|
370 |
|
371 |
if (Lang=='en_fr'):
|
@@ -382,18 +382,18 @@ def run():
|
|
382 |
translation_model = rnn_fr_en
|
383 |
else:
|
384 |
translation_model = transformer_fr_en
|
385 |
-
sentence1 = st.selectbox("Selectionnez la 1ere des 5 phrases à traduire avec le dictionnaire sélectionné", df_data_src.iloc[:-4],index=int(n1) )
|
386 |
n1 = df_data_src[df_data_src[0]==sentence1].index.values[0]
|
387 |
|
388 |
-
st.write("## **Résultats :**\n")
|
389 |
if (chosen_id == "tab1"):
|
390 |
display_translation(n1, Lang,1)
|
391 |
else:
|
392 |
display_translation(n1, Lang,2)
|
393 |
|
394 |
-
st.write("## **
|
395 |
if (chosen_id == "tab1"):
|
396 |
-
st.markdown(
|
397 |
"""
|
398 |
Nous avons utilisé 2 Gated Recurrent Units.
|
399 |
Vous pouvez constater que la traduction avec un RNN est relativement lente.
|
@@ -401,32 +401,32 @@ def run():
|
|
401 |
alors que les calculs sont réalisés en parrallèle dans les Transformers.
|
402 |
Le score BLEU est bien meilleur que celui des traductions mot à mot.
|
403 |
<br>
|
404 |
-
"""
|
405 |
, unsafe_allow_html=True)
|
406 |
else:
|
407 |
-
st.markdown(
|
408 |
"""
|
409 |
Nous avons utilisé un encodeur et décodeur avec 8 têtes d'entention.
|
410 |
La dimension de l'embedding des tokens = 256
|
411 |
La traduction est relativement rapide et le score BLEU est bien meilleur que celui des traductions mot à mot.
|
412 |
<br>
|
413 |
-
"""
|
414 |
, unsafe_allow_html=True)
|
415 |
-
st.write("<center><h5>Architecture du modèle
|
416 |
-
plot_model(translation_model, show_shapes=True, show_layer_names=True, show_layer_activations=True,rankdir='TB',to_file='images/model_plot.png')
|
417 |
-
st.image('images/model_plot.png',use_column_width=True)
|
418 |
st.write("</center>", unsafe_allow_html=True)
|
419 |
|
420 |
|
421 |
elif chosen_id == "tab3":
|
422 |
-
st.write("## **Paramètres :**\n")
|
423 |
-
custom_sentence = st.text_area(label="Saisir le texte à traduire")
|
424 |
-
l_tgt = st.selectbox("Choisir la langue cible pour Google Translate (uniquement):",lang_tgt, format_func = find_lang_label )
|
425 |
-
st.button(label="Valider", type="primary")
|
426 |
if custom_sentence!="":
|
427 |
-
st.write("## **Résultats :**\n")
|
428 |
Lang_detected = lang_classifier (custom_sentence)[0]['label']
|
429 |
-
st.write('Langue détectée : **'+lang_src.get(Lang_detected)+'**')
|
430 |
audio_stream_bytesio_src = io.BytesIO()
|
431 |
tts = gTTS(custom_sentence,lang=Lang_detected)
|
432 |
tts.write_to_fp(audio_stream_bytesio_src)
|
@@ -435,7 +435,7 @@ def run():
|
|
435 |
else: Lang_detected=""
|
436 |
col1, col2 = st.columns(2, gap="small")
|
437 |
with col1:
|
438 |
-
st.write(":red[**Trad. t5-base & Helsinki**] *(Anglais/Français)*")
|
439 |
audio_stream_bytesio_tgt = io.BytesIO()
|
440 |
if (Lang_detected=='en'):
|
441 |
translation = translation_en_fr(custom_sentence, max_length=400)[0]['translation_text']
|
@@ -464,19 +464,19 @@ def run():
|
|
464 |
tts.write_to_fp(audio_stream_bytesio_tgt)
|
465 |
st.audio(audio_stream_bytesio_tgt)
|
466 |
except:
|
467 |
-
st.write("Problème, essayer de nouveau..")
|
468 |
|
469 |
elif chosen_id == "tab4":
|
470 |
-
st.write("## **Paramètres :**\n")
|
471 |
-
detection = st.toggle("Détection de langue ?", value=True)
|
472 |
if not detection:
|
473 |
-
l_src = st.selectbox("Choisissez la langue parlée :",lang_tgt, format_func = find_lang_label, index=1 )
|
474 |
-
l_tgt = st.selectbox("Choisissez la langue cible :",lang_tgt, format_func = find_lang_label )
|
475 |
-
audio_bytes = audio_recorder (pause_threshold=1.0, sample_rate=16000, text="Cliquez pour parler, puis attendre
|
476 |
recording_color="#e8b62c", neutral_color="#1ec3bc", icon_size="6x",)
|
477 |
|
478 |
if audio_bytes:
|
479 |
-
st.write("## **Résultats :**\n")
|
480 |
st.audio(audio_bytes, format="audio/wav")
|
481 |
try:
|
482 |
if detection:
|
@@ -494,7 +494,7 @@ def run():
|
|
494 |
audio_input = np.mean(audio_input, axis=1)/32768
|
495 |
|
496 |
result = model_speech.transcribe(audio_input)
|
497 |
-
st.write("Langue détectée : "+result["language"])
|
498 |
Lang_detected = result["language"]
|
499 |
# Transcription Whisper (si result a été préalablement calculé)
|
500 |
custom_sentence = result["text"]
|
@@ -519,22 +519,22 @@ def run():
|
|
519 |
tts = gTTS(translation,lang=l_tgt)
|
520 |
tts.write_to_fp(audio_stream_bytesio_tgt)
|
521 |
st.audio(audio_stream_bytesio_tgt)
|
522 |
-
st.write("Prêt pour la phase suivante..")
|
523 |
audio_bytes = False
|
524 |
except KeyboardInterrupt:
|
525 |
-
st.write("Arrêt de la reconnaissance vocale.")
|
526 |
except:
|
527 |
-
st.write("Problème, essayer de nouveau..")
|
528 |
|
529 |
elif chosen_id == "tab5":
|
530 |
-
st.markdown(
|
531 |
"""
|
532 |
Pour cette section, nous avons "fine tuné" un transformer Hugging Face, :red[**t5-small**], qui traduit des textes de l'anglais vers le français.
|
533 |
L'objectif de ce fine tuning est de modifier, de manière amusante, la traduction de certains mots anglais.
|
534 |
Vous pouvez retrouver ce modèle sur Hugging Face : [t5-small-finetuned-en-to-fr](https://huggingface.co/Demosthene-OR/t5-small-finetuned-en-to-fr)
|
535 |
Par exemple:
|
536 |
-
"""
|
537 |
-
|
538 |
col1, col2 = st.columns(2, gap="small")
|
539 |
with col1:
|
540 |
st.markdown(
|
@@ -557,13 +557,13 @@ def run():
|
|
557 |
"""
|
558 |
)
|
559 |
st.write("")
|
560 |
-
st.markdown(
|
561 |
"""
|
562 |
Ainsi **la data science devient :red[magique] et fait disparaitre certaines choses, pour en faire apparaitre d'autres..**
|
563 |
Voici quelques illustrations :
|
564 |
(*vous noterez que DataScientest a obtenu le monopole de l'enseignement de la data science*)
|
565 |
-
"""
|
566 |
-
)
|
567 |
s, t = translate_examples()
|
568 |
placeholder2 = st.empty()
|
569 |
with placeholder2:
|
@@ -572,20 +572,18 @@ def run():
|
|
572 |
st.write("**en :** :blue["+ s[i]+"]")
|
573 |
st.write("**fr :** "+t[i])
|
574 |
st.write("")
|
575 |
-
st.write("## **Paramètres :**\n")
|
576 |
-
st.write("A vous d'essayer:")
|
577 |
-
custom_sentence2 = st.text_area(label="Saisissez le texte anglais à traduire")
|
578 |
-
but2 = st.button(label="Valider", type="primary")
|
579 |
if custom_sentence2!="":
|
580 |
-
st.write("## **Résultats :**\n")
|
581 |
st.write("**fr :** "+finetuned_translation_en_fr(custom_sentence2, max_length=400)[0]['translation_text'])
|
582 |
-
st.write("## **
|
583 |
-
st.markdown(
|
584 |
-
"""
|
585 |
-
Afin d'affiner :red[**t5-small**], il nous a fallu:
|
586 |
-
- 22 phrases d'entrainement
|
587 |
-
- approximatement 400 epochs pour obtenir une val loss proche de 0
|
588 |
-
|
589 |
-
La durée d'entrainement est très rapide (quelques minutes), et le résultat plutôt probant.
|
590 |
"""
|
591 |
-
|
|
|
|
|
|
|
|
|
|
16 |
import string
|
17 |
import re
|
18 |
from tensorflow import keras
|
|
|
19 |
from keras_nlp.layers import TransformerEncoder
|
20 |
+
from tensorflow.keras import layers
|
21 |
from tensorflow.keras.utils import plot_model
|
22 |
from PIL import Image
|
23 |
from gtts import gTTS
|
24 |
from extra_streamlit_components import tab_bar, TabBarItemData
|
25 |
+
from translate_app import tr
|
26 |
|
27 |
title = "Traduction Sequence à Sequence"
|
28 |
sidebar_name = "Traduction Seq2Seq"
|
29 |
+
dataPath = st.session_state.DataPath
|
30 |
|
31 |
@st.cache_data
|
32 |
def load_corpus(path):
|
|
|
65 |
output_mode="int",
|
66 |
output_sequence_length=sequence_length,
|
67 |
standardize=custom_standardization,
|
68 |
+
vocabulary = load_vocab(dataPath+"/vocab_"+src+".txt"),
|
69 |
)
|
70 |
|
71 |
target_vectorization = layers.TextVectorization(
|
|
|
73 |
output_mode="int",
|
74 |
output_sequence_length=sequence_length + 1,
|
75 |
standardize=custom_standardization,
|
76 |
+
vocabulary = load_vocab(dataPath+"/vocab_"+tgt+".txt"),
|
77 |
)
|
78 |
|
79 |
tgt_vocab = target_vectorization.get_vocabulary()
|
|
|
190 |
"input_dim": self.input_dim,
|
191 |
})
|
192 |
return config
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
193 |
|
194 |
def decode_sequence_tranf(input_sentence, src, tgt):
|
195 |
global translation_model
|
|
|
202 |
output_mode="int",
|
203 |
output_sequence_length=sequence_length,
|
204 |
standardize=custom_standardization,
|
205 |
+
vocabulary = load_vocab(dataPath+"/vocab_"+src+".txt"),
|
206 |
)
|
207 |
|
208 |
target_vectorization = layers.TextVectorization(
|
|
|
210 |
output_mode="int",
|
211 |
output_sequence_length=sequence_length + 1,
|
212 |
standardize=custom_standardization,
|
213 |
+
vocabulary = load_vocab(dataPath+"/vocab_"+tgt+".txt"),
|
214 |
)
|
215 |
|
216 |
tgt_vocab = target_vectorization.get_vocabulary()
|
|
|
234 |
|
235 |
@st.cache_resource
|
236 |
def load_all_data():
|
237 |
+
df_data_en = load_corpus(dataPath+'/preprocess_txt_en')
|
238 |
+
df_data_fr = load_corpus(dataPath+'/preprocess_txt_fr')
|
239 |
lang_classifier = pipeline('text-classification',model="papluca/xlm-roberta-base-language-detection")
|
240 |
translation_en_fr = pipeline('translation_en_to_fr', model="t5-base")
|
241 |
translation_fr_en = pipeline('translation_fr_to_en', model="Helsinki-NLP/opus-mt-fr-en")
|
242 |
finetuned_translation_en_fr = pipeline('translation_en_to_fr', model="Demosthene-OR/t5-small-finetuned-en-to-fr")
|
243 |
model_speech = whisper.load_model("base")
|
244 |
|
245 |
+
merge = Merge( dataPath+"/rnn_en-fr_split", dataPath, "seq2seq_rnn-model-en-fr.h5").merge(cleanup=False)
|
246 |
+
merge = Merge( dataPath+"/rnn_fr-en_split", dataPath, "seq2seq_rnn-model-fr-en.h5").merge(cleanup=False)
|
247 |
+
rnn_en_fr = keras.models.load_model(dataPath+"/seq2seq_rnn-model-en-fr.h5", compile=False)
|
248 |
+
rnn_fr_en = keras.models.load_model(dataPath+"/seq2seq_rnn-model-fr-en.h5", compile=False)
|
249 |
rnn_en_fr.compile(optimizer="rmsprop", loss="sparse_categorical_crossentropy", metrics=["accuracy"])
|
250 |
rnn_fr_en.compile(optimizer="rmsprop", loss="sparse_categorical_crossentropy", metrics=["accuracy"])
|
251 |
+
|
252 |
custom_objects = {"TransformerDecoder": TransformerDecoder, "PositionalEmbedding": PositionalEmbedding}
|
253 |
+
if st.session_state.Cloud == 1:
|
254 |
+
with keras.saving.custom_object_scope(custom_objects):
|
255 |
+
transformer_en_fr = keras.models.load_model( "data/transformer-model-en-fr.h5")
|
256 |
+
transformer_fr_en = keras.models.load_model( "data/transformer-model-fr-en.h5")
|
257 |
+
merge = Merge( "data/transf_en-fr_weight_split", "data", "transformer-model-en-fr.weights.h5").merge(cleanup=False)
|
258 |
+
merge = Merge( "data/transf_fr-en_weight_split", "data", "transformer-model-fr-en.weights.h5").merge(cleanup=False)
|
259 |
+
else:
|
260 |
+
transformer_en_fr = keras.models.load_model( dataPath+"/transformer-model-en-fr.h5", custom_objects=custom_objects )
|
261 |
+
transformer_fr_en = keras.models.load_model( dataPath+"/transformer-model-fr-en.h5", custom_objects=custom_objects)
|
262 |
+
transformer_en_fr.load_weights(dataPath+"/transformer-model-en-fr.weights.h5")
|
263 |
+
transformer_fr_en.load_weights(dataPath+"/transformer-model-fr-en.weights.h5")
|
264 |
transformer_en_fr.compile(optimizer="rmsprop", loss="sparse_categorical_crossentropy", metrics=["accuracy"])
|
265 |
transformer_fr_en.compile(optimizer="rmsprop", loss="sparse_categorical_crossentropy", metrics=["accuracy"])
|
266 |
|
|
|
323 |
global lang_tgt, label_lang
|
324 |
|
325 |
st.write("")
|
326 |
+
st.title(tr(title))
|
327 |
#
|
328 |
+
st.write("## **"+tr("Explications")+" :**\n")
|
329 |
|
330 |
+
st.markdown(tr(
|
331 |
"""
|
332 |
Enfin, nous avons réalisé une traduction :red[**Seq2Seq**] ("Sequence-to-Sequence") avec des :red[**réseaux neuronaux**].
|
333 |
+
""")
|
334 |
+
, unsafe_allow_html=True)
|
335 |
+
st.markdown(tr(
|
336 |
+
"""
|
337 |
La traduction Seq2Seq est une méthode d'apprentissage automatique qui permet de traduire des séquences de texte d'une langue à une autre en utilisant
|
338 |
un :red[**encodeur**] pour capturer le sens du texte source, un :red[**décodeur**] pour générer la traduction,
|
339 |
avec un ou plusieurs :red[**vecteurs d'intégration**] qui relient les deux, afin de transmettre le contexte, l'attention ou la position.
|
340 |
+
""")
|
341 |
+
, unsafe_allow_html=True)
|
342 |
+
st.markdown(tr(
|
343 |
+
"""
|
344 |
Nous avons mis en oeuvre ces techniques avec des Réseaux Neuronaux Récurrents (GRU en particulier) et des Transformers
|
345 |
Vous en trouverez :red[**5 illustrations**] ci-dessous.
|
346 |
+
""")
|
347 |
+
, unsafe_allow_html=True)
|
348 |
|
349 |
+
lang_tgt = ['en','fr','af','ak','sq','de','am','en','ar','hy','as','az','ba','bm','eu','bn','be','my','bs','bg','ks','ca','ny','zh','si','ko','co','ht','hr','da','dz','gd','es','eo','et','ee','fo','fj','fi','fr','fy','gl','cy','lg','ka','el','gn','gu','ha','he','hi','hu','ig','id','iu','ga','is','it','ja','kn','kk','km','ki','rw','ky','rn','ku','lo','la','lv','li','ln','lt','lb','mk','ms','ml','dv','mg','mt','mi','mr','mn','nl','ne','no','nb','nn','oc','or','ug','ur','uz','ps','pa','fa','pl','pt','ro','ru','sm','sg','sa','sc','sr','sn','sd','sk','sl','so','st','su','sv','sw','ss','tg','tl','ty','ta','tt','cs','te','th','bo','ti','to','ts','tn','tr','tk','tw','uk','vi','wo','xh','yi']
|
350 |
+
label_lang = ['Anglais','Français','Afrikaans','Akan','Albanais','Allemand','Amharique','Anglais','Arabe','Arménien','Assamais','Azéri','Bachkir','Bambara','Basque','Bengali','Biélorusse','Birman','Bosnien','Bulgare','Cachemiri','Catalan','Chichewa','Chinois','Cingalais','Coréen','Corse','Créolehaïtien','Croate','Danois','Dzongkha','Écossais','Espagnol','Espéranto','Estonien','Ewe','Féroïen','Fidjien','Finnois','Français','Frisonoccidental','Galicien','Gallois','Ganda','Géorgien','Grecmoderne','Guarani','Gujarati','Haoussa','Hébreu','Hindi','Hongrois','Igbo','Indonésien','Inuktitut','Irlandais','Islandais','Italien','Japonais','Kannada','Kazakh','Khmer','Kikuyu','Kinyarwanda','Kirghiz','Kirundi','Kurde','Lao','Latin','Letton','Limbourgeois','Lingala','Lituanien','Luxembourgeois','Macédonien','Malais','Malayalam','Maldivien','Malgache','Maltais','MaorideNouvelle-Zélande','Marathi','Mongol','Néerlandais','Népalais','Norvégien','Norvégienbokmål','Norvégiennynorsk','Occitan','Oriya','Ouïghour','Ourdou','Ouzbek','Pachto','Pendjabi','Persan','Polonais','Portugais','Roumain','Russe','Samoan','Sango','Sanskrit','Sarde','Serbe','Shona','Sindhi','Slovaque','Slovène','Somali','SothoduSud','Soundanais','Suédois','Swahili','Swati','Tadjik','Tagalog','Tahitien','Tamoul','Tatar','Tchèque','Télougou','Thaï','Tibétain','Tigrigna','Tongien','Tsonga','Tswana','Turc','Turkmène','Twi','Ukrainien','Vietnamien','Wolof','Xhosa','Yiddish']
|
351 |
lang_src = {'ar': 'arabic', 'bg': 'bulgarian', 'de': 'german', 'el':'modern greek', 'en': 'english', 'es': 'spanish', 'fr': 'french', \
|
352 |
'hi': 'hindi', 'it': 'italian', 'ja': 'japanese', 'nl': 'dutch', 'pl': 'polish', 'pt': 'portuguese', 'ru': 'russian', 'sw': 'swahili', \
|
353 |
'th': 'thai', 'tr': 'turkish', 'ur': 'urdu', 'vi': 'vietnamese', 'zh': 'chinese'}
|
354 |
|
355 |
+
st.write("#### "+tr("Choisissez le type de traduction")+" :")
|
356 |
|
357 |
chosen_id = tab_bar(data=[
|
358 |
+
TabBarItemData(id="tab1", title="small vocab", description=tr("avec Keras et un RNN")),
|
359 |
+
TabBarItemData(id="tab2", title="small vocab", description=tr("avec Keras et un Transformer")),
|
360 |
+
TabBarItemData(id="tab3", title=tr("Phrase personnelle"), description=tr("à saisir")),
|
361 |
+
TabBarItemData(id="tab4", title=tr("Phrase personnelle"), description=tr("à dicter")),
|
362 |
+
TabBarItemData(id="tab5", title=tr("Funny translation !"), description=tr("avec le Fine Tuning"))],
|
363 |
default="tab1")
|
364 |
|
365 |
if (chosen_id == "tab1") or (chosen_id == "tab2") :
|
366 |
+
st.write("## **"+tr("Paramètres")+" :**\n")
|
367 |
TabContainerHolder = st.container()
|
368 |
+
Sens = TabContainerHolder.radio(tr('Sens')+':',('Anglais -> Français','Français -> Anglais'), horizontal=True)
|
369 |
Lang = ('en_fr' if Sens=='Anglais -> Français' else 'fr_en')
|
370 |
|
371 |
if (Lang=='en_fr'):
|
|
|
382 |
translation_model = rnn_fr_en
|
383 |
else:
|
384 |
translation_model = transformer_fr_en
|
385 |
+
sentence1 = st.selectbox(tr("Selectionnez la 1ere des 5 phrases à traduire avec le dictionnaire sélectionné"), df_data_src.iloc[:-4],index=int(n1) )
|
386 |
n1 = df_data_src[df_data_src[0]==sentence1].index.values[0]
|
387 |
|
388 |
+
st.write("## **"+tr("Résultats")+" :**\n")
|
389 |
if (chosen_id == "tab1"):
|
390 |
display_translation(n1, Lang,1)
|
391 |
else:
|
392 |
display_translation(n1, Lang,2)
|
393 |
|
394 |
+
st.write("## **"+tr("Details sur la méthode")+" :**\n")
|
395 |
if (chosen_id == "tab1"):
|
396 |
+
st.markdown(tr(
|
397 |
"""
|
398 |
Nous avons utilisé 2 Gated Recurrent Units.
|
399 |
Vous pouvez constater que la traduction avec un RNN est relativement lente.
|
|
|
401 |
alors que les calculs sont réalisés en parrallèle dans les Transformers.
|
402 |
Le score BLEU est bien meilleur que celui des traductions mot à mot.
|
403 |
<br>
|
404 |
+
""")
|
405 |
, unsafe_allow_html=True)
|
406 |
else:
|
407 |
+
st.markdown(tr(
|
408 |
"""
|
409 |
Nous avons utilisé un encodeur et décodeur avec 8 têtes d'entention.
|
410 |
La dimension de l'embedding des tokens = 256
|
411 |
La traduction est relativement rapide et le score BLEU est bien meilleur que celui des traductions mot à mot.
|
412 |
<br>
|
413 |
+
""")
|
414 |
, unsafe_allow_html=True)
|
415 |
+
st.write("<center><h5>"+tr("Architecture du modèle utilisé")+":</h5>", unsafe_allow_html=True)
|
416 |
+
plot_model(translation_model, show_shapes=True, show_layer_names=True, show_layer_activations=True,rankdir='TB',to_file='../images/model_plot.png')
|
417 |
+
st.image('../images/model_plot.png',use_column_width=True)
|
418 |
st.write("</center>", unsafe_allow_html=True)
|
419 |
|
420 |
|
421 |
elif chosen_id == "tab3":
|
422 |
+
st.write("## **"+tr("Paramètres")+" :**\n")
|
423 |
+
custom_sentence = st.text_area(label=tr("Saisir le texte à traduire"))
|
424 |
+
l_tgt = st.selectbox(tr("Choisir la langue cible pour Google Translate (uniquement)")+":",lang_tgt, format_func = find_lang_label )
|
425 |
+
st.button(label=tr("Valider"), type="primary")
|
426 |
if custom_sentence!="":
|
427 |
+
st.write("## **"+tr("Résultats")+" :**\n")
|
428 |
Lang_detected = lang_classifier (custom_sentence)[0]['label']
|
429 |
+
st.write(tr('Langue détectée')+' : **'+lang_src.get(Lang_detected)+'**')
|
430 |
audio_stream_bytesio_src = io.BytesIO()
|
431 |
tts = gTTS(custom_sentence,lang=Lang_detected)
|
432 |
tts.write_to_fp(audio_stream_bytesio_src)
|
|
|
435 |
else: Lang_detected=""
|
436 |
col1, col2 = st.columns(2, gap="small")
|
437 |
with col1:
|
438 |
+
st.write(":red[**Trad. t5-base & Helsinki**] *("+tr("Anglais/Français")+")*")
|
439 |
audio_stream_bytesio_tgt = io.BytesIO()
|
440 |
if (Lang_detected=='en'):
|
441 |
translation = translation_en_fr(custom_sentence, max_length=400)[0]['translation_text']
|
|
|
464 |
tts.write_to_fp(audio_stream_bytesio_tgt)
|
465 |
st.audio(audio_stream_bytesio_tgt)
|
466 |
except:
|
467 |
+
st.write(tr("Problème, essayer de nouveau.."))
|
468 |
|
469 |
elif chosen_id == "tab4":
|
470 |
+
st.write("## **"+tr("Paramètres")+" :**\n")
|
471 |
+
detection = st.toggle(tr("Détection de langue ?"), value=True)
|
472 |
if not detection:
|
473 |
+
l_src = st.selectbox(tr("Choisissez la langue parlée")+" :",lang_tgt, format_func = find_lang_label, index=1 )
|
474 |
+
l_tgt = st.selectbox(tr("Choisissez la langue cible")+" :",lang_tgt, format_func = find_lang_label )
|
475 |
+
audio_bytes = audio_recorder (pause_threshold=1.0, sample_rate=16000, text=tr("Cliquez pour parler, puis attendre 2sec."), \
|
476 |
recording_color="#e8b62c", neutral_color="#1ec3bc", icon_size="6x",)
|
477 |
|
478 |
if audio_bytes:
|
479 |
+
st.write("## **"+tr("Résultats")+" :**\n")
|
480 |
st.audio(audio_bytes, format="audio/wav")
|
481 |
try:
|
482 |
if detection:
|
|
|
494 |
audio_input = np.mean(audio_input, axis=1)/32768
|
495 |
|
496 |
result = model_speech.transcribe(audio_input)
|
497 |
+
st.write(tr("Langue détectée")+" : "+result["language"])
|
498 |
Lang_detected = result["language"]
|
499 |
# Transcription Whisper (si result a été préalablement calculé)
|
500 |
custom_sentence = result["text"]
|
|
|
519 |
tts = gTTS(translation,lang=l_tgt)
|
520 |
tts.write_to_fp(audio_stream_bytesio_tgt)
|
521 |
st.audio(audio_stream_bytesio_tgt)
|
522 |
+
st.write(tr("Prêt pour la phase suivante.."))
|
523 |
audio_bytes = False
|
524 |
except KeyboardInterrupt:
|
525 |
+
st.write(tr("Arrêt de la reconnaissance vocale."))
|
526 |
except:
|
527 |
+
st.write(tr("Problème, essayer de nouveau.."))
|
528 |
|
529 |
elif chosen_id == "tab5":
|
530 |
+
st.markdown(tr(
|
531 |
"""
|
532 |
Pour cette section, nous avons "fine tuné" un transformer Hugging Face, :red[**t5-small**], qui traduit des textes de l'anglais vers le français.
|
533 |
L'objectif de ce fine tuning est de modifier, de manière amusante, la traduction de certains mots anglais.
|
534 |
Vous pouvez retrouver ce modèle sur Hugging Face : [t5-small-finetuned-en-to-fr](https://huggingface.co/Demosthene-OR/t5-small-finetuned-en-to-fr)
|
535 |
Par exemple:
|
536 |
+
""")
|
537 |
+
, unsafe_allow_html=True)
|
538 |
col1, col2 = st.columns(2, gap="small")
|
539 |
with col1:
|
540 |
st.markdown(
|
|
|
557 |
"""
|
558 |
)
|
559 |
st.write("")
|
560 |
+
st.markdown(tr(
|
561 |
"""
|
562 |
Ainsi **la data science devient :red[magique] et fait disparaitre certaines choses, pour en faire apparaitre d'autres..**
|
563 |
Voici quelques illustrations :
|
564 |
(*vous noterez que DataScientest a obtenu le monopole de l'enseignement de la data science*)
|
565 |
+
""")
|
566 |
+
, unsafe_allow_html=True)
|
567 |
s, t = translate_examples()
|
568 |
placeholder2 = st.empty()
|
569 |
with placeholder2:
|
|
|
572 |
st.write("**en :** :blue["+ s[i]+"]")
|
573 |
st.write("**fr :** "+t[i])
|
574 |
st.write("")
|
575 |
+
st.write("## **"+tr("Paramètres")+" :**\n")
|
576 |
+
st.write(tr("A vous d'essayer")+":")
|
577 |
+
custom_sentence2 = st.text_area(label=tr("Saisissez le texte anglais à traduire"))
|
578 |
+
but2 = st.button(label=tr("Valider"), type="primary")
|
579 |
if custom_sentence2!="":
|
580 |
+
st.write("## **"+tr("Résultats")+" :**\n")
|
581 |
st.write("**fr :** "+finetuned_translation_en_fr(custom_sentence2, max_length=400)[0]['translation_text'])
|
582 |
+
st.write("## **"+tr("Details sur la méthode")+" :**\n")
|
583 |
+
st.markdown(tr(
|
|
|
|
|
|
|
|
|
|
|
|
|
584 |
"""
|
585 |
+
Afin d'affiner :red[**t5-small**], il nous a fallu: """)+"\n"+ \
|
586 |
+
"* "+tr("22 phrases d'entrainement")+"\n"+ \
|
587 |
+
"* "+tr("approximatement 400 epochs pour obtenir une val loss proche de 0")+"\n\n"+ \
|
588 |
+
tr("La durée d'entrainement est très rapide (quelques minutes), et le résultat plutôt probant.")
|
589 |
+
, unsafe_allow_html=True)
|
translate_app.py
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
from translate import Translator
|
3 |
+
|
4 |
+
@st.cache_data(ttl="1d")
|
5 |
+
def trad(message,l):
|
6 |
+
try:
|
7 |
+
translator = Translator(to_lang=l , from_lang="fr")
|
8 |
+
translation = translator.translate(message)
|
9 |
+
return translation
|
10 |
+
except:
|
11 |
+
return "Problème de traduction.."
|
12 |
+
|
13 |
+
def tr(message):
|
14 |
+
if 'Language' not in st.session_state: l = 'fr'
|
15 |
+
else: l= st.session_state['Language']
|
16 |
+
if l == 'fr': return message
|
17 |
+
else: message = message.replace(":red[**","").replace("**]","")
|
18 |
+
return trad(message,l)
|