4
votes

Diviser l'ensemble de données d'image en ensembles de données de test de train

J'ai donc un dossier principal qui contient des sous-dossiers qui à leur tour contiennent des images pour l'ensemble de données comme suit.

-main_db

--- CLASSE_1

----- img_1

----- img_2

----- img_3

----- img_4

--- CLASSE_2

----- img_1

----- img_2

----- img_3

----- img_4

--- CLASSE_3

----- img_1

----- img_2

----- img_3

----- img_4

Je dois diviser cet ensemble de données en 2 parties, à savoir les données de train (70%) et les données de test (30%). Voici la hiérarchie que je souhaite atteindre

-main_db

---données d'entraînement

----- CLASSE_1

------- img_1

------- img_2

------- img_3

------- img_4

--- CLASSE_2

------- img_1

------- img_2

------- img_3

------- img_4

--- testing_data

----- CLASSE_1

------- img_5

------- img_6

------- img_7

------- img_8

--- CLASSE_2

------- img_5

------- img_6

------- img_7

------- img_8

Toute aide appréciée. Merci

J'ai essayé ce module. Mais cela ne fonctionne pas pour moi. Ce module n'est pas du tout importé.

https://github.com/jfilter/split-folders

C'est exactement ce que je veux.


6 commentaires

Vous semblez avoir trouvé une solution vous-même mais l'outil ne fonctionne pas. Comme il s'agit d'une question très spécifique et qu'il est peu probable que cela aide un public général, essayez de classer un problème avec split-folders si vous rencontrez des problèmes. Ils sont beaucoup plus susceptibles de vous aider que les gens d'ici!


D'où viennent les img_5 / img_6 / img_7 / img_8 ?


@ AriCooper-Davis la même classe je crois!


@nemo Vous avez absolument raison et j'ai déjà ouvert un problème sur leur repo. !


Si, en supposant hypothétiquement, j'ai 20 images dans tous les sous-dossiers, le dossier du jeu d'entraînement doit contenir 16 images et le jeu de test contient 4 images. Cette répartition envisage un ratio de répartition de 80% à 20%. @ AriCooper-Davis


