📝 : Added section on the Embeddings approach with CamemBERT

This commit is contained in:
2025-10-28 20:49:07 +01:00
parent 098c5e3738
commit e2ecb1a49f
+43 -22
View File
@@ -62,7 +62,7 @@ Compte tenu du temps de prétraitement et d'entraînement, j'ai effectué mes ex
Deux fonctions de nettoyage ont été testées. La première (`clean_text_old`) était une tentative de nettoyage en profondeur à base de regex. Deux fonctions de nettoyage ont été testées. La première (`clean_text_old`) était une tentative de nettoyage en profondeur à base de regex.
```python ```py
# Ancienne version # Ancienne version
def clean_text(example): def clean_text(example):
text = example["complete_text"] text = example["complete_text"]
@@ -76,34 +76,34 @@ def clean_text(example):
else: else:
date = str(parts[0]) date = str(parts[0])
# 1. Retirer les numéros de page # Retirer les numéros de page
text = re.sub(r"[—\-]\s*\d+\s*[—\-]", " ", text) text = re.sub(r"[—\-]\s*\d+\s*[—\-]", " ", text)
# 2. Corriger les apostrophes et guillemets échappés # Corriger les apostrophes et guillemets échappés
text = text.replace("\\'", "'") text = text.replace("\\'", "'")
text = text.replace("\\\"", "\"") text = text.replace("\\\"", "\"")
text = text.replace("\\n", " ") text = text.replace("\\n", " ")
text = text.replace("\\r", " ") text = text.replace("\\r", " ")
text = text.replace("\\t", " ") text = text.replace("\\t", " ")
# 3. Corriger les mots coupés (pattern plus précis) # Corriger les mots coupés (pattern plus précis)
text = re.sub(r'([a-zàâäæçéèêëïîôùûüœ])\s+([a-zàâäæçéèêëïîôùûüœ]{2,})', text = re.sub(r'([a-zàâäæçéèêëïîôùûüœ])\s+([a-zàâäæçéèêëïîôùûüœ]{2,})',
r'\1\2', text) r'\1\2', text)
# 4. Corriger les cas avec plusieurs espaces # Corriger les cas avec plusieurs espaces
text = re.sub(r'([a-zàâäæçéèêëïîôùûüœ])\s{2,}([a-zàâäæçéèêëïîôùûüœ])', text = re.sub(r'([a-zàâäæçéèêëïîôùûüœ])\s{2,}([a-zàâäæçéèêëïîôùûüœ])',
r'\1\2', text) r'\1\2', text)
# 5. Normaliser les espaces multiples # Normaliser les espaces multiples
text = re.sub(r"\s+", " ", text) text = re.sub(r"\s+", " ", text)
# 6. Nettoyer les caractères spéciaux # Nettoyer les caractères spéciaux
text = re.sub(r"[^\w\s\.,;:\?!'\-\"«»À-ÖØ-öø-ÿœŒ]", " ", text) text = re.sub(r"[^\w\s\.,;:\?!'\-\"«»À-ÖØ-öø-ÿœŒ]", " ", text)
# 7. Re-normaliser après nettoyage # Re-normaliser après nettoyage
text = re.sub(r"\s+", " ", text) text = re.sub(r"\s+", " ", text)
# 8. Corriger la ponctuation # Corriger la ponctuation
text = re.sub(r"\s+([,.\?!;:])", r"\1", text) text = re.sub(r"\s+([,.\?!;:])", r"\1", text)
text = re.sub(r"([,.\?!;:])\s*([,.\?!;:])", r"\1\2", text) text = re.sub(r"([,.\?!;:])\s*([,.\?!;:])", r"\1\2", text)
@@ -123,8 +123,7 @@ Cette fonction s'est avérée complexe et pas nécessairement plus performante.
Pour l'approche par embeddings, j'ai opté pour une version simplifiée, se concentrant sur la miniscule, la suppression de la ponctuation et des stopwords. Pour l'approche par embeddings, j'ai opté pour une version simplifiée, se concentrant sur la miniscule, la suppression de la ponctuation et des stopwords.
```python ```py
# Version actuelle (depuis work.ipynb)
def clean_text(example): def clean_text(example):
""" """
Nettoie le texte d'entrée Nettoie le texte d'entrée
@@ -132,7 +131,7 @@ def clean_text(example):
text = example["complete_text"] text = example["complete_text"]
date = example.get("date", None) date = example.get("date", None)
# --- Nettoyage de la date # Nettoyage de la date
if "-" in str(date) and date is not None: if "-" in str(date) and date is not None:
parts = str(date).split("-") parts = str(date).split("-")
if (parts[1].isdigit() and len(parts[1]) == 4) and parts[0] == "????" if (parts[1].isdigit() and len(parts[1]) == 4) and parts[0] == "????"
@@ -140,7 +139,7 @@ def clean_text(example):
else: else:
date = str(parts[0]) date = str(parts[0])
# --- Nettoyage de texte # Nettoyage de texte
text = (text.replace("\\\\n", " ") text = (text.replace("\\\\n", " ")
.replace("\\\\r", " ") .replace("\\\\r", " ")
.replace("\\\\t", " ")) .replace("\\\\t", " "))
@@ -188,7 +187,7 @@ french_stopwords = set([
Pour la classification, j'ai groupé les textes par périodes de 10 ans et 50 ans. Pour la classification, j'ai groupé les textes par périodes de 10 ans et 50 ans.
```python ```py
def create_period_label(example, period_length=50): def create_period_label(example, period_length=50):
""" """
Crée une étiquette de période basée sur l'année de publication. Crée une étiquette de période basée sur l'année de publication.
@@ -209,7 +208,7 @@ dataset_with_labels = cleaned_ds.map(create_period_label)
Ma première approche a servi de base. J'ai utilisé un `TfidfVectorizer` pour transformer le texte en vecteurs de fréquence de mots, puis entraîné un `SGDClassifier`. Ma première approche a servi de base. J'ai utilisé un `TfidfVectorizer` pour transformer le texte en vecteurs de fréquence de mots, puis entraîné un `SGDClassifier`.
```python ```py
def train_and_evaluate_tfidf(dataset, period_length_value): def train_and_evaluate_tfidf(dataset, period_length_value):
# Séparer en ensembles d'entraînement (80%) et de test (20%) # Séparer en ensembles d'entraînement (80%) et de test (20%)
@@ -233,13 +232,35 @@ def train_and_evaluate_tfidf(dataset, period_length_value):
sgd_classifier = SGDClassifier(loss='log_loss', random_state=42, max_iter=1000, tol=1e-3) sgd_classifier = SGDClassifier(loss='log_loss', random_state=42, max_iter=1000, tol=1e-3)
sgd_classifier.fit(X_train_tfidf, y_train) sgd_classifier.fit(X_train_tfidf, y_train)
# Évaluation
y_pred_sgd = sgd_classifier.predict(X_test_tfidf)
accuracy = accuracy_score(y_test, y_pred_sgd)
print(f"Accuracy: {accuracy:.4f}")
print(classification_report(y_test, y_pred_sgd, zero_division=0))
return sgd_classifier, tfidf_vectorizer, X_test, y_test return sgd_classifier, tfidf_vectorizer, X_test, y_test
``` ```
## 5\. Classification sémantique par Embeddings (Seconde approche)
L'objectif est de transformer chaque texte en un vecteur qui représente son sens. Des textes sémantiquement similaires auront des vecteurs proches.
Le modèle choisi est [dangvantuan/sentence-camembert-base](https://huggingface.co/dangvantuan/sentence-camembert-base), il spécialisé pour le français.
### 5.2. Implémentation
Le code ci-dessous, illustre le chargement du modèle d'embedding et l'entraînement du classifieur :
```py
# Charger le modèle
model = SentenceTransformer("dangvantuan/sentence-camembert-base")
# Génération des embeddings
# train_texts et test_texts sont créés lors du prétraitement
X_train_embeddings = model.encode(train_texts, show_progress_bar=True)
X_test_embeddings = model.encode(test_texts, show_progress_bar=True)
# Entrainement
sgd_classifier_emb = SGDClassifier(
loss='log_loss',
random_state=42,
max_iter=1000,
tol=1e-3
)
sgd_classifier_emb.fit(X_train_embeddings, train_labels)
```