Conception de l'interface des modules et implémentation
Le programme adopte une approche fonctionnelle pour implémenter la détection de plagiat. Les fonctions principales sont :
- lire_document(chemin_fichier) : Responsable de la lecture du contenu des fichiers.
- calculer_similarite_cosinus(texte1, texte2) : Vectorise les textes et calcule la similarité cosinus.
- execution_principale() : Orchestre le flux d'exécution, lit les fichiers et affiche les résultats.
La fonction execution_principale appelle lire_document pour obtenir le texte original et le texte suspect, puis utilise calculer_similarite_cosinus pour évaluer leur similarité. L'algorithme clé transforme les textes en vecteurs TF-IDF pour pondérer l'importance des termes, puis mesure l'angle entre les vecteurs via la similarité cosinus.
Optimisations de performance
Des améliorations ont été apportées pour renforcer l'efficacité :
- Mise en cache du vectoriseur : Une instance globale de
TfidfVectorizerest réutilisée pour éviter la reconstruction répétée du vocabulaire, réduisant ainsi le temps de calcul. - Gestion des threads : Un verrou (
threading.Lock) est introduit pour garantir la sécurité lors de l'accès concurrent au vectoriseur, bien que le programme actuel ne nécessite pas de parallélisme. - Utilisation de matrices creuses : Le vectoriseur retourne des matrices creuses par défaut, ce qui diminue la consommation mémoire pour les textes volumineux.
- Prétraitement du texte : Les textes sont normalisés en minuscules et sans ponctuation pour améliorer la précision, au détriment d'un léger surcoût computationnel dû à la reconstruction du vocabulaire à chaque appel.
- Gestion des exceptions : Des mécanismes de capture d'erreurs sont ajoutés pour les opérations d'E/S et la vectorisation, offrant des retours d'erreur clairs.
Ces modifications ont amélioré la précision grâce à la normalisation du texte et réduit l'empreinte mémoire via les matrices creuses, bien que le gain en vitesse soit modeste pour les petits ensembles de données.
Tests unitaires
Des tests unitaires ont été conçus pour valider la fonction calculer_similarite_cosinus. Voici un exemple de code de test réécrit avec des noms de variables et de méthodes modifiés :
import unittest
class DetectionPlagiatTests(unittest.TestCase):
def test_textes_identiques(self):
extrait = "Le soleil brille aujourd'hui."
score = calculer_similarite_cosinus(extrait, extrait)
self.assertAlmostEqual(score, 1.0, places=2)
def test_textes_opposes(self):
texte_a = "La pluie tombe fort ce matin."
texte_b = "Les algorithmes optimisent les données."
score = calculer_similarite_cosinus(texte_a, texte_b)
self.assertAlmostEqual(score, 0.0, delta=0.1)
def test_similarite_partielle(self):
segment1 = "Je lis un livre passionnant."
segment2 = "La lecture d'un roman captivant est agréable."
score = calculer_similarite_cosinus(segment1, segment2)
self.assertGreater(score, 0.4)
def test_texte_vide(self):
vide = ""
contenu = "Texte arbitraire."
score = calculer_similarite_cosinus(vide, contenu)
self.assertEqual(score, 0.0)
if __name__ == '__main__':
unittest.main()
Ces tests couvrent des scénarios variés : textes identiques, totalement différents, partiellement similaires et cas limites comme les entrées vides. Les données de test sont choisies pour refléter différentes langues et structures, assurant ainsi la robustesse de l'algorithme.
Gestion des exceptions
Le programme intègre plusieurs mécanismes de gestion d'erreurs pour améliorer la fiabilité :
- Erreurs de lecture de fichier : Capture des exceptions
FileNotFoundErrorlorsque le chemin est invalide, avec un message d'erreur informatif. - Fichiers vides : Vérification du contenu après lecture ; si vide, une
ValueErrorest levée pour alerter l'utilisateur. - Erreurs de vectorisation : Protection contre les exceptions lors de l'appel au vectoriseur, par exemple pour des caractères spéciaux ou des entrées non textuelles.
Des tests unitaires supplémentaires validant ces scénarios d'erreur ont été implémentés, par exemple :
def test_fichier_introuvable(self):
with self.assertRaises(FileNotFoundError):
lire_document("chemin_inexistant.txt")
def test_entree_numerique(self):
avec_nombre = 12345
texte_normal = "Une chaîne de caractères."
with self.assertRaises(AttributeError):
calculer_similarite_cosinus(avec_nombre, texte_normal)
Cela garantit que le programme se comporte de manière prévisible face à des entrées invalides ou des erreurs système.