Le module split-folders résout ce problème (je suis l'auteur). Je ne sais pas pourquoi cela ne fonctionnait pas pour vous.


4 Réponses :


7
votes

Cela devrait le faire. Il calculera le nombre d'images dans chaque dossier, puis les divisera en conséquence, enregistrant les données de test dans un dossier différent avec la même structure. Enregistrez le code dans le fichier main.py et exécutez la commande:

python3 main.py ----data_path=/path1 --test_data_path_to_save=/path2 --train_ratio=0.7

import shutil
import os
import numpy as np
import argparse

def get_files_from_folder(path):

    files = os.listdir(path)
    return np.asarray(files)

def main(path_to_data, path_to_test_data, train_ratio):
    # get dirs
    _, dirs, _ = next(os.walk(path_to_data))

    # calculates how many train data per class
    data_counter_per_class = np.zeros((len(dirs)))
    for i in range(len(dirs)):
        path = os.path.join(path_to_data, dirs[i])
        files = get_files_from_folder(path)
        data_counter_per_class[i] = len(files)
    test_counter = np.round(data_counter_per_class * (1 - train_ratio))

    # transfers files
    for i in range(len(dirs)):
        path_to_original = os.path.join(path_to_data, dirs[i])
        path_to_save = os.path.join(path_to_test_data, dirs[i])

        #creates dir
        if not os.path.exists(path_to_save):
            os.makedirs(path_to_save)
        files = get_files_from_folder(path_to_original)
        # moves data
        for j in range(int(test_counter[i])):
            dst = os.path.join(path_to_save, files[j])
            src = os.path.join(path_to_original, files[j])
            shutil.move(src, dst)


def parse_args():
  parser = argparse.ArgumentParser(description="Dataset divider")
  parser.add_argument("--data_path", required=True,
    help="Path to data")
  parser.add_argument("--test_data_path_to_save", required=True,
    help="Path to test data where to save")
  parser.add_argument("--train_ratio", required=True,
    help="Train ratio - 0.7 means splitting data in 70 % train and 30 % test")
  return parser.parse_args()

if __name__ == "__main__":
  args = parse_args()
  main(args.data_path, args.test_data_path_to_save, float(args.train_ratio))


1 commentaires

Je vais essayer cette pièce et vous le faire savoir! Merci d'avoir répondu !



1
votes

Si vous n'aimez pas trop le codage, il existe un package python appelé split-folders que vous pouvez utiliser. Il est extrêmement facile à utiliser et peut être trouvé ici. Voici comment il peut être utilisé.

pip install split_folders
import split-folders
input_folder = "input_path"
output = "output_path" #where you want the split datasets saved. one will be created if none is set

split_folders.ratio('input_folder', output="output", seed=42, ratio=(.8, .1, .1)) # ratio of split are in order of train/val/test. You can change to whatever you want. For train/val sets only, you could do .75, .25 for example.

Cependant, je recommande fortement de coder les réponses présentées ci-dessus car elles vous aident à apprendre.


2 commentaires

Bien que ce lien puisse répondre à la question, il est préférable d'inclure les parties essentielles de la réponse ici et de fournir le lien pour référence. Les réponses aux liens uniquement peuvent devenir invalides si la page liée change. - De l'avis


Ceci est un package, pas un site Web. Il sera disponible via pypi pendant longtemps.



0
votes

si vous archivez leur documentation ici , ils ont mis à jour la syntaxe. En gros, j'ai rencontré un problème similaire, mais j'ai trouvé que la nouvelle syntaxe suivante fonctionnait selon la mise à jour:

import splitfolders  # or import split_folders
splitfolders.ratio("input_folder", output="output", seed=1337, ratio=(.8, .1, .1), 
group_prefix=None) # default values

# Split with a ratio.
#To only split into training and validation set, set a tuple to `ratio`, i.e,`(.8,    
# .2)`.
splitfolders.ratio("input_folder", output="output", seed=1337, ratio=(.8, .1, .1), 
group_prefix=None) # default values

# Split val/test with a fixed number of items e.g. 100 for each set.
# To only split into training and validation set, use a single number to `fixed`, 
i.e., 
# `10`.
splitfolders.fixed("input_folder", output="output", seed=1337, fixed=(100, 100), 
oversample=False, group_prefix=None) # default values


0 commentaires

1
votes

** Visitez ce lien https://www.kaggle.com/questions-and-answers/102677 Le crédit va au commentaire "saravanansaminathan" sur Kaggle Pour le même problème sur mes ensembles de données avec la structure de dossiers suivante. / TTSplit / 0 /001_01.jpg ....... / 1 /001_04.jpg ....... J'ai suivi en prenant le lien ci-dessus comme référence. **

import os
import numpy as np
import shutil
import random
root_dir = '/home/dipak/Desktop/TTSplit/'
classes_dir = ['0', '1']

test_ratio = 0.20

for cls in classes_dir:
    os.makedirs(root_dir +'train/' + cls)
    os.makedirs(root_dir +'test/' + cls)

src = root_dir + cls

allFileNames = os.listdir(src)
np.random.shuffle(allFileNames)
train_FileNames, test_FileNames = np.split(np.array(allFileNames),
                                                          [int(len(allFileNames)* (1 - test_ratio))])


train_FileNames = [src+'/'+ name for name in train_FileNames.tolist()]
test_FileNames = [src+'/' + name for name in test_FileNames.tolist()]

print("*****************************")
print('Total images: ', len(allFileNames))
print('Training: ', len(train_FileNames))
print('Testing: ', len(test_FileNames))
print("*****************************")


lab = ['0', '1']

for name in train_FileNames:
    for i in lab:
        shutil.copy(name, root_dir +'train/' + i)

for name in test_FileNames:
    for i in lab:
        shutil.copy(name, root_dir +'test/' + i)
print("Copying Done!")


0 commentaires