import os import random import zlib def preparer_training_data(dossiers, nbr_fich_training, coupe_entete, aléatoire): """Sous-fonction : Préparation du Training Set""" training_data = [] # Liste de dictionnaires pour stocker contenu + Cx2 for doss in dossiers: category_name = os.path.basename(doss) all_files = [os.path.join(doss, f) for f in os.listdir(doss)] if aléatoire: selection = random.sample(all_files, min(nbr_fich_training, len(all_files))) else: selection=all_files[0:nbr_fich_training] selection.sort() for filepath in selection: with open(filepath, 'r', encoding='utf-8', errors='ignore') as f: content = f.read() if coupe_entete: if '\n\n' in content: content = content.split('\n\n', 1)[1] training_data.append({"content": content, "label": category_name}) return training_data def preparer_test_files(test_folders, nbr_fich_test, aléatoire): """Sous-fonction : Préparation du Test Set""" test_files_paths = [] for doss_test in test_folders: all_test_files = [os.path.join(doss_test, f) for f in os.listdir(doss_test)] if aléatoire: test_files_paths.extend(random.sample(all_test_files, min(nbr_fich_test, len(all_test_files)))) else: test_files_paths=all_test_files[0:nbr_fich_test] return test_files_paths def NCD (str1, str2): cx1 = len(zlib.compress(str1.encode('utf8'))) cx2 = len(zlib.compress(str2.encode('utf8'))) str = str1+str2 cx = len(zlib.compress(str.encode('utf8'))) ncd = (cx-min(cx1,cx2))/max(cx1,cx2) return ncd def ouvre_fich(fich1,coupe_entete = False): fi = open(fich1,'r',encoding='utf-8') chaine = fi.read() fi.close() if coupe_entete: if '\n\n' in chaine: res = chaine.split('\n\n', 1)[1] else : res = chaine else: res = chaine return res def evaluer_classification(test_files_paths, training_data, k, coupe_entete): """Sous-fonction : Classification et calcul du score""" vrai = 0 compt = 0 total_test = len(test_files_paths) for filepath in test_files_paths: # La catégorie réelle est le nom du fichier real_category = os.path.basename(os.path.dirname(filepath)) # NCD fichier1=ouvre_fich(filepath,coupe_entete) distances = [] for train_item in training_data: fichier2 = train_item['content'] ncd = NCD(fichier1,fichier2) distances.append((ncd, train_item["label"])) # k distances.sort(key=lambda x: x[0]) top_k = [distances[i][1] for i in range(k)] predict_class = max(set(top_k), key=top_k.count) if predict_class == real_category: vrai += 1 #print(f"Réussite pour {real_category}") compt += 1 print(f'Progression: {int(100/total_test*compt)}%', end='\r') return (vrai / total_test) * 100 def classification(dossiers:list, test_folders:list, k:int, nbr_fich_training:int, nbr_fich_test:int, coupe_entete:bool = False, aléatoire = False ): """Fonction principale (Orchestrateur)""" # 1. Préparation du Training Set training_data = preparer_training_data(dossiers, nbr_fich_training, coupe_entete, aléatoire) # 2. Préparation du Test Set test_files_paths = preparer_test_files(test_folders, nbr_fich_test, aléatoire) # 3. Classification et retour du résultat return evaluer_classification(test_files_paths, training_data, k, coupe_entete) """ Fonctionnement général: - On compresse les différents fichier déja classé de notre base de donnée - Puis on les compresse en y ajoutant le fichier que l'on souhaite classer - Après chaque double compression on attribue un score (calculé en fontction de la difference de taille des 2 compressions) allant de 0 à 1 au fichier ** On calcul la différence entre les 2 compressions puis on la divise par la compressions des 2 fichiers pour garder un score entre 0 et 1 - Ensuite on effectue une liste croissante des scores et on regarde les catégories des k (parametre a decider pour le k plus proche voisins) premier scores - Et pour finir on attribue a notre fichier la categorie la plus représentée dans les k premiers score """