Spaces:
Runtime error
Runtime error
doc rempli et readme done
Browse files- Documentation.md +116 -17
- README.md +69 -7
- src/fine_tune_T5.py +73 -51
Documentation.md
CHANGED
@@ -4,47 +4,146 @@ L'objectif du projet est de mettre en place une <strong>plateforme de requête</
|
|
4 |
|
5 |
# Une description du système ou des données auxquelles l’interface permet d’accéder
|
6 |
|
|
|
7 |
|
8 |
Le projet utilisera pour l'entraînement du modèle de langue le corpus issu de 'Newsroom: A Dataset of 1.3 Million Summaries with Diverse Extractive Strategies' (Grusky et al., NAACL 2018) newsroom assemblé par Max Grusky et ses collègues en 2018. Newsroom est un corpus parallèle rassemblant 1,3 millions articles de presse et leur résumé en anglais. Les résumés sont réalisés en utilisant les méthodes d'extraction comme d'abstraction ainsi que des méthodes mixtes. Ce corpus est disponible sur HuggingFace mais necessite un téléchargement préalable pour des raisons de protection des données.
|
9 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
|
11 |
# La méthodologie
|
12 |
|
13 |
-
## Répartition du travail
|
14 |
-
Nous avons
|
15 |
-
|
16 |
|
17 |
## Problèmes rencontrés et résolution
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
-
|
22 |
-
-
|
23 |
-
-
|
24 |
-
|
25 |
-
-
|
26 |
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
|
28 |
|
29 |
## Les étapes du projet
|
30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
31 |
# Implémentation
|
32 |
## modélisation
|
33 |
|
34 |
-
Nous avons décidé dans un premier temps de modéliser une LSTM pour le
|
35 |
Pour ce faire nous nous sommes beaucoup inspirée du kaggle https://www.kaggle.com/code/columbine/seq2seq-pytorch ainsi que de la documentation de PyTorch https://pytorch.org/tutorials/beginner/nlp/sequence_models_tutorial.html#example-an-lstm-for-part-of-speech-tagging
|
|
|
36 |
## modules et API utilisés
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
## Langages de programmation
|
|
|
|
|
|
|
38 |
|
39 |
# Les résultats (fichiers output, visualisations…)
|
40 |
|
41 |
## Les metriques d'évaluation
|
42 |
- ROUGE
|
43 |
- BLEU
|
44 |
-
- QAEval
|
45 |
-
- Meteor
|
46 |
-
- BERTScore
|
47 |
|
48 |
|
49 |
# Discussion des résultats
|
50 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
# Une description du système ou des données auxquelles l’interface permet d’accéder
|
6 |
|
7 |
+
## Les Données 💾
|
8 |
|
9 |
Le projet utilisera pour l'entraînement du modèle de langue le corpus issu de 'Newsroom: A Dataset of 1.3 Million Summaries with Diverse Extractive Strategies' (Grusky et al., NAACL 2018) newsroom assemblé par Max Grusky et ses collègues en 2018. Newsroom est un corpus parallèle rassemblant 1,3 millions articles de presse et leur résumé en anglais. Les résumés sont réalisés en utilisant les méthodes d'extraction comme d'abstraction ainsi que des méthodes mixtes. Ce corpus est disponible sur HuggingFace mais necessite un téléchargement préalable pour des raisons de protection des données.
|
10 |
|
11 |
+
Le corpus est nettoyé avant d'être utilisé pour l'entraînement du LSTM. Seule les parties 'text' et 'summary' du jsonl sont utilisées.
|
12 |
+
|
13 |
+
## Le système 🖥️
|
14 |
+
|
15 |
+
2 systèmes :
|
16 |
+
- LSTM réalisé à partir du <a href="https://loicgrobol.github.io//neural-networks/slides/03-transformers/transformers-slides.py.ipynb">cours</a> et de cet <a href="https://www.kaggle.com/code/columbine/seq2seq-pytorch">exemple</a> et de beaucoup d'autres référence en ligne.
|
17 |
+
- Fine-tuned transformers modèle lancé et pré-entrainé par Google :<a href="https://huggingface.co/google/mt5-small">google/mt5-small</a>, il s'agit d'une variance du <a href="https://huggingface.co/docs/transformers/v4.16.2/en/model_doc/mt5">mT5</a>. Le model est entrainé pour notre tâche en se basant sur la documentation sur <a href="https://huggingface.co/docs/transformers/tasks/summarization">Summarisation</a> proposé par Huggingface.
|
18 |
|
19 |
# La méthodologie
|
20 |
|
21 |
+
## Répartition du travail 👥
|
22 |
+
Nous avons travaillé avec le logiciel de gestion de version Github en mettant en place une intégration continue envoyant directement les `pull request` sur l'espace Huggingface.
|
23 |
+
<strong>'avons pas mis en place ces restrictions à cause de la difficulté à gérer Docker dans Huggingface qui nous a nécessité beaucoup de modification.
|
24 |
|
25 |
## Problèmes rencontrés et résolution
|
26 |
+
|
27 |
+
### Problème sur le corpus 📚
|
28 |
+
|
29 |
+
- [x] Problème Mojibake depuis les fichiers jsonl :
|
30 |
+
- [x] encodage en cp1252 et decodage en utf-8 avec ignore pour éviter les erreurs sur les caractères utf-8 présents dans le fichier à l'encodage
|
31 |
+
- ❔Le problème ne se présente étrangement pas sur toutes les machines.
|
32 |
+
- [x] Agglomération des pronoms et des verbes
|
33 |
+
- D'abord remplacement des `'` par des espaces avant le `split`
|
34 |
+
- Utilisation d'un dictionnaire de correspondance
|
35 |
+
- [ ] Split des noms propres composés ('Ivory Coast', 'Inter Milan') :
|
36 |
+
- [ ] pas de résolution à ce jour
|
37 |
+
- [ ] Problème des mots non disponibles dans le vocabulaire
|
38 |
+
- À terme, entraînement sur tout le corpus ?
|
39 |
+
- [ ] Problème de la qualité du corpus :
|
40 |
+
- Résumés tronqués : "Did Tatum O'Neal's latest battle with ex-husband John McEnroe put her back on drugs? The \"Paper Moon\"star checked herself into L.A.'s Promises rehab facility after a friend caught her smoking crack, according to The National Enquirer. O'Neal emerged clean and sober from Promises' 34-day recovery program in late July, the tab reports. The actress is said to have plunged into her old habits because of" ...
|
41 |
+
- Résumés plus proche de titres que de résumés : "SAN DIEGO PADRES team notebook"
|
42 |
+
- [ ] pas de résolution à ce jour
|
43 |
+
|
44 |
+
### Problème sur le Réseau de Neurone 🕸️
|
45 |
+
|
46 |
+
- [x] Prise en compte du padding dans l'apprentissage :
|
47 |
+
- [ ] utilisation de la fonctionnalité ignore_index de NLLLoss avec un padding d'une valeur à -100
|
48 |
+
- [ ] Temps d'apprentissage très long :
|
49 |
+
- [ ] essai de mise en place d'un entraînement par batch
|
50 |
+
- [ ] Répetition des déterminants après entraînement du modèle - https://huggingface.co/blog/how-to-generate
|
51 |
+
- [x] mise en place d'un Beam Search - non fructueux
|
52 |
+
- [ ] Passage vers du Sampling
|
53 |
+
|
54 |
+
### Problème sur le fine-tuning
|
55 |
+
- [x] La fonction map ne peut pas s'appliquer :
|
56 |
+
- Dans le prétrainement des données, utilise Dataset.from_dict(dataframe) pour obtenir les donneés en Dataset au lieu de Dataframe
|
57 |
+
- [x] Problème de la permission d'appel du model privé enregistré sur HuggingFace :
|
58 |
+
- Se connecter à l'aide de `huggingface-cli login` et mettre `use_auth_token=True` en appelant le model.
|
59 |
+
- [x] Processus arrêté sans erruers détectées :
|
60 |
+
- Diminuer le nombre de données
|
61 |
+
- Modifier les paramètres d'entrainement en diminuant le nombre d'epoch d'entrainement
|
62 |
+
- [ ] Warning message pour les tokens non identifiables causé par
|
63 |
+
la conversion de sentencepiece tokenizer en fast tokenizer:
|
64 |
+
- [ ] pas de résolution à ce jour
|
65 |
+
- [ ] Les résultats d'évaluation selon ROUGE sont très mauvais, rouge2 à 0:
|
66 |
+
- [ ] pas de résolution à ce jour
|
67 |
+
### Problème sur l'interface
|
68 |
+
|
69 |
+
### Problème de l'Intégration continue
|
70 |
+
|
71 |
+
- [x] Pas de lien possible entre Huggingface et un github dont l'history contient des fichier de plus de 10Mo
|
72 |
+
- 💣 Explosion du github
|
73 |
+
- [ ] Docker qui fonctionne en local mais en sur Huggingface
|
74 |
+
- Problème de path de fichier
|
75 |
|
76 |
|
77 |
## Les étapes du projet
|
78 |
|
79 |
+
1. Initialisation du Github
|
80 |
+
2. Premiers pas dans le réseau de neurone
|
81 |
+
3. Réalisation de la plateforme
|
82 |
+
4. Intégration à Huggingface
|
83 |
+
5. Fine-tuning de modèle
|
84 |
+
6. Finalisation
|
85 |
+
|
86 |
# Implémentation
|
87 |
## modélisation
|
88 |
|
89 |
+
Nous avons décidé dans un premier temps de modéliser une LSTM pour le résumé automatique sur la base du réseau de neurone réalisé en cours.
|
90 |
Pour ce faire nous nous sommes beaucoup inspirée du kaggle https://www.kaggle.com/code/columbine/seq2seq-pytorch ainsi que de la documentation de PyTorch https://pytorch.org/tutorials/beginner/nlp/sequence_models_tutorial.html#example-an-lstm-for-part-of-speech-tagging
|
91 |
+
|
92 |
## modules et API utilisés
|
93 |
+
### Dataloader :
|
94 |
+
- Data
|
95 |
+
```
|
96 |
+
A class used to get data from file
|
97 |
+
...
|
98 |
+
|
99 |
+
Attributes
|
100 |
+
----------
|
101 |
+
path : str
|
102 |
+
the path to the file containing the data
|
103 |
+
|
104 |
+
Methods
|
105 |
+
-------
|
106 |
+
open()
|
107 |
+
open the jsonl file with pandas
|
108 |
+
clean_data(text_type)
|
109 |
+
clean the data got by opening the file and adds <start> and
|
110 |
+
<end> tokens depending on the text_type
|
111 |
+
get_words()
|
112 |
+
get the dataset vocabulary
|
113 |
+
```
|
114 |
+
- Vectoriser
|
115 |
+
```
|
116 |
+
```
|
117 |
+
|
118 |
+
### Model :
|
119 |
+
|
120 |
+
### train :
|
121 |
+
|
122 |
+
### inference :
|
123 |
+
|
124 |
+
### api :
|
125 |
+
|
126 |
+
### templates :
|
127 |
+
|
128 |
## Langages de programmation
|
129 |
+
- 🐳 Docker
|
130 |
+
- yaml
|
131 |
+
- 🐍 et python evidemment
|
132 |
|
133 |
# Les résultats (fichiers output, visualisations…)
|
134 |
|
135 |
## Les metriques d'évaluation
|
136 |
- ROUGE
|
137 |
- BLEU
|
|
|
|
|
|
|
138 |
|
139 |
|
140 |
# Discussion des résultats
|
141 |
+
|
142 |
+
## Résultats du LSTM
|
143 |
+
|
144 |
+
Les résultats du LSTM sont inutilisables mais ont permis au moins de se confronter à la difficulté de mettre en place des réseaux de neurones depuis pas grand chose.
|
145 |
+
On aurait aimé avoir plus de temps pour aller plus loin et comprendre mieux encore : l'entraîement par batch, pourquoi les résultats sont si mauvais, mettre d'autres stratégies de génération en place, ...
|
146 |
+
|
147 |
+
## Résultat du fine-tuning
|
148 |
+
|
149 |
+
Les résumés générés ne sont pas grammaticalement corrects à 100% mais les informations importantes du texte sont bien présentes dans le résumé, et la longeur du résumé correspond bien à notre attente. Cependant les résultats d'évaluation selon ROUGE est très mauvais, malgré une amélioration de 0.007 à 0.06 pour rouge1, il n'ést plus possible d'obtenir de meilleurs scores.
|
README.md
CHANGED
@@ -1,7 +1,69 @@
|
|
1 |
-
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Project Deep Learning - Text Summarisation tool and it's application programming interface
|
2 |
+
|
3 |
+
As part of the master course "Neural Network",for this university project, our task is about creating a application, a interface or a python library in the use of NLP(Natural Language Processing) with the help of an artificial neural network system.
|
4 |
+
|
5 |
+
|
6 |
+
## Description
|
7 |
+
|
8 |
+
**Objectives of our project :**
|
9 |
+
|
10 |
+
Create a interface which allows users to sammrize a long text like press article into a brief version.
|
11 |
+
|
12 |
+
To achieve this general objective, for the algorithm part, we would like to test two different deep learning methods: setting up a LSTM model and fine tuning Transformer model.
|
13 |
+
|
14 |
+
For the interface, having a interface building with fastAPI framework and putting the application on Huggingface.
|
15 |
+
|
16 |
+
|
17 |
+
## Getting Started
|
18 |
+
|
19 |
+
### Préparation
|
20 |
+
|
21 |
+
* Open the link below directing towards our interface on huggingface.
|
22 |
+
```
|
23 |
+
https://huggingface.co/spaces/EveSa/SummaryProject
|
24 |
+
```
|
25 |
+
### The interface
|
26 |
+
|
27 |
+
* 1- Choosing a model for your summarization task (LSTM/Fine-tuned T5) by clicking on the scroll-down list. And click the Select model botton.
|
28 |
+
|
29 |
+
* 2- Enter your text to summarize in the left section.
|
30 |
+
|
31 |
+
* 3- Click on 'Go!' botton and you will get your sammary!
|
32 |
+
|
33 |
+
* 4- Dont forget to reset the App for your next try. The botton is at the right next to 'Go!'.
|
34 |
+
|
35 |
+
## In case you want to try to execute our scripts :
|
36 |
+
|
37 |
+
### Préparation
|
38 |
+
* In order to run the script, you need:
|
39 |
+
|
40 |
+
* 1- Create a virtual environment named .venv
|
41 |
+
```
|
42 |
+
python3 -m virtualenv .venv
|
43 |
+
source .venv/bin/activate
|
44 |
+
```
|
45 |
+
* 2- Also install the dependencies
|
46 |
+
```
|
47 |
+
pip install -U -r requirements.txt
|
48 |
+
```
|
49 |
+
|
50 |
+
* You are now ready to execute the scripts ^^
|
51 |
+
|
52 |
+
### The programme api.py
|
53 |
+
|
54 |
+
* Run the script with the command below:
|
55 |
+
```
|
56 |
+
python3 api.py
|
57 |
+
```
|
58 |
+
* This code generate the same page as on Huggingface in your browser. To do the task your may follow the steps in the previous section.
|
59 |
+
|
60 |
+
## Authors
|
61 |
+
|
62 |
+
Eve Sauvage
|
63 |
+
Estelle SALMON
|
64 |
+
Lingyun GAO
|
65 |
+
|
66 |
+
|
67 |
+
## License
|
68 |
+
|
69 |
+
This project is licensed under the [M2 TAL] License
|
src/fine_tune_T5.py
CHANGED
@@ -1,49 +1,55 @@
|
|
1 |
-
import re
|
2 |
import os
|
|
|
3 |
import string
|
|
|
4 |
import contractions
|
5 |
-
import torch
|
6 |
import datasets
|
7 |
-
|
8 |
import pandas as pd
|
|
|
|
|
9 |
from tqdm import tqdm
|
10 |
-
import
|
11 |
-
|
12 |
-
|
13 |
-
from transformers import DataCollatorForSeq2Seq
|
14 |
|
15 |
|
16 |
def clean_text(texts):
|
17 |
-
|
18 |
texts = texts.lower()
|
19 |
texts = contractions.fix(texts)
|
20 |
texts = texts.translate(str.maketrans("", "", string.punctuation))
|
21 |
-
texts = re.sub(r
|
22 |
return texts
|
23 |
|
24 |
|
25 |
def datasetmaker(path=str):
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
data = pd.read_json(path, lines=True)
|
30 |
-
df = data.drop(
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
|
|
|
|
|
|
|
|
41 |
tqdm.pandas()
|
42 |
-
df[
|
43 |
-
df[
|
44 |
dataset = Dataset.from_dict(df)
|
45 |
return dataset
|
46 |
|
|
|
47 |
# voir si le model par hasard esr déjà bien
|
48 |
|
49 |
# test_text = dataset['text'][0]
|
@@ -67,16 +73,24 @@ def calculate_metric(dataset, metric, model, tokenizer,
|
|
67 |
column_summary='summary'):
|
68 |
"""this fonction evaluate the model with metric rouge and
|
69 |
print a table of rouge scores rouge1', 'rouge2', 'rougeL', 'rougeLsum'"""
|
|
|
70 |
article_batches = list(
|
71 |
-
str(generate_batch_sized_chunks(dataset[column_text], batch_size))
|
|
|
72 |
target_batches = list(
|
73 |
-
str(generate_batch_sized_chunks(dataset[column_summary], batch_size))
|
|
|
74 |
|
75 |
for article_batch, target_batch in tqdm(
|
76 |
-
|
77 |
-
|
78 |
-
inputs = tokenizer(
|
79 |
-
|
|
|
|
|
|
|
|
|
|
|
80 |
# parameter for length penalty ensures that the model does not
|
81 |
# generate sequences that are too long.
|
82 |
summaries = model.generate(
|
@@ -84,16 +98,18 @@ def calculate_metric(dataset, metric, model, tokenizer,
|
|
84 |
attention_mask=inputs["attention_mask"].to(device),
|
85 |
length_penalty=0.8,
|
86 |
num_beams=8,
|
87 |
-
max_length=128
|
|
|
88 |
|
89 |
# Décode les textes
|
90 |
# renplacer les tokens, ajouter des textes décodés avec les rédéfences
|
91 |
# vers la métrique.
|
92 |
decoded_summaries = [
|
93 |
tokenizer.decode(
|
94 |
-
s,
|
95 |
-
|
96 |
-
|
|
|
97 |
|
98 |
decoded_summaries = [d.replace("", " ") for d in decoded_summaries]
|
99 |
|
@@ -103,9 +119,9 @@ def calculate_metric(dataset, metric, model, tokenizer,
|
|
103 |
|
104 |
# compute et return les ROUGE scores.
|
105 |
results = metric.compute()
|
106 |
-
rouge_names = [
|
107 |
rouge_dict = dict((rn, results[rn]) for rn in rouge_names)
|
108 |
-
return pd.DataFrame(rouge_dict, index=[
|
109 |
|
110 |
|
111 |
def convert_ex_to_features(example_batch):
|
@@ -114,14 +130,14 @@ def convert_ex_to_features(example_batch):
|
|
114 |
max_length=1024, truncation=True)
|
115 |
|
116 |
labels = tokenizer(
|
117 |
-
example_batch[
|
118 |
max_length=128,
|
119 |
truncation=True)
|
120 |
|
121 |
return {
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
}
|
126 |
|
127 |
|
@@ -129,7 +145,8 @@ if __name__ == '__main__':
|
|
129 |
# réalisation des datasets propres
|
130 |
train_dataset = datasetmaker('data/train_extract.jsonl')
|
131 |
|
132 |
-
|
|
|
133 |
|
134 |
test_dataset = datasetmaker('data/test_extract.jsonl')
|
135 |
|
@@ -139,24 +156,26 @@ if __name__ == '__main__':
|
|
139 |
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
|
140 |
# faire appel au model à entrainer
|
141 |
tokenizer = AutoTokenizer.from_pretrained('google/mt5-small')
|
|
|
142 |
mt5_config = AutoConfig.from_pretrained(
|
143 |
-
|
144 |
max_length=128,
|
145 |
length_penalty=0.6,
|
146 |
no_repeat_ngram_size=2,
|
147 |
num_beams=15,
|
148 |
)
|
|
|
149 |
model = (AutoModelForSeq2SeqLM
|
150 |
.from_pretrained('google/mt5-small', config=mt5_config)
|
151 |
.to(device))
|
152 |
#convertir les exemples en inputFeatures
|
|
|
153 |
dataset_pt = dataset.map(
|
154 |
convert_ex_to_features,
|
155 |
-
remove_columns=[
|
156 |
-
"summary",
|
157 |
-
"text"],
|
158 |
batched=True,
|
159 |
-
batch_size=128
|
|
|
160 |
|
161 |
data_collator = DataCollatorForSeq2Seq(
|
162 |
tokenizer, model=model, return_tensors="pt")
|
@@ -187,8 +206,8 @@ if __name__ == '__main__':
|
|
187 |
args=training_args,
|
188 |
data_collator=data_collator,
|
189 |
# compute_metrics = calculate_metric,
|
190 |
-
train_dataset=dataset_pt[
|
191 |
-
eval_dataset=dataset_pt[
|
192 |
tokenizer=tokenizer,
|
193 |
)
|
194 |
|
@@ -202,8 +221,9 @@ if __name__ == '__main__':
|
|
202 |
tokenizer,
|
203 |
batch_size=2,
|
204 |
device=device,
|
205 |
-
column_text=
|
206 |
-
column_summary=
|
|
|
207 |
print(score)
|
208 |
|
209 |
# Fine Tuning terminés et à sauvgarder
|
@@ -215,11 +235,13 @@ if __name__ == '__main__':
|
|
215 |
else:
|
216 |
trainer.model.save_pretrained("t5_summary")
|
217 |
tokenizer.save_pretrained("t5_summary")
|
|
|
218 |
# faire appel au model en local
|
219 |
model = (AutoModelForSeq2SeqLM
|
220 |
.from_pretrained("t5_summary")
|
221 |
.to(device))
|
222 |
|
|
|
223 |
# mettre en usage : TEST
|
224 |
|
225 |
# gen_kwargs = {"length_penalty" : 0.8, "num_beams" : 8, "max_length" : 128}
|
|
|
|
|
1 |
import os
|
2 |
+
import re
|
3 |
import string
|
4 |
+
|
5 |
import contractions
|
|
|
6 |
import datasets
|
7 |
+
import evaluate
|
8 |
import pandas as pd
|
9 |
+
import torch
|
10 |
+
from datasets import Dataset
|
11 |
from tqdm import tqdm
|
12 |
+
from transformers import (AutoConfig, AutoModelForSeq2SeqLM, AutoTokenizer,
|
13 |
+
DataCollatorForSeq2Seq, Seq2SeqTrainer,
|
14 |
+
Seq2SeqTrainingArguments)
|
|
|
15 |
|
16 |
|
17 |
def clean_text(texts):
|
18 |
+
"""This fonction makes clean text for the future use"""
|
19 |
texts = texts.lower()
|
20 |
texts = contractions.fix(texts)
|
21 |
texts = texts.translate(str.maketrans("", "", string.punctuation))
|
22 |
+
texts = re.sub(r"\n", " ", texts)
|
23 |
return texts
|
24 |
|
25 |
|
26 |
def datasetmaker(path=str):
|
27 |
+
"""This fonction take the jsonl file, read it to a dataframe,
|
28 |
+
remove the colums not needed for the task and turn it into a file type Dataset
|
29 |
+
"""
|
30 |
data = pd.read_json(path, lines=True)
|
31 |
+
df = data.drop(
|
32 |
+
[
|
33 |
+
"url",
|
34 |
+
"archive",
|
35 |
+
"title",
|
36 |
+
"date",
|
37 |
+
"compression",
|
38 |
+
"coverage",
|
39 |
+
"density",
|
40 |
+
"compression_bin",
|
41 |
+
"coverage_bin",
|
42 |
+
"density_bin",
|
43 |
+
],
|
44 |
+
axis=1,
|
45 |
+
)
|
46 |
tqdm.pandas()
|
47 |
+
df["text"] = df.text.apply(lambda texts: clean_text(texts))
|
48 |
+
df["summary"] = df.summary.apply(lambda summary: clean_text(summary))
|
49 |
dataset = Dataset.from_dict(df)
|
50 |
return dataset
|
51 |
|
52 |
+
|
53 |
# voir si le model par hasard esr déjà bien
|
54 |
|
55 |
# test_text = dataset['text'][0]
|
|
|
73 |
column_summary='summary'):
|
74 |
"""this fonction evaluate the model with metric rouge and
|
75 |
print a table of rouge scores rouge1', 'rouge2', 'rougeL', 'rougeLsum'"""
|
76 |
+
|
77 |
article_batches = list(
|
78 |
+
str(generate_batch_sized_chunks(dataset[column_text], batch_size))
|
79 |
+
)
|
80 |
target_batches = list(
|
81 |
+
str(generate_batch_sized_chunks(dataset[column_summary], batch_size))
|
82 |
+
)
|
83 |
|
84 |
for article_batch, target_batch in tqdm(
|
85 |
+
zip(article_batches, target_batches), total=len(article_batches)
|
86 |
+
):
|
87 |
+
inputs = tokenizer(
|
88 |
+
article_batch,
|
89 |
+
max_length=1024,
|
90 |
+
truncation=True,
|
91 |
+
padding="max_length",
|
92 |
+
return_tensors="pt",
|
93 |
+
)
|
94 |
# parameter for length penalty ensures that the model does not
|
95 |
# generate sequences that are too long.
|
96 |
summaries = model.generate(
|
|
|
98 |
attention_mask=inputs["attention_mask"].to(device),
|
99 |
length_penalty=0.8,
|
100 |
num_beams=8,
|
101 |
+
max_length=128,
|
102 |
+
)
|
103 |
|
104 |
# Décode les textes
|
105 |
# renplacer les tokens, ajouter des textes décodés avec les rédéfences
|
106 |
# vers la métrique.
|
107 |
decoded_summaries = [
|
108 |
tokenizer.decode(
|
109 |
+
s, skip_special_tokens=True, clean_up_tokenization_spaces=True
|
110 |
+
)
|
111 |
+
for s in summaries
|
112 |
+
]
|
113 |
|
114 |
decoded_summaries = [d.replace("", " ") for d in decoded_summaries]
|
115 |
|
|
|
119 |
|
120 |
# compute et return les ROUGE scores.
|
121 |
results = metric.compute()
|
122 |
+
rouge_names = ["rouge1", "rouge2", "rougeL", "rougeLsum"]
|
123 |
rouge_dict = dict((rn, results[rn]) for rn in rouge_names)
|
124 |
+
return pd.DataFrame(rouge_dict, index=["T5"])
|
125 |
|
126 |
|
127 |
def convert_ex_to_features(example_batch):
|
|
|
130 |
max_length=1024, truncation=True)
|
131 |
|
132 |
labels = tokenizer(
|
133 |
+
example_batch["summary"],
|
134 |
max_length=128,
|
135 |
truncation=True)
|
136 |
|
137 |
return {
|
138 |
+
"input_ids": input_encodings["input_ids"],
|
139 |
+
"attention_mask": input_encodings["attention_mask"],
|
140 |
+
"labels": labels["input_ids"],
|
141 |
}
|
142 |
|
143 |
|
|
|
145 |
# réalisation des datasets propres
|
146 |
train_dataset = datasetmaker('data/train_extract.jsonl')
|
147 |
|
148 |
+
|
149 |
+
dev_dataset = datasetmaker("data/dev_extract.jsonl")
|
150 |
|
151 |
test_dataset = datasetmaker('data/test_extract.jsonl')
|
152 |
|
|
|
156 |
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
|
157 |
# faire appel au model à entrainer
|
158 |
tokenizer = AutoTokenizer.from_pretrained('google/mt5-small')
|
159 |
+
|
160 |
mt5_config = AutoConfig.from_pretrained(
|
161 |
+
"google/mt5-small",
|
162 |
max_length=128,
|
163 |
length_penalty=0.6,
|
164 |
no_repeat_ngram_size=2,
|
165 |
num_beams=15,
|
166 |
)
|
167 |
+
|
168 |
model = (AutoModelForSeq2SeqLM
|
169 |
.from_pretrained('google/mt5-small', config=mt5_config)
|
170 |
.to(device))
|
171 |
#convertir les exemples en inputFeatures
|
172 |
+
|
173 |
dataset_pt = dataset.map(
|
174 |
convert_ex_to_features,
|
175 |
+
remove_columns=["summary", "text"],
|
|
|
|
|
176 |
batched=True,
|
177 |
+
batch_size=128,
|
178 |
+
)
|
179 |
|
180 |
data_collator = DataCollatorForSeq2Seq(
|
181 |
tokenizer, model=model, return_tensors="pt")
|
|
|
206 |
args=training_args,
|
207 |
data_collator=data_collator,
|
208 |
# compute_metrics = calculate_metric,
|
209 |
+
train_dataset=dataset_pt["train"],
|
210 |
+
eval_dataset=dataset_pt["dev"].select(range(10)),
|
211 |
tokenizer=tokenizer,
|
212 |
)
|
213 |
|
|
|
221 |
tokenizer,
|
222 |
batch_size=2,
|
223 |
device=device,
|
224 |
+
column_text="text",
|
225 |
+
column_summary="summary",
|
226 |
+
)
|
227 |
print(score)
|
228 |
|
229 |
# Fine Tuning terminés et à sauvgarder
|
|
|
235 |
else:
|
236 |
trainer.model.save_pretrained("t5_summary")
|
237 |
tokenizer.save_pretrained("t5_summary")
|
238 |
+
|
239 |
# faire appel au model en local
|
240 |
model = (AutoModelForSeq2SeqLM
|
241 |
.from_pretrained("t5_summary")
|
242 |
.to(device))
|
243 |
|
244 |
+
|
245 |
# mettre en usage : TEST
|
246 |
|
247 |
# gen_kwargs = {"length_penalty" : 0.8, "num_beams" : 8, "max_length" : 128}
|