Cette fois, j'ai résumé la méthode de saisie des données de séquence dans PyTorch. Je suis sûr que de nombreux aspects ne peuvent être atteints, mais j'apprécierais vos conseils techniques. Ce que vous pouvez voir dans cet article est comment charger un ensemble de données dans PyTorch dans un morceau d'images en mouvement de longueur fixe. En particulier, on suppose que les ensembles de données tels que UCSD DATASET, qui ne sont pas enregistrés en tant qu'images animées mais sont enregistrés en tant qu'images de numéro de série pour chaque dossier, sont traités.
DATASET/ ├ train/ │ └ img_0001.png ← 1ère image de la vidéo │ └ img_0002.png ← 2ème image de la vidéo │ └ img_0003.png : │ : └ test/
Je voulais utiliser PyTorch pour entraîner le LSTM sans professeur et faire diverses choses, mais comme il n'y avait pas de module de chargement vidéo (dans mes recherches), j'ai décidé à contrecœur de le faire moi-même.
** En supposant que l'ensemble de données au format image est lu en premier, une image en mouvement (série temporelle partielle) avec une longueur fixe est créée à partir de celle-ci, et elle est consolidée par la taille du lot et entraînée par LSTM. Je vais. ** **
Dans PyTorch, les classes Dataset et DataLoader pour la lecture de l'ensemble de données d'apprentissage sont préparées, et les données existantes dans le répertoire donné au moment de la déclaration d'objet sont préparées pour la taille du lot pour chaque époque, donc au moment de l'apprentissage Très pratique. Si vous vous référez à ici, il y a les trois caractères suivants liés à la lecture.
transforms
--Module en charge du prétraitement des données
Dataset
--Un module qui renvoie un ensemble de données et l'étiquette correspondante --Retourne prétraités à l'aide de transformations lors du renvoi de données.
DataLoader
En général, les transformations sont utilisées pour définir le prétraitement de l'ensemble de données (standardisation, conversion de taille, etc.), puis Dataset est utilisé pour appliquer le mappage d'étiquettes et le prétraitement, et enfin Data Loader est utilisé pour définir la taille du lot. Je pense que ce sera un flux de retour en bloc. Cependant, ce n'est le cas que si l'entrée de l'ensemble de données est i.i.d., et cela pose un problème si vous souhaitez entrer ** des données de séquence. ** ** Je veux un module capable de gérer les données de séquence, en particulier les données d'images en mouvement, alors j'y ai pensé.
Premièrement, puisque la base est la classe Dataset, nous en héritons et déclarons une sous-classe (Seq_Dataset: SD) avec Ds comme classe parent (super classe).
Seule la méthode que vous souhaitez modifier sera à nouveau décrite sur la carte SD. (Les méthodes non définies sont automatiquement remplacées.)
Fondamentalement, lorsque vous étendez la classe Dataset et que vous l'étendez, vous écrirez des modifications dans __len__
et __getitem__
.
En particulier, dans __getitem__
, décrivez le traitement (conversion d'image en mouvement) pour l'objet Dataset lu (données d'image cette fois).
Le débit supposé cette fois est ** Paramètre de pré-traitement avec transformation → Lecture et traitement des données d'image avec Image Folder (Dataset) → Enfin, Seq_Dataset crée une image en mouvement de longueur fixe (série chronologique partielle) et en renvoie la taille du lot ** ..
Vous trouverez ci-dessous la classe SD qui est une extension de Ds cette fois. Je vais expliquer brièvement chaque fonction.
dataset.py
import torch
from torch.utils.data import Dataset
class Seq_Dataset(Dataset):
def __init__(self, datasets ,time_steps):
self.dataset = datasets
self.time_steps = time_steps
channels = self.dataset[0][0].size(0)
img_size = self.dataset[0][0].size(1)
video = torch.Tensor()
self.video = video.new_zeros((time_steps,channels,img_size,img_size))
def __len__(self):
return len(self.dataset)-self.time_steps
def __getitem__(self, index):
for i in range(self.time_steps):
self.video[i] = self.dataset[index+i][0]
img_label =self.dataset[index]
return self.video,img_label
Dans __init__
, nous définissons simplement les variables nécessaires. Cette fois, j'ai pris une longueur fixe, c'est-à-dire time_steprs comme argument. En outre, la variable appelée vidéo est un tenseur qui stocke une série temporelle partielle de longueur fixe et est initialisé avec 0. Ce sera sous la forme de stocker les données d'image dans les ensembles de données que j'ai écrits ici.
Dans __len__
, il ne renvoie que le nombre total de données. Cette fois, les données d'image lues sont finalement renvoyées sous la forme d'une image en mouvement de longueur fixe, donc le nombre total est len (dataset) -time_steps.
Dans __getitem__
, une série chronologique partielle pour time_steps est générée et affectée à la vidéo et renvoyée. Vous pouvez également décrire ici les opérations de niveau sur les images. Puisqu'il y a un arrière-plan d'apprentissage non supervisé cette fois, il est scandaleux que la valeur de l'image soit substituée telle quelle sans rien spécifier pour l'étiquette. Concernant la méthode de spécification de l'étiquette, je pense qu'il existe de nombreux exemples de référence si vous vous référez à d'autres. (Désolé pour cette application)
Lors de l'entraînement, je pense que ce sera sous la forme d'utiliser l'objet data_loader et de le tourner avec for pour entraîner le modèle. La procédure pour obtenir data_loader est la suivante, définissez chaque variable et suivez le flux de ImageFolder → Seq_Dataset → DataLoader.
main.py
data_dir = "./data/train/"
time_steps = 10
num_workers = 4
dataset = datasets.ImageFolder(data_dir, transform=transform)
data_ = dataset.Seq_Dataset(dataset, time_steps)
data_loader = DataLoader(data_, batch_size=opt.batch_size, shuffle=True, num_workers=num_workers)
La forme du tenseur de séries chronologiques partielles qui est finalement sorti a [batchsize, timeouts, channels, imgsize, imgsize]. À l'avenir, j'aimerais publier l'implémentation LSTM dans PyTorch en utilisant ce module auto-conçu. Merci d'avoir regardé jusqu'à la fin.
Recommended Posts