Précautions lors de l'héritage de la classe DatasetMixin

À propos de cet article

J'ai décidé d'utiliser Trainer avec Chainer, et quand j'ai hérité de DatasetMixin, qui est une classe pour transmettre des données à lIterator, et créé mon propre jeu de données, j'ai fait une légère erreur, mais j'ai fait une légère erreur, donc je vais le garder comme un enregistrement.

(Ajout) La version de Chainer supposée dans cet article est 1.20. La situation peut changer avec la nouvelle version.

Message d'erreur rencontré

Le message d'erreur de sortie était difficile (difficile à comprendre) pour résoudre la cause.

  File "cupy/cuda/device.pyx", line 66, in cupy.cuda.device.Device.__enter__ (cupy/cuda/device.cpp:1621)
  File "cupy/cuda/device.pyx", line 81, in cupy.cuda.device.Device.use (cupy/cuda/device.cpp:1862)
  File "cupy/cuda/runtime.pyx", line 178, in cupy.cuda.runtime.setDevice (cupy/cuda/runtime.cpp:2702)
  File "cupy/cuda/runtime.pyx", line 130, in cupy.cuda.runtime.check_status (cupy/cuda/runtime.cpp:2028)
cupy.cuda.runtime.CUDARuntimeError: cudaErrorInvalidDevice: invalid device ordinal

Quand j'ai vu ce message, j'ai pensé: "Ai-je fait une erreur en écrivant le traitement GPU du modèle ou des données?" J'ai donc essayé désespérément de jouer avec cuda.cupy, mais je n'ai pas trouvé de solution.

Vous l'avez peut-être remarqué si vous lisez attentivement la documentation, mais à la fin, j'ai regardé la source du chainer pour comprendre la cause.

Une partie du code que j'ai créé

class MyDataset(chainer.dataset.DatasetMixin):
    def __init__(self, path):
        label_list = {}
        def get_label(l):
            num = label_list.get(l, -1)
            if num < 0:
                label_list[l] = len(label_list)
                return label_list[l]
            return num
        flist = []
        llist = []
        for root, dirs, files in os.walk(path):
            label = os.path.basename(root) #Utilisez le nom du répertoire comme étiquette
            label_num = get_label(label)
            for file in files:
                flist.append(os.path.join(root, file))
                llist.append(label_num)
        self.flist = flist
        self.llist = llist

    def __len__(self):
        return len(self.flist)

    def get_example(self, i):
        fname = self.flist[i]
        label = self.llist[i]
        img = Image.open(fname)
        img = np.asarray(img, dtype=np.float32).transpose(2, 0, 1)
        return img, label

Si vous utilisez cette classe pour vous entraîner en utilisant Iterator et Trainer avec un chainer compatible GPU, l'erreur ci-dessus se produira indépendamment de l'utilisation ou non du GPU.

L'erreur suivante s'est produite sur la version CPU du chainer.

    check_cuda_available()
  File "/path/to/lib/python3.4/site-packages/chainer/cuda.py", line 83, in check_cuda_available
    raise RuntimeError(msg)
RuntimeError: CUDA environment is not correctly set up
(see https://github.com/pfnet/chainer#installation).CuPy is not correctly installed. Please check your environment, uninstall Chainer and reinstall it with `pip install chainer --no-cache-dir -vvvv`.

Cause

L'histoire simple est que la valeur d'étiquette renvoyée par get_example n'est pas un objet numpy. Lors de l'écriture de code sans utiliser Trainer, il est facile de remarquer que TypeError ("numpy.ndarray ou cuda.ndarray sont attendus.") Apparaîtra s'il ne s'agit pas d'un objet numpy au moment de l'encapsulation de la valeur dans Variable. Cependant, quand je l'ai laissé à Iterator / Trainer, j'ai eu une erreur différente, donc je n'ai pas pu trouver la cause (dois-je demander une vérification de type?).

Contre-mesures

Dans ce cas, la solution est de transformer le tableau llist contenant les valeurs d'étiquette en un objet numpy.

@@ -16,7 +16,7 @@
                 flist.append(os.path.join(root, file))
                 llist.append(label_num)
         self.flist = flist
-        self.llist = llist
+        self.llist = np.asarray(llist, dtype=np.int32)
 
     def __len__(self):
         return len(self.flist)

finalement

Si vous utilisez Trainer, vous pouvez obtenir une sortie de progression sophistiquée (ProgressBar ()) et c'est cool, alors utilisons Trainer.

Recommended Posts

Précautions lors de l'héritage de la classe DatasetMixin
Précautions lors de l'utilisation de la fonction urllib.parse.quote
Argument de variable Python Un mémorandum lors de l'héritage d'une classe définie
Précautions lors de l'installation de packages dans l'environnement conda
Précautions à prendre lors de la manipulation de Luigi
Précautions lors de l'installation de fbprophet
Précautions lors de l'utilisation de Chainer
Précautions pour la mise à niveau de TensorFlow (vers la version 1.3)
Précautions lors de la création d'un tableau à deux dimensions avec toutes les mêmes valeurs
Précautions lors de l'utilisation d'une liste ou d'un dictionnaire comme argument par défaut