J'ai un ensemble de données de 400 images, 10 images de 40 personnes différentes. Il y a 2 tableaux NumPy, "olivetti_faces" contient les images (400x64x64) et "olivetti_faces_target" contient les classes de ces images (400), une classe pour chaque personne. Donc "olivetti_faces" est de la forme: array([<img1>, <img2>, ..., <img400>])<img> est un tableau de nombres 64x64, et "olivetti_faces_target" est de la forme: array([0, 0, ..., 39]).

Vous pouvez accéder à l'ensemble de données ici. Vous pouvez les charger après le téléchargement comme suit:

import numpy as np
data=np.load("olivetti_faces.npy")
target=np.load("olivetti_faces_target.npy")

Je voudrais choisir au hasard 100 des images, avec au moins une image de chacune des 40 personnes. Comment puis-je y parvenir dans NumPy?

Jusqu'à présent, je pouvais obtenir 100 images au hasard en utilisant le code suivant:

n = 100 # number of images to retrieve
rand_indeces = np.random.choice(data.shape[0], n, replace=False)
data_random = data[rand_indeces]
target_random = target_random[rand_indeces]

Mais cela ne garantit pas qu'au moins une image de chacune des 40 classes soit incluse dans data_random.

0
Sayyor Y 25 oct. 2020 à 15:57

2 réponses

Meilleure réponse

Comme suggéré dans mon commentaire, choisissez d'abord un index aléatoire de chaque classe. Choisissez ensuite des index aléatoires dans tout le tableau. Cela garantira que chaque classe a une entrée dans le résultat final.

Étant donné que chaque classe a 10 éléments, vous pouvez parcourir les classes 0-39 et choisir une valeur 0-9.

Essayez ce code:

import numpy as np
import random

data=np.load("olivetti_faces.npy")
target=np.load("olivetti_faces_target.npy")

# target is groups of 10, so select random index in each block
for i in range(40):  # class 0-39
   rndindex.append(i*10 + random.randint(0,9)) # one per class
   
for i in range(60):  # up to 100
   idx = rndindex[0]
   while idx in rndindex:  # prevent duplicates
       idx = random.randint(0,399)  # other indexes can be anywhere
   rndindex.append(idx)

rand_indeces = []  # np array objects
for idx in rndindex:
   rand_indeces.append(data[idx])

print(rndindex)
#print(rand_indeces)

Sortie (notez que les 40 premiers se situent dans des blocs de 10)

[9, 17, 23, 31, 41, 52, 60, 72, 83, 95, 
 100, 119, 121, 136, 140, 150, 166, 175, 188, 198, 
 209, 211, 221, 238, 243, 250, 261, 276, 289, 290, 
 306, 315, 325, 333, 344, 351, 368, 376, 382, 391, 
 62, 296, 327, 241, 393, 215, 64, 59, 185, 286, 
 162, 163, 364, 309, 220, 273, 32, 214, 217, 182, 
 172, 98, 19, 358, 92, 322, 68, 399, 226, 285, 
 103, 155, 249, 1, 75, 303, 311, 125, 339, 106, 
 127, 94, 101, 113, 35, 20, 189, 199, 128, 30, 
 131, 317, 337, 156, 340, 99, 397, 385, 384, 193]
1
Mike67 25 oct. 2020 à 16:50

Une façon de le faire, comme @xrisk l'a suggéré, serait d'obtenir au hasard 100 images jusqu'à ce que la condition soit remplie, comme suit:

n = 100 # number of images to retrieve
n_unique = len(np.unique(target)) # number of classes
containsAllCats = False
while not containsAllCats:
    rand_indeces = np.random.choice(data.shape[0], n, replace=False)
    data_random = data[rand_indeces]
    target_random = target[rand_indeces]
    containsAllCats = len(np.unique(target_random)) == n_unique

Cependant, il semble plutôt inefficace, nécessitant la plupart du temps plusieurs itérations.

0
Sayyor Y 25 oct. 2020 à 13:47