web-dev-qa-db-fra.com

Augmentation de données dans PyTorch

Je suis un peu confus au sujet de l'augmentation des données réalisée dans PyTorch. Pour autant que je sache, lorsque nous effectuons une augmentation de données, nous GARDONS notre jeu de données d'origine et en ajoutons d'autres versions (Retournement, Recadrage, etc.). Mais cela ne semble pas se produire dans PyTorch. D'après ce que j'ai compris des références, lorsque nous utilisons data.transforms dans PyTorch, il les applique un par un. Donc par exemple:

data_transforms = {
    'train': transforms.Compose([
        transforms.RandomResizedCrop(224),
        transforms.RandomHorizontalFlip(),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ]),
    'val': transforms.Compose([
        transforms.Resize(256),
        transforms.CenterCrop(224),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ]),
}

Ici, pour la formation, nous rognons d’abord aléatoirement l’image et la redimensionnons pour la mettre en forme (224,224). Ensuite, nous prenons ces (224,224) images et en les retournant horizontalement. Par conséquent, notre ensemble de données contient désormais SEULEMENT les images retournées horizontalement, de sorte que nos images d'origine sont perdues dans ce cas.

Ai-je raison? Cette compréhension est-elle correcte? Sinon, comment indiquer à PyTorch dans le code ci-dessus (tiré de la documentation officielle) de conserver les images d'origine et de les redimensionner à la forme souhaitée (224,224)?

Merci

24
H.S

Les opérations transforms sont appliquées à vos images d'origine à chaque génération de lot. Si votre jeu de données reste inchangé, seules les images de lot sont copiées et transformées à chaque itération.

La confusion vient peut-être du fait que, comme dans votre exemple, transforms sont utilisés à la fois pour la préparation des données (redimensionnement/recadrage aux dimensions attendues, valeurs de normalisation, etc.) et pour l’augmentation des données (redimensionnement aléatoire/recadrage, retournement aléatoire des images, etc.).


Ce que fait votre data_transforms['train']:

  • Redimensionnez de manière aléatoire l'image fournie et recadrez-la de manière aléatoire pour obtenir un patch (224, 224).
  • Appliquez ou non un basculement horizontal aléatoire à ce patch, avec une chance de 50/50
  • Convertissez-le en Tensor
  • Normaliser le résultat Tensor, en fonction de la moyenne et des valeurs de déviation fournies

Ce que fait votre data_transforms['val']:

  • Redimensionnez votre image à (256, 256)
  • Recadrez au centre l'image redimensionnée pour obtenir un correctif (224, 224)
  • Convertissez-le en Tensor
  • Normaliser le résultat Tensor, en fonction de la moyenne et des valeurs de déviation fournies

(c'est-à-dire que le redimensionnement/recadrage aléatoire des données d'apprentissage est remplacé par une opération fixe pour la validation, afin d'obtenir des résultats de validation fiables)


Si vous ne voulez pas que vos images d'entraînement soient inversées horizontalement avec une chance 50/50, supprimez simplement la ligne transforms.RandomHorizontalFlip().

De même, si vous souhaitez que vos images soient toujours cadrées au centre, remplacez transforms.RandomResizedCrop Par transforms.Resize Et transforms.CenterCrop, Comme pour data_transforms['val'].

15
benjaminplanche

Je suppose que vous demandez si ces transformations d’augmentation des données (par exemple, RandomHorizontalFlip) réellement augmentent la taille du jeu de données, ou sont-elles appliquées sur chaque élément du jeu de données, un par un et non en ajoutant à la taille de l'ensemble de données.

En exécutant le fragment de code simple suivant, nous pouvons observer que ce dernier est vrai, c’est-à-dire si vous avez un jeu de données de 8 images, et créez un objet jeu de données PyTorch pour ce jeu de données lorsque vous parcourez le jeu de données, les transformations sont appelés sur chaque point de données et le point de données transformé est renvoyé. Ainsi, par exemple, si vous effectuez un basculement aléatoire, certains des points de données sont renvoyés sous forme d'origine, d'autres sous forme retournée (par exemple, 4 inversés et 4 d'origine). En d'autres termes, par une itération parmi les éléments du jeu de données, vous obtenez 8 points de données (certains retournés et d'autres non). [Ce qui est en contradiction avec la compréhension conventionnelle d'augmenter le jeu de données (par exemple, dans ce cas, avoir 16 points de données dans le jeu de données augmenté)]

class experimental_dataset(Dataset):

    def __init__(self, data, transform):
        self.data = data
        self.transform = transform

    def __len__(self):
        return len(self.data.shape[0])

    def __getitem__(self, idx):
        item = self.data[idx]
        item = self.transform(item)
        return item

    transform = transforms.Compose([
        transforms.ToPILImage(),
        transforms.RandomHorizontalFlip(),
        transforms.ToTensor()
    ])

x = torch.Rand(8, 1, 2, 2)
print(x)

dataset = experimental_dataset(x,transform)

for item in dataset:
    print(item)

Résultats: (Les petites différences en points flottants sont causées par la transformation en image pil et retour)

Jeu de données factice original:

tensor([[[[0.1872, 0.5518],
          [0.5733, 0.6593]]],


    [[[0.6570, 0.6487],
      [0.4415, 0.5883]]],


    [[[0.5682, 0.3294],
      [0.9346, 0.1243]]],


    [[[0.1829, 0.5607],
      [0.3661, 0.6277]]],


    [[[0.1201, 0.1574],
      [0.4224, 0.6146]]],


    [[[0.9301, 0.3369],
      [0.9210, 0.9616]]],


    [[[0.8567, 0.2297],
      [0.1789, 0.8954]]],


    [[[0.0068, 0.8932],
      [0.9971, 0.3548]]]])

ensemble de données transformé:

tensor([[[0.1843, 0.5490],
     [0.5725, 0.6588]]])
tensor([[[0.6549, 0.6471],
     [0.4392, 0.5882]]])
tensor([[[0.5647, 0.3255],
         [0.9333, 0.1216]]])
tensor([[[0.5569, 0.1804],
         [0.6275, 0.3647]]])
tensor([[[0.1569, 0.1176],
         [0.6118, 0.4196]]])
tensor([[[0.9294, 0.3333],
         [0.9176, 0.9608]]])
tensor([[[0.8549, 0.2275],
         [0.1765, 0.8941]]])
tensor([[[0.8902, 0.0039],
         [0.3529, 0.9961]]])
27
Ashkan